aigency 0.0.1rc235167702__tar.gz → 0.0.1rc238211992__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 (32) hide show
  1. {aigency-0.0.1rc235167702 → aigency-0.0.1rc238211992}/PKG-INFO +1 -1
  2. aigency-0.0.1rc238211992/aigency/agents/client.py +59 -0
  3. aigency-0.0.1rc238211992/aigency/agents/communicator.py +121 -0
  4. aigency-0.0.1rc238211992/aigency/agents/generator.py +138 -0
  5. {aigency-0.0.1rc235167702 → aigency-0.0.1rc238211992}/aigency/schemas/agent/agent.py +6 -2
  6. aigency-0.0.1rc238211992/aigency/schemas/agent/remote_agent.py +9 -0
  7. {aigency-0.0.1rc235167702 → aigency-0.0.1rc238211992}/aigency/schemas/agent/tools.py +19 -5
  8. {aigency-0.0.1rc235167702 → aigency-0.0.1rc238211992}/aigency/utils/utils.py +19 -1
  9. {aigency-0.0.1rc235167702 → aigency-0.0.1rc238211992}/aigency.egg-info/PKG-INFO +1 -1
  10. {aigency-0.0.1rc235167702 → aigency-0.0.1rc238211992}/aigency.egg-info/SOURCES.txt +3 -0
  11. {aigency-0.0.1rc235167702 → aigency-0.0.1rc238211992}/pyproject.toml +1 -1
  12. aigency-0.0.1rc235167702/aigency/agents/generator.py +0 -75
  13. {aigency-0.0.1rc235167702 → aigency-0.0.1rc238211992}/README.md +0 -0
  14. {aigency-0.0.1rc235167702 → aigency-0.0.1rc238211992}/aigency/__init__.py +0 -0
  15. {aigency-0.0.1rc235167702 → aigency-0.0.1rc238211992}/aigency/agents/executor.py +0 -0
  16. {aigency-0.0.1rc235167702 → aigency-0.0.1rc238211992}/aigency/schemas/agent/model.py +0 -0
  17. {aigency-0.0.1rc235167702 → aigency-0.0.1rc238211992}/aigency/schemas/agent/skills.py +0 -0
  18. {aigency-0.0.1rc235167702 → aigency-0.0.1rc238211992}/aigency/schemas/aigency_config.py +0 -0
  19. {aigency-0.0.1rc235167702 → aigency-0.0.1rc238211992}/aigency/schemas/metadata/metadata.py +0 -0
  20. {aigency-0.0.1rc235167702 → aigency-0.0.1rc238211992}/aigency/schemas/observability/observability.py +0 -0
  21. {aigency-0.0.1rc235167702 → aigency-0.0.1rc238211992}/aigency/schemas/observability/phoenix.py +0 -0
  22. {aigency-0.0.1rc235167702 → aigency-0.0.1rc238211992}/aigency/schemas/service/capabilities.py +0 -0
  23. {aigency-0.0.1rc235167702 → aigency-0.0.1rc238211992}/aigency/schemas/service/interface.py +0 -0
  24. {aigency-0.0.1rc235167702 → aigency-0.0.1rc238211992}/aigency/schemas/service/service.py +0 -0
  25. {aigency-0.0.1rc235167702 → aigency-0.0.1rc238211992}/aigency/tools/generator.py +0 -0
  26. {aigency-0.0.1rc235167702 → aigency-0.0.1rc238211992}/aigency/utils/config_service.py +0 -0
  27. {aigency-0.0.1rc235167702 → aigency-0.0.1rc238211992}/aigency/utils/logger.py +0 -0
  28. {aigency-0.0.1rc235167702 → aigency-0.0.1rc238211992}/aigency/utils/singleton.py +0 -0
  29. {aigency-0.0.1rc235167702 → aigency-0.0.1rc238211992}/aigency.egg-info/dependency_links.txt +0 -0
  30. {aigency-0.0.1rc235167702 → aigency-0.0.1rc238211992}/aigency.egg-info/requires.txt +0 -0
  31. {aigency-0.0.1rc235167702 → aigency-0.0.1rc238211992}/aigency.egg-info/top_level.txt +0 -0
  32. {aigency-0.0.1rc235167702 → aigency-0.0.1rc238211992}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: aigency
3
- Version: 0.0.1rc235167702
3
+ Version: 0.0.1rc238211992
4
4
  Summary: Add your description here
5
5
  Requires-Python: >=3.12
6
6
  Description-Content-Type: text/markdown
@@ -0,0 +1,59 @@
1
+ import httpx
2
+
3
+ from a2a.client.client import ClientConfig
4
+ from a2a.client.client_factory import ClientFactory
5
+ from a2a.types import AgentCard, Message, SendMessageResponse
6
+ #TODO: Enable when auth is implemented
7
+ #from a2a.client.auth.interceptor import AuthInterceptor
8
+
9
+
10
+ class AgentClient:
11
+ """A class to hold the connections to the remote agents.
12
+
13
+ This class manages connections to remote agents using the A2A protocol.
14
+ It provides methods for retrieving agent information and sending messages
15
+ to remote agents.
16
+
17
+ Attributes:
18
+ _httpx_client (httpx.AsyncClient): The HTTP client used for asynchronous requests.
19
+ agent_card (AgentCard): The agent card containing metadata about the remote agent.
20
+ """
21
+
22
+ def __init__(self, agent_card: AgentCard):
23
+ """Initialize a connection to a remote agent.
24
+
25
+ Args:
26
+ agent_card (AgentCard): The agent card containing metadata about the remote agent.
27
+
28
+ Raises:
29
+ None
30
+
31
+ Returns:
32
+ None
33
+ """
34
+ self._httpx_client = httpx.AsyncClient(timeout=60)
35
+ self.card = agent_card
36
+
37
+ config = ClientConfig(httpx_client=self._httpx_client)
38
+ factory = ClientFactory(config=config)
39
+ self.agent_client = factory.create(agent_card)
40
+
41
+ def get_agent(self) -> AgentCard:
42
+ """Get the agent card for this remote agent connection.
43
+
44
+ Returns:
45
+ AgentCard: The agent card containing metadata about the remote agent.
46
+ """
47
+ return self.card
48
+
49
+ async def send_message(self, message_request: Message) -> SendMessageResponse:
50
+ """Send a message to the remote agent.
51
+
52
+ Args:
53
+ message_request (Message): The message request to send to the remote agent.
54
+
55
+ Returns:
56
+ SendMessageResponse: The response from the remote agent.
57
+ """
58
+ async for response in self.agent_client.send_message(message_request):
59
+ yield response
@@ -0,0 +1,121 @@
1
+ import uuid
2
+ from typing import Any, Awaitable, List
3
+
4
+ from a2a.types import Message, Task
5
+ from google.adk.tools.tool_context import ToolContext
6
+
7
+ from aigency.utils.logger import get_logger
8
+
9
+ logger = get_logger()
10
+
11
+ class Communicator:
12
+ """Clase base para la comunicación entre agentes (Agent-to-Agent)."""
13
+
14
+ def __init__(self, remote_agent_connections: dict[str, Any] | None = None):
15
+ """Inicializa el comunicador con las conexiones a los agentes remotos.
16
+
17
+ Args:
18
+ remote_agent_connections: Un diccionario que mapea nombres de agentes
19
+ a sus objetos de conexión de cliente.
20
+ """
21
+ self.remote_agent_connections: dict[str, Any] = remote_agent_connections or {}
22
+
23
+ async def send_message(
24
+ self, agent_name: str, task: str, tool_context: ToolContext
25
+ ) -> Awaitable[Task | None]:
26
+ """Delega una tarea a un agente remoto específico.
27
+
28
+ Este método envía un mensaje a un agente remoto, solicitando que realice una
29
+ tarea. Gestiona la creación del payload del mensaje y la comunicación.
30
+
31
+ Args:
32
+ agent_name: Nombre del agente remoto al que se envía la tarea.
33
+ task: Descripción detallada de la tarea para el agente remoto.
34
+ tool_context: Objeto de contexto que contiene el estado y otra información.
35
+
36
+ Returns:
37
+ Un objeto Task si la comunicación es exitosa, o None en caso contrario.
38
+
39
+ Raises:
40
+ ValueError: Si el agente especificado no se encuentra en las conexiones.
41
+ """
42
+ logger.info(
43
+ f"`send_message` iniciado para el agente: '{agent_name}' con la tarea: '{task}'"
44
+ )
45
+ client = self.remote_agent_connections.get(agent_name)
46
+ if not client:
47
+ available_agents = list(self.remote_agent_connections.keys())
48
+ logger.error(
49
+ f"El LLM intentó llamar a '{agent_name}', pero no se encontró. "
50
+ f"Agentes disponibles: {available_agents}"
51
+ )
52
+ raise ValueError(f"Agente '{agent_name}' no encontrado. Agentes disponibles: {available_agents}")
53
+
54
+ state = tool_context.state
55
+
56
+ # Simplifica la creación y obtención de contextos de agente usando setdefault
57
+ contexts = state.setdefault("remote_agent_contexts", {})
58
+ agent_context = contexts.setdefault(agent_name, {"context_id": str(uuid.uuid4())})
59
+ context_id = agent_context["context_id"]
60
+
61
+ # Obtiene IDs de forma más segura y clara
62
+ task_id = state.get("task_id")
63
+ input_metadata = state.get("input_message_metadata", {})
64
+ message_id = input_metadata.get("message_id")
65
+
66
+ # El message_id se pasa directamente al creador del payload
67
+ payload = self.create_send_message_payload(
68
+ text=task, task_id=task_id, context_id=context_id, message_id=message_id
69
+ )
70
+ logger.debug("`send_message` con el siguiente payload: %s", payload)
71
+
72
+ send_response = None
73
+ # Este bucle está diseñado para consumir un generador asíncrono y obtener
74
+ # la última respuesta, que suele ser el resultado final.
75
+ async for resp in client.send_message(
76
+ message_request=Message(**payload["message"])
77
+ ):
78
+ send_response = resp
79
+
80
+ if isinstance(send_response, tuple):
81
+ send_response, _ = send_response
82
+
83
+ if not isinstance(send_response, Task):
84
+ logger.warning(
85
+ f"La respuesta recibida del agente '{agent_name}' no es un objeto Task. "
86
+ f"Tipo recibido: {type(send_response)}"
87
+ )
88
+ return None
89
+
90
+ return send_response
91
+
92
+ @staticmethod
93
+ def create_send_message_payload(
94
+ text: str,
95
+ task_id: str | None = None,
96
+ context_id: str | None = None,
97
+ message_id: str | None = None,
98
+ ) -> dict[str, Any]:
99
+ """Crea el payload de un mensaje para enviarlo a un agente remoto.
100
+
101
+ Args:
102
+ text: El contenido de texto del mensaje.
103
+ task_id: ID de tarea opcional para asociar con el mensaje.
104
+ context_id: ID de contexto opcional para asociar con el mensaje.
105
+ message_id: ID de mensaje opcional. Si es None, se generará uno nuevo.
106
+
107
+ Returns:
108
+ Un diccionario que contiene el payload del mensaje formateado.
109
+ """
110
+ payload: dict[str, Any] = {
111
+ "message": {
112
+ "role": "user",
113
+ "parts": [{"type": "text", "text": text}],
114
+ "message_id": message_id or uuid.uuid4().hex,
115
+ },
116
+ }
117
+ if task_id:
118
+ payload["message"]["task_id"] = task_id
119
+ if context_id:
120
+ payload["message"]["context_id"] = context_id
121
+ return payload
@@ -0,0 +1,138 @@
1
+ import logging
2
+ import httpx
3
+ from typing import List
4
+ import asyncio
5
+
6
+ from a2a.types import AgentCapabilities, AgentCard, AgentSkill
7
+ from a2a.client import A2ACardResolver
8
+ from google.adk.agents import Agent
9
+ from google.adk.artifacts import InMemoryArtifactService
10
+ from google.adk.memory.in_memory_memory_service import InMemoryMemoryService
11
+ from google.adk.runners import Runner
12
+ from google.adk.sessions import InMemorySessionService
13
+
14
+ from aigency.agents.executor import AgentA2AExecutor
15
+ from aigency.agents.client import AgentClient
16
+ from aigency.schemas.aigency_config import AigencyConfig
17
+ from aigency.schemas.agent.remote_agent import RemoteAgent
18
+ from aigency.tools.generator import ToolGenerator
19
+ from aigency.utils.utils import generate_url, safe_async_run
20
+ from aigency.agents.communicator import Communicator
21
+ from aigency.utils.logger import get_logger
22
+
23
+ logger = get_logger()
24
+
25
+ class AgentA2AGenerator:
26
+
27
+ @staticmethod
28
+ def create_agent(agent_config: AigencyConfig) -> Agent:
29
+
30
+ tools = [
31
+ ToolGenerator.create_tool(tool_cfg) for tool_cfg in agent_config.agent.tools
32
+ ]
33
+
34
+ remote_agents = agent_config.agent.remote_agents
35
+ if remote_agents:
36
+ remote_agent_connections = AgentA2AGenerator.build_remote_agent_connections(
37
+ agent_config
38
+ )
39
+ logger.info(f"Remote agent connections: {remote_agent_connections}")
40
+ communicator = Communicator(
41
+ remote_agent_connections=remote_agent_connections
42
+ )
43
+ tools.append(communicator.send_message)
44
+
45
+ return Agent(
46
+ name=agent_config.metadata.name,
47
+ model=agent_config.agent.model.name,
48
+ instruction=agent_config.agent.instruction,
49
+ tools=tools,
50
+ )
51
+
52
+ @staticmethod
53
+ def build_agent_card(agent_config: AigencyConfig) -> AgentCard:
54
+
55
+ # TODO: Parse properly
56
+ capabilities = AgentCapabilities(
57
+ streaming=agent_config.service.capabilities.streaming
58
+ )
59
+
60
+ skills = [
61
+ AgentSkill(
62
+ id=skill.id,
63
+ name=skill.name,
64
+ description=skill.description,
65
+ tags=skill.tags,
66
+ examples=skill.examples,
67
+ )
68
+ for skill in agent_config.agent.skills
69
+ ]
70
+
71
+ return AgentCard(
72
+ name=agent_config.metadata.name,
73
+ description=agent_config.metadata.description,
74
+ url=agent_config.service.url,
75
+ version=agent_config.metadata.version,
76
+ default_input_modes=agent_config.service.interface.default_input_modes,
77
+ default_output_modes=agent_config.service.interface.default_output_modes,
78
+ capabilities=capabilities,
79
+ skills=skills,
80
+ )
81
+
82
+ @staticmethod
83
+ def build_executor(agent: Agent, agent_card: AgentCard) -> AgentA2AExecutor:
84
+
85
+ runner = Runner(
86
+ app_name=agent.name,
87
+ agent=agent,
88
+ artifact_service=InMemoryArtifactService(),
89
+ session_service=InMemorySessionService(),
90
+ memory_service=InMemoryMemoryService(),
91
+ )
92
+
93
+ return AgentA2AExecutor(runner=runner, card=agent_card)
94
+
95
+ @staticmethod
96
+ def build_remote_agent_connections(agent_config: AigencyConfig):
97
+ """Initialize connections to all remote agents asynchronously.
98
+
99
+ Tests each connection individually with detailed logging to help identify
100
+ any connection issues. It attempts to connect to each remote agent address,
101
+ retrieve its agent card, and store the connection for later use.
102
+
103
+ Raises:
104
+ No exceptions are raised, but errors are logged.
105
+ """
106
+
107
+ if not agent_config.agent.remote_agents:
108
+ return {}
109
+
110
+ remote_agent_configs = [
111
+ {"url": generate_url(host=remote_agent.host, port=remote_agent.port)}
112
+ for remote_agent in agent_config.agent.remote_agents
113
+ ]
114
+
115
+ async def _connect():
116
+ remote_agent_connections = {}
117
+ async with httpx.AsyncClient(timeout=60) as client:
118
+ for config in remote_agent_configs:
119
+ address = config.get("url")
120
+ logger.debug(f"--- Attempting connection to: {address} ---")
121
+ try:
122
+ card_resolver = A2ACardResolver(client, address)
123
+ card = await card_resolver.get_agent_card()
124
+ remote_connection = AgentClient(agent_card=card)
125
+ remote_agent_connections[card.name] = remote_connection
126
+ except Exception as e:
127
+ logger.error(
128
+ f"--- CRITICAL FAILURE for address: {address} ---",
129
+ exc_info=True,
130
+ )
131
+ raise e
132
+ return remote_agent_connections
133
+
134
+ try:
135
+ return safe_async_run(_connect())
136
+ except Exception as e:
137
+ logger.error("--- CRITICAL FAILURE", exc_info=True)
138
+ raise e
@@ -2,11 +2,15 @@ from pydantic import BaseModel
2
2
  from typing import List, Optional
3
3
  from aigency.schemas.agent.model import AgentModel
4
4
  from aigency.schemas.agent.skills import Skill
5
- from aigency.schemas.agent.tools import FunctionTool, McpTool
5
+ from aigency.schemas.agent.tools import Tool
6
+ from aigency.schemas.agent.remote_agent import RemoteAgent
7
+
6
8
 
7
9
  class Agent(BaseModel):
8
10
  """El 'cerebro' del agente: su lógica, modelo y capacidades."""
11
+
9
12
  model: AgentModel
10
13
  instruction: str
11
14
  skills: List[Skill]
12
- tools: Optional[List[FunctionTool | McpTool]] = []
15
+ tools: Optional[List[Tool]] = []
16
+ remote_agents: Optional[List[RemoteAgent]] = []
@@ -0,0 +1,9 @@
1
+ from pydantic import BaseModel, Field
2
+
3
+
4
+ class RemoteAgent(BaseModel):
5
+ """Remote agent configuration."""
6
+
7
+ name: str
8
+ host: str
9
+ port: int = Field(..., ge=1, le=65535)
@@ -1,39 +1,53 @@
1
1
  """Tool models for agent configuration."""
2
2
 
3
3
  from enum import Enum
4
- from typing import Dict, List, Optional
4
+ from typing import Dict, List, Optional, TypeAlias
5
5
 
6
6
  from pydantic import BaseModel
7
7
 
8
8
 
9
9
  class ToolType(str, Enum):
10
10
  """Enum for tool types."""
11
+
11
12
  MCP = "mcp"
12
13
  FUNCTION = "function"
13
14
 
14
- class Tool(BaseModel):
15
+
16
+ class BaseTool(BaseModel):
15
17
  """Define an external tool that the agent can use."""
18
+
16
19
  type: ToolType
17
20
  name: str
18
21
  description: str
19
22
 
20
- class FunctionTool(Tool):
23
+
24
+ class FunctionTool(BaseTool):
21
25
  """Configuration for function-based tools."""
26
+
22
27
  module_path: str
23
28
  function_name: str
24
29
 
30
+
25
31
  class McpTypeStreamable(BaseModel):
26
32
  """Model for streamable tool type."""
33
+
27
34
  url: str
28
35
  port: int
29
36
  path: str = "/"
30
37
 
38
+
31
39
  class McpTypeStdio(BaseModel):
32
40
  """Model for stdio tool type."""
41
+
33
42
  command: str
34
43
  args: List[str]
35
44
  env: Optional[Dict[str, str]] = None
36
45
 
37
- class McpTool(Tool):
46
+
47
+ class McpTool(BaseTool):
38
48
  """Configuration for MCP-based tools."""
39
- mcp_config: McpTypeStreamable | McpTypeStdio
49
+
50
+ mcp_config: McpTypeStreamable | McpTypeStdio
51
+
52
+
53
+ Tool: TypeAlias = FunctionTool | McpTool
@@ -11,6 +11,7 @@ from aigency.utils.logger import get_logger
11
11
 
12
12
  logger = get_logger()
13
13
 
14
+
14
15
  def convert_a2a_part_to_genai(part: Part) -> types.Part:
15
16
  """Convert a single A2A Part type into a Google Gen AI Part type.
16
17
 
@@ -54,6 +55,7 @@ def convert_genai_part_to_a2a(part: types.Part) -> Part:
54
55
  )
55
56
  raise ValueError(f"Unsupported part type: {part}")
56
57
 
58
+
57
59
  def expand_env_vars(env_dict):
58
60
  """
59
61
  Expande los valores del diccionario usando variables de entorno solo si el valor es una clave de entorno existente.
@@ -67,6 +69,21 @@ def expand_env_vars(env_dict):
67
69
  logger.warning(f"Environment variable {v} not found")
68
70
  return result
69
71
 
72
+
73
+ def generate_url(host: str, port: int, path: str = "") -> str:
74
+ """Generate a URL from host, port, and path components.
75
+
76
+ Args:
77
+ host (str): Hostname or IP address.
78
+ port (int): Port number.
79
+ path (str, optional): URL path. Defaults to "".
80
+
81
+ Returns:
82
+ str: Complete URL in the format http://host:port/path.
83
+ """
84
+ return f"http://{host}:{port}{path}"
85
+
86
+
70
87
  def safe_async_run(coro):
71
88
  """Simple wrapper to safely run async code."""
72
89
  try:
@@ -93,4 +110,5 @@ def safe_async_run(coro):
93
110
  else:
94
111
  return loop.run_until_complete(coro)
95
112
  except RuntimeError:
96
- return asyncio.run(coro)
113
+ return asyncio.run(coro)
114
+
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: aigency
3
- Version: 0.0.1rc235167702
3
+ Version: 0.0.1rc238211992
4
4
  Summary: Add your description here
5
5
  Requires-Python: >=3.12
6
6
  Description-Content-Type: text/markdown
@@ -6,11 +6,14 @@ aigency.egg-info/SOURCES.txt
6
6
  aigency.egg-info/dependency_links.txt
7
7
  aigency.egg-info/requires.txt
8
8
  aigency.egg-info/top_level.txt
9
+ aigency/agents/client.py
10
+ aigency/agents/communicator.py
9
11
  aigency/agents/executor.py
10
12
  aigency/agents/generator.py
11
13
  aigency/schemas/aigency_config.py
12
14
  aigency/schemas/agent/agent.py
13
15
  aigency/schemas/agent/model.py
16
+ aigency/schemas/agent/remote_agent.py
14
17
  aigency/schemas/agent/skills.py
15
18
  aigency/schemas/agent/tools.py
16
19
  aigency/schemas/metadata/metadata.py
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "aigency"
3
- version = "0.0.1rc235167702"
3
+ version = "0.0.1rc238211992"
4
4
  description = "Add your description here"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.12"
@@ -1,75 +0,0 @@
1
- """Agent generator module for creating A2A agents."""
2
-
3
- from typing import Any, Dict, List
4
-
5
- from a2a.types import AgentCapabilities, AgentCard, AgentSkill
6
- from google.adk.agents import Agent
7
- from google.adk.artifacts import InMemoryArtifactService
8
- from google.adk.memory.in_memory_memory_service import InMemoryMemoryService
9
- from google.adk.runners import Runner
10
- from google.adk.sessions import InMemorySessionService
11
-
12
- from aigency.agents.executor import AgentA2AExecutor
13
- from aigency.schemas.aigency_config import AigencyConfig
14
- from aigency.tools.generator import ToolGenerator
15
-
16
-
17
- class AgentA2AGenerator:
18
- """Generator for creating A2A agents and related components."""
19
-
20
- @staticmethod
21
- def create_agent(agent_config: AigencyConfig) -> Agent:
22
-
23
- tools = [
24
- ToolGenerator.create_tool(tool_cfg) for tool_cfg in agent_config.agent.tools
25
- ]
26
-
27
- return Agent(
28
- name=agent_config.metadata.name,
29
- model=agent_config.agent.model.name,
30
- instruction=agent_config.agent.instruction,
31
- tools=tools,
32
- )
33
-
34
- @staticmethod
35
- def build_agent_card(agent_config: AigencyConfig) -> AgentCard:
36
-
37
- # TODO: Parse properly
38
- capabilities = AgentCapabilities(
39
- streaming=agent_config.service.capabilities.streaming
40
- )
41
-
42
- skills = [
43
- AgentSkill(
44
- id=skill.id,
45
- name=skill.name,
46
- description=skill.description,
47
- tags=skill.tags,
48
- examples=skill.examples,
49
- )
50
- for skill in agent_config.agent.skills
51
- ]
52
-
53
- return AgentCard(
54
- name=agent_config.metadata.name,
55
- description=agent_config.metadata.description,
56
- url=agent_config.service.url,
57
- version=agent_config.metadata.version,
58
- default_input_modes=agent_config.service.interface.default_input_modes,
59
- default_output_modes=agent_config.service.interface.default_output_modes,
60
- capabilities=capabilities,
61
- skills=skills,
62
- )
63
-
64
- @staticmethod
65
- def build_executor(agent: Agent, agent_card: AgentCard) -> AgentA2AExecutor:
66
-
67
- runner = Runner(
68
- app_name=agent.name,
69
- agent=agent,
70
- artifact_service=InMemoryArtifactService(),
71
- session_service=InMemorySessionService(),
72
- memory_service=InMemoryMemoryService(),
73
- )
74
-
75
- return AgentA2AExecutor(runner=runner, card=agent_card)