distributed-a2a 0.1.5rc19__tar.gz → 0.1.6rc1__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.
- {distributed_a2a-0.1.5rc19/distributed_a2a.egg-info → distributed_a2a-0.1.6rc1}/PKG-INFO +1 -1
- {distributed_a2a-0.1.5rc19 → distributed_a2a-0.1.6rc1}/distributed_a2a/__init__.py +2 -0
- {distributed_a2a-0.1.5rc19 → distributed_a2a-0.1.6rc1}/distributed_a2a/agent.py +0 -1
- {distributed_a2a-0.1.5rc19 → distributed_a2a-0.1.6rc1}/distributed_a2a/executors.py +45 -1
- {distributed_a2a-0.1.5rc19 → distributed_a2a-0.1.6rc1}/distributed_a2a/model.py +7 -0
- distributed_a2a-0.1.6rc1/distributed_a2a/router.py +41 -0
- {distributed_a2a-0.1.5rc19 → distributed_a2a-0.1.6rc1/distributed_a2a.egg-info}/PKG-INFO +1 -1
- {distributed_a2a-0.1.5rc19 → distributed_a2a-0.1.6rc1}/distributed_a2a.egg-info/SOURCES.txt +1 -1
- {distributed_a2a-0.1.5rc19 → distributed_a2a-0.1.6rc1}/pyproject.toml +1 -1
- distributed_a2a-0.1.5rc19/distributed_a2a/tool_registry_test.py +0 -6
- {distributed_a2a-0.1.5rc19 → distributed_a2a-0.1.6rc1}/LICENSE +0 -0
- {distributed_a2a-0.1.5rc19 → distributed_a2a-0.1.6rc1}/MANIFEST.in +0 -0
- {distributed_a2a-0.1.5rc19 → distributed_a2a-0.1.6rc1}/README.md +0 -0
- {distributed_a2a-0.1.5rc19 → distributed_a2a-0.1.6rc1}/distributed_a2a/client.py +0 -0
- {distributed_a2a-0.1.5rc19 → distributed_a2a-0.1.6rc1}/distributed_a2a/registry.py +0 -0
- {distributed_a2a-0.1.5rc19 → distributed_a2a-0.1.6rc1}/distributed_a2a/server.py +0 -0
- {distributed_a2a-0.1.5rc19 → distributed_a2a-0.1.6rc1}/distributed_a2a.egg-info/dependency_links.txt +0 -0
- {distributed_a2a-0.1.5rc19 → distributed_a2a-0.1.6rc1}/distributed_a2a.egg-info/requires.txt +0 -0
- {distributed_a2a-0.1.5rc19 → distributed_a2a-0.1.6rc1}/distributed_a2a.egg-info/top_level.txt +0 -0
- {distributed_a2a-0.1.5rc19 → distributed_a2a-0.1.6rc1}/requirements.txt +0 -0
- {distributed_a2a-0.1.5rc19 → distributed_a2a-0.1.6rc1}/setup.cfg +0 -0
- {distributed_a2a-0.1.5rc19 → distributed_a2a-0.1.6rc1}/setup.py +0 -0
|
@@ -4,7 +4,6 @@ from a2a.types import TaskState
|
|
|
4
4
|
from langchain.agents import create_agent
|
|
5
5
|
from langchain_core.runnables import RunnableConfig
|
|
6
6
|
from langchain_core.tools import BaseTool
|
|
7
|
-
from langgraph.checkpoint.memory import MemorySaver
|
|
8
7
|
from langgraph_dynamodb_checkpoint import DynamoDBSaver
|
|
9
8
|
from pydantic import BaseModel, Field
|
|
10
9
|
|
|
@@ -9,7 +9,7 @@ from a2a.utils import new_text_artifact
|
|
|
9
9
|
from langchain_core.tools import BaseTool
|
|
10
10
|
|
|
11
11
|
from .agent import StatusAgent, RoutingResponse, StringResponse
|
|
12
|
-
from .model import AgentConfig
|
|
12
|
+
from .model import AgentConfig, RouterConfig
|
|
13
13
|
|
|
14
14
|
logger = logging.getLogger(__name__)
|
|
15
15
|
|
|
@@ -80,3 +80,47 @@ class RoutingAgentExecutor(AgentExecutor):
|
|
|
80
80
|
final=True,
|
|
81
81
|
context_id=context.context_id,
|
|
82
82
|
task_id=context.task_id))
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
class RoutingExecutor(AgentExecutor):
|
|
86
|
+
def __init__(self, router_config: RouterConfig, routing_tool: BaseTool):
|
|
87
|
+
super().__init__()
|
|
88
|
+
api_key = os.environ.get(router_config.agent.llm.api_key_env)
|
|
89
|
+
self.routing_agent = StatusAgent[RoutingResponse](
|
|
90
|
+
llm_config=router_config.agent.llm,
|
|
91
|
+
system_prompt=ROUTING_SYSTEM_PROMPT,
|
|
92
|
+
name=router_config.router.card.name,
|
|
93
|
+
api_key=api_key,
|
|
94
|
+
is_routing=True,
|
|
95
|
+
tools=[routing_tool]
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
async def cancel(self, context: RequestContext, event_queue: EventQueue) -> None:
|
|
99
|
+
raise NotImplementedError
|
|
100
|
+
|
|
101
|
+
async def execute(self, context: RequestContext, event_queue: EventQueue) -> None:
|
|
102
|
+
await event_queue.enqueue_event(TaskStatusUpdateEvent(status=TaskStatus(state=TaskState.working),
|
|
103
|
+
final=False,
|
|
104
|
+
context_id=context.context_id,
|
|
105
|
+
task_id=context.task_id))
|
|
106
|
+
|
|
107
|
+
agent_response: RoutingResponse = await self.routing_agent(message=context.get_user_input(),
|
|
108
|
+
context_id=context.context_id)
|
|
109
|
+
agent_name: str = json.loads(agent_response.agent_card)["name"]
|
|
110
|
+
logger.info(f"Request with id {context.context_id} got rejected and will be rerouted to a '{agent_name}'.",
|
|
111
|
+
extra={"card": agent_response.agent_card})
|
|
112
|
+
artifact = new_text_artifact(name='target_agent', description='New target agent for request.',
|
|
113
|
+
text=agent_response.agent_card)
|
|
114
|
+
|
|
115
|
+
# publish actual result
|
|
116
|
+
await event_queue.enqueue_event(TaskArtifactUpdateEvent(append=False,
|
|
117
|
+
context_id=context.context_id,
|
|
118
|
+
task_id=context.task_id,
|
|
119
|
+
last_chunk=True,
|
|
120
|
+
artifact=artifact))
|
|
121
|
+
# set and publish the final status
|
|
122
|
+
await event_queue.enqueue_event(TaskStatusUpdateEvent(status=TaskStatus(
|
|
123
|
+
state=TaskState(agent_response.status)),
|
|
124
|
+
final=True,
|
|
125
|
+
context_id=context.context_id,
|
|
126
|
+
task_id=context.task_id))
|
|
@@ -49,6 +49,13 @@ class AgentConfig(BaseModel):
|
|
|
49
49
|
agent: AgentItem = Field(description="The agent configuration node")
|
|
50
50
|
|
|
51
51
|
|
|
52
|
+
class RouterItem(BaseModel):
|
|
53
|
+
card: CardConfig = Field(description="The router card configuration node")
|
|
54
|
+
llm: LLMConfig = Field(description="The LLM configuration node")
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
class RouterConfig(BaseModel):
|
|
58
|
+
router: RouterItem = Field(description="The router configuration node")
|
|
52
59
|
|
|
53
60
|
def get_model(api_key: str, model: str, base_url: str, reasoning_effort: str) -> BaseChatModel:
|
|
54
61
|
return ChatOpenAI(
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
from typing import Any
|
|
2
|
+
|
|
3
|
+
from a2a.server.apps import A2ARESTFastAPIApplication
|
|
4
|
+
from a2a.server.request_handlers import DefaultRequestHandler
|
|
5
|
+
from a2a.server.tasks import InMemoryTaskStore
|
|
6
|
+
from a2a.types import AgentCard
|
|
7
|
+
from fastapi import FastAPI
|
|
8
|
+
|
|
9
|
+
from distributed_a2a.distributed_a2a.executors import RoutingExecutor
|
|
10
|
+
from distributed_a2a.distributed_a2a.model import RouterConfig
|
|
11
|
+
from distributed_a2a.distributed_a2a.registry import DynamoDbRegistryLookup
|
|
12
|
+
from distributed_a2a.distributed_a2a.server import CAPABILITIES, AGENT_CARD_TABLE
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def load_router(router_dic: dict[str, Any]) -> FastAPI:
|
|
16
|
+
router_config = RouterConfig.model_validate(router_dic)
|
|
17
|
+
agent_card = AgentCard(
|
|
18
|
+
name="Router",
|
|
19
|
+
description="Agent to redirect to the best matching agent based on the agent card",
|
|
20
|
+
url="",
|
|
21
|
+
version="1.0.0",
|
|
22
|
+
default_input_modes=router_config.agent.card.default_input_modes,
|
|
23
|
+
default_output_modes=router_config.agent.card.default_output_modes,
|
|
24
|
+
skills=[],
|
|
25
|
+
preferred_transport=router_config.agent.card.preferred_transport_protocol,
|
|
26
|
+
capabilities=CAPABILITIES
|
|
27
|
+
)
|
|
28
|
+
executor = RoutingExecutor(
|
|
29
|
+
router_config=router_config,
|
|
30
|
+
routing_tool=DynamoDbRegistryLookup(agent_card_tabel=AGENT_CARD_TABLE).as_tool()
|
|
31
|
+
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
return A2ARESTFastAPIApplication(
|
|
35
|
+
agent_card=agent_card,
|
|
36
|
+
http_handler=DefaultRequestHandler(
|
|
37
|
+
agent_executor=executor,
|
|
38
|
+
task_store=InMemoryTaskStore() # TODO replace with dynamodb store
|
|
39
|
+
|
|
40
|
+
)).build(title=agent_card.name,
|
|
41
|
+
root_path=f"/{router_config.agent.card.name}")
|
|
@@ -10,8 +10,8 @@ distributed_a2a/client.py
|
|
|
10
10
|
distributed_a2a/executors.py
|
|
11
11
|
distributed_a2a/model.py
|
|
12
12
|
distributed_a2a/registry.py
|
|
13
|
+
distributed_a2a/router.py
|
|
13
14
|
distributed_a2a/server.py
|
|
14
|
-
distributed_a2a/tool_registry_test.py
|
|
15
15
|
distributed_a2a.egg-info/PKG-INFO
|
|
16
16
|
distributed_a2a.egg-info/SOURCES.txt
|
|
17
17
|
distributed_a2a.egg-info/dependency_links.txt
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{distributed_a2a-0.1.5rc19 → distributed_a2a-0.1.6rc1}/distributed_a2a.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
{distributed_a2a-0.1.5rc19 → distributed_a2a-0.1.6rc1}/distributed_a2a.egg-info/requires.txt
RENAMED
|
File without changes
|
{distributed_a2a-0.1.5rc19 → distributed_a2a-0.1.6rc1}/distributed_a2a.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|