mirror of
https://github.com/crewAIInc/crewAI.git
synced 2026-01-28 09:38:17 +00:00
feat: additional a2a transports
Some checks failed
CodeQL Advanced / Analyze (actions) (push) Has been cancelled
CodeQL Advanced / Analyze (python) (push) Has been cancelled
Check Documentation Broken Links / Check broken links (push) Has been cancelled
Notify Downstream / notify-downstream (push) Has been cancelled
Mark stale issues and pull requests / stale (push) Has been cancelled
Some checks failed
CodeQL Advanced / Analyze (actions) (push) Has been cancelled
CodeQL Advanced / Analyze (python) (push) Has been cancelled
Check Documentation Broken Links / Check broken links (push) Has been cancelled
Notify Downstream / notify-downstream (push) Has been cancelled
Mark stale issues and pull requests / stale (push) Has been cancelled
Co-authored-by: Koushiv Sadhukhan <koushiv.777@gmail.com> Co-authored-by: Greyson LaLonde <greyson.r.lalonde@gmail.com>
This commit is contained in:
@@ -91,6 +91,10 @@ The `A2AConfig` class accepts the following parameters:
|
|||||||
Update mechanism for receiving task status. Options: `StreamingConfig`, `PollingConfig`, or `PushNotificationConfig`.
|
Update mechanism for receiving task status. Options: `StreamingConfig`, `PollingConfig`, or `PushNotificationConfig`.
|
||||||
</ParamField>
|
</ParamField>
|
||||||
|
|
||||||
|
<ParamField path="transport_protocol" type="Literal['JSONRPC', 'GRPC', 'HTTP+JSON']" default="JSONRPC">
|
||||||
|
Transport protocol for A2A communication. Options: `JSONRPC` (default), `GRPC`, or `HTTP+JSON`.
|
||||||
|
</ParamField>
|
||||||
|
|
||||||
## Authentication
|
## Authentication
|
||||||
|
|
||||||
For A2A agents that require authentication, use one of the provided auth schemes:
|
For A2A agents that require authentication, use one of the provided auth schemes:
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ This module is separate from experimental.a2a to avoid circular imports.
|
|||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from typing import Annotated, Any, ClassVar
|
from typing import Annotated, Any, ClassVar, Literal
|
||||||
|
|
||||||
from pydantic import (
|
from pydantic import (
|
||||||
BaseModel,
|
BaseModel,
|
||||||
@@ -53,6 +53,7 @@ class A2AConfig(BaseModel):
|
|||||||
fail_fast: If True, raise error when agent unreachable; if False, skip and continue.
|
fail_fast: If True, raise error when agent unreachable; if False, skip and continue.
|
||||||
trust_remote_completion_status: If True, return A2A agent's result directly when completed.
|
trust_remote_completion_status: If True, return A2A agent's result directly when completed.
|
||||||
updates: Update mechanism config.
|
updates: Update mechanism config.
|
||||||
|
transport_protocol: A2A transport protocol (grpc, jsonrpc, http+json).
|
||||||
"""
|
"""
|
||||||
|
|
||||||
model_config: ClassVar[ConfigDict] = ConfigDict(extra="forbid")
|
model_config: ClassVar[ConfigDict] = ConfigDict(extra="forbid")
|
||||||
@@ -82,3 +83,7 @@ class A2AConfig(BaseModel):
|
|||||||
default_factory=_get_default_update_config,
|
default_factory=_get_default_update_config,
|
||||||
description="Update mechanism config",
|
description="Update mechanism config",
|
||||||
)
|
)
|
||||||
|
transport_protocol: Literal["JSONRPC", "GRPC", "HTTP+JSON"] = Field(
|
||||||
|
default="JSONRPC",
|
||||||
|
description="Specified mode of A2A transport protocol",
|
||||||
|
)
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ from collections.abc import AsyncIterator, MutableMapping
|
|||||||
from contextlib import asynccontextmanager
|
from contextlib import asynccontextmanager
|
||||||
from functools import lru_cache
|
from functools import lru_cache
|
||||||
import time
|
import time
|
||||||
from typing import TYPE_CHECKING, Any
|
from typing import TYPE_CHECKING, Any, Literal
|
||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
from a2a.client import A2AClientHTTPError, Client, ClientConfig, ClientFactory
|
from a2a.client import A2AClientHTTPError, Client, ClientConfig, ClientFactory
|
||||||
@@ -18,7 +18,6 @@ from a2a.types import (
|
|||||||
PushNotificationConfig as A2APushNotificationConfig,
|
PushNotificationConfig as A2APushNotificationConfig,
|
||||||
Role,
|
Role,
|
||||||
TextPart,
|
TextPart,
|
||||||
TransportProtocol,
|
|
||||||
)
|
)
|
||||||
from aiocache import cached # type: ignore[import-untyped]
|
from aiocache import cached # type: ignore[import-untyped]
|
||||||
from aiocache.serializers import PickleSerializer # type: ignore[import-untyped]
|
from aiocache.serializers import PickleSerializer # type: ignore[import-untyped]
|
||||||
@@ -259,6 +258,7 @@ async def _afetch_agent_card_impl(
|
|||||||
|
|
||||||
def execute_a2a_delegation(
|
def execute_a2a_delegation(
|
||||||
endpoint: str,
|
endpoint: str,
|
||||||
|
transport_protocol: Literal["JSONRPC", "GRPC", "HTTP+JSON"],
|
||||||
auth: AuthScheme | None,
|
auth: AuthScheme | None,
|
||||||
timeout: int,
|
timeout: int,
|
||||||
task_description: str,
|
task_description: str,
|
||||||
@@ -282,6 +282,23 @@ def execute_a2a_delegation(
|
|||||||
use aexecute_a2a_delegation directly.
|
use aexecute_a2a_delegation directly.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
|
endpoint: A2A agent endpoint URL (AgentCard URL)
|
||||||
|
transport_protocol: Optional A2A transport protocol (grpc, jsonrpc, http+json)
|
||||||
|
auth: Optional AuthScheme for authentication (Bearer, OAuth2, API Key, HTTP Basic/Digest)
|
||||||
|
timeout: Request timeout in seconds
|
||||||
|
task_description: The task to delegate
|
||||||
|
context: Optional context information
|
||||||
|
context_id: Context ID for correlating messages/tasks
|
||||||
|
task_id: Specific task identifier
|
||||||
|
reference_task_ids: List of related task IDs
|
||||||
|
metadata: Additional metadata (external_id, request_id, etc.)
|
||||||
|
extensions: Protocol extensions for custom fields
|
||||||
|
conversation_history: Previous Message objects from conversation
|
||||||
|
agent_id: Agent identifier for logging
|
||||||
|
agent_role: Role of the CrewAI agent delegating the task
|
||||||
|
agent_branch: Optional agent tree branch for logging
|
||||||
|
response_model: Optional Pydantic model for structured outputs
|
||||||
|
turn_number: Optional turn number for multi-turn conversations
|
||||||
endpoint: A2A agent endpoint URL.
|
endpoint: A2A agent endpoint URL.
|
||||||
auth: Optional AuthScheme for authentication.
|
auth: Optional AuthScheme for authentication.
|
||||||
timeout: Request timeout in seconds.
|
timeout: Request timeout in seconds.
|
||||||
@@ -323,6 +340,7 @@ def execute_a2a_delegation(
|
|||||||
agent_role=agent_role,
|
agent_role=agent_role,
|
||||||
agent_branch=agent_branch,
|
agent_branch=agent_branch,
|
||||||
response_model=response_model,
|
response_model=response_model,
|
||||||
|
transport_protocol=transport_protocol,
|
||||||
turn_number=turn_number,
|
turn_number=turn_number,
|
||||||
updates=updates,
|
updates=updates,
|
||||||
)
|
)
|
||||||
@@ -333,6 +351,7 @@ def execute_a2a_delegation(
|
|||||||
|
|
||||||
async def aexecute_a2a_delegation(
|
async def aexecute_a2a_delegation(
|
||||||
endpoint: str,
|
endpoint: str,
|
||||||
|
transport_protocol: Literal["JSONRPC", "GRPC", "HTTP+JSON"],
|
||||||
auth: AuthScheme | None,
|
auth: AuthScheme | None,
|
||||||
timeout: int,
|
timeout: int,
|
||||||
task_description: str,
|
task_description: str,
|
||||||
@@ -356,6 +375,23 @@ async def aexecute_a2a_delegation(
|
|||||||
in an async context (e.g., with Crew.akickoff() or agent.aexecute_task()).
|
in an async context (e.g., with Crew.akickoff() or agent.aexecute_task()).
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
|
endpoint: A2A agent endpoint URL
|
||||||
|
transport_protocol: Optional A2A transport protocol (grpc, jsonrpc, http+json)
|
||||||
|
auth: Optional AuthScheme for authentication
|
||||||
|
timeout: Request timeout in seconds
|
||||||
|
task_description: Task to delegate
|
||||||
|
context: Optional context
|
||||||
|
context_id: Context ID for correlation
|
||||||
|
task_id: Specific task identifier
|
||||||
|
reference_task_ids: Related task IDs
|
||||||
|
metadata: Additional metadata
|
||||||
|
extensions: Protocol extensions
|
||||||
|
conversation_history: Previous Message objects
|
||||||
|
turn_number: Current turn number
|
||||||
|
agent_branch: Agent tree branch for logging
|
||||||
|
agent_id: Agent identifier for logging
|
||||||
|
agent_role: Agent role for logging
|
||||||
|
response_model: Optional Pydantic model for structured outputs
|
||||||
endpoint: A2A agent endpoint URL.
|
endpoint: A2A agent endpoint URL.
|
||||||
auth: Optional AuthScheme for authentication.
|
auth: Optional AuthScheme for authentication.
|
||||||
timeout: Request timeout in seconds.
|
timeout: Request timeout in seconds.
|
||||||
@@ -414,6 +450,7 @@ async def aexecute_a2a_delegation(
|
|||||||
agent_role=agent_role,
|
agent_role=agent_role,
|
||||||
response_model=response_model,
|
response_model=response_model,
|
||||||
updates=updates,
|
updates=updates,
|
||||||
|
transport_protocol=transport_protocol,
|
||||||
)
|
)
|
||||||
|
|
||||||
crewai_event_bus.emit(
|
crewai_event_bus.emit(
|
||||||
@@ -431,6 +468,7 @@ async def aexecute_a2a_delegation(
|
|||||||
|
|
||||||
async def _aexecute_a2a_delegation_impl(
|
async def _aexecute_a2a_delegation_impl(
|
||||||
endpoint: str,
|
endpoint: str,
|
||||||
|
transport_protocol: Literal["JSONRPC", "GRPC", "HTTP+JSON"],
|
||||||
auth: AuthScheme | None,
|
auth: AuthScheme | None,
|
||||||
timeout: int,
|
timeout: int,
|
||||||
task_description: str,
|
task_description: str,
|
||||||
@@ -524,7 +562,6 @@ async def _aexecute_a2a_delegation_impl(
|
|||||||
extensions=extensions,
|
extensions=extensions,
|
||||||
)
|
)
|
||||||
|
|
||||||
transport_protocol = TransportProtocol("JSONRPC")
|
|
||||||
new_messages: list[Message] = [*conversation_history, message]
|
new_messages: list[Message] = [*conversation_history, message]
|
||||||
crewai_event_bus.emit(
|
crewai_event_bus.emit(
|
||||||
None,
|
None,
|
||||||
@@ -596,7 +633,7 @@ async def _aexecute_a2a_delegation_impl(
|
|||||||
@asynccontextmanager
|
@asynccontextmanager
|
||||||
async def _create_a2a_client(
|
async def _create_a2a_client(
|
||||||
agent_card: AgentCard,
|
agent_card: AgentCard,
|
||||||
transport_protocol: TransportProtocol,
|
transport_protocol: Literal["JSONRPC", "GRPC", "HTTP+JSON"],
|
||||||
timeout: int,
|
timeout: int,
|
||||||
headers: MutableMapping[str, str],
|
headers: MutableMapping[str, str],
|
||||||
streaming: bool,
|
streaming: bool,
|
||||||
@@ -640,7 +677,7 @@ async def _create_a2a_client(
|
|||||||
|
|
||||||
config = ClientConfig(
|
config = ClientConfig(
|
||||||
httpx_client=httpx_client,
|
httpx_client=httpx_client,
|
||||||
supported_transports=[str(transport_protocol.value)],
|
supported_transports=[transport_protocol],
|
||||||
streaming=streaming and not use_polling,
|
streaming=streaming and not use_polling,
|
||||||
polling=use_polling,
|
polling=use_polling,
|
||||||
accepted_output_modes=["application/json"],
|
accepted_output_modes=["application/json"],
|
||||||
|
|||||||
@@ -771,6 +771,7 @@ def _delegate_to_a2a(
|
|||||||
response_model=agent_config.response_model,
|
response_model=agent_config.response_model,
|
||||||
turn_number=turn_num + 1,
|
turn_number=turn_num + 1,
|
||||||
updates=agent_config.updates,
|
updates=agent_config.updates,
|
||||||
|
transport_protocol=agent_config.transport_protocol,
|
||||||
)
|
)
|
||||||
|
|
||||||
conversation_history = a2a_result.get("history", [])
|
conversation_history = a2a_result.get("history", [])
|
||||||
@@ -1085,6 +1086,7 @@ async def _adelegate_to_a2a(
|
|||||||
agent_branch=agent_branch,
|
agent_branch=agent_branch,
|
||||||
response_model=agent_config.response_model,
|
response_model=agent_config.response_model,
|
||||||
turn_number=turn_num + 1,
|
turn_number=turn_num + 1,
|
||||||
|
transport_protocol=agent_config.transport_protocol,
|
||||||
updates=agent_config.updates,
|
updates=agent_config.updates,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user