a2a-adapter 0.1.4__tar.gz → 0.1.5__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 (21) hide show
  1. {a2a_adapter-0.1.4 → a2a_adapter-0.1.5}/PKG-INFO +39 -12
  2. {a2a_adapter-0.1.4 → a2a_adapter-0.1.5}/README.md +38 -11
  3. {a2a_adapter-0.1.4 → a2a_adapter-0.1.5}/a2a_adapter/__init__.py +1 -1
  4. {a2a_adapter-0.1.4 → a2a_adapter-0.1.5}/a2a_adapter/client.py +57 -13
  5. {a2a_adapter-0.1.4 → a2a_adapter-0.1.5}/a2a_adapter/integrations/__init__.py +5 -0
  6. a2a_adapter-0.1.5/a2a_adapter/integrations/openclaw.py +1297 -0
  7. {a2a_adapter-0.1.4 → a2a_adapter-0.1.5}/a2a_adapter/loader.py +31 -1
  8. {a2a_adapter-0.1.4 → a2a_adapter-0.1.5}/a2a_adapter.egg-info/PKG-INFO +39 -12
  9. {a2a_adapter-0.1.4 → a2a_adapter-0.1.5}/a2a_adapter.egg-info/SOURCES.txt +2 -1
  10. {a2a_adapter-0.1.4 → a2a_adapter-0.1.5}/pyproject.toml +1 -1
  11. {a2a_adapter-0.1.4 → a2a_adapter-0.1.5}/LICENSE +0 -0
  12. {a2a_adapter-0.1.4 → a2a_adapter-0.1.5}/a2a_adapter/adapter.py +0 -0
  13. {a2a_adapter-0.1.4 → a2a_adapter-0.1.5}/a2a_adapter/integrations/callable.py +0 -0
  14. {a2a_adapter-0.1.4 → a2a_adapter-0.1.5}/a2a_adapter/integrations/crewai.py +0 -0
  15. {a2a_adapter-0.1.4 → a2a_adapter-0.1.5}/a2a_adapter/integrations/langchain.py +0 -0
  16. {a2a_adapter-0.1.4 → a2a_adapter-0.1.5}/a2a_adapter/integrations/langgraph.py +0 -0
  17. {a2a_adapter-0.1.4 → a2a_adapter-0.1.5}/a2a_adapter/integrations/n8n.py +0 -0
  18. {a2a_adapter-0.1.4 → a2a_adapter-0.1.5}/a2a_adapter.egg-info/dependency_links.txt +0 -0
  19. {a2a_adapter-0.1.4 → a2a_adapter-0.1.5}/a2a_adapter.egg-info/requires.txt +0 -0
  20. {a2a_adapter-0.1.4 → a2a_adapter-0.1.5}/a2a_adapter.egg-info/top_level.txt +0 -0
  21. {a2a_adapter-0.1.4 → a2a_adapter-0.1.5}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: a2a-adapter
3
- Version: 0.1.4
3
+ Version: 0.1.5
4
4
  Summary: A2A Protocol Adapter SDK for integrating various agent frameworks
5
5
  Author-email: HYBRO AI <info@hybro.ai>
6
6
  License: Apache-2.0
@@ -52,7 +52,7 @@ Dynamic: license-file
52
52
 
53
53
  **🚀 Open Source A2A Protocol Adapter SDK - Make Any Agent Framework A2A-Compatible in 3 Lines**
54
54
 
55
- A Python SDK that enables seamless integration of various agent frameworks (n8n, LangGraph, CrewAI, LangChain, etc.) with the [A2A (Agent-to-Agent) Protocol](https://github.com/a2aproject/A2A). Build interoperable AI agent systems that can communicate across different platforms and frameworks.
55
+ A Python SDK that enables seamless integration of various agent frameworks (n8n, LangGraph, CrewAI, LangChain, etc.) and personal AI agents (OpenClaw) with the [A2A (Agent-to-Agent) Protocol](https://github.com/a2aproject/A2A). Build interoperable AI agent systems that can communicate across different platforms and frameworks.
56
56
 
57
57
  **✨ Key Benefits:**
58
58
 
@@ -67,7 +67,7 @@ A Python SDK that enables seamless integration of various agent frameworks (n8n,
67
67
 
68
68
  ## Features
69
69
 
70
- ✨ **Framework Agnostic**: Integrate n8n workflows, LangGraph workflows, CrewAI crews, LangChain chains, and more
70
+ ✨ **Framework Agnostic**: Integrate n8n workflows, LangGraph workflows, CrewAI crews, LangChain chains, OpenClaw personal agents, and more
71
71
  🔌 **Simple API**: 3-line setup to expose any agent as A2A-compliant
72
72
  🌊 **Streaming Support**: Built-in streaming for LangGraph, LangChain, and custom adapters
73
73
  🎯 **Type Safe**: Leverages official A2A SDK types
@@ -88,12 +88,13 @@ A Python SDK that enables seamless integration of various agent frameworks (n8n,
88
88
  │ - LangGraph │
89
89
  │ - CrewAI │
90
90
  │ - LangChain │
91
+ │ - OpenClaw │
91
92
  │ - Callable │
92
93
  └────────┬────────┘
93
94
 
94
95
 
95
96
  ┌─────────────────┐
96
- │ Your Agent │ (n8n workflow / CrewAI crew / Chain)
97
+ │ Your Agent │ (n8n workflow / CrewAI crew / Chain / OpenClaw)
97
98
  └─────────────────┘
98
99
  ```
99
100
 
@@ -226,6 +227,16 @@ adapter = await load_a2a_agent({
226
227
  })
227
228
  ```
228
229
 
230
+ ### OpenClaw Agent → A2A Agent
231
+
232
+ ```python
233
+ adapter = await load_a2a_agent({
234
+ "adapter": "openclaw",
235
+ "thinking": "low",
236
+ "async_mode": True
237
+ })
238
+ ```
239
+
229
240
  📚 **[View all examples →](https://github.com/hybroai/a2a-adapter/tree/main/examples/)**
230
241
 
231
242
  ## Advanced Usage
@@ -397,6 +408,19 @@ See [examples/06_langgraph_single_agent.py](https://github.com/hybroai/a2a-adapt
397
408
  }
398
409
  ```
399
410
 
411
+ ### OpenClaw Adapter
412
+
413
+ ```python
414
+ {
415
+ "adapter": "openclaw",
416
+ "session_id": "my-session", # Optional, auto-generated if not provided
417
+ "agent_id": None, # Optional, use default agent
418
+ "thinking": "low", # Optional: off|minimal|low|medium|high|xhigh
419
+ "timeout": 600, # Optional, command timeout in seconds
420
+ "async_mode": True # Optional, return Task immediately (default: True)
421
+ }
422
+ ```
423
+
400
424
  ## Examples
401
425
 
402
426
  The `examples/` directory contains complete working examples:
@@ -408,6 +432,7 @@ The `examples/` directory contains complete working examples:
408
432
  - **05_custom_adapter.py** - Custom adapter implementations
409
433
  - **06_langgraph_single_agent.py** - Calling A2A agents from LangGraph
410
434
  - **07_langgraph_server.py** - LangGraph workflow as A2A server
435
+ - **08_openclaw_agent.py** - OpenClaw personal AI agent
411
436
 
412
437
  Run any example:
413
438
 
@@ -511,15 +536,16 @@ Convert framework output to A2A Message or Task.
511
536
 
512
537
  Check if this adapter supports streaming responses.
513
538
 
514
- ## Framework Support
539
+ ## Adapter Support
515
540
 
516
- | Framework | Adapter | Non-Streaming | Streaming | Async Tasks | Status |
517
- | ------------- | ------------------------ | ------------- | --------- | ----------- | --------- |
518
- | **n8n** | `N8nAgentAdapter` | ✅ | ❌ | ✅ | ✅ Stable |
519
- | **LangGraph** | `LangGraphAgentAdapter` | ✅ | ✅ | ✅ | ✅ Stable |
520
- | **CrewAI** | `CrewAIAgentAdapter` | ✅ | ❌ | ✅ | ✅ Stable |
521
- | **LangChain** | `LangChainAgentAdapter` | ✅ | ✅ | ❌ | ✅ Stable |
522
- | **Callable** | `CallableAgentAdapter` | ✅ | | | ✅ Stable |
541
+ | Agent/Framework | Adapter | Non-Streaming | Streaming | Async Tasks | Status |
542
+ | --------------- | ------------------------ | ------------- | --------- | ----------- | --------- |
543
+ | **n8n** | `N8nAgentAdapter` | ✅ | ❌ | ✅ | ✅ Stable |
544
+ | **LangGraph** | `LangGraphAgentAdapter` | ✅ | ✅ | ✅ | ✅ Stable |
545
+ | **CrewAI** | `CrewAIAgentAdapter` | ✅ | ❌ | ✅ | ✅ Stable |
546
+ | **LangChain** | `LangChainAgentAdapter` | ✅ | ✅ | ❌ | ✅ Stable |
547
+ | **OpenClaw** | `OpenClawAgentAdapter` | ✅ | | | ✅ Stable |
548
+ | **Callable** | `CallableAgentAdapter` | ✅ | ✅ | ❌ | ✅ Stable |
523
549
 
524
550
  ## 🤝 Contributing
525
551
 
@@ -551,6 +577,7 @@ We welcome contributions from the community! Whether you're fixing bugs, adding
551
577
  - [x] CrewAI adapter (with async task support)
552
578
  - [x] LangChain adapter (with streaming)
553
579
  - [x] Callable adapter (with streaming)
580
+ - [x] OpenClaw adapter (with async tasks)
554
581
  - [x] Comprehensive examples
555
582
  - [x] Task support (async execution pattern)
556
583
  - [ ] Artifact support (file uploads/downloads)
@@ -7,7 +7,7 @@
7
7
 
8
8
  **🚀 Open Source A2A Protocol Adapter SDK - Make Any Agent Framework A2A-Compatible in 3 Lines**
9
9
 
10
- A Python SDK that enables seamless integration of various agent frameworks (n8n, LangGraph, CrewAI, LangChain, etc.) with the [A2A (Agent-to-Agent) Protocol](https://github.com/a2aproject/A2A). Build interoperable AI agent systems that can communicate across different platforms and frameworks.
10
+ A Python SDK that enables seamless integration of various agent frameworks (n8n, LangGraph, CrewAI, LangChain, etc.) and personal AI agents (OpenClaw) with the [A2A (Agent-to-Agent) Protocol](https://github.com/a2aproject/A2A). Build interoperable AI agent systems that can communicate across different platforms and frameworks.
11
11
 
12
12
  **✨ Key Benefits:**
13
13
 
@@ -22,7 +22,7 @@ A Python SDK that enables seamless integration of various agent frameworks (n8n,
22
22
 
23
23
  ## Features
24
24
 
25
- ✨ **Framework Agnostic**: Integrate n8n workflows, LangGraph workflows, CrewAI crews, LangChain chains, and more
25
+ ✨ **Framework Agnostic**: Integrate n8n workflows, LangGraph workflows, CrewAI crews, LangChain chains, OpenClaw personal agents, and more
26
26
  🔌 **Simple API**: 3-line setup to expose any agent as A2A-compliant
27
27
  🌊 **Streaming Support**: Built-in streaming for LangGraph, LangChain, and custom adapters
28
28
  🎯 **Type Safe**: Leverages official A2A SDK types
@@ -43,12 +43,13 @@ A Python SDK that enables seamless integration of various agent frameworks (n8n,
43
43
  │ - LangGraph │
44
44
  │ - CrewAI │
45
45
  │ - LangChain │
46
+ │ - OpenClaw │
46
47
  │ - Callable │
47
48
  └────────┬────────┘
48
49
 
49
50
 
50
51
  ┌─────────────────┐
51
- │ Your Agent │ (n8n workflow / CrewAI crew / Chain)
52
+ │ Your Agent │ (n8n workflow / CrewAI crew / Chain / OpenClaw)
52
53
  └─────────────────┘
53
54
  ```
54
55
 
@@ -181,6 +182,16 @@ adapter = await load_a2a_agent({
181
182
  })
182
183
  ```
183
184
 
185
+ ### OpenClaw Agent → A2A Agent
186
+
187
+ ```python
188
+ adapter = await load_a2a_agent({
189
+ "adapter": "openclaw",
190
+ "thinking": "low",
191
+ "async_mode": True
192
+ })
193
+ ```
194
+
184
195
  📚 **[View all examples →](https://github.com/hybroai/a2a-adapter/tree/main/examples/)**
185
196
 
186
197
  ## Advanced Usage
@@ -352,6 +363,19 @@ See [examples/06_langgraph_single_agent.py](https://github.com/hybroai/a2a-adapt
352
363
  }
353
364
  ```
354
365
 
366
+ ### OpenClaw Adapter
367
+
368
+ ```python
369
+ {
370
+ "adapter": "openclaw",
371
+ "session_id": "my-session", # Optional, auto-generated if not provided
372
+ "agent_id": None, # Optional, use default agent
373
+ "thinking": "low", # Optional: off|minimal|low|medium|high|xhigh
374
+ "timeout": 600, # Optional, command timeout in seconds
375
+ "async_mode": True # Optional, return Task immediately (default: True)
376
+ }
377
+ ```
378
+
355
379
  ## Examples
356
380
 
357
381
  The `examples/` directory contains complete working examples:
@@ -363,6 +387,7 @@ The `examples/` directory contains complete working examples:
363
387
  - **05_custom_adapter.py** - Custom adapter implementations
364
388
  - **06_langgraph_single_agent.py** - Calling A2A agents from LangGraph
365
389
  - **07_langgraph_server.py** - LangGraph workflow as A2A server
390
+ - **08_openclaw_agent.py** - OpenClaw personal AI agent
366
391
 
367
392
  Run any example:
368
393
 
@@ -466,15 +491,16 @@ Convert framework output to A2A Message or Task.
466
491
 
467
492
  Check if this adapter supports streaming responses.
468
493
 
469
- ## Framework Support
494
+ ## Adapter Support
470
495
 
471
- | Framework | Adapter | Non-Streaming | Streaming | Async Tasks | Status |
472
- | ------------- | ------------------------ | ------------- | --------- | ----------- | --------- |
473
- | **n8n** | `N8nAgentAdapter` | ✅ | ❌ | ✅ | ✅ Stable |
474
- | **LangGraph** | `LangGraphAgentAdapter` | ✅ | ✅ | ✅ | ✅ Stable |
475
- | **CrewAI** | `CrewAIAgentAdapter` | ✅ | ❌ | ✅ | ✅ Stable |
476
- | **LangChain** | `LangChainAgentAdapter` | ✅ | ✅ | ❌ | ✅ Stable |
477
- | **Callable** | `CallableAgentAdapter` | ✅ | | | ✅ Stable |
496
+ | Agent/Framework | Adapter | Non-Streaming | Streaming | Async Tasks | Status |
497
+ | --------------- | ------------------------ | ------------- | --------- | ----------- | --------- |
498
+ | **n8n** | `N8nAgentAdapter` | ✅ | ❌ | ✅ | ✅ Stable |
499
+ | **LangGraph** | `LangGraphAgentAdapter` | ✅ | ✅ | ✅ | ✅ Stable |
500
+ | **CrewAI** | `CrewAIAgentAdapter` | ✅ | ❌ | ✅ | ✅ Stable |
501
+ | **LangChain** | `LangChainAgentAdapter` | ✅ | ✅ | ❌ | ✅ Stable |
502
+ | **OpenClaw** | `OpenClawAgentAdapter` | ✅ | | | ✅ Stable |
503
+ | **Callable** | `CallableAgentAdapter` | ✅ | ✅ | ❌ | ✅ Stable |
478
504
 
479
505
  ## 🤝 Contributing
480
506
 
@@ -506,6 +532,7 @@ We welcome contributions from the community! Whether you're fixing bugs, adding
506
532
  - [x] CrewAI adapter (with async task support)
507
533
  - [x] LangChain adapter (with streaming)
508
534
  - [x] Callable adapter (with streaming)
535
+ - [x] OpenClaw adapter (with async tasks)
509
536
  - [x] Comprehensive examples
510
537
  - [x] Task support (async execution pattern)
511
538
  - [ ] Artifact support (file uploads/downloads)
@@ -26,7 +26,7 @@ Example:
26
26
  >>> asyncio.run(main())
27
27
  """
28
28
 
29
- __version__ = "0.1.4"
29
+ __version__ = "0.1.5"
30
30
 
31
31
  from .adapter import BaseAgentAdapter
32
32
  from .client import build_agent_app, serve_agent
@@ -27,6 +27,7 @@ from a2a.types import (
27
27
  ListTaskPushNotificationConfigResponse,
28
28
  Message,
29
29
  MessageSendParams,
30
+ PushNotificationConfig,
30
31
  SetTaskPushNotificationConfigRequest,
31
32
  SetTaskPushNotificationConfigResponse,
32
33
  Task,
@@ -43,6 +44,11 @@ class AdapterRequestHandler(RequestHandler):
43
44
 
44
45
  This class bridges the gap between our adapter abstraction and the
45
46
  official A2A SDK's RequestHandler protocol.
47
+
48
+ Supports:
49
+ - Basic message send (sync and async)
50
+ - Task get/cancel for async adapters
51
+ - Push notification configuration for adapters that support it
46
52
  """
47
53
 
48
54
  def __init__(self, adapter: BaseAgentAdapter):
@@ -89,23 +95,37 @@ class AdapterRequestHandler(RequestHandler):
89
95
  async for event in self.adapter.handle_stream(params):
90
96
  yield event
91
97
 
92
- # Task-related methods (not supported by default)
98
+ # Task-related methods
93
99
 
94
100
  async def on_get_task(
95
101
  self,
96
102
  params: GetTaskRequest,
97
103
  context: ServerCallContext
98
104
  ) -> GetTaskResponse:
99
- """Get task status - not supported."""
100
- raise ServerError(error=UnsupportedOperationError())
105
+ """Get task status."""
106
+ if not self.adapter.supports_async_tasks():
107
+ raise ServerError(error=UnsupportedOperationError())
108
+
109
+ task = await self.adapter.get_task(params.id)
110
+ if task is None:
111
+ raise ServerError(error=UnsupportedOperationError(message=f"Task {params.id} not found"))
112
+
113
+ return GetTaskResponse(result=task)
101
114
 
102
115
  async def on_cancel_task(
103
116
  self,
104
117
  params: CancelTaskRequest,
105
118
  context: ServerCallContext
106
119
  ) -> CancelTaskResponse:
107
- """Cancel task - not supported."""
108
- raise ServerError(error=UnsupportedOperationError())
120
+ """Cancel task."""
121
+ if not self.adapter.supports_async_tasks():
122
+ raise ServerError(error=UnsupportedOperationError())
123
+
124
+ task = await self.adapter.cancel_task(params.id)
125
+ if task is None:
126
+ raise ServerError(error=UnsupportedOperationError(message=f"Task {params.id} not found"))
127
+
128
+ return CancelTaskResponse(result=task)
109
129
 
110
130
  async def on_resubscribe_to_task(
111
131
  self,
@@ -116,30 +136,47 @@ class AdapterRequestHandler(RequestHandler):
116
136
  raise ServerError(error=UnsupportedOperationError())
117
137
  yield # Make this an async generator
118
138
 
119
- # Push notification methods (not supported by default)
139
+ # Push notification methods
120
140
 
121
141
  async def on_set_task_push_notification_config(
122
142
  self,
123
143
  params: SetTaskPushNotificationConfigRequest,
124
144
  context: ServerCallContext
125
145
  ) -> SetTaskPushNotificationConfigResponse:
126
- """Set push notification config - not supported."""
127
- raise ServerError(error=UnsupportedOperationError())
146
+ """Set push notification config."""
147
+ if not hasattr(self.adapter, 'supports_push_notifications') or not self.adapter.supports_push_notifications():
148
+ raise ServerError(error=UnsupportedOperationError())
149
+
150
+ success = await self.adapter.set_push_notification_config(
151
+ params.taskId,
152
+ params.pushNotificationConfig
153
+ )
154
+ if not success:
155
+ raise ServerError(error=UnsupportedOperationError(message=f"Task {params.taskId} not found"))
156
+
157
+ return SetTaskPushNotificationConfigResponse(result=params.pushNotificationConfig)
128
158
 
129
159
  async def on_get_task_push_notification_config(
130
160
  self,
131
161
  params: GetTaskPushNotificationConfigParams,
132
162
  context: ServerCallContext
133
163
  ) -> GetTaskPushNotificationConfigResponse:
134
- """Get push notification config - not supported."""
135
- raise ServerError(error=UnsupportedOperationError())
164
+ """Get push notification config."""
165
+ if not hasattr(self.adapter, 'supports_push_notifications') or not self.adapter.supports_push_notifications():
166
+ raise ServerError(error=UnsupportedOperationError())
167
+
168
+ config = await self.adapter.get_push_notification_config(params.taskId)
169
+ if config is None:
170
+ raise ServerError(error=UnsupportedOperationError(message=f"No push config for task {params.taskId}"))
171
+
172
+ return GetTaskPushNotificationConfigResponse(result=config)
136
173
 
137
174
  async def on_list_task_push_notification_config(
138
175
  self,
139
176
  params: ListTaskPushNotificationConfigParams,
140
177
  context: ServerCallContext
141
178
  ) -> ListTaskPushNotificationConfigResponse:
142
- """List push notification configs - not supported."""
179
+ """List push notification configs - not supported (would need to track all configs)."""
143
180
  raise ServerError(error=UnsupportedOperationError())
144
181
 
145
182
  async def on_delete_task_push_notification_config(
@@ -147,8 +184,15 @@ class AdapterRequestHandler(RequestHandler):
147
184
  params: DeleteTaskPushNotificationConfigParams,
148
185
  context: ServerCallContext
149
186
  ) -> DeleteTaskPushNotificationConfigResponse:
150
- """Delete push notification config - not supported."""
151
- raise ServerError(error=UnsupportedOperationError())
187
+ """Delete push notification config."""
188
+ if not hasattr(self.adapter, 'supports_push_notifications') or not self.adapter.supports_push_notifications():
189
+ raise ServerError(error=UnsupportedOperationError())
190
+
191
+ success = await self.adapter.delete_push_notification_config(params.taskId)
192
+ if not success:
193
+ raise ServerError(error=UnsupportedOperationError(message=f"No push config for task {params.taskId}"))
194
+
195
+ return DeleteTaskPushNotificationConfigResponse(result={})
152
196
 
153
197
 
154
198
  def build_agent_app(
@@ -7,6 +7,7 @@ This package contains concrete adapter implementations for various agent framewo
7
7
  - LangChain: LLM application framework with LCEL support
8
8
  - LangGraph: Stateful workflow orchestration framework
9
9
  - Callable: Generic Python async function adapter
10
+ - OpenClaw: Personal AI super agent CLI wrapper
10
11
  """
11
12
 
12
13
  __all__ = [
@@ -15,6 +16,7 @@ __all__ = [
15
16
  "LangChainAgentAdapter",
16
17
  "LangGraphAgentAdapter",
17
18
  "CallableAgentAdapter",
19
+ "OpenClawAgentAdapter",
18
20
  ]
19
21
 
20
22
  # Lazy imports to avoid requiring all optional dependencies
@@ -34,4 +36,7 @@ def __getattr__(name: str):
34
36
  elif name == "CallableAgentAdapter":
35
37
  from .callable import CallableAgentAdapter
36
38
  return CallableAgentAdapter
39
+ elif name == "OpenClawAgentAdapter":
40
+ from .openclaw import OpenClawAgentAdapter
41
+ return OpenClawAgentAdapter
37
42
  raise AttributeError(f"module {__name__!r} has no attribute {name!r}")