From a02d7d64b90ad3e93f9948596a7bea5054a0d2af Mon Sep 17 00:00:00 2001 From: collhoun <2904yr@mail.ru> Date: Sun, 19 Apr 2026 16:51:03 +0300 Subject: [PATCH 1/6] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D0=B0=20=D0=B0=D0=B2=D1=82=D0=BE=D1=80=D0=B8=D0=B7=D0=B0?= =?UTF-8?q?=D1=86=D0=B8=D1=8F=20=D1=87=D0=B5=D1=80=D0=B5=D0=B7=20composio?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/agent/base.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/agent/base.py b/src/agent/base.py index f635ba8..dce4088 100644 --- a/src/agent/base.py +++ b/src/agent/base.py @@ -2,6 +2,7 @@ import os from deepagents import create_deep_agent from langchain_openai import ChatOpenAI from langgraph.checkpoint.memory import MemorySaver +from composio import Composio def create_agent(): @@ -11,9 +12,13 @@ def create_agent(): api_key=os.environ["PROVIDER_API_KEY"], ) + composio = Composio() + session = composio.create(user_id="default_user") + tools = session.tools() + return create_deep_agent( model=model, - system_prompt="You are a helpful assistant.", + system_prompt="You are a helpful assistant. Use Composio tools to take action when needed.", checkpointer=MemorySaver(), - ) - + tools=tools + ) \ No newline at end of file From ad89138afc76704a909497f0fc951355dd32a249 Mon Sep 17 00:00:00 2001 From: collhoun <2904yr@mail.ru> Date: Sun, 19 Apr 2026 16:52:05 +0300 Subject: [PATCH 2/6] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D0=B0=20=D0=BE=D0=B1=D1=80=D0=B0=D1=82=D0=BE=D0=BA=D0=B0?= =?UTF-8?q?=20=D0=B0=D0=B2=D1=82=D1=80=D0=B8=D0=B7=D0=B0=D1=86=D0=B8=D0=B8?= =?UTF-8?q?=20=D1=87=D0=B5=D1=80=D0=B5=D0=B7=20composio?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/agent/service.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/agent/service.py b/src/agent/service.py index 05f50c4..04c4e47 100644 --- a/src/agent/service.py +++ b/src/agent/service.py @@ -45,10 +45,16 @@ class AgentService: # 2. Инструмент завершил работу и вернул результат elif kind == "on_tool_end": - yield MsgEventToolResult( - tool_name=event["name"], - result=event["data"].get("output") - ) + result = event["data"].get("output") + + # Перехватываем ссылку на авторизацию Composio v3 + if result and "connect.composio.dev" in str(result): + yield MsgEventTextChunk(text=f"\n⚠️ Для выполнения действия требуется авторизация. Перейдите по ссылке: {result}\n") + else: + yield MsgEventToolResult( + tool_name=event["name"], + result=str(result) # Страховка от ошибки сериализации JSON + ) # 3. В конце генерации отправляем событие завершения yield MsgEventEnd(tokens_used=0) # потом заменить на метадату From f6e28eaca2bb04525116db57b34d1a9f0402e9fa Mon Sep 17 00:00:00 2001 From: collhoun <2904yr@mail.ru> Date: Sun, 19 Apr 2026 16:52:26 +0300 Subject: [PATCH 3/6] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=20composio?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- uv.lock | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/uv.lock b/uv.lock index 22446ee..b20be97 100644 --- a/uv.lock +++ b/uv.lock @@ -7,6 +7,7 @@ name = "agent" version = "0.1.0" source = { virtual = "." } dependencies = [ + { name = "composio" }, { name = "deepagents" }, { name = "fastapi" }, { name = "langchain-openai" }, @@ -15,6 +16,7 @@ dependencies = [ [package.metadata] requires-dist = [ + { name = "composio", specifier = ">=0.11.5" }, { name = "deepagents", specifier = ">=0.1.0" }, { name = "fastapi", specifier = ">=0.135.3" }, { name = "langchain-openai", specifier = ">=1.1.12" }, @@ -183,6 +185,40 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" }, ] +[[package]] +name = "composio" +version = "0.11.5" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "composio-client" }, + { name = "json-schema-to-pydantic" }, + { name = "openai" }, + { name = "pydantic" }, + { name = "pysher" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/8e/9e/d9ac27e293a3c60c823bd4e45fd2552b214d9291a60dade3e4e3f22fa77f/composio-0.11.5.tar.gz", hash = "sha256:524bc722b76af00b5ff4f4a88424f123aa41c77e84b336399464cfa9ad27ed3a", size = 171371, upload-time = "2026-04-10T07:59:42.952Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ba/cb/afca4cd94abf1c52060a78bca1cc2b1229e47f1b535c5aad5ba65320cc86/composio-0.11.5-py3-none-any.whl", hash = "sha256:5ba13a4d68508d9f93873810f37c71238897ccf3af5d951dad8a5f1bc229030b", size = 117125, upload-time = "2026-04-10T07:59:28.316Z" }, +] + +[[package]] +name = "composio-client" +version = "1.33.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, + { name = "distro" }, + { name = "httpx" }, + { name = "pydantic" }, + { name = "sniffio" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/4b/11/88d09721f03431deb8b055fe39cedb79697e5a72d4342fa033d277b1eb70/composio_client-1.33.0.tar.gz", hash = "sha256:3b92400383ca2454a361e3ad8d55e2b447b47ed3c4cd4910f61466e5933554c1", size = 225669, upload-time = "2026-04-10T01:35:31.478Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/93/bc/83efc07964e39109c4471f8873dda98cd16137c8e4e2d4456a8a5d8f9c42/composio_client-1.33.0-py3-none-any.whl", hash = "sha256:8c01f096772272398760f5c553b3444b5706e346b294856f613b092f1d3afd6b", size = 252699, upload-time = "2026-04-10T01:35:30.003Z" }, +] + [[package]] name = "cryptography" version = "46.0.6" @@ -428,6 +464,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/f9/8e/7def204fea9f9be8b3c21a6f2dd6c020cf56c7d5ff753e0e23ed7f9ea57e/jiter-0.13.0-cp314-cp314t-win_arm64.whl", hash = "sha256:2c26cf47e2cad140fa23b6d58d435a7c0161f5c514284802f25e87fddfe11024", size = 187152, upload-time = "2026-02-02T12:37:22.124Z" }, ] +[[package]] +name = "json-schema-to-pydantic" +version = "0.4.11" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pydantic" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/60/d8/423895b918706c80db1cee679c13fbe810200b9a9d9a9442c7a58d35c3f2/json_schema_to_pydantic-0.4.11.tar.gz", hash = "sha256:35448ed711a28dd33396b095c8492939b4925aa30eb31942e9b8e08d04279465", size = 56597, upload-time = "2026-03-09T20:53:55.692Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f3/64/7cfeb8c6d2a5e73e0f8d732032aa62be9a7724c04beb461d677de0b4beb3/json_schema_to_pydantic-0.4.11-py3-none-any.whl", hash = "sha256:da2ccc39d070ee03dbcf0517d16720e3e33f7aa8d61257ace09af8c51bd46348", size = 17842, upload-time = "2026-03-09T20:53:54.576Z" }, +] + [[package]] name = "jsonpatch" version = "1.33" @@ -757,6 +805,16 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/9f/ed/068e41660b832bb0b1aa5b58011dea2a3fe0ba7861ff38c4d4904c1c1a99/pydantic_core-2.41.5-cp314-cp314t-win_arm64.whl", hash = "sha256:35b44f37a3199f771c3eaa53051bc8a70cd7b54f333531c59e29fd4db5d15008", size = 1974769, upload-time = "2025-11-04T13:42:01.186Z" }, ] +[[package]] +name = "pysher" +version = "1.0.8" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "requests" }, + { name = "websocket-client" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/12/a0/d0638470df605ce266991fb04f74c69ab1bed3b90ac3838e9c3c8b69b66a/Pysher-1.0.8.tar.gz", hash = "sha256:7849c56032b208e49df67d7bd8d49029a69042ab0bb45b2ed59fa08f11ac5988", size = 9071, upload-time = "2022-10-10T13:41:09.936Z" } + [[package]] name = "python-dotenv" version = "1.2.2" @@ -1069,6 +1127,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/eb/d8/0d1d2e9d3fabcf5d6840362adcf05f8cf3cd06a73358140c3a97189238ae/wcmatch-10.1-py3-none-any.whl", hash = "sha256:5848ace7dbb0476e5e55ab63c6bbd529745089343427caa5537f230cc01beb8a", size = 39854, upload-time = "2025-06-22T19:14:00.978Z" }, ] +[[package]] +name = "websocket-client" +version = "1.9.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/2c/41/aa4bf9664e4cda14c3b39865b12251e8e7d239f4cd0e3cc1b6c2ccde25c1/websocket_client-1.9.0.tar.gz", hash = "sha256:9e813624b6eb619999a97dc7958469217c3176312b3a16a4bd1bc7e08a46ec98", size = 70576, upload-time = "2025-10-07T21:16:36.495Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/34/db/b10e48aa8fff7407e67470363eac595018441cf32d5e1001567a7aeba5d2/websocket_client-1.9.0-py3-none-any.whl", hash = "sha256:af248a825037ef591efbf6ed20cc5faa03d3b47b9e5a2230a529eeee1c1fc3ef", size = 82616, upload-time = "2025-10-07T21:16:34.951Z" }, +] + [[package]] name = "websockets" version = "16.0" From 7f4618d72ff425f6f6fd518731e75205f0c23567 Mon Sep 17 00:00:00 2001 From: collhoun <2904yr@mail.ru> Date: Sun, 19 Apr 2026 16:52:44 +0300 Subject: [PATCH 4/6] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D0=B0=20=D0=B2=D0=B5=D1=80=D1=81=D0=B8=D1=8F=20composio?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pyproject.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/pyproject.toml b/pyproject.toml index d6d46d1..c436267 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -9,4 +9,5 @@ dependencies = [ "uvicorn[standard]>=0.34.0", "deepagents>=0.1.0", "langchain-openai>=1.1.12", + "composio>=0.11.5", ] From e4a070b701b277826e97fb914a382407ed9ae644 Mon Sep 17 00:00:00 2001 From: collhoun <2904yr@mail.ru> Date: Mon, 20 Apr 2026 21:17:42 +0300 Subject: [PATCH 5/6] =?UTF-8?q?=D0=9E=D0=B1=D0=BD=D0=BE=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D0=B0=20=D0=B8=D0=BD=D1=82=D0=B5=D0=B3=D1=80=D0=B0=D1=86?= =?UTF-8?q?=D0=B8=D1=8F=20=D1=81=20composio?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pyproject.toml | 1 + src/agent/base.py | 9 +++++---- src/agent/service.py | 1 + uv.lock | 15 +++++++++++++++ 4 files changed, 22 insertions(+), 4 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index c436267..f039ec1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -10,4 +10,5 @@ dependencies = [ "deepagents>=0.1.0", "langchain-openai>=1.1.12", "composio>=0.11.5", + "composio-langchain>=0.11.5" ] diff --git a/src/agent/base.py b/src/agent/base.py index dce4088..dc5247a 100644 --- a/src/agent/base.py +++ b/src/agent/base.py @@ -3,16 +3,17 @@ from deepagents import create_deep_agent from langchain_openai import ChatOpenAI from langgraph.checkpoint.memory import MemorySaver from composio import Composio - +from composio_langchain import LangchainProvider def create_agent(): model = ChatOpenAI( model=os.environ["PROVIDER_MODEL"], base_url=os.environ["PROVIDER_URL"], - api_key=os.environ["PROVIDER_API_KEY"], + api_key=os.environ["PROVIDER_API_KEY"] ) - composio = Composio() + + composio = Composio(provider=LangchainProvider()) session = composio.create(user_id="default_user") tools = session.tools() @@ -21,4 +22,4 @@ def create_agent(): system_prompt="You are a helpful assistant. Use Composio tools to take action when needed.", checkpointer=MemorySaver(), tools=tools - ) \ No newline at end of file + ) diff --git a/src/agent/service.py b/src/agent/service.py index 04c4e47..f285630 100644 --- a/src/agent/service.py +++ b/src/agent/service.py @@ -56,6 +56,7 @@ class AgentService: result=str(result) # Страховка от ошибки сериализации JSON ) + # 3. В конце генерации отправляем событие завершения yield MsgEventEnd(tokens_used=0) # потом заменить на метадату diff --git a/uv.lock b/uv.lock index b20be97..f360545 100644 --- a/uv.lock +++ b/uv.lock @@ -8,6 +8,7 @@ version = "0.1.0" source = { virtual = "." } dependencies = [ { name = "composio" }, + { name = "composio-langchain" }, { name = "deepagents" }, { name = "fastapi" }, { name = "langchain-openai" }, @@ -17,6 +18,7 @@ dependencies = [ [package.metadata] requires-dist = [ { name = "composio", specifier = ">=0.11.5" }, + { name = "composio-langchain", specifier = ">=0.11.5" }, { name = "deepagents", specifier = ">=0.1.0" }, { name = "fastapi", specifier = ">=0.135.3" }, { name = "langchain-openai", specifier = ">=1.1.12" }, @@ -219,6 +221,19 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/93/bc/83efc07964e39109c4471f8873dda98cd16137c8e4e2d4456a8a5d8f9c42/composio_client-1.33.0-py3-none-any.whl", hash = "sha256:8c01f096772272398760f5c553b3444b5706e346b294856f613b092f1d3afd6b", size = 252699, upload-time = "2026-04-10T01:35:30.003Z" }, ] +[[package]] +name = "composio-langchain" +version = "0.11.5" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "composio" }, + { name = "langchain" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/31/13/fdf3a471044369f89b33c9ba917a9bfc4dafbe6f44547866449e71655b4b/composio_langchain-0.11.5.tar.gz", hash = "sha256:1eccea5eff9255241c1894b30b90b050cde876e5a028ef210e316865efc3181c", size = 2678, upload-time = "2026-04-10T07:59:50.093Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4f/d4/8cc58a41a45a2a12180e6a7d042206b2f4426e7a052b163b3620cf022d0f/composio_langchain-0.11.5-py3-none-any.whl", hash = "sha256:527539ae3bc41813b860911927d1aa1697ec0e1f6052f9a8311aa98c6e05a6f6", size = 2964, upload-time = "2026-04-10T07:59:36.936Z" }, +] + [[package]] name = "cryptography" version = "46.0.6" From 592777d8749125dab074000d0a6a4c9bf866ae43 Mon Sep 17 00:00:00 2001 From: collhoun <2904yr@mail.ru> Date: Mon, 20 Apr 2026 21:18:35 +0300 Subject: [PATCH 6/6] =?UTF-8?q?=D0=9E=D0=B1=D0=BD=D0=BE=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=20env?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env.example | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.env.example b/.env.example index 4332b87..0efd9f4 100644 --- a/.env.example +++ b/.env.example @@ -1,3 +1,5 @@ PROVIDER_URL=http://localhost:8000/v1 PROVIDER_API_KEY=your-api-key PROVIDER_MODEL=gpt-4 +AGENT_API_PATH=path-to-api +COMPOSIO_API_KEY=your-api-key \ No newline at end of file