composio-langgraph 0.3.28__py3-none-any.whl → 0.10.5__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,13 +1,3 @@
1
- from composio import Action, App, Tag, Trigger, WorkspaceType
1
+ from .provider import LanggraphProvider
2
2
 
3
- from .toolset import ComposioToolSet
4
-
5
-
6
- __all__ = (
7
- "Action",
8
- "App",
9
- "Tag",
10
- "Trigger",
11
- "WorkspaceType",
12
- "ComposioToolSet",
13
- )
3
+ __all__ = ("LanggraphProvider",)
@@ -0,0 +1,93 @@
1
+ """ComposioLangChain class definition"""
2
+
3
+ import types
4
+ import typing as t
5
+ from inspect import Signature
6
+
7
+ import pydantic
8
+ from langchain_core.tools import StructuredTool as BaseStructuredTool
9
+
10
+ from composio.core.provider import AgenticProvider, AgenticProviderExecuteFn
11
+ from composio.types import Tool
12
+ from composio.utils.pydantic import parse_pydantic_error
13
+ from composio.utils.shared import (
14
+ get_signature_format_from_schema_params,
15
+ json_schema_to_model,
16
+ )
17
+
18
+
19
+ class StructuredTool(BaseStructuredTool): # type: ignore[misc]
20
+ def run(self, *args, **kwargs):
21
+ try:
22
+ return super().run(*args, **kwargs)
23
+ except pydantic.ValidationError as e:
24
+ return {"successful": False, "error": parse_pydantic_error(e), "data": None}
25
+
26
+
27
+ class LanggraphProvider(
28
+ AgenticProvider[StructuredTool, t.List[StructuredTool]],
29
+ name="langgraph",
30
+ ):
31
+ """
32
+ Composio toolset for Langchain framework.
33
+ """
34
+
35
+ def _wrap_action(
36
+ self,
37
+ tool: str,
38
+ description: str,
39
+ schema_params: t.Dict,
40
+ execute_tool: AgenticProviderExecuteFn,
41
+ ):
42
+ def function(**kwargs: t.Any) -> t.Dict:
43
+ """Wrapper function for composio action."""
44
+ return execute_tool(tool, kwargs)
45
+
46
+ action_func = types.FunctionType(
47
+ function.__code__,
48
+ globals=globals(),
49
+ name=tool,
50
+ closure=function.__closure__,
51
+ )
52
+ action_func.__signature__ = Signature( # type: ignore
53
+ parameters=get_signature_format_from_schema_params(
54
+ schema_params=schema_params
55
+ )
56
+ )
57
+ action_func.__doc__ = description
58
+ return action_func
59
+
60
+ def wrap_tool(
61
+ self, tool: Tool, execute_tool: AgenticProviderExecuteFn
62
+ ) -> StructuredTool:
63
+ """Wraps composio tool as Langchain StructuredTool object."""
64
+ return t.cast(
65
+ StructuredTool,
66
+ StructuredTool.from_function(
67
+ name=tool.slug,
68
+ description=tool.description,
69
+ args_schema=json_schema_to_model(
70
+ json_schema=tool.input_parameters,
71
+ skip_default=self.skip_default,
72
+ ),
73
+ return_schema=True,
74
+ func=self._wrap_action(
75
+ tool=tool.slug,
76
+ description=tool.description,
77
+ schema_params=tool.input_parameters,
78
+ execute_tool=execute_tool,
79
+ ),
80
+ handle_tool_error=True,
81
+ handle_validation_error=True,
82
+ ),
83
+ )
84
+
85
+ def wrap_tools(
86
+ self,
87
+ tools: t.Sequence[Tool],
88
+ execute_tool: AgenticProviderExecuteFn,
89
+ ) -> t.List[StructuredTool]:
90
+ """
91
+ Get composio tools wrapped as Langchain StructuredTool objects.
92
+ """
93
+ return [self.wrap_tool(tool=tool, execute_tool=execute_tool) for tool in tools]
File without changes
@@ -0,0 +1,138 @@
1
+ Metadata-Version: 2.4
2
+ Name: composio-langgraph
3
+ Version: 0.10.5
4
+ Summary: Use Composio to get array of tools with LangGraph Agent Workflows.
5
+ Home-page: https://github.com/ComposioHQ/composio
6
+ Author: composio
7
+ Author-email: Composio <tech@composio.dev>
8
+ Project-URL: Homepage, https://github.com/ComposioHQ/composio
9
+ Classifier: Programming Language :: Python :: 3
10
+ Classifier: License :: OSI Approved :: Apache Software License
11
+ Classifier: Operating System :: OS Independent
12
+ Requires-Python: >=3.9,<4
13
+ Description-Content-Type: text/markdown
14
+ Requires-Dist: langgraph
15
+ Requires-Dist: composio
16
+ Dynamic: author
17
+ Dynamic: home-page
18
+ Dynamic: requires-python
19
+
20
+ ## 🦜🕸️ Using Composio With LangGraph
21
+
22
+ Integrate Composio with LangGraph Agentic workflows & enable them to interact seamlessly with external apps, enhancing their functionality and reach.
23
+
24
+ ### Goal
25
+
26
+ - **Star a repository on GitHub** using natural language commands through a LangGraph Agent.
27
+
28
+ ### Installation and Setup
29
+
30
+ Ensure you have the necessary packages installed and connect your GitHub account to allow your agents to utilize GitHub functionalities.
31
+
32
+ ```bash
33
+ # Install Composio LangGraph package
34
+ pip install composio-langgraph
35
+
36
+ # Connect your GitHub account
37
+ composio-cli add github
38
+
39
+ # View available applications you can connect with
40
+ composio-cli show-apps
41
+ ```
42
+
43
+ ### Usage Steps
44
+
45
+ #### 1. Import Base Packages
46
+
47
+ Prepare your environment by initializing necessary imports from LangGraph & LangChain for setting up your agent.
48
+
49
+ ```python
50
+ from typing import Literal
51
+
52
+ from langchain_openai import ChatOpenAI
53
+ from langgraph.graph import MessagesState, StateGraph
54
+ from langgraph.prebuilt import ToolNode
55
+ ```
56
+
57
+ #### 2. Fetch GitHub LangGraph Tools via Composio
58
+
59
+ Access GitHub tools provided by Composio for LangGraph, initialize a `ToolNode` with necessary tools obtaned from `ComposioToolSet`.
60
+
61
+ ```python
62
+ from composio_langgraph import Action, ComposioToolSet
63
+
64
+ # Initialize the toolset for GitHub
65
+ composio_toolset = ComposioToolSet()
66
+ tools = composio_toolset.get_actions(
67
+ actions=[
68
+ Action.GITHUB_ACTIVITY_STAR_REPO_FOR_AUTHENTICATED_USER,
69
+ Action.GITHUB_USERS_GET_AUTHENTICATED,
70
+ ])
71
+ tool_node = ToolNode(tools)
72
+ ```
73
+
74
+ #### 3. Prepare the model
75
+
76
+ Initialize the LLM class and bind obtained tools to the model.
77
+
78
+ ```python
79
+ model = ChatOpenAI(temperature=0, streaming=True)
80
+ model_with_tools = model.bind_tools(functions)
81
+ ```
82
+ #### 4. Define the Graph Nodes
83
+
84
+ LangGraph expects you to define different nodes of the agentic workflow as separate functions. Here we define a node for calling the LLM model.
85
+
86
+ ```python
87
+ def call_model(state: MessagesState):
88
+ messages = state["messages"]
89
+ response = model_with_tools.invoke(messages)
90
+ return {"messages": [response]}
91
+ ```
92
+ #### 5. Define the Graph Nodes and Edges
93
+
94
+ To establish the agent's workflow, we begin by initializing the workflow with `agent` and `tools` node, followed by specifying the connecting edges between nodes, finally compiling the workflow. These edges can be straightforward or conditional, depending on the workflow requirements.
95
+
96
+ ```python
97
+ def should_continue(state: MessagesState) -> Literal["tools", "__end__"]:
98
+ messages = state["messages"]
99
+ last_message = messages[-1]
100
+ if last_message.tool_calls:
101
+ return "tools"
102
+ return "__end__"
103
+
104
+
105
+ workflow = StateGraph(MessagesState)
106
+
107
+ # Define the two nodes we will cycle between
108
+ workflow.add_node("agent", call_model)
109
+ workflow.add_node("tools", tool_node)
110
+
111
+ workflow.add_edge("__start__", "agent")
112
+ workflow.add_conditional_edges(
113
+ "agent",
114
+ should_continue,
115
+ )
116
+ workflow.add_edge("tools", "agent")
117
+
118
+ app = workflow.compile()
119
+ ```
120
+ #### 6. Invoke & Check Response
121
+
122
+ After the compilation of workflow, we invoke the LLM with a task, and stream the response.
123
+
124
+ ```python
125
+ for chunk in app.stream(
126
+ {
127
+ "messages": [
128
+ (
129
+ "human",
130
+ # "Star the Github Repository composiohq/composio",
131
+ "Get my information.",
132
+ )
133
+ ]
134
+ },
135
+ stream_mode="values",
136
+ ):
137
+ chunk["messages"][-1].pretty_print()
138
+ ```
@@ -0,0 +1,7 @@
1
+ composio_langgraph/__init__.py,sha256=UmBCWVwsgGM4UCdYf0bxQ6byIkifzDZ_LFYLyWzRODs,74
2
+ composio_langgraph/provider.py,sha256=Unomz2dvgpfPUJs5vZGpkmEg3kWlRBnTACz5yQxlaaQ,2959
3
+ composio_langgraph/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
+ composio_langgraph-0.10.5.dist-info/METADATA,sha256=oLUbKgbIheTd__I_wcngUktT3HM9bGVC4qfMC7rS368,4068
5
+ composio_langgraph-0.10.5.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
6
+ composio_langgraph-0.10.5.dist-info/top_level.txt,sha256=fT5qLVROO6_k0FCyW8_fOkGRJc_lxwWX-c6R6kN-llc,19
7
+ composio_langgraph-0.10.5.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (71.1.0)
2
+ Generator: setuptools (80.9.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,124 +0,0 @@
1
- import typing as t
2
-
3
- from composio import WorkspaceConfigType
4
- from composio.constants import DEFAULT_ENTITY_ID
5
-
6
- from composio_langchain import ComposioToolSet as BaseComposioToolSet
7
-
8
-
9
- class ComposioToolSet(BaseComposioToolSet):
10
- """
11
- Composio toolset for LangGraph framework.
12
-
13
- Example:
14
- ```python
15
- import json
16
- import operator
17
- from typing import Annotated, TypedDict, Sequence
18
-
19
- from langchain_openai import ChatOpenAI
20
- from langchain_core.utils.function_calling import convert_to_openai_function
21
- from langchain_core.messages import BaseMessage, HumanMessage, FunctionMessage
22
-
23
- from langgraph.graph import StateGraph, END
24
- from langgraph.prebuilt import ToolInvocation, ToolExecutor
25
- from composio_langgraph import Action, ComposioToolSet
26
-
27
- composio_toolset = ComposioToolSet()
28
- tools = composio_toolset.get_actions(
29
- actions=[Action.GITHUB_ACTIVITY_STAR_REPO_FOR_AUTHENTICATED_USER]
30
- )
31
- tool_executor = ToolExecutor(tools)
32
- functions = [convert_to_openai_function(t) for t in tools]
33
-
34
- model = ChatOpenAI(temperature=0, streaming=True)
35
- model = model.bind_functions(functions)
36
-
37
-
38
- def function_1(state):
39
- messages = state['messages']
40
- response = model.invoke(messages)
41
- return {"messages": [response]}
42
-
43
-
44
- def function_2(state):
45
- messages = state['messages']
46
- last_message = messages[-1]
47
- parsed_function_call = last_message.additional_kwargs["function_call"]
48
-
49
- action = ToolInvocation(
50
- tool=parsed_function_call["name"],
51
- tool_input=json.loads(parsed_function_call["arguments"]),
52
- )
53
-
54
- # We call the tool_executor and get back a response
55
- response = tool_executor.invoke(action)
56
-
57
- # We use the response to create a FunctionMessage
58
- function_message = FunctionMessage(
59
- content=str(response),
60
- name=action.tool
61
- )
62
-
63
- return {"messages": [function_message]}
64
-
65
-
66
- def where_to_go(state):
67
- messages = state['messages']
68
- last_message = messages[-1]
69
-
70
- if "function_call" in last_message.additional_kwargs:
71
- return "continue"
72
- else:
73
- return "end"
74
-
75
-
76
- class AgentState(TypedDict):
77
- messages: Annotated[Sequence[BaseMessage], operator.add]
78
-
79
-
80
- workflow = StateGraph(AgentState)
81
- workflow.add_node("agent", function_1)
82
- workflow.add_node("tool", function_2)
83
- workflow.add_conditional_edges(
84
- "agent",
85
- where_to_go,
86
- {
87
- "continue": "tool",
88
- "end": END
89
- }
90
- )
91
- workflow.add_edge('tool', 'agent')
92
- workflow.set_entry_point("agent")
93
-
94
- app = workflow.compile()
95
- ```
96
- """
97
-
98
- def __init__(
99
- self,
100
- api_key: t.Optional[str] = None,
101
- base_url: t.Optional[str] = None,
102
- entity_id: str = DEFAULT_ENTITY_ID,
103
- output_in_file: bool = False,
104
- workspace_config: t.Optional[WorkspaceConfigType] = None,
105
- workspace_id: t.Optional[str] = None,
106
- ) -> None:
107
- """
108
- Initialize composio toolset.
109
-
110
- :param api_key: Composio API key
111
- :param base_url: Base URL for the Composio API server
112
- :param entity_id: Entity ID for making function calls
113
- :param output_in_file: Whether to write output to a file
114
- """
115
- super().__init__(
116
- api_key=api_key,
117
- base_url=base_url,
118
- entity_id=entity_id,
119
- output_in_file=output_in_file,
120
- workspace_config=workspace_config,
121
- workspace_id=workspace_id,
122
- )
123
-
124
- self._runtime = "langgraph"
@@ -1,164 +0,0 @@
1
- Metadata-Version: 2.1
2
- Name: composio_langgraph
3
- Version: 0.3.28
4
- Summary: Use Composio to get array of tools with LnagGraph Agent Workflows
5
- Home-page: https://github.com/ComposioHQ/composio
6
- Author: Sawradip
7
- Author-email: sawradip@composio.dev
8
- Classifier: Programming Language :: Python :: 3
9
- Classifier: License :: OSI Approved :: Apache Software License
10
- Classifier: Operating System :: OS Independent
11
- Requires-Python: >=3.9,<4
12
- Description-Content-Type: text/markdown
13
- Requires-Dist: langchain-core >=0.2.17
14
- Requires-Dist: composio-langchain ==0.3.28
15
-
16
- ## 🦜🕸️ Using Composio With LangGraph
17
-
18
- Integrate Composio with LangGraph Agentic workflows & enable them to interact seamlessly with external apps, enhancing their functionality and reach.
19
-
20
- ### Goal
21
-
22
- - **Star a repository on GitHub** using natural language commands through a LangGraph Agent.
23
-
24
- ### Installation and Setup
25
-
26
- Ensure you have the necessary packages installed and connect your GitHub account to allow your agents to utilize GitHub functionalities.
27
-
28
- ```bash
29
- # Install Composio LangGraph package
30
- pip install composio-langgraph
31
-
32
- # Connect your GitHub account
33
- composio-cli add github
34
-
35
- # View available applications you can connect with
36
- composio-cli show-apps
37
- ```
38
-
39
- ### Usage Steps
40
-
41
- #### 1. Import Base Packages
42
-
43
- Prepare your environment by initializing necessary imports from LangGraph & LangChain for setting up your agent.
44
-
45
- ```python
46
- from langchain.agents import create_openai_functions_agent, AgentExecutor
47
- import json
48
- import operator
49
- from typing import Annotated, TypedDict, Sequence
50
-
51
- from langchain_openai import ChatOpenAI
52
- from langchain_core.utils.function_calling import convert_to_openai_function
53
- from langchain_core.messages import BaseMessage, HumanMessage, FunctionMessage
54
-
55
- from langgraph.graph import StateGraph, END
56
- from langgraph.prebuilt import ToolInvocation, ToolExecutor
57
- ```
58
-
59
- #### 2. Fetch GitHub LangGraph Tools via Composio
60
-
61
- Access GitHub tools provided by Composio for LangGraph, initialize a `tool_executor` and get OpenAI-format function schemas from the tools.
62
-
63
- ```python
64
- from composio_langgraph import Action, ComposioToolSet
65
-
66
- # Initialize the toolset for GitHub
67
- composio_toolset = ComposioToolSet()
68
- tools = composio_toolset.get_actions(
69
- actions=[Action.GITHUB_ACTIVITY_STAR_REPO_FOR_AUTHENTICATED_USER]
70
- )
71
- tool_executor = ToolExecutor(tools)
72
- functions = [convert_to_openai_function(t) for t in tools]
73
- ```
74
-
75
- #### 3. Prepare the model
76
-
77
- Initialize the LLM class and bind obtained functions to the model.
78
-
79
- ```python
80
- model = ChatOpenAI(temperature=0, streaming=True)
81
- model = model.bind_functions(functions)
82
- ```
83
- #### 4. Define the Graph Nodes
84
-
85
- LangGraph expects you to define different nodes of the agentic workflow as separate functions.
86
-
87
- Here we define one node for calling the LLM and another for executing the correct tool(function), with appropriate parameters.
88
-
89
- ```python
90
- def function_1(state):
91
- messages = state['messages']
92
- response = model.invoke(messages)
93
- return {"messages": [response]}
94
-
95
-
96
- def function_2(state):
97
- messages = state['messages']
98
- last_message = messages[-1]
99
-
100
- parsed_function_call = last_message.additional_kwargs["function_call"]
101
-
102
- action = ToolInvocation(
103
- tool=parsed_function_call["name"],
104
- tool_input=json.loads(parsed_function_call["arguments"]),
105
- )
106
-
107
- response = tool_executor.invoke(action)
108
-
109
- function_message = FunctionMessage(content=str(response), name=action.tool)
110
-
111
- return {"messages": [function_message]}
112
-
113
- ```
114
- #### 5. Define the Graph Edges
115
-
116
- To establish the agent's workflow, we begin by initializing the workflow with an `AgentState` to maintain state, followed by specifying the connecting edges between nodes. These edges can be straightforward or conditional, depending on the workflow requirements.
117
-
118
- ```python
119
-
120
- def where_to_go(state):
121
- messages = state['messages']
122
- last_message = messages[-1]
123
-
124
- if "function_call" in last_message.additional_kwargs:
125
- return "continue"
126
- else:
127
- return "end"
128
-
129
-
130
- class AgentState(TypedDict):
131
- messages: Annotated[Sequence[BaseMessage], operator.add]
132
-
133
-
134
- workflow = StateGraph(AgentState)
135
- workflow.add_node("agent", function_1)
136
- workflow.add_node("tool", function_2)
137
- workflow.add_conditional_edges(
138
- "agent",
139
- where_to_go,
140
- {
141
- "continue": "tool",
142
- "end": END
143
- }
144
- )
145
- workflow.add_edge('tool', 'agent')
146
- workflow.set_entry_point("agent")
147
-
148
- app = workflow.compile()
149
- ```
150
- #### 6. Invoke & Check Response
151
-
152
- After the compilation of workflow, we invoke the LLM with a task, and print the final response.
153
-
154
- ```python
155
- inputs = {
156
- "messages": [
157
- HumanMessage(
158
- content="Star the Github repository sawradip/sawradip"
159
- )
160
- ]
161
- }
162
- response = app.invoke(inputs)
163
- print(response)
164
- ```
@@ -1,6 +0,0 @@
1
- composio_langgraph/__init__.py,sha256=sjr9YY5lPNx-vI75_pmbFgPWUaEuh0WIUozsskDlQOE,211
2
- composio_langgraph/toolset.py,sha256=Ud3wFuFIiOm4InjhiNZGSjLzUElDL1YR84LEsOEyb88,3625
3
- composio_langgraph-0.3.28.dist-info/METADATA,sha256=_Un_fuNZaX0MHSPYJ0odHsNB9y76fZw1A8FK8LvAYLw,4758
4
- composio_langgraph-0.3.28.dist-info/WHEEL,sha256=Wyh-_nZ0DJYolHNn1_hMa4lM7uDedD_RGVwbmTjyItk,91
5
- composio_langgraph-0.3.28.dist-info/top_level.txt,sha256=fT5qLVROO6_k0FCyW8_fOkGRJc_lxwWX-c6R6kN-llc,19
6
- composio_langgraph-0.3.28.dist-info/RECORD,,