acp-sdk 0.0.5__tar.gz → 0.1.0rc5__tar.gz

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.
Files changed (175) hide show
  1. {acp_sdk-0.0.5 → acp_sdk-0.1.0rc5}/.gitignore +39 -3
  2. acp_sdk-0.1.0rc5/.python-version +1 -0
  3. acp_sdk-0.1.0rc5/PKG-INFO +78 -0
  4. acp_sdk-0.1.0rc5/README.md +59 -0
  5. acp_sdk-0.1.0rc5/examples/clients/advanced.py +21 -0
  6. acp_sdk-0.1.0rc5/examples/clients/simple.py +17 -0
  7. acp_sdk-0.1.0rc5/examples/clients/stream.py +14 -0
  8. acp_sdk-0.1.0rc5/examples/servers/awaiting.py +23 -0
  9. acp_sdk-0.1.0rc5/examples/servers/echo.py +22 -0
  10. acp_sdk-0.1.0rc5/examples/servers/multi-echo.py +59 -0
  11. acp_sdk-0.1.0rc5/pyproject.toml +38 -0
  12. acp_sdk-0.1.0rc5/src/acp_sdk/__init__.py +1 -0
  13. acp_sdk-0.1.0rc5/src/acp_sdk/client/__init__.py +1 -0
  14. acp_sdk-0.1.0rc5/src/acp_sdk/client/client.py +139 -0
  15. acp_sdk-0.1.0rc5/src/acp_sdk/models/__init__.py +3 -0
  16. acp_sdk-0.1.0rc5/src/acp_sdk/models/errors.py +23 -0
  17. acp_sdk-0.1.0rc5/src/acp_sdk/models/models.py +181 -0
  18. acp_sdk-0.1.0rc5/src/acp_sdk/models/schemas.py +39 -0
  19. acp_sdk-0.1.0rc5/src/acp_sdk/server/__init__.py +6 -0
  20. acp_sdk-0.1.0rc5/src/acp_sdk/server/agent.py +105 -0
  21. acp_sdk-0.1.0rc5/src/acp_sdk/server/app.py +161 -0
  22. acp_sdk-0.1.0rc5/src/acp_sdk/server/bundle.py +131 -0
  23. acp_sdk-0.1.0rc5/src/acp_sdk/server/context.py +33 -0
  24. acp_sdk-0.1.0rc5/src/acp_sdk/server/errors.py +54 -0
  25. acp_sdk-0.1.0rc5/src/acp_sdk/server/logging.py +16 -0
  26. acp_sdk-0.1.0rc5/src/acp_sdk/server/server.py +120 -0
  27. acp_sdk-0.1.0rc5/src/acp_sdk/server/telemetry.py +52 -0
  28. acp_sdk-0.1.0rc5/src/acp_sdk/server/types.py +6 -0
  29. acp_sdk-0.1.0rc5/src/acp_sdk/server/utils.py +14 -0
  30. acp_sdk-0.0.5/.github/ISSUE_TEMPLATE/bug_report.md +0 -38
  31. acp_sdk-0.0.5/.github/ISSUE_TEMPLATE/feature_request.md +0 -20
  32. acp_sdk-0.0.5/.github/workflows/check-lock.yml +0 -25
  33. acp_sdk-0.0.5/.github/workflows/main-checks.yml +0 -13
  34. acp_sdk-0.0.5/.github/workflows/publish-pypi.yml +0 -55
  35. acp_sdk-0.0.5/.github/workflows/pull-request-checks.yml +0 -8
  36. acp_sdk-0.0.5/.github/workflows/shared.yml +0 -69
  37. acp_sdk-0.0.5/.pre-commit-config.yaml +0 -24
  38. acp_sdk-0.0.5/CLAUDE.md +0 -114
  39. acp_sdk-0.0.5/CODE_OF_CONDUCT.md +0 -128
  40. acp_sdk-0.0.5/CONTRIBUTING.md +0 -66
  41. acp_sdk-0.0.5/LICENSE +0 -22
  42. acp_sdk-0.0.5/PKG-INFO +0 -46
  43. acp_sdk-0.0.5/README.md +0 -9
  44. acp_sdk-0.0.5/RELEASE.md +0 -15
  45. acp_sdk-0.0.5/SECURITY.md +0 -14
  46. acp_sdk-0.0.5/examples/README.md +0 -5
  47. acp_sdk-0.0.5/examples/clients/simple-chatbot/.python-version +0 -1
  48. acp_sdk-0.0.5/examples/clients/simple-chatbot/README.MD +0 -110
  49. acp_sdk-0.0.5/examples/clients/simple-chatbot/mcp_simple_chatbot/.env.example +0 -1
  50. acp_sdk-0.0.5/examples/clients/simple-chatbot/mcp_simple_chatbot/main.py +0 -429
  51. acp_sdk-0.0.5/examples/clients/simple-chatbot/mcp_simple_chatbot/requirements.txt +0 -4
  52. acp_sdk-0.0.5/examples/clients/simple-chatbot/mcp_simple_chatbot/servers_config.json +0 -12
  53. acp_sdk-0.0.5/examples/clients/simple-chatbot/mcp_simple_chatbot/test.db +0 -0
  54. acp_sdk-0.0.5/examples/clients/simple-chatbot/pyproject.toml +0 -48
  55. acp_sdk-0.0.5/examples/clients/simple-chatbot/uv.lock +0 -555
  56. acp_sdk-0.0.5/examples/highlevel/agents.py +0 -26
  57. acp_sdk-0.0.5/examples/highlevel/complex_inputs.py +0 -30
  58. acp_sdk-0.0.5/examples/highlevel/desktop.py +0 -25
  59. acp_sdk-0.0.5/examples/highlevel/echo.py +0 -30
  60. acp_sdk-0.0.5/examples/highlevel/memory.py +0 -349
  61. acp_sdk-0.0.5/examples/highlevel/parameter_descriptions.py +0 -21
  62. acp_sdk-0.0.5/examples/highlevel/readme-quickstart.py +0 -18
  63. acp_sdk-0.0.5/examples/highlevel/screenshot.py +0 -29
  64. acp_sdk-0.0.5/examples/highlevel/simple_echo.py +0 -14
  65. acp_sdk-0.0.5/examples/highlevel/text_me.py +0 -72
  66. acp_sdk-0.0.5/examples/highlevel/unicode_example.py +0 -64
  67. acp_sdk-0.0.5/examples/servers/simple-prompt/.python-version +0 -1
  68. acp_sdk-0.0.5/examples/servers/simple-prompt/README.md +0 -55
  69. acp_sdk-0.0.5/examples/servers/simple-prompt/mcp_simple_prompt/__init__.py +0 -1
  70. acp_sdk-0.0.5/examples/servers/simple-prompt/mcp_simple_prompt/__main__.py +0 -5
  71. acp_sdk-0.0.5/examples/servers/simple-prompt/mcp_simple_prompt/server.py +0 -127
  72. acp_sdk-0.0.5/examples/servers/simple-prompt/pyproject.toml +0 -47
  73. acp_sdk-0.0.5/examples/servers/simple-resource/.python-version +0 -1
  74. acp_sdk-0.0.5/examples/servers/simple-resource/README.md +0 -48
  75. acp_sdk-0.0.5/examples/servers/simple-resource/mcp_simple_resource/__init__.py +0 -1
  76. acp_sdk-0.0.5/examples/servers/simple-resource/mcp_simple_resource/__main__.py +0 -5
  77. acp_sdk-0.0.5/examples/servers/simple-resource/mcp_simple_resource/server.py +0 -84
  78. acp_sdk-0.0.5/examples/servers/simple-resource/pyproject.toml +0 -47
  79. acp_sdk-0.0.5/examples/servers/simple-tool/.python-version +0 -1
  80. acp_sdk-0.0.5/examples/servers/simple-tool/README.md +0 -48
  81. acp_sdk-0.0.5/examples/servers/simple-tool/mcp_simple_tool/__init__.py +0 -1
  82. acp_sdk-0.0.5/examples/servers/simple-tool/mcp_simple_tool/__main__.py +0 -5
  83. acp_sdk-0.0.5/examples/servers/simple-tool/mcp_simple_tool/server.py +0 -97
  84. acp_sdk-0.0.5/examples/servers/simple-tool/pyproject.toml +0 -47
  85. acp_sdk-0.0.5/pyproject.toml +0 -76
  86. acp_sdk-0.0.5/src/acp/__init__.py +0 -138
  87. acp_sdk-0.0.5/src/acp/cli/__init__.py +0 -6
  88. acp_sdk-0.0.5/src/acp/cli/claude.py +0 -139
  89. acp_sdk-0.0.5/src/acp/cli/cli.py +0 -471
  90. acp_sdk-0.0.5/src/acp/client/__init__.py +0 -0
  91. acp_sdk-0.0.5/src/acp/client/__main__.py +0 -79
  92. acp_sdk-0.0.5/src/acp/client/session.py +0 -372
  93. acp_sdk-0.0.5/src/acp/client/sse.py +0 -142
  94. acp_sdk-0.0.5/src/acp/client/stdio.py +0 -153
  95. acp_sdk-0.0.5/src/acp/server/__init__.py +0 -3
  96. acp_sdk-0.0.5/src/acp/server/__main__.py +0 -50
  97. acp_sdk-0.0.5/src/acp/server/highlevel/__init__.py +0 -9
  98. acp_sdk-0.0.5/src/acp/server/highlevel/agents/__init__.py +0 -5
  99. acp_sdk-0.0.5/src/acp/server/highlevel/agents/agent_manager.py +0 -110
  100. acp_sdk-0.0.5/src/acp/server/highlevel/agents/base.py +0 -20
  101. acp_sdk-0.0.5/src/acp/server/highlevel/agents/templates.py +0 -21
  102. acp_sdk-0.0.5/src/acp/server/highlevel/context.py +0 -185
  103. acp_sdk-0.0.5/src/acp/server/highlevel/exceptions.py +0 -25
  104. acp_sdk-0.0.5/src/acp/server/highlevel/prompts/__init__.py +0 -4
  105. acp_sdk-0.0.5/src/acp/server/highlevel/prompts/base.py +0 -167
  106. acp_sdk-0.0.5/src/acp/server/highlevel/prompts/manager.py +0 -50
  107. acp_sdk-0.0.5/src/acp/server/highlevel/prompts/prompt_manager.py +0 -33
  108. acp_sdk-0.0.5/src/acp/server/highlevel/resources/__init__.py +0 -23
  109. acp_sdk-0.0.5/src/acp/server/highlevel/resources/base.py +0 -48
  110. acp_sdk-0.0.5/src/acp/server/highlevel/resources/resource_manager.py +0 -94
  111. acp_sdk-0.0.5/src/acp/server/highlevel/resources/templates.py +0 -80
  112. acp_sdk-0.0.5/src/acp/server/highlevel/resources/types.py +0 -185
  113. acp_sdk-0.0.5/src/acp/server/highlevel/server.py +0 -705
  114. acp_sdk-0.0.5/src/acp/server/highlevel/tools/__init__.py +0 -4
  115. acp_sdk-0.0.5/src/acp/server/highlevel/tools/base.py +0 -83
  116. acp_sdk-0.0.5/src/acp/server/highlevel/tools/tool_manager.py +0 -53
  117. acp_sdk-0.0.5/src/acp/server/highlevel/utilities/__init__.py +0 -1
  118. acp_sdk-0.0.5/src/acp/server/highlevel/utilities/func_metadata.py +0 -210
  119. acp_sdk-0.0.5/src/acp/server/highlevel/utilities/logging.py +0 -43
  120. acp_sdk-0.0.5/src/acp/server/highlevel/utilities/types.py +0 -54
  121. acp_sdk-0.0.5/src/acp/server/lowlevel/__init__.py +0 -3
  122. acp_sdk-0.0.5/src/acp/server/lowlevel/helper_types.py +0 -9
  123. acp_sdk-0.0.5/src/acp/server/lowlevel/server.py +0 -643
  124. acp_sdk-0.0.5/src/acp/server/models.py +0 -17
  125. acp_sdk-0.0.5/src/acp/server/session.py +0 -315
  126. acp_sdk-0.0.5/src/acp/server/sse.py +0 -175
  127. acp_sdk-0.0.5/src/acp/server/stdio.py +0 -83
  128. acp_sdk-0.0.5/src/acp/server/websocket.py +0 -61
  129. acp_sdk-0.0.5/src/acp/shared/__init__.py +0 -0
  130. acp_sdk-0.0.5/src/acp/shared/context.py +0 -14
  131. acp_sdk-0.0.5/src/acp/shared/exceptions.py +0 -14
  132. acp_sdk-0.0.5/src/acp/shared/memory.py +0 -87
  133. acp_sdk-0.0.5/src/acp/shared/progress.py +0 -40
  134. acp_sdk-0.0.5/src/acp/shared/session.py +0 -413
  135. acp_sdk-0.0.5/src/acp/shared/version.py +0 -3
  136. acp_sdk-0.0.5/src/acp/types.py +0 -1258
  137. acp_sdk-0.0.5/tasks.toml +0 -67
  138. acp_sdk-0.0.5/tests/__init__.py +0 -0
  139. acp_sdk-0.0.5/tests/client/__init__.py +0 -0
  140. acp_sdk-0.0.5/tests/client/test_config.py +0 -52
  141. acp_sdk-0.0.5/tests/client/test_session.py +0 -100
  142. acp_sdk-0.0.5/tests/client/test_stdio.py +0 -38
  143. acp_sdk-0.0.5/tests/conftest.py +0 -6
  144. acp_sdk-0.0.5/tests/issues/test_100_tool_listing.py +0 -35
  145. acp_sdk-0.0.5/tests/issues/test_129_resource_templates.py +0 -44
  146. acp_sdk-0.0.5/tests/issues/test_141_resource_templates.py +0 -118
  147. acp_sdk-0.0.5/tests/issues/test_152_resource_mime_type.py +0 -146
  148. acp_sdk-0.0.5/tests/issues/test_176_progress_token.py +0 -46
  149. acp_sdk-0.0.5/tests/issues/test_88_random_error.py +0 -111
  150. acp_sdk-0.0.5/tests/server/__init__.py +0 -0
  151. acp_sdk-0.0.5/tests/server/fastmcp/__init__.py +0 -0
  152. acp_sdk-0.0.5/tests/server/fastmcp/prompts/__init__.py +0 -0
  153. acp_sdk-0.0.5/tests/server/fastmcp/prompts/test_base.py +0 -206
  154. acp_sdk-0.0.5/tests/server/fastmcp/prompts/test_manager.py +0 -112
  155. acp_sdk-0.0.5/tests/server/fastmcp/resources/__init__.py +0 -0
  156. acp_sdk-0.0.5/tests/server/fastmcp/resources/test_file_resources.py +0 -119
  157. acp_sdk-0.0.5/tests/server/fastmcp/resources/test_function_resources.py +0 -138
  158. acp_sdk-0.0.5/tests/server/fastmcp/resources/test_resource_manager.py +0 -141
  159. acp_sdk-0.0.5/tests/server/fastmcp/resources/test_resource_template.py +0 -188
  160. acp_sdk-0.0.5/tests/server/fastmcp/resources/test_resources.py +0 -101
  161. acp_sdk-0.0.5/tests/server/fastmcp/servers/__init__.py +0 -0
  162. acp_sdk-0.0.5/tests/server/fastmcp/servers/test_file_server.py +0 -123
  163. acp_sdk-0.0.5/tests/server/fastmcp/test_func_metadata.py +0 -401
  164. acp_sdk-0.0.5/tests/server/fastmcp/test_parameter_descriptions.py +0 -30
  165. acp_sdk-0.0.5/tests/server/fastmcp/test_server.py +0 -743
  166. acp_sdk-0.0.5/tests/server/fastmcp/test_tool_manager.py +0 -322
  167. acp_sdk-0.0.5/tests/server/test_read_resource.py +0 -109
  168. acp_sdk-0.0.5/tests/server/test_session.py +0 -101
  169. acp_sdk-0.0.5/tests/server/test_stdio.py +0 -68
  170. acp_sdk-0.0.5/tests/shared/test_memory.py +0 -47
  171. acp_sdk-0.0.5/tests/shared/test_session.py +0 -127
  172. acp_sdk-0.0.5/tests/shared/test_sse.py +0 -254
  173. acp_sdk-0.0.5/tests/test_examples.py +0 -72
  174. acp_sdk-0.0.5/tests/test_types.py +0 -32
  175. {acp_sdk-0.0.5/src/acp → acp_sdk-0.1.0rc5/src/acp_sdk}/py.typed +0 -0
@@ -1,5 +1,40 @@
1
+ ### NextJS template
2
+ # dependencies
3
+ node_modules
4
+ /.pnp
5
+ .pnp.js
6
+
7
+ # testing
8
+ /coverage
9
+
10
+ # next.js
11
+ /.next/
12
+ /out/
13
+
14
+ # production
15
+ /build
16
+
17
+ # misc
1
18
  .DS_Store
19
+ *.pem
20
+
21
+ # debug
22
+ npm-debug.log*
23
+ yarn-debug.log*
24
+ yarn-error.log*
25
+ .pnpm-debug.log*
26
+
27
+ # local env files
28
+ .env*.local
29
+
30
+ # vercel
31
+ .vercel
32
+
33
+ # typescript
34
+ *.tsbuildinfo
35
+ next-env.d.ts
2
36
 
37
+ ### Python template
3
38
  # Byte-compiled / optimized / DLL files
4
39
  __pycache__/
5
40
  *.py[cod]
@@ -13,6 +48,7 @@ __pycache__/
13
48
  build/
14
49
  develop-eggs/
15
50
  dist/
51
+ dist-py/
16
52
  downloads/
17
53
  eggs/
18
54
  .eggs/
@@ -161,7 +197,7 @@ cython_debug/
161
197
  # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
162
198
  # and can be added to the global gitignore or merged into this file. For a more nuclear
163
199
  # option (not recommended) you can uncomment the following to ignore the entire idea folder.
164
- #.idea/
200
+ .idea/
165
201
 
166
- # vscode
167
- .vscode/
202
+ # Mise
203
+ mise.local.toml
@@ -0,0 +1 @@
1
+ 3.11
@@ -0,0 +1,78 @@
1
+ Metadata-Version: 2.4
2
+ Name: acp-sdk
3
+ Version: 0.1.0rc5
4
+ Summary: Agent Communication Protocol SDK
5
+ Requires-Python: <4.0,>=3.11
6
+ Requires-Dist: opentelemetry-api>=1.31.1
7
+ Requires-Dist: pydantic>=2.11.1
8
+ Provides-Extra: client
9
+ Requires-Dist: httpx-sse>=0.4.0; extra == 'client'
10
+ Requires-Dist: httpx>=0.28.1; extra == 'client'
11
+ Requires-Dist: opentelemetry-instrumentation-httpx>=0.52b1; extra == 'client'
12
+ Provides-Extra: server
13
+ Requires-Dist: fastapi[standard]>=0.115.8; extra == 'server'
14
+ Requires-Dist: janus>=2.0.0; extra == 'server'
15
+ Requires-Dist: opentelemetry-exporter-otlp-proto-http>=1.31.1; extra == 'server'
16
+ Requires-Dist: opentelemetry-instrumentation-fastapi>=0.52b1; extra == 'server'
17
+ Requires-Dist: opentelemetry-sdk>=1.31.1; extra == 'server'
18
+ Description-Content-Type: text/markdown
19
+
20
+ # Agent Communication Protocol SDK for Python
21
+
22
+ Agent Communication Protocol SDK for Python provides allows developers to serve and consume agents over the Agent Communication Protocol.
23
+
24
+ ## Prerequisites
25
+
26
+ ✅ Python >= 3.11
27
+
28
+ ## Installation
29
+
30
+ Install to use client:
31
+
32
+ ```shell
33
+ pip install acp-sdk[client]
34
+ ```
35
+
36
+ Install to use server:
37
+
38
+ ```shell
39
+ pip install acp-sdk[server]
40
+ ```
41
+
42
+ ## Overview
43
+
44
+ ### Client
45
+
46
+ The `client` submodule exposes [httpx]() based client with simple methods for communication over ACP.
47
+
48
+ ```python
49
+ async with Client(base_url="http://localhost:8000") as client:
50
+ run = await client.run_sync(agent="echo", input=Message(TextMessagePart(content="Howdy!")))
51
+ print(run.output)
52
+ ```
53
+
54
+ ### Server
55
+
56
+ The `server` submodule exposes [fastapi] application factory that makes it easy to expose any agent over ACP.
57
+
58
+ ```python
59
+ class EchoAgent(Agent):
60
+ @property
61
+ def name(self) -> str:
62
+ return "echo"
63
+
64
+ @property
65
+ def description(self) -> str:
66
+ return "Echoes everything"
67
+
68
+ async def run(self, input: Message, *, context: Context) -> AsyncGenerator[Message | Await, AwaitResume]:
69
+ for part in input:
70
+ await asyncio.sleep(0.5)
71
+ yield {"thought": "I should echo everyting"}
72
+ yield Message(part)
73
+
74
+
75
+ serve(EchoAgent())
76
+ ```
77
+
78
+ ➡️ Explore more in our [examples library](/python/examples).
@@ -0,0 +1,59 @@
1
+ # Agent Communication Protocol SDK for Python
2
+
3
+ Agent Communication Protocol SDK for Python provides allows developers to serve and consume agents over the Agent Communication Protocol.
4
+
5
+ ## Prerequisites
6
+
7
+ ✅ Python >= 3.11
8
+
9
+ ## Installation
10
+
11
+ Install to use client:
12
+
13
+ ```shell
14
+ pip install acp-sdk[client]
15
+ ```
16
+
17
+ Install to use server:
18
+
19
+ ```shell
20
+ pip install acp-sdk[server]
21
+ ```
22
+
23
+ ## Overview
24
+
25
+ ### Client
26
+
27
+ The `client` submodule exposes [httpx]() based client with simple methods for communication over ACP.
28
+
29
+ ```python
30
+ async with Client(base_url="http://localhost:8000") as client:
31
+ run = await client.run_sync(agent="echo", input=Message(TextMessagePart(content="Howdy!")))
32
+ print(run.output)
33
+ ```
34
+
35
+ ### Server
36
+
37
+ The `server` submodule exposes [fastapi] application factory that makes it easy to expose any agent over ACP.
38
+
39
+ ```python
40
+ class EchoAgent(Agent):
41
+ @property
42
+ def name(self) -> str:
43
+ return "echo"
44
+
45
+ @property
46
+ def description(self) -> str:
47
+ return "Echoes everything"
48
+
49
+ async def run(self, input: Message, *, context: Context) -> AsyncGenerator[Message | Await, AwaitResume]:
50
+ for part in input:
51
+ await asyncio.sleep(0.5)
52
+ yield {"thought": "I should echo everyting"}
53
+ yield Message(part)
54
+
55
+
56
+ serve(EchoAgent())
57
+ ```
58
+
59
+ ➡️ Explore more in our [examples library](/python/examples).
@@ -0,0 +1,21 @@
1
+ import asyncio
2
+
3
+ import httpx
4
+ from acp_sdk.client.client import Client
5
+ from acp_sdk.models import Message, TextMessagePart
6
+
7
+
8
+ async def example() -> None:
9
+ async with Client(
10
+ client=httpx.AsyncClient(
11
+ base_url="http://localhost:8000",
12
+ auth=httpx.BasicAuth(username="username", password="password"),
13
+ # Additional client configuration
14
+ )
15
+ ) as client:
16
+ run = await client.run_sync(agent="echo", input=Message(TextMessagePart(content="Howdy!")))
17
+ print(run.output)
18
+
19
+
20
+ if __name__ == "__main__":
21
+ asyncio.run(example())
@@ -0,0 +1,17 @@
1
+ import asyncio
2
+
3
+ from acp_sdk.client import Client
4
+ from acp_sdk.models import (
5
+ Message,
6
+ TextMessagePart,
7
+ )
8
+
9
+
10
+ async def example() -> None:
11
+ async with Client(base_url="http://localhost:8000") as client:
12
+ run = await client.run_sync(agent="echo", input=Message(TextMessagePart(content="Howdy!")))
13
+ print(run.output)
14
+
15
+
16
+ if __name__ == "__main__":
17
+ asyncio.run(example())
@@ -0,0 +1,14 @@
1
+ import asyncio
2
+
3
+ from acp_sdk.client import Client
4
+ from acp_sdk.models import Message, TextMessagePart
5
+
6
+
7
+ async def example() -> None:
8
+ async with Client(base_url="http://localhost:8000") as client:
9
+ async for event in client.run_stream(agent="echo", input=Message(TextMessagePart(content="Howdy!"))):
10
+ print(event)
11
+
12
+
13
+ if __name__ == "__main__":
14
+ asyncio.run(example())
@@ -0,0 +1,23 @@
1
+ from collections.abc import AsyncGenerator
2
+ from typing import Any
3
+
4
+ from acp_sdk.models import (
5
+ Await,
6
+ AwaitResume,
7
+ Message,
8
+ TextMessagePart,
9
+ )
10
+ from acp_sdk.server import Context, Server
11
+
12
+ server = Server()
13
+
14
+
15
+ @server.agent()
16
+ async def awaiting(input: Message, context: Context) -> AsyncGenerator[Message | Await | Any, AwaitResume]:
17
+ """Greets and awaits for more data"""
18
+ yield Message(TextMessagePart(content="Hello!"))
19
+ data = yield Await()
20
+ yield Message(TextMessagePart(content=f"Thanks for {data}"))
21
+
22
+
23
+ server.run()
@@ -0,0 +1,22 @@
1
+ import asyncio
2
+ from collections.abc import AsyncGenerator
3
+
4
+ from acp_sdk.models import (
5
+ Message,
6
+ )
7
+ from acp_sdk.server import Context, RunYield, RunYieldResume, Server
8
+
9
+ server = Server()
10
+
11
+
12
+ @server.agent()
13
+ async def echo(input: Message, context: Context) -> AsyncGenerator[RunYield, RunYieldResume]:
14
+ """Echoes everything"""
15
+ for part in input:
16
+ await asyncio.sleep(0.5)
17
+ yield {"thought": "I should echo everyting"}
18
+ await asyncio.sleep(0.5)
19
+ yield Message(part)
20
+
21
+
22
+ server.run()
@@ -0,0 +1,59 @@
1
+ from collections.abc import AsyncGenerator, Generator
2
+
3
+ from acp_sdk.models import (
4
+ Message,
5
+ )
6
+ from acp_sdk.server import Agent, Context, RunYield, RunYieldResume, Server
7
+
8
+ # This example showcases several ways to create echo agent using decoratos.
9
+
10
+ server = Server()
11
+
12
+
13
+ @server.agent()
14
+ async def async_gen_echo(input: Message, context: Context) -> AsyncGenerator[RunYield, RunYieldResume]:
15
+ """Echoes everything"""
16
+ yield {"thought": "I should echo everyting"}
17
+ yield input
18
+
19
+
20
+ @server.agent()
21
+ async def async_echo(input: Message, context: Context) -> RunYield:
22
+ """Echoes everything"""
23
+ await context.yield_async({"thought": "I should echo everyting"})
24
+ return input
25
+
26
+
27
+ @server.agent()
28
+ def gen_echo(input: Message, context: Context) -> Generator[RunYield, RunYieldResume]:
29
+ """Echoes everything"""
30
+ yield {"thought": "I should echo everyting"}
31
+ return input
32
+
33
+
34
+ @server.agent()
35
+ def sync_echo(input: Message, context: Context) -> RunYield:
36
+ """Echoes everything"""
37
+ context.yield_sync({"thought": "I should echo everyting"})
38
+ return input
39
+
40
+
41
+ class EchoAgent(Agent):
42
+ @property
43
+ def name(self) -> str:
44
+ return "class_echo"
45
+
46
+ @property
47
+ def description(self) -> str:
48
+ return "Echoes everything"
49
+
50
+ async def run(self, input: Message, context: Context) -> AsyncGenerator[RunYield, RunYieldResume]:
51
+ """Echoes everything"""
52
+ yield {"thought": "I should echo everyting"}
53
+ yield input
54
+
55
+
56
+ server.register(EchoAgent())
57
+
58
+
59
+ server.run()
@@ -0,0 +1,38 @@
1
+ [project]
2
+ name = "acp-sdk"
3
+ version = "0.1.0rc5"
4
+ description = "Agent Communication Protocol SDK"
5
+ readme = "README.md"
6
+ authors = []
7
+ requires-python = ">=3.11, <4.0"
8
+ dependencies = ["opentelemetry-api>=1.31.1", "pydantic>=2.11.1"]
9
+
10
+ [project.optional-dependencies]
11
+ client = [
12
+ "httpx>=0.28.1",
13
+ "httpx-sse>=0.4.0",
14
+ "opentelemetry-instrumentation-httpx>=0.52b1",
15
+ ]
16
+ server = [
17
+ "fastapi[standard]>=0.115.8",
18
+ "opentelemetry-exporter-otlp-proto-http>=1.31.1",
19
+ "opentelemetry-instrumentation-fastapi>=0.52b1",
20
+ "opentelemetry-sdk>=1.31.1",
21
+ "janus>=2.0.0",
22
+ ]
23
+
24
+ [tool.uv]
25
+ dev-dependencies = [
26
+ "httpx>=0.28.1",
27
+ "httpx-sse>=0.4.0",
28
+ "opentelemetry-instrumentation-httpx>=0.52b1",
29
+ "fastapi[standard]>=0.115.8",
30
+ "opentelemetry-exporter-otlp-proto-http>=1.31.1",
31
+ "opentelemetry-instrumentation-fastapi>=0.52b1",
32
+ "opentelemetry-sdk>=1.31.1",
33
+ "janus>=2.0.0",
34
+ ]
35
+
36
+ [build-system]
37
+ requires = ["hatchling"]
38
+ build-backend = "hatchling.build"
@@ -0,0 +1 @@
1
+ from acp_sdk.models import * # noqa: F403
@@ -0,0 +1 @@
1
+ from acp_sdk.client.client import Client as Client
@@ -0,0 +1,139 @@
1
+ from collections.abc import AsyncIterator
2
+ from types import TracebackType
3
+ from typing import Self
4
+
5
+ import httpx
6
+ from httpx_sse import EventSource, aconnect_sse
7
+ from opentelemetry.instrumentation.httpx import HTTPXClientInstrumentor
8
+ from pydantic import TypeAdapter
9
+
10
+ from acp_sdk.models import (
11
+ ACPError,
12
+ Agent,
13
+ AgentName,
14
+ AgentReadResponse,
15
+ AgentsListResponse,
16
+ AwaitResume,
17
+ Error,
18
+ Message,
19
+ Run,
20
+ RunCancelResponse,
21
+ RunCreateRequest,
22
+ RunCreateResponse,
23
+ RunEvent,
24
+ RunId,
25
+ RunMode,
26
+ RunResumeRequest,
27
+ RunResumeResponse,
28
+ )
29
+
30
+
31
+ class Client:
32
+ def __init__(self, *, base_url: httpx.URL | str = "", client: httpx.AsyncClient | None = None) -> None:
33
+ self.base_url = base_url
34
+
35
+ self._client = self._init_client(client)
36
+
37
+ def _init_client(self, client: httpx.AsyncClient | None = None) -> httpx.AsyncClient:
38
+ client = client or httpx.AsyncClient(base_url=self.base_url)
39
+ HTTPXClientInstrumentor.instrument_client(client)
40
+ return client
41
+
42
+ async def __aenter__(self) -> Self:
43
+ await self._client.__aenter__()
44
+ return self
45
+
46
+ async def __aexit__(
47
+ self,
48
+ exc_type: type[BaseException] | None = None,
49
+ exc_value: BaseException | None = None,
50
+ traceback: TracebackType | None = None,
51
+ ) -> None:
52
+ await self._client.__aexit__(exc_type, exc_value, traceback)
53
+
54
+ async def agents(self) -> AsyncIterator[Agent]:
55
+ response = await self._client.get("/agents")
56
+ self._raise_error(response)
57
+ for agent in AgentsListResponse.model_validate(response.json()).agents:
58
+ yield agent
59
+
60
+ async def agent(self, *, name: AgentName) -> Agent:
61
+ response = await self._client.get(f"/agents/{name}")
62
+ self._raise_error(response)
63
+ return AgentReadResponse.model_validate(response.json())
64
+
65
+ async def run_sync(self, *, agent: AgentName, input: Message) -> Run:
66
+ response = await self._client.post(
67
+ "/runs",
68
+ json=RunCreateRequest(agent_name=agent, input=input, mode=RunMode.SYNC).model_dump(),
69
+ )
70
+ self._raise_error(response)
71
+ return RunCreateResponse.model_validate(response.json())
72
+
73
+ async def run_async(self, *, agent: AgentName, input: Message) -> Run:
74
+ response = await self._client.post(
75
+ "/runs",
76
+ json=RunCreateRequest(agent_name=agent, input=input, mode=RunMode.ASYNC).model_dump(),
77
+ )
78
+ self._raise_error(response)
79
+ return RunCreateResponse.model_validate(response.json())
80
+
81
+ async def run_stream(self, *, agent: AgentName, input: Message) -> AsyncIterator[RunEvent]:
82
+ async with aconnect_sse(
83
+ self._client,
84
+ "POST",
85
+ "/runs",
86
+ json=RunCreateRequest(agent_name=agent, input=input, mode=RunMode.STREAM).model_dump(),
87
+ ) as event_source:
88
+ async for event in self._validate_stream(event_source):
89
+ yield event
90
+
91
+ async def run_status(self, *, run_id: RunId) -> Run:
92
+ response = await self._client.get(f"/runs/{run_id}")
93
+ self._raise_error(response)
94
+ return Run.model_validate(response.json())
95
+
96
+ async def run_cancel(self, *, run_id: RunId) -> Run:
97
+ response = await self._client.post(f"/runs/{run_id}/cancel")
98
+ self._raise_error(response)
99
+ return RunCancelResponse.model_validate(response.json())
100
+
101
+ async def run_resume_sync(self, *, run_id: RunId, await_: AwaitResume) -> Run:
102
+ response = await self._client.post(
103
+ f"/runs/{run_id}",
104
+ json=RunResumeRequest(await_=await_, mode=RunMode.SYNC).model_dump(),
105
+ )
106
+ self._raise_error(response)
107
+ return RunResumeResponse.model_validate(response.json())
108
+
109
+ async def run_resume_async(self, *, run_id: RunId, await_: AwaitResume) -> Run:
110
+ response = await self._client.post(
111
+ f"/runs/{run_id}",
112
+ json=RunResumeRequest(await_=await_, mode=RunMode.ASYNC).model_dump(),
113
+ )
114
+ self._raise_error(response)
115
+ return RunResumeResponse.model_validate(response.json())
116
+
117
+ async def run_resume_stream(self, *, run_id: RunId, await_: AwaitResume) -> AsyncIterator[RunEvent]:
118
+ async with aconnect_sse(
119
+ self._client,
120
+ "POST",
121
+ f"/runs/{run_id}",
122
+ json=RunResumeRequest(await_=await_, mode=RunMode.STREAM).model_dump(),
123
+ ) as event_source:
124
+ async for event in self._validate_stream(event_source):
125
+ yield event
126
+
127
+ async def _validate_stream(
128
+ self,
129
+ event_source: EventSource,
130
+ ) -> AsyncIterator[RunEvent]:
131
+ async for event in event_source.aiter_sse():
132
+ event = TypeAdapter(RunEvent).validate_json(event.data)
133
+ yield event
134
+
135
+ def _raise_error(self, response: httpx.Response) -> None:
136
+ try:
137
+ response.raise_for_status()
138
+ except httpx.HTTPError:
139
+ raise ACPError(Error.model_validate(response.json()))
@@ -0,0 +1,3 @@
1
+ from acp_sdk.models.errors import * # noqa: F403
2
+ from acp_sdk.models.models import * # noqa: F403
3
+ from acp_sdk.models.schemas import * # noqa: F403
@@ -0,0 +1,23 @@
1
+ from enum import Enum
2
+
3
+ from pydantic import BaseModel
4
+
5
+
6
+ class ErrorCode(str, Enum):
7
+ SERVER_ERROR = "server_error"
8
+ INVALID_INPUT = "invalid_input"
9
+ NOT_FOUND = "not_found"
10
+
11
+
12
+ class Error(BaseModel):
13
+ code: ErrorCode
14
+ message: str
15
+
16
+
17
+ class ACPError(Exception):
18
+ def __init__(self, error: Error) -> None:
19
+ super().__init__()
20
+ self.error = error
21
+
22
+ def __str__(self) -> str:
23
+ return str(self.error.message)