agent-api-server 2.2.1__tar.gz → 2.2.1a2__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 (92) hide show
  1. agent_api_server-2.2.1a2/PKG-INFO +308 -0
  2. agent_api_server-2.2.1a2/README.md +275 -0
  3. agent_api_server-2.2.1a2/adapters/__init__.py +43 -0
  4. agent_api_server-2.2.1a2/adapters/langgraph_adapter/__init__.py +53 -0
  5. agent_api_server-2.2.1a2/adapters/langgraph_adapter/formatter.py +225 -0
  6. agent_api_server-2.2.1a2/adapters/langgraph_adapter/langgraph_adapter.py +121 -0
  7. agent_api_server-2.2.1a2/adapters/openclaw_adapter/__init__.py +26 -0
  8. agent_api_server-2.2.1a2/adapters/openclaw_adapter/openclaw_adapter.py +893 -0
  9. agent_api_server-2.2.1a2/agent_api_server.py +12 -0
  10. agent_api_server-2.2.1a2/api/__init__.py +3 -0
  11. {agent_api_server-2.2.1/agent_api_server/api/v1 → agent_api_server-2.2.1a2/api}/config.py +5 -17
  12. {agent_api_server-2.2.1/agent_api_server/api/v1 → agent_api_server-2.2.1a2/api}/graph.py +3 -3
  13. agent_api_server-2.2.1/agent_api_server/api/v1/api.py → agent_api_server-2.2.1a2/api/router.py +5 -10
  14. {agent_api_server-2.2.1/agent_api_server/api/v1 → agent_api_server-2.2.1a2/api}/schema.py +6 -30
  15. agent_api_server-2.2.1a2/api/thread.py +577 -0
  16. agent_api_server-2.2.1a2/client/css/styles.css +561 -0
  17. agent_api_server-2.2.1a2/client/index.html +106 -0
  18. agent_api_server-2.2.1a2/client/js/app.js +892 -0
  19. agent_api_server-2.2.1a2/common/__init__.py +25 -0
  20. agent_api_server-2.2.1a2/common/config.py +106 -0
  21. agent_api_server-2.2.1a2/common/formatting.py +46 -0
  22. agent_api_server-2.2.1a2/common/logging.py +126 -0
  23. agent_api_server-2.2.1a2/common/nats.py +103 -0
  24. {agent_api_server-2.2.1/agent_api_server/memeory → agent_api_server-2.2.1a2/common}/postgres.py +27 -92
  25. agent_api_server-2.2.1/agent_api_server/cache/redis_cache.py → agent_api_server-2.2.1a2/common/redis.py +71 -148
  26. agent_api_server-2.2.1a2/core/__init__.py +57 -0
  27. agent_api_server-2.2.1a2/core/loader.py +203 -0
  28. agent_api_server-2.2.1a2/core/model/__init__.py +35 -0
  29. agent_api_server-2.2.1a2/core/model/agent_models.py +121 -0
  30. {agent_api_server-2.2.1/agent_api_server/dynamic_llm → agent_api_server-2.2.1a2/core/model}/dynamic_llm.py +52 -9
  31. agent_api_server-2.2.1a2/core/model/input_normalization.py +50 -0
  32. agent_api_server-2.2.1/agent_api_server/middleware/model.py → agent_api_server-2.2.1a2/core/model/middleware.py +11 -6
  33. agent_api_server-2.2.1/agent_api_server/shared/get_model_info.py → agent_api_server-2.2.1a2/core/model/model_info.py +11 -5
  34. agent_api_server-2.2.1a2/core/model/streaming.py +89 -0
  35. agent_api_server-2.2.1a2/core/runtime/__init__.py +26 -0
  36. agent_api_server-2.2.1a2/core/runtime/base.py +98 -0
  37. agent_api_server-2.2.1a2/core/runtime/manager.py +180 -0
  38. agent_api_server-2.2.1a2/demo.py +25 -0
  39. agent_api_server-2.2.1a2/integration/__init__.py +10 -0
  40. {agent_api_server-2.2.1/agent_api_server → agent_api_server-2.2.1a2/integration}/listener.py +43 -39
  41. agent_api_server-2.2.1/agent_api_server/register/register.py → agent_api_server-2.2.1a2/integration/registry.py +4 -7
  42. {agent_api_server-2.2.1/agent_api_server/log → agent_api_server-2.2.1a2}/logging.json +2 -2
  43. {agent_api_server-2.2.1 → agent_api_server-2.2.1a2}/pyproject.toml +17 -22
  44. agent_api_server-2.2.1a2/sdk/__init__.py +3 -0
  45. agent_api_server-2.2.1a2/sdk/client.py +326 -0
  46. agent_api_server-2.2.1a2/service.py +198 -0
  47. agent_api_server-2.2.1/PKG-INFO +0 -110
  48. agent_api_server-2.2.1/README.md +0 -70
  49. agent_api_server-2.2.1/agent_api_server/__init__.py +0 -0
  50. agent_api_server-2.2.1/agent_api_server/api/__init__.py +0 -0
  51. agent_api_server-2.2.1/agent_api_server/api/v1/__init__.py +0 -0
  52. agent_api_server-2.2.1/agent_api_server/api/v1/thread.py +0 -562
  53. agent_api_server-2.2.1/agent_api_server/cache/__init__.py +0 -0
  54. agent_api_server-2.2.1/agent_api_server/callback_handler.py +0 -18
  55. agent_api_server-2.2.1/agent_api_server/client/css/styles.css +0 -1202
  56. agent_api_server-2.2.1/agent_api_server/client/index.html +0 -102
  57. agent_api_server-2.2.1/agent_api_server/client/js/app.js +0 -1499
  58. agent_api_server-2.2.1/agent_api_server/config_center/config_center.py +0 -239
  59. agent_api_server-2.2.1/agent_api_server/configs/__init__.py +0 -3
  60. agent_api_server-2.2.1/agent_api_server/configs/config.py +0 -163
  61. agent_api_server-2.2.1/agent_api_server/dynamic_llm/__init__.py +0 -0
  62. agent_api_server-2.2.1/agent_api_server/dynamic_llm/model.py +0 -43
  63. agent_api_server-2.2.1/agent_api_server/log/__init__.py +0 -0
  64. agent_api_server-2.2.1/agent_api_server/log/formatters.py +0 -122
  65. agent_api_server-2.2.1/agent_api_server/mcp_convert/__init__.py +0 -0
  66. agent_api_server-2.2.1/agent_api_server/mcp_convert/mcp_convert.py +0 -367
  67. agent_api_server-2.2.1/agent_api_server/mcp_interceptor/__init__.py +0 -0
  68. agent_api_server-2.2.1/agent_api_server/mcp_interceptor/mcp_intecerpter.py +0 -20
  69. agent_api_server-2.2.1/agent_api_server/memeory/__init__.py +0 -0
  70. agent_api_server-2.2.1/agent_api_server/middleware/__init__.py +0 -0
  71. agent_api_server-2.2.1/agent_api_server/middleware/schema.py +0 -6
  72. agent_api_server-2.2.1/agent_api_server/register/__init__.py +0 -0
  73. agent_api_server-2.2.1/agent_api_server/schema/__init__.py +0 -0
  74. agent_api_server-2.2.1/agent_api_server/schema/context.py +0 -13
  75. agent_api_server-2.2.1/agent_api_server/service.py +0 -354
  76. agent_api_server-2.2.1/agent_api_server/service_hub/service_hub.py +0 -233
  77. agent_api_server-2.2.1/agent_api_server/service_hub/service_hub_test.py +0 -700
  78. agent_api_server-2.2.1/agent_api_server/shared/__init__.py +0 -0
  79. agent_api_server-2.2.1/agent_api_server/shared/message.py +0 -383
  80. agent_api_server-2.2.1/agent_api_server/shared/util_func.py +0 -372
  81. agent_api_server-2.2.1/agent_api_server/sso_service/__init__.py +0 -1
  82. agent_api_server-2.2.1/agent_api_server/sso_service/sdk/__init__.py +0 -1
  83. agent_api_server-2.2.1/agent_api_server/sso_service/sdk/client.py +0 -224
  84. agent_api_server-2.2.1/agent_api_server/sso_service/sdk/credential.py +0 -11
  85. agent_api_server-2.2.1/agent_api_server/sso_service/sdk/encoding.py +0 -22
  86. agent_api_server-2.2.1/agent_api_server/sso_service/sso_service.py +0 -177
  87. {agent_api_server-2.2.1/agent_api_server → agent_api_server-2.2.1a2}/client/favicon.ico +0 -0
  88. {agent_api_server-2.2.1/agent_api_server → agent_api_server-2.2.1a2}/client/js/index.umd.js +0 -0
  89. /agent_api_server-2.2.1/agent_api_server/shared/ase.py → /agent_api_server-2.2.1a2/common/crypto.py +0 -0
  90. {agent_api_server-2.2.1/agent_api_server/shared → agent_api_server-2.2.1a2/core/model}/base_model.py +0 -0
  91. {agent_api_server-2.2.1/agent_api_server/shared → agent_api_server-2.2.1a2/core/model}/detect_message.py +0 -0
  92. /agent_api_server-2.2.1/agent_api_server/shared/common.py → /agent_api_server-2.2.1a2/core/model/schema_utils.py +0 -0
@@ -0,0 +1,308 @@
1
+ Metadata-Version: 2.3
2
+ Name: agent-api-server
3
+ Version: 2.2.1a2
4
+ Summary: A Langgraph agent API server that implements Langgraph agent's web capabilities and can interact with chatbot
5
+ Keywords: fastapi,langgraph,agent,api-server
6
+ Requires-Python: >=3.11,<3.14
7
+ Classifier: Development Status :: 4 - Beta
8
+ Classifier: Framework :: FastAPI
9
+ Classifier: Programming Language :: Python :: 3
10
+ Classifier: Programming Language :: Python :: 3.11
11
+ Classifier: Programming Language :: Python :: 3.12
12
+ Classifier: Programming Language :: Python :: 3.13
13
+ Requires-Dist: aiofiles (>=24.1.0,<25.0.0)
14
+ Requires-Dist: cryptography (>=45.0.4,<46.0.0)
15
+ Requires-Dist: fastapi (>=0.117.0,<0.121.2)
16
+ Requires-Dist: langchain (>=1.2.0,<2.0.0)
17
+ Requires-Dist: langchain-core (>=1.2.5,<2.0.0)
18
+ Requires-Dist: langgraph (>=1.0.6,<2.0.0)
19
+ Requires-Dist: langgraph-checkpoint (>=4.0.0,<5.0.0)
20
+ Requires-Dist: langgraph-checkpoint-postgres (>=3.0.3,<4.0.0)
21
+ Requires-Dist: llm-sdk (==1.0.1)
22
+ Requires-Dist: model-manage-client (>=0.0.1.8)
23
+ Requires-Dist: nats-py (>=2.11.0,<3.0.0)
24
+ Requires-Dist: openclaw-sdk (>=2.1.0,<3.0.0)
25
+ Requires-Dist: psycopg-binary (>=3.2.9,<4.0.0)
26
+ Requires-Dist: psycopg-pool (>=3.2.6,<4.0.0)
27
+ Requires-Dist: pydantic-settings (>=2.9.1,<3.0.0)
28
+ Requires-Dist: redis (>=6.2.0,<7.0.0)
29
+ Requires-Dist: starlette (>=0.49.3,<0.50.0)
30
+ Requires-Dist: tenacity (>=9.1.2,<10.0.0)
31
+ Description-Content-Type: text/markdown
32
+
33
+ # agent-api-server
34
+
35
+ `agent-api-server` is an agent runtime that now supports both:
36
+
37
+ - API Server mode for HTTP/SSE access
38
+ - SDK mode for direct in-process agent execution
39
+
40
+ It keeps compatibility with existing LangGraph-based agents and introduces a framework abstraction so additional runtimes such as OpenClaw can be added behind the same interface.
41
+
42
+ ## Features
43
+
44
+ - FastAPI application factory for embedding or standalone deployment
45
+ - Direct SDK entry via root module `agent_api_server.py`
46
+ - Framework-neutral agent loading with LangGraph and OpenClaw adapters
47
+ - Backward-compatible LangGraph-oriented API routes under `/api/v1`
48
+ - Built-in static client assets bundled in both sdist and wheel artifacts
49
+ - Redis-backed thread storage and PostgreSQL checkpoint integration
50
+ - Optional integration with model management registration and listener services
51
+ - Layered package structure centered on `adapters/`, `core/`, `common/`, `api/`, `integration/`, and `sdk/`
52
+
53
+ ## Requirements
54
+
55
+ - Python 3.11 to 3.13
56
+ - Redis
57
+ - PostgreSQL
58
+ - Access to all runtime dependencies declared in `pyproject.toml`
59
+
60
+ ## Installation
61
+
62
+ Install from a package index that provides all required dependencies:
63
+
64
+ ```bash
65
+ pip install agent-api-server
66
+ ```
67
+
68
+ This project depends on `llm-sdk` and `model-manage-client`. If those packages are hosted on a private index in your environment, configure `pip` or Poetry to use that index before installation.
69
+
70
+ ## Configuration
71
+
72
+ The runtime reads configuration from environment variables. Common settings include:
73
+
74
+ ```env
75
+ REDIS_URL=redis://localhost:6379/0
76
+ POSTGRES_URL=postgresql://postgres:postgres@localhost:5432/postgres
77
+ MODEL_MANAGER_SERVICE_URL=http://127.0.0.1:10053
78
+ CLIENT_TOKEN=
79
+ SERVER_PORT=8080
80
+ SERVER_WORKER_AMOUNT=1
81
+ LOG_LEVEL=INFO
82
+ ```
83
+
84
+ See `.env_example` for a more complete example.
85
+
86
+ ## Agent Config
87
+
88
+ `agents.json` is now the primary agent registry. Existing deployments that still use `langgraph.json` remain compatible via fallback loading. LangGraph string entries still work:
89
+
90
+ ```json
91
+ {
92
+ "graphs": {
93
+ "demo-agent": "./agents/demo.py:graph"
94
+ }
95
+ }
96
+ ```
97
+
98
+ You can also use the extended form to declare the framework explicitly and attach adapter-specific settings:
99
+
100
+ ```json
101
+ {
102
+ "graphs": {
103
+ "demo-agent": {
104
+ "framework": "langgraph",
105
+ "entrypoint": "./agents/demo.py:graph"
106
+ },
107
+ "openclaw-agent": {
108
+ "framework": "openclaw",
109
+ "agent_id": "openclaw-agent",
110
+ "create_agent": true,
111
+ "agent_config": {
112
+ "name": "OpenClaw Agent"
113
+ },
114
+ "client": {
115
+ "gateway_ws_url": "ws://127.0.0.1:18789/gateway",
116
+ "api_key": "your_gateway_token",
117
+ "scopes": ["operator.read", "operator.write"],
118
+ "device_identity_path": "~/.openclaw/identity/device.json",
119
+ "timeout": 60
120
+ },
121
+ "input_schema": {
122
+ "type": "object",
123
+ "properties": {
124
+ "query": {
125
+ "type": "string"
126
+ }
127
+ },
128
+ "required": ["query"]
129
+ },
130
+ "context_schema": {
131
+ "type": "object",
132
+ "properties": {
133
+ "CHAT_PROVIDER": {
134
+ "type": "string"
135
+ }
136
+ }
137
+ }
138
+ }
139
+ }
140
+ }
141
+ ```
142
+
143
+ For OpenClaw agents, API and SDK calls map the local `thread_id` to the OpenClaw SDK `session_name`, so each Chatbot conversation uses an isolated OpenClaw session by default. When `create_agent` is enabled, thread creation calls `list_agents()` and creates the remote OpenClaw agent if it is missing. If `workspace` is omitted, the adapter creates the agent under the OpenClaw client work directory using the OpenClaw workspace naming convention, for example `.openclaw/workspace-openclaw-agent`.
144
+
145
+ The Gateway protocol requires both `auth.token` and a signed `device` identity during `connect`. In practice that means `client.api_key` alone is not enough for a normal WS connection: you also need a paired device identity (default `~/.openclaw/identity/device.json`) or a gateway configured for insecure local auth.
146
+
147
+ When `client.api_key` is configured, this project now auto-generates a local Ed25519 device identity if `client.device_identity_path` does not exist yet. The first connection may still require device approval on the gateway before `hello-ok.auth.deviceToken` is issued.
148
+
149
+ ## Request Payloads
150
+
151
+ Thread `run` and `stream` endpoints accept the current payload shape:
152
+
153
+ ```json
154
+ {
155
+ "query": "hello",
156
+ "attachments": []
157
+ }
158
+ ```
159
+
160
+ They also accept the legacy Chatbot payload shape:
161
+
162
+ ```json
163
+ {
164
+ "inputs": {
165
+ "user_input": "hello"
166
+ },
167
+ "attachments": []
168
+ }
169
+ ```
170
+
171
+ Internally both forms are normalized to `{"query": "hello"}` plus an attachment list before they reach the adapter. OpenClaw SSE events include `conversation_id` and use `model` / `tools` nodes for `node_message`, `tools_message`, and `token_stream` events.
172
+
173
+ ## Running the server
174
+
175
+ Run the application with Uvicorn:
176
+
177
+ ```bash
178
+ uvicorn service:create_fastapi_app --factory --host 0.0.0.0 --port 8080
179
+ ```
180
+
181
+ After startup:
182
+
183
+ - API root: `http://127.0.0.1:8080/api/v1`
184
+ - OpenAPI docs: `http://127.0.0.1:8080/docs`
185
+ - Built-in client: `http://127.0.0.1:8080/site`
186
+
187
+ ## SDK Usage
188
+
189
+ For OpenClaw agents, a package consumer can configure the gateway directly in the SDK constructor instead of shipping an `agents.json` file:
190
+
191
+ ```python
192
+ import asyncio
193
+
194
+ from agent_api_server import AgentSDK
195
+
196
+
197
+ async def main():
198
+ sdk = AgentSDK(
199
+ agent_name="demo-openclaw-agent",
200
+ agent_id="your-openclaw-agent-id",
201
+ gateway_ws_url="ws://127.0.0.1:18789/gateway",
202
+ api_key="your_gateway_token",
203
+ scopes=["operator.read", "operator.write"],
204
+ device_identity_path="~/.openclaw/identity/device.json",
205
+ timeout=60,
206
+ )
207
+ result = await sdk.run(query="hello", thread_id="sdk-run-thread")
208
+ print(result.content)
209
+
210
+
211
+ asyncio.run(main())
212
+ ```
213
+
214
+ To print each streamed chunk to the console as it arrives:
215
+
216
+ ```python
217
+ import asyncio
218
+
219
+ from agent_api_server import AgentSDK
220
+
221
+
222
+ async def main():
223
+ sdk = AgentSDK(
224
+ agent_name="demo-openclaw-agent",
225
+ agent_id="your-openclaw-agent-id",
226
+ gateway_ws_url="ws://127.0.0.1:18789/gateway",
227
+ api_key="your_gateway_token",
228
+ scopes=["operator.read", "operator.write"],
229
+ device_identity_path="~/.openclaw/identity/device.json",
230
+ timeout=60,
231
+ )
232
+ async for chunk in sdk.stream(query="hello", thread_id="sdk-stream-thread"):
233
+ print(chunk, end="", flush=True)
234
+
235
+
236
+ asyncio.run(main())
237
+ ```
238
+
239
+ The existing config-file style remains supported:
240
+
241
+ ```python
242
+ import asyncio
243
+
244
+ from agent_api_server import AgentSDK
245
+
246
+
247
+ async def main():
248
+ sdk = AgentSDK()
249
+ result = await sdk.run(
250
+ "demo-agent",
251
+ {"query": "hello"},
252
+ thread_id="sdk-thread",
253
+ )
254
+ print(result.content)
255
+
256
+
257
+ asyncio.run(main())
258
+ ```
259
+
260
+ For synchronous usage with direct OpenClaw settings:
261
+
262
+ ```python
263
+ from agent_api_server import AgentSDK
264
+
265
+ sdk = AgentSDK(
266
+ agent_name="demo-openclaw-agent",
267
+ agent_id="your-openclaw-agent-id",
268
+ gateway_ws_url="ws://127.0.0.1:18789/gateway",
269
+ api_key="your_gateway_token",
270
+ scopes=["operator.read", "operator.write"],
271
+ device_identity_path="~/.openclaw/identity/device.json",
272
+ timeout=60,
273
+ )
274
+ result = sdk.run_sync(query="hello", thread_id="sdk-sync-thread")
275
+ print(result.content)
276
+ ```
277
+
278
+ For synchronous usage with config-file-managed agents:
279
+
280
+ ```python
281
+ from agent_api_server import AgentSDK
282
+
283
+ sdk = AgentSDK()
284
+ result = sdk.run_sync("demo-agent", {"query": "hello"}, thread_id="sync-thread")
285
+ print(result.content)
286
+ ```
287
+
288
+ `attachments` is the public file/URL metadata channel. `ts_tenant`, `ei_token`, `runtime_config`, and `use_system_llm` are optional advanced parameters for deployments that need tenant-specific model credentials or LangGraph runtime configuration.
289
+
290
+ ## Build
291
+
292
+ Build source and wheel distributions with Poetry:
293
+
294
+ ```bash
295
+ poetry build
296
+ ```
297
+
298
+ ## Layout
299
+
300
+ The repository is now organized as layered packages:
301
+
302
+ - `adapters/` for framework-specific agent adapters
303
+ - `core/` for agent runtime, loading, and shared execution models
304
+ - `common/` for config, logging, crypto, Redis, Postgres, NATS, and formatting helpers
305
+ - `api/` for FastAPI route modules
306
+ - `integration/` for registration and model-update listener integrations
307
+ - `sdk/` for the direct SDK client
308
+
@@ -0,0 +1,275 @@
1
+ # agent-api-server
2
+
3
+ `agent-api-server` is an agent runtime that now supports both:
4
+
5
+ - API Server mode for HTTP/SSE access
6
+ - SDK mode for direct in-process agent execution
7
+
8
+ It keeps compatibility with existing LangGraph-based agents and introduces a framework abstraction so additional runtimes such as OpenClaw can be added behind the same interface.
9
+
10
+ ## Features
11
+
12
+ - FastAPI application factory for embedding or standalone deployment
13
+ - Direct SDK entry via root module `agent_api_server.py`
14
+ - Framework-neutral agent loading with LangGraph and OpenClaw adapters
15
+ - Backward-compatible LangGraph-oriented API routes under `/api/v1`
16
+ - Built-in static client assets bundled in both sdist and wheel artifacts
17
+ - Redis-backed thread storage and PostgreSQL checkpoint integration
18
+ - Optional integration with model management registration and listener services
19
+ - Layered package structure centered on `adapters/`, `core/`, `common/`, `api/`, `integration/`, and `sdk/`
20
+
21
+ ## Requirements
22
+
23
+ - Python 3.11 to 3.13
24
+ - Redis
25
+ - PostgreSQL
26
+ - Access to all runtime dependencies declared in `pyproject.toml`
27
+
28
+ ## Installation
29
+
30
+ Install from a package index that provides all required dependencies:
31
+
32
+ ```bash
33
+ pip install agent-api-server
34
+ ```
35
+
36
+ This project depends on `llm-sdk` and `model-manage-client`. If those packages are hosted on a private index in your environment, configure `pip` or Poetry to use that index before installation.
37
+
38
+ ## Configuration
39
+
40
+ The runtime reads configuration from environment variables. Common settings include:
41
+
42
+ ```env
43
+ REDIS_URL=redis://localhost:6379/0
44
+ POSTGRES_URL=postgresql://postgres:postgres@localhost:5432/postgres
45
+ MODEL_MANAGER_SERVICE_URL=http://127.0.0.1:10053
46
+ CLIENT_TOKEN=
47
+ SERVER_PORT=8080
48
+ SERVER_WORKER_AMOUNT=1
49
+ LOG_LEVEL=INFO
50
+ ```
51
+
52
+ See `.env_example` for a more complete example.
53
+
54
+ ## Agent Config
55
+
56
+ `agents.json` is now the primary agent registry. Existing deployments that still use `langgraph.json` remain compatible via fallback loading. LangGraph string entries still work:
57
+
58
+ ```json
59
+ {
60
+ "graphs": {
61
+ "demo-agent": "./agents/demo.py:graph"
62
+ }
63
+ }
64
+ ```
65
+
66
+ You can also use the extended form to declare the framework explicitly and attach adapter-specific settings:
67
+
68
+ ```json
69
+ {
70
+ "graphs": {
71
+ "demo-agent": {
72
+ "framework": "langgraph",
73
+ "entrypoint": "./agents/demo.py:graph"
74
+ },
75
+ "openclaw-agent": {
76
+ "framework": "openclaw",
77
+ "agent_id": "openclaw-agent",
78
+ "create_agent": true,
79
+ "agent_config": {
80
+ "name": "OpenClaw Agent"
81
+ },
82
+ "client": {
83
+ "gateway_ws_url": "ws://127.0.0.1:18789/gateway",
84
+ "api_key": "your_gateway_token",
85
+ "scopes": ["operator.read", "operator.write"],
86
+ "device_identity_path": "~/.openclaw/identity/device.json",
87
+ "timeout": 60
88
+ },
89
+ "input_schema": {
90
+ "type": "object",
91
+ "properties": {
92
+ "query": {
93
+ "type": "string"
94
+ }
95
+ },
96
+ "required": ["query"]
97
+ },
98
+ "context_schema": {
99
+ "type": "object",
100
+ "properties": {
101
+ "CHAT_PROVIDER": {
102
+ "type": "string"
103
+ }
104
+ }
105
+ }
106
+ }
107
+ }
108
+ }
109
+ ```
110
+
111
+ For OpenClaw agents, API and SDK calls map the local `thread_id` to the OpenClaw SDK `session_name`, so each Chatbot conversation uses an isolated OpenClaw session by default. When `create_agent` is enabled, thread creation calls `list_agents()` and creates the remote OpenClaw agent if it is missing. If `workspace` is omitted, the adapter creates the agent under the OpenClaw client work directory using the OpenClaw workspace naming convention, for example `.openclaw/workspace-openclaw-agent`.
112
+
113
+ The Gateway protocol requires both `auth.token` and a signed `device` identity during `connect`. In practice that means `client.api_key` alone is not enough for a normal WS connection: you also need a paired device identity (default `~/.openclaw/identity/device.json`) or a gateway configured for insecure local auth.
114
+
115
+ When `client.api_key` is configured, this project now auto-generates a local Ed25519 device identity if `client.device_identity_path` does not exist yet. The first connection may still require device approval on the gateway before `hello-ok.auth.deviceToken` is issued.
116
+
117
+ ## Request Payloads
118
+
119
+ Thread `run` and `stream` endpoints accept the current payload shape:
120
+
121
+ ```json
122
+ {
123
+ "query": "hello",
124
+ "attachments": []
125
+ }
126
+ ```
127
+
128
+ They also accept the legacy Chatbot payload shape:
129
+
130
+ ```json
131
+ {
132
+ "inputs": {
133
+ "user_input": "hello"
134
+ },
135
+ "attachments": []
136
+ }
137
+ ```
138
+
139
+ Internally both forms are normalized to `{"query": "hello"}` plus an attachment list before they reach the adapter. OpenClaw SSE events include `conversation_id` and use `model` / `tools` nodes for `node_message`, `tools_message`, and `token_stream` events.
140
+
141
+ ## Running the server
142
+
143
+ Run the application with Uvicorn:
144
+
145
+ ```bash
146
+ uvicorn service:create_fastapi_app --factory --host 0.0.0.0 --port 8080
147
+ ```
148
+
149
+ After startup:
150
+
151
+ - API root: `http://127.0.0.1:8080/api/v1`
152
+ - OpenAPI docs: `http://127.0.0.1:8080/docs`
153
+ - Built-in client: `http://127.0.0.1:8080/site`
154
+
155
+ ## SDK Usage
156
+
157
+ For OpenClaw agents, a package consumer can configure the gateway directly in the SDK constructor instead of shipping an `agents.json` file:
158
+
159
+ ```python
160
+ import asyncio
161
+
162
+ from agent_api_server import AgentSDK
163
+
164
+
165
+ async def main():
166
+ sdk = AgentSDK(
167
+ agent_name="demo-openclaw-agent",
168
+ agent_id="your-openclaw-agent-id",
169
+ gateway_ws_url="ws://127.0.0.1:18789/gateway",
170
+ api_key="your_gateway_token",
171
+ scopes=["operator.read", "operator.write"],
172
+ device_identity_path="~/.openclaw/identity/device.json",
173
+ timeout=60,
174
+ )
175
+ result = await sdk.run(query="hello", thread_id="sdk-run-thread")
176
+ print(result.content)
177
+
178
+
179
+ asyncio.run(main())
180
+ ```
181
+
182
+ To print each streamed chunk to the console as it arrives:
183
+
184
+ ```python
185
+ import asyncio
186
+
187
+ from agent_api_server import AgentSDK
188
+
189
+
190
+ async def main():
191
+ sdk = AgentSDK(
192
+ agent_name="demo-openclaw-agent",
193
+ agent_id="your-openclaw-agent-id",
194
+ gateway_ws_url="ws://127.0.0.1:18789/gateway",
195
+ api_key="your_gateway_token",
196
+ scopes=["operator.read", "operator.write"],
197
+ device_identity_path="~/.openclaw/identity/device.json",
198
+ timeout=60,
199
+ )
200
+ async for chunk in sdk.stream(query="hello", thread_id="sdk-stream-thread"):
201
+ print(chunk, end="", flush=True)
202
+
203
+
204
+ asyncio.run(main())
205
+ ```
206
+
207
+ The existing config-file style remains supported:
208
+
209
+ ```python
210
+ import asyncio
211
+
212
+ from agent_api_server import AgentSDK
213
+
214
+
215
+ async def main():
216
+ sdk = AgentSDK()
217
+ result = await sdk.run(
218
+ "demo-agent",
219
+ {"query": "hello"},
220
+ thread_id="sdk-thread",
221
+ )
222
+ print(result.content)
223
+
224
+
225
+ asyncio.run(main())
226
+ ```
227
+
228
+ For synchronous usage with direct OpenClaw settings:
229
+
230
+ ```python
231
+ from agent_api_server import AgentSDK
232
+
233
+ sdk = AgentSDK(
234
+ agent_name="demo-openclaw-agent",
235
+ agent_id="your-openclaw-agent-id",
236
+ gateway_ws_url="ws://127.0.0.1:18789/gateway",
237
+ api_key="your_gateway_token",
238
+ scopes=["operator.read", "operator.write"],
239
+ device_identity_path="~/.openclaw/identity/device.json",
240
+ timeout=60,
241
+ )
242
+ result = sdk.run_sync(query="hello", thread_id="sdk-sync-thread")
243
+ print(result.content)
244
+ ```
245
+
246
+ For synchronous usage with config-file-managed agents:
247
+
248
+ ```python
249
+ from agent_api_server import AgentSDK
250
+
251
+ sdk = AgentSDK()
252
+ result = sdk.run_sync("demo-agent", {"query": "hello"}, thread_id="sync-thread")
253
+ print(result.content)
254
+ ```
255
+
256
+ `attachments` is the public file/URL metadata channel. `ts_tenant`, `ei_token`, `runtime_config`, and `use_system_llm` are optional advanced parameters for deployments that need tenant-specific model credentials or LangGraph runtime configuration.
257
+
258
+ ## Build
259
+
260
+ Build source and wheel distributions with Poetry:
261
+
262
+ ```bash
263
+ poetry build
264
+ ```
265
+
266
+ ## Layout
267
+
268
+ The repository is now organized as layered packages:
269
+
270
+ - `adapters/` for framework-specific agent adapters
271
+ - `core/` for agent runtime, loading, and shared execution models
272
+ - `common/` for config, logging, crypto, Redis, Postgres, NATS, and formatting helpers
273
+ - `api/` for FastAPI route modules
274
+ - `integration/` for registration and model-update listener integrations
275
+ - `sdk/` for the direct SDK client
@@ -0,0 +1,43 @@
1
+ from importlib import import_module
2
+ from typing import TYPE_CHECKING
3
+
4
+
5
+ _EXPORTS = {
6
+ "LangGraphAgentAdapter": (
7
+ "adapters.langgraph_adapter.langgraph_adapter",
8
+ "LangGraphAgentAdapter",
9
+ ),
10
+ "OpenClawAgentAdapter": (
11
+ "adapters.openclaw_adapter.openclaw_adapter",
12
+ "OpenClawAgentAdapter",
13
+ ),
14
+ "handle_stream_event": (
15
+ "adapters.langgraph_adapter.formatter",
16
+ "handle_stream_event",
17
+ ),
18
+ "langchain_to_chat_message": (
19
+ "adapters.langgraph_adapter.formatter",
20
+ "langchain_to_chat_message",
21
+ ),
22
+ }
23
+
24
+ __all__ = list(_EXPORTS)
25
+
26
+
27
+ def __getattr__(name: str):
28
+ if name not in _EXPORTS:
29
+ raise AttributeError(f"module 'adapters' has no attribute '{name}'")
30
+ module_name, attr_name = _EXPORTS[name]
31
+ module = import_module(module_name)
32
+ value = getattr(module, attr_name)
33
+ globals()[name] = value
34
+ return value
35
+
36
+
37
+ if TYPE_CHECKING:
38
+ from adapters.langgraph_adapter.formatter import (
39
+ handle_stream_event,
40
+ langchain_to_chat_message,
41
+ )
42
+ from adapters.langgraph_adapter.langgraph_adapter import LangGraphAgentAdapter
43
+ from adapters.openclaw_adapter.openclaw_adapter import OpenClawAgentAdapter
@@ -0,0 +1,53 @@
1
+ from importlib import import_module
2
+ from typing import TYPE_CHECKING
3
+
4
+
5
+ _EXPORTS = {
6
+ "LangGraphAgentAdapter": (
7
+ "adapters.langgraph_adapter.langgraph_adapter",
8
+ "LangGraphAgentAdapter",
9
+ ),
10
+ "convert_message_content": (
11
+ "adapters.langgraph_adapter.formatter",
12
+ "convert_message_content",
13
+ ),
14
+ "format_state_snapshot": (
15
+ "adapters.langgraph_adapter.formatter",
16
+ "format_state_snapshot",
17
+ ),
18
+ "handle_stream_event": (
19
+ "adapters.langgraph_adapter.formatter",
20
+ "handle_stream_event",
21
+ ),
22
+ "langchain_to_chat_message": (
23
+ "adapters.langgraph_adapter.formatter",
24
+ "langchain_to_chat_message",
25
+ ),
26
+ "process_node_updates": (
27
+ "adapters.langgraph_adapter.formatter",
28
+ "process_node_updates",
29
+ ),
30
+ }
31
+
32
+ __all__ = list(_EXPORTS)
33
+
34
+
35
+ def __getattr__(name: str):
36
+ if name not in _EXPORTS:
37
+ raise AttributeError(f"module 'adapters.langgraph_adapter' has no attribute '{name}'")
38
+ module_name, attr_name = _EXPORTS[name]
39
+ module = import_module(module_name)
40
+ value = getattr(module, attr_name)
41
+ globals()[name] = value
42
+ return value
43
+
44
+
45
+ if TYPE_CHECKING:
46
+ from adapters.langgraph_adapter.formatter import (
47
+ convert_message_content,
48
+ format_state_snapshot,
49
+ handle_stream_event,
50
+ langchain_to_chat_message,
51
+ process_node_updates,
52
+ )
53
+ from adapters.langgraph_adapter.langgraph_adapter import LangGraphAgentAdapter