Skip to content

Commit d930047

Browse files
committed
feat(a2a): add persistent/redis context store for a2a server
1 parent 050ff4f commit d930047

File tree

15 files changed

+587
-98
lines changed

15 files changed

+587
-98
lines changed

AgentCrew/app.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,8 @@ def run_server(
172172
api_key: Optional[str] = None,
173173
mcp_config: Optional[str] = None,
174174
memory_llm: Optional[str] = None,
175+
store_type: str = "memory",
176+
store_options: Optional[dict] = None,
175177
) -> None:
176178
from AgentCrew.modules.a2a.server import A2AServer
177179
from AgentCrew.modules.mcpclient import MCPSessionManager
@@ -209,6 +211,8 @@ def run_server(
209211
port=port,
210212
base_url=base_url,
211213
api_key=api_key,
214+
store_type=store_type,
215+
store_options=store_options,
212216
)
213217

214218
click.echo(f"Starting A2A server on {host}:{port}")

AgentCrew/main.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,17 @@ def chat(
311311
@common_options
312312
@click.option("--model-id", default=None, help="Model ID from provider")
313313
@click.option("--api-key", default=None, help="API key for authentication (optional)")
314+
@click.option(
315+
"--store-type",
316+
default="memory",
317+
type=click.Choice(["memory", "file", "redis"]),
318+
help="Task store backend: memory, file, or redis",
319+
)
320+
@click.option(
321+
"--store-option",
322+
multiple=True,
323+
help="Store options as key=value pairs (e.g. --store-option base_dir=./data --store-option redis_url=redis://localhost:6379)",
324+
)
314325
def a2a_server(
315326
host,
316327
port,
@@ -322,13 +333,21 @@ def a2a_server(
322333
memory_path,
323334
model_id,
324335
api_key,
336+
store_type,
337+
store_option,
325338
):
326339
"""Start an A2A server exposing all SwissKnife agents"""
327340
from AgentCrew.app import AgentCrewApplication
328341

329342
if memory_path:
330343
os.environ["MEMORYDB_PATH"] = memory_path
331344

345+
store_options = {}
346+
for opt in store_option:
347+
if "=" in opt:
348+
k, v = opt.split("=", 1)
349+
store_options[k.strip()] = v.strip()
350+
332351
app = AgentCrewApplication()
333352
app.run_server(
334353
host=host,
@@ -340,6 +359,8 @@ def a2a_server(
340359
api_key=api_key,
341360
mcp_config=mcp_config,
342361
memory_llm=memory_llm,
362+
store_type=store_type,
363+
store_options=store_options if store_options else None,
343364
)
344365

345366

AgentCrew/main_docker.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,17 @@ def chat(provider, agent_config, mcp_config, memory_llm, memory_path):
9999
@common_options
100100
@click.option("--model-id", default=None, help="Model ID from provider")
101101
@click.option("--api-key", default=None, help="API key for authentication (optional)")
102+
@click.option(
103+
"--store-type",
104+
default="memory",
105+
type=click.Choice(["memory", "file", "redis"]),
106+
help="Task store backend: memory, file, or redis",
107+
)
108+
@click.option(
109+
"--store-option",
110+
multiple=True,
111+
help="Store options as key=value pairs (e.g. --store-option base_dir=./data)",
112+
)
102113
def a2a_server(
103114
host,
104115
port,
@@ -110,13 +121,21 @@ def a2a_server(
110121
memory_path,
111122
model_id,
112123
api_key,
124+
store_type,
125+
store_option,
113126
):
114127
"""Start an A2A server exposing all SwissKnife agents"""
115128
from AgentCrew.app import AgentCrewApplication
116129

117130
if memory_path:
118131
os.environ["MEMORYDB_PATH"] = memory_path
119132

133+
store_options = {}
134+
for opt in store_option:
135+
if "=" in opt:
136+
k, v = opt.split("=", 1)
137+
store_options[k.strip()] = v.strip()
138+
120139
app = AgentCrewApplication()
121140
app.run_server(
122141
host=host,
@@ -128,6 +147,8 @@ def a2a_server(
128147
api_key=api_key,
129148
mcp_config=mcp_config,
130149
memory_llm=memory_llm,
150+
store_type=store_type,
151+
store_options=store_options if store_options else None,
131152
)
132153

133154

AgentCrew/modules/a2a/__init__.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,19 @@
44
"""
55

66
from .server import A2AServer
7+
from .task_store import (
8+
TaskStore,
9+
InMemoryTaskStore,
10+
FileTaskStore,
11+
RedisTaskStore,
12+
create_task_store,
13+
)
714

8-
__all__ = ["A2AServer"]
15+
__all__ = [
16+
"A2AServer",
17+
"TaskStore",
18+
"InMemoryTaskStore",
19+
"FileTaskStore",
20+
"RedisTaskStore",
21+
"create_task_store",
22+
]

AgentCrew/modules/a2a/server.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ def __init__(
4444
port: int = 41241,
4545
base_url: Optional[str] = None,
4646
api_key: Optional[str] = None,
47+
store_type: str = "memory",
48+
store_options: Optional[dict] = None,
4749
):
4850
logger.info(f"Initializing A2A server with host={host}, port={port}")
4951
self.agent_manager = agent_manager
@@ -55,13 +57,14 @@ def __init__(
5557

5658
self.exposed_url = os.getenv("A2A_SERVER_EXPOSED_URL", self.base_url)
5759

58-
# Create agent registry
5960
self.agent_registry = AgentRegistry(agent_manager, self.exposed_url)
6061

61-
# Create task manager
62-
self.task_manager = MultiAgentTaskManager(agent_manager)
62+
self.task_manager = MultiAgentTaskManager(
63+
agent_manager,
64+
store_type=store_type,
65+
store_options=store_options,
66+
)
6367

64-
# Create Starlette app
6568
self.app = self._create_app()
6669

6770
def _create_app(self) -> Starlette:

0 commit comments

Comments
 (0)