> ## Documentation Index
> Fetch the complete documentation index at: https://composio-27-feat-docs-revamp.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# 🦜🕸️ Using Composio With LangGraph

> Integrate Composio with LangGraph agents to let them seamlessly interact with external apps

## Star A Repository on GitHub

In this example, we will use LangGraph Agent to star a repository on GitHub using Composio Tools

<Steps>
  <Step title="Install Packages">
    <CodeGroup>
      ```bash Python
      pip install composio-langgraph
      ```

      ```bash TypeScript
      npm i @langchain/langgraph
      npm i composio-core 
      npm i @langchain/openai
      npm i @langchain/core
      ```
    </CodeGroup>
  </Step>

  <Step title="Import Libraries & Initialize ComposioToolSet">
    <CodeGroup>
      ```python Python
      from typing import Literal
      from langchain_openai import ChatOpenAI
      from langgraph.graph import MessagesState, StateGraph
      from langgraph.prebuilt import ToolNode
      from composio_langgraph import Action, ComposioToolSet, App

      composio_toolset = ComposioToolSet()
      ```

      ```typescript TypeScript
      import { LangGraphToolSet } from "composio-core";
      import { ToolNode } from "@langchain/langgraph/prebuilt";
      import { ChatOpenAI } from "@langchain/openai";
      import { StateGraph, END, MessagesAnnotation, START } from "@langchain/langgraph";
      import { HumanMessage } from "@langchain/core/messages";

      const composioToolset = new LangGraphToolSet();
      ```
    </CodeGroup>
  </Step>

  <Step title="Connect Your GitHub Account">
    <Info>You need to have an active GitHub Integration. Learn how to do this [here](https://youtu.be/LmyWy4LiedQ?si=u5uFArlNL0tew0Wf)</Info>

    <CodeGroup>
      ```shell CLI
      composio login
      composio add github
      ```

      ```python Python
      request = composio_toolset.initiate_connection(app=App.GITHUB)
      print(f"Open this URL to authenticate: {request.redirectUrl}")
      ```

      ```javascript TypeScript
      const connection = await composioToolset.connectedAccounts.initiate({appName: "github"})
      console.log(`Open this URL to authenticate: ${connection.redirectUrl}`);
      ```
    </CodeGroup>

    <Tip>
      Don't forget to set your `COMPOSIO_API_KEY` and `OPENAI_API_KEY` in your environment variables.
    </Tip>
  </Step>

  <Step title="Get And Bind Tools">
    You can get all the tools for a given app as shown below, but you can get **specific actions** and filter actions using **usecase** & **tags**. Learn more [here](../../patterns/tools/use-tools/use-specific-actions)

    <CodeGroup>
      ```python Python
      tools = composio_toolset.get_tools(
          apps=[App.GITHUB]
      )
      tool_node = ToolNode(tools)
      model = ChatOpenAI(temperature=0, streaming=True)
      model_with_tools = model.bind_tools(tools)
      ```

      ```typescript TypeScript
      const tools = await composioToolset.getTools({
          apps: ["github"],
      });

      const toolNode = new ToolNode(tools);

      const model = new ChatOpenAI({ temperature: 0, apiKey:""}).bindTools(tools);
      ```
    </CodeGroup>
  </Step>

  <Step title="Define the model calling function">
    <CodeGroup>
      ```python Python
      def call_model(state: MessagesState):
          """
          Process messages through the LLM and return the response
          """
          messages = state["messages"]
          response = model_with_tools.invoke(messages)
          return {"messages": [response]}
      ```

      ```typescript TypeScript
      async function callModal(state) {
          const { messages } = state;
          const response = await model.invoke(messages);
          return { messages: [response] };
      }
      ```
    </CodeGroup>
  </Step>

  <Step title="Define the decision function for workflow routing">
    <CodeGroup>
      ```python Python
      def should_continue(state: MessagesState) -> Literal["tools", "__end__"]:
          """
          Determine if the conversation should continue to tools or end
          Returns:
              - "tools" if the last message contains tool calls
              - "__end__" otherwise
          """
          messages = state["messages"]
          last_message = messages[-1]
          if last_message.tool_calls:
              return "tools"
          return "__end__"
      ```

      ```typescript TypeScript
      async function shouldContinue(state) {
          const { messages } = state;
          const lastMessage = messages[messages.length - 1];

          if (lastMessage.additional_kwargs.tool_calls) {
              return "tools";
          } else {
              return END;
          }
      }
      ```
    </CodeGroup>
  </Step>

  <Step title="Define the workflow graph">
    <CodeGroup>
      ```python Python
      workflow = StateGraph(MessagesState)

      workflow.add_node("agent", call_model)
      workflow.add_node("tools", tool_node)
      workflow.add_edge("__start__", "agent")
      workflow.add_conditional_edges(
          "agent",
          should_continue,
      )
      workflow.add_edge("tools", "agent")

      app = workflow.compile()
      ```

      ```typescript TypeScript
      const workflow = new StateGraph(MessagesAnnotation)
          .addNode("agent", callModal)
          .addEdge(START, "agent")
          .addNode("tools", toolNode)
          .addConditionalEdges("agent", shouldContinue)
          .addEdge("tools", "agent");

      const app = workflow.compile();
      ```
    </CodeGroup>
  </Step>

  <Step title="Execute the workflow">
    <CodeGroup>
      ```python Python
      for chunk in app.stream(
          {
              "messages": [
                  (
                      "human",
                      "Star the GitHub Repository composiohq/composio",
                  )
              ]
          },
          stream_mode="values",
      ):
          chunk["messages"][-1].pretty_print()
      ```

      ```typescript TypeScript
      const stream = await app.invoke({
          messages: [
              new HumanMessage("Star the GitHub Repository composiohq/composio"),
          ],
      });

      console.log(stream.messages[stream.messages.length - 1].content);
      ```
    </CodeGroup>
  </Step>
</Steps>
