a2a-adapter 0.1.3__py3-none-any.whl → 0.1.4__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
a2a_adapter/loader.py CHANGED
@@ -13,27 +13,31 @@ from .adapter import BaseAgentAdapter
13
13
  async def load_a2a_agent(config: Dict[str, Any]) -> BaseAgentAdapter:
14
14
  """
15
15
  Factory function to load an agent adapter based on configuration.
16
-
16
+
17
17
  This function inspects the 'adapter' key in the config dictionary and
18
18
  instantiates the appropriate adapter class with the provided configuration.
19
-
19
+
20
20
  Args:
21
21
  config: Configuration dictionary with at least an 'adapter' key.
22
22
  Additional keys depend on the adapter type:
23
-
23
+
24
24
  - n8n: requires 'webhook_url', optional 'timeout', 'headers',
25
- 'payload_template', 'message_field'
26
- - crewai: requires 'crew' (CrewAI Crew instance)
25
+ 'payload_template', 'message_field', 'async_mode'
26
+ - crewai: requires 'crew' (CrewAI Crew instance),
27
+ optional 'inputs_key', 'async_mode'
27
28
  - langchain: requires 'runnable', optional 'input_key', 'output_key'
28
- - callable: requires 'callable' (async function)
29
-
29
+ - langgraph: requires 'graph' (CompiledGraph instance),
30
+ optional 'input_key', 'output_key', 'async_mode'
31
+ - callable: requires 'callable' (async function),
32
+ optional 'supports_streaming'
33
+
30
34
  Returns:
31
35
  Configured BaseAgentAdapter instance
32
-
36
+
33
37
  Raises:
34
38
  ValueError: If adapter type is unknown or required config is missing
35
39
  ImportError: If required framework package is not installed
36
-
40
+
37
41
  Examples:
38
42
  >>> # Load n8n adapter (basic)
39
43
  >>> adapter = await load_a2a_agent({
@@ -41,7 +45,7 @@ async def load_a2a_agent(config: Dict[str, Any]) -> BaseAgentAdapter:
41
45
  ... "webhook_url": "https://n8n.example.com/webhook/agent",
42
46
  ... "timeout": 30
43
47
  ... })
44
-
48
+
45
49
  >>> # Load n8n adapter with custom payload mapping
46
50
  >>> adapter = await load_a2a_agent({
47
51
  ... "adapter": "n8n",
@@ -49,7 +53,7 @@ async def load_a2a_agent(config: Dict[str, Any]) -> BaseAgentAdapter:
49
53
  ... "payload_template": {"name": "A2A Agent"}, # Static fields
50
54
  ... "message_field": "event" # Use "event" instead of "message"
51
55
  ... })
52
-
56
+
53
57
  >>> # Load CrewAI adapter
54
58
  >>> from crewai import Crew, Agent, Task
55
59
  >>> crew = Crew(agents=[...], tasks=[...])
@@ -57,7 +61,7 @@ async def load_a2a_agent(config: Dict[str, Any]) -> BaseAgentAdapter:
57
61
  ... "adapter": "crewai",
58
62
  ... "crew": crew
59
63
  ... })
60
-
64
+
61
65
  >>> # Load LangChain adapter
62
66
  >>> from langchain_core.runnables import RunnablePassthrough
63
67
  >>> adapter = await load_a2a_agent({
@@ -65,67 +69,106 @@ async def load_a2a_agent(config: Dict[str, Any]) -> BaseAgentAdapter:
65
69
  ... "runnable": chain,
66
70
  ... "input_key": "input"
67
71
  ... })
72
+
73
+ >>> # Load LangGraph adapter
74
+ >>> from langgraph.graph import StateGraph
75
+ >>> graph = builder.compile()
76
+ >>> adapter = await load_a2a_agent({
77
+ ... "adapter": "langgraph",
78
+ ... "graph": graph,
79
+ ... "input_key": "messages"
80
+ ... })
81
+
82
+ >>> # Load callable adapter
83
+ >>> async def my_agent(inputs: dict) -> str:
84
+ ... return f"Processed: {inputs['message']}"
85
+ >>> adapter = await load_a2a_agent({
86
+ ... "adapter": "callable",
87
+ ... "callable": my_agent
88
+ ... })
68
89
  """
69
90
  adapter_type = config.get("adapter")
70
-
91
+
71
92
  if not adapter_type:
72
93
  raise ValueError("Config must include 'adapter' key specifying adapter type")
73
-
94
+
74
95
  if adapter_type == "n8n":
75
96
  from .integrations.n8n import N8nAgentAdapter
76
-
97
+
77
98
  webhook_url = config.get("webhook_url")
78
99
  if not webhook_url:
79
100
  raise ValueError("n8n adapter requires 'webhook_url' in config")
80
-
101
+
81
102
  return N8nAgentAdapter(
82
103
  webhook_url=webhook_url,
83
104
  timeout=config.get("timeout", 30),
84
105
  headers=config.get("headers"),
85
106
  payload_template=config.get("payload_template"),
86
107
  message_field=config.get("message_field", "message"),
108
+ async_mode=config.get("async_mode", False),
109
+ task_store=config.get("task_store"),
110
+ async_timeout=config.get("async_timeout", 300),
87
111
  )
88
-
112
+
89
113
  elif adapter_type == "crewai":
90
114
  from .integrations.crewai import CrewAIAgentAdapter
91
-
115
+
92
116
  crew = config.get("crew")
93
117
  if crew is None:
94
118
  raise ValueError("crewai adapter requires 'crew' instance in config")
95
-
119
+
96
120
  return CrewAIAgentAdapter(
97
121
  crew=crew,
98
122
  inputs_key=config.get("inputs_key", "inputs"),
123
+ async_mode=config.get("async_mode", False),
124
+ task_store=config.get("task_store"),
125
+ async_timeout=config.get("async_timeout", 600),
99
126
  )
100
-
127
+
101
128
  elif adapter_type == "langchain":
102
129
  from .integrations.langchain import LangChainAgentAdapter
103
-
130
+
104
131
  runnable = config.get("runnable")
105
132
  if runnable is None:
106
133
  raise ValueError("langchain adapter requires 'runnable' in config")
107
-
134
+
108
135
  return LangChainAgentAdapter(
109
136
  runnable=runnable,
110
137
  input_key=config.get("input_key", "input"),
111
138
  output_key=config.get("output_key"),
112
139
  )
113
-
140
+
141
+ elif adapter_type == "langgraph":
142
+ from .integrations.langgraph import LangGraphAgentAdapter
143
+
144
+ graph = config.get("graph")
145
+ if graph is None:
146
+ raise ValueError("langgraph adapter requires 'graph' (CompiledGraph) in config")
147
+
148
+ return LangGraphAgentAdapter(
149
+ graph=graph,
150
+ input_key=config.get("input_key", "messages"),
151
+ output_key=config.get("output_key"),
152
+ state_key=config.get("state_key"),
153
+ async_mode=config.get("async_mode", False),
154
+ task_store=config.get("task_store"),
155
+ async_timeout=config.get("async_timeout", 300),
156
+ )
157
+
114
158
  elif adapter_type == "callable":
115
159
  from .integrations.callable import CallableAgentAdapter
116
-
160
+
117
161
  func = config.get("callable")
118
162
  if func is None:
119
163
  raise ValueError("callable adapter requires 'callable' function in config")
120
-
164
+
121
165
  return CallableAgentAdapter(
122
166
  func=func,
123
167
  supports_streaming=config.get("supports_streaming", False),
124
168
  )
125
-
169
+
126
170
  else:
127
171
  raise ValueError(
128
172
  f"Unknown adapter type: {adapter_type}. "
129
- f"Supported types: n8n, crewai, langchain, callable"
173
+ f"Supported types: n8n, crewai, langchain, langgraph, callable"
130
174
  )
131
-
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: a2a-adapter
3
- Version: 0.1.3
3
+ Version: 0.1.4
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,20 +52,24 @@ 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, 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.) 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
 
59
59
  - 🔌 **3-line setup** - Expose any agent as A2A-compliant
60
- - 🌐 **Framework agnostic** - Works with n8n, CrewAI, LangChain, and more
60
+ - 🌐 **Framework agnostic** - Works with n8n, LangGraph, CrewAI, LangChain, and more
61
61
  - 🌊 **Streaming support** - Built-in streaming for real-time responses
62
62
  - 🎯 **Production ready** - Type-safe, well-tested, and actively maintained
63
63
 
64
+ **▶️ Demo: n8n → A2A Agent**
65
+
66
+ [![A2A Adapter Demo](https://img.youtube.com/vi/rHWi7tLQ444/0.jpg)](https://youtu.be/rHWi7tLQ444)
67
+
64
68
  ## Features
65
69
 
66
- ✨ **Framework Agnostic**: Integrate n8n workflows, CrewAI crews, LangChain chains, and more
70
+ ✨ **Framework Agnostic**: Integrate n8n workflows, LangGraph workflows, CrewAI crews, LangChain chains, and more
67
71
  🔌 **Simple API**: 3-line setup to expose any agent as A2A-compliant
68
- 🌊 **Streaming Support**: Built-in streaming for LangChain and custom adapters
72
+ 🌊 **Streaming Support**: Built-in streaming for LangGraph, LangChain, and custom adapters
69
73
  🎯 **Type Safe**: Leverages official A2A SDK types
70
74
  🔧 **Extensible**: Easy to add custom adapters for new frameworks
71
75
  📦 **Minimal Dependencies**: Optional dependencies per framework
@@ -81,9 +85,10 @@ A Python SDK that enables seamless integration of various agent frameworks (n8n,
81
85
  ┌─────────────────┐
82
86
  │ A2A Adapter │ (This SDK)
83
87
  │ - N8n │
88
+ │ - LangGraph │
84
89
  │ - CrewAI │
85
90
  │ - LangChain │
86
- │ - Custom
91
+ │ - Callable
87
92
  └────────┬────────┘
88
93
 
89
94
 
@@ -198,6 +203,17 @@ adapter = await load_a2a_agent({
198
203
  })
199
204
  ```
200
205
 
206
+ ### LangGraph Workflow → A2A Agent (with Streaming)
207
+
208
+ ```python
209
+ adapter = await load_a2a_agent({
210
+ "adapter": "langgraph",
211
+ "graph": your_compiled_graph,
212
+ "input_key": "messages",
213
+ "output_key": "output"
214
+ })
215
+ ```
216
+
201
217
  ### Custom Function → A2A Agent
202
218
 
203
219
  ```python
@@ -271,9 +287,35 @@ class StreamingAdapter(BaseAgentAdapter):
271
287
  return True
272
288
  ```
273
289
 
274
- ### Using with LangGraph
290
+ ### LangGraph Workflow as A2A Server
275
291
 
276
- Integrate A2A agents into LangGraph workflows:
292
+ Expose a LangGraph workflow as an A2A server:
293
+
294
+ ```python
295
+ from langgraph.graph import StateGraph, END
296
+
297
+ # Build your workflow
298
+ builder = StateGraph(YourState)
299
+ builder.add_node("process", process_node)
300
+ builder.set_entry_point("process")
301
+ builder.add_edge("process", END)
302
+ graph = builder.compile()
303
+
304
+ # Expose as A2A agent
305
+ adapter = await load_a2a_agent({
306
+ "adapter": "langgraph",
307
+ "graph": graph,
308
+ "input_key": "messages",
309
+ "output_key": "output"
310
+ })
311
+ serve_agent(agent_card=card, adapter=adapter, port=9002)
312
+ ```
313
+
314
+ See [examples/07_langgraph_server.py](https://github.com/hybroai/a2a-adapter/blob/main/examples/07_langgraph_server.py) for complete example.
315
+
316
+ ### Using A2A Agents from LangGraph
317
+
318
+ Call A2A agents from within a LangGraph workflow:
277
319
 
278
320
  ```python
279
321
  from langgraph.graph import StateGraph
@@ -332,6 +374,19 @@ See [examples/06_langgraph_single_agent.py](https://github.com/hybroai/a2a-adapt
332
374
  }
333
375
  ```
334
376
 
377
+ ### LangGraph Adapter
378
+
379
+ ```python
380
+ {
381
+ "adapter": "langgraph",
382
+ "graph": compiled_graph, # Required: CompiledGraph from StateGraph.compile()
383
+ "input_key": "messages", # Optional, default: "messages" (for chat) or "input"
384
+ "output_key": None, # Optional, extracts specific key from final state
385
+ "async_mode": False, # Optional, enables async task execution
386
+ "async_timeout": 300 # Optional, timeout for async mode (default: 300s)
387
+ }
388
+ ```
389
+
335
390
  ### Callable Adapter
336
391
 
337
392
  ```python
@@ -351,7 +406,8 @@ The `examples/` directory contains complete working examples:
351
406
  - **03_single_langchain_agent.py** - LangChain streaming agent
352
407
  - **04_single_agent_client.py** - A2A client for testing
353
408
  - **05_custom_adapter.py** - Custom adapter implementations
354
- - **06_langgraph_single_agent.py** - LangGraph + A2A integration
409
+ - **06_langgraph_single_agent.py** - Calling A2A agents from LangGraph
410
+ - **07_langgraph_server.py** - LangGraph workflow as A2A server
355
411
 
356
412
  Run any example:
357
413
 
@@ -457,11 +513,13 @@ Check if this adapter supports streaming responses.
457
513
 
458
514
  ## Framework Support
459
515
 
460
- | Framework | Adapter | Non-Streaming | Streaming | Status |
461
- | ------------- | ----------------------- | ------------- | ---------- | ---------- |
462
- | **n8n** | `N8nAgentAdapter` | ✅ | 🔜 Planned | ✅ Stable |
463
- | **CrewAI** | `CrewAIAgentAdapter` | 🔜 Planned | 🔜 Planned | 🔜 Planned |
464
- | **LangChain** | `LangChainAgentAdapter` | 🔜 Planned | 🔜 Planned | 🔜 Planned |
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 |
465
523
 
466
524
  ## 🤝 Contributing
467
525
 
@@ -488,12 +546,13 @@ We welcome contributions from the community! Whether you're fixing bugs, adding
488
546
  ## Roadmap
489
547
 
490
548
  - [x] Core adapter abstraction
491
- - [x] N8n adapter
492
- - [ ] CrewAI adapter
493
- - [ ] LangChain adapter with streaming
494
- - [ ] Callable adapter
495
- - [ ] Comprehensive examples
496
- - [ ] Task support (async execution pattern)
549
+ - [x] N8n adapter (with async task support)
550
+ - [x] LangGraph adapter (with streaming and async tasks)
551
+ - [x] CrewAI adapter (with async task support)
552
+ - [x] LangChain adapter (with streaming)
553
+ - [x] Callable adapter (with streaming)
554
+ - [x] Comprehensive examples
555
+ - [x] Task support (async execution pattern)
497
556
  - [ ] Artifact support (file uploads/downloads)
498
557
  - [ ] AutoGen adapter
499
558
  - [ ] Semantic Kernel adapter
@@ -528,12 +587,6 @@ We welcome contributions from the community! Whether you're fixing bugs, adding
528
587
 
529
588
  Apache-2.0 License - see [LICENSE](https://github.com/hybroai/a2a-adapter/blob/main/LICENSE) file for details.
530
589
 
531
- ## Credits
532
-
533
- Built with ❤️ by [HYBRO AI](https://hybro.ai)
534
-
535
- Powered by the [A2A Protocol](https://github.com/a2aproject/A2A)
536
-
537
590
  ## 💬 Community & Support
538
591
 
539
592
  - 📚 **[Full Documentation](https://github.com/hybroai/a2a-adapter/blob/main/README.md)** - Complete API reference and guides
@@ -0,0 +1,15 @@
1
+ a2a_adapter/__init__.py,sha256=vnE2Qh7pjEP7nXUjqxgcE_hk0MpTzseeY4_5LTltHW8,1252
2
+ a2a_adapter/adapter.py,sha256=xCHmNNi5C_71A8OlIf_UZ1gUcvAFAIMrq8vGV_tYuTM,6098
3
+ a2a_adapter/client.py,sha256=TLkYBGQitZdrw_FY_ov9EjHicJX0dqqXaQ-dwfkUv2I,7397
4
+ a2a_adapter/loader.py,sha256=_A4Bqa9urE1mrV16emNJWJljvtKOhHDnz_FO4imDEDc,6399
5
+ a2a_adapter/integrations/__init__.py,sha256=W5k7qzAHwaqxpS2ojMGd-6R_L1PQU7N1bXWHktL_Aj0,1314
6
+ a2a_adapter/integrations/callable.py,sha256=TLtHtFwYr3vPmYWCcCvYGqSEAPV3QZxm8DnYAsy92KM,9404
7
+ a2a_adapter/integrations/crewai.py,sha256=YjTR-qU5m5XK0ojkngVRB6vWicfi6c6ZkGBoHBxrbR8,20410
8
+ a2a_adapter/integrations/langchain.py,sha256=0zpjd2vTTAEBdywsG-3rc04hVGl7Wsw-7mwJfPyc2ZM,11118
9
+ a2a_adapter/integrations/langgraph.py,sha256=euOpSXmgsqEw-mYzn_fmMxX3INaFI7gYqiNULvplTDw,27035
10
+ a2a_adapter/integrations/n8n.py,sha256=d9RqAS7y4eJZPWBaSOHBnT-wqFvTuJtmbE4rsvu5V2o,30171
11
+ a2a_adapter-0.1.4.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
12
+ a2a_adapter-0.1.4.dist-info/METADATA,sha256=GLrBjqSJUMWsUT1e01G3KtdYzUKc0y7fzAprMMoJP3g,19474
13
+ a2a_adapter-0.1.4.dist-info/WHEEL,sha256=qELbo2s1Yzl39ZmrAibXA2jjPLUYfnVhUNTlyF1rq0Y,92
14
+ a2a_adapter-0.1.4.dist-info/top_level.txt,sha256=b1O1dTJ2AoPEB2x-r5IHEsS2x1fczOzTrpR2DgF3LgE,12
15
+ a2a_adapter-0.1.4.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (80.9.0)
2
+ Generator: setuptools (80.10.1)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,14 +0,0 @@
1
- a2a_adapter/__init__.py,sha256=PZu--DO6e7lo5gr8OEmP8F64uJKrhG8_SCAF-kpGZyg,1252
2
- a2a_adapter/adapter.py,sha256=xCHmNNi5C_71A8OlIf_UZ1gUcvAFAIMrq8vGV_tYuTM,6098
3
- a2a_adapter/client.py,sha256=TLkYBGQitZdrw_FY_ov9EjHicJX0dqqXaQ-dwfkUv2I,7397
4
- a2a_adapter/loader.py,sha256=QEhozlS0dOu4qXoWpqglV1J2x2FN-CtWq4_ueq5Pr7o,4692
5
- a2a_adapter/integrations/__init__.py,sha256=vDYdcveV_U-nr39fvSnpIif2QgDF_AS6CPlElpBDrDs,1099
6
- a2a_adapter/integrations/callable.py,sha256=GsKZO5TyJVMOAS21cr7JNVKqjg7Z2CSc9Q9vhzgkapY,5917
7
- a2a_adapter/integrations/crewai.py,sha256=S4mF1mJeTAfMdif-su1E7jUjWgxAeFKlgz9WXlZEKN0,4813
8
- a2a_adapter/integrations/langchain.py,sha256=raaaJA_FS3qBsURbCbBq2bcfsRMdKgpVbKEUN3rWA4s,5866
9
- a2a_adapter/integrations/n8n.py,sha256=d9RqAS7y4eJZPWBaSOHBnT-wqFvTuJtmbE4rsvu5V2o,30171
10
- a2a_adapter-0.1.3.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
11
- a2a_adapter-0.1.3.dist-info/METADATA,sha256=PDtE_QDY4006UYYEbSt_9FKOom9eXuXvPyHdszf6Gow,17499
12
- a2a_adapter-0.1.3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
13
- a2a_adapter-0.1.3.dist-info/top_level.txt,sha256=b1O1dTJ2AoPEB2x-r5IHEsS2x1fczOzTrpR2DgF3LgE,12
14
- a2a_adapter-0.1.3.dist-info/RECORD,,