a2a workflows fix (#1860)

This commit is contained in:
Giles Odigwe
2025-11-03 10:47:09 -08:00
committed by GitHub
Unverified
parent e462d209fd
commit a766a81243
2 changed files with 56 additions and 3 deletions
@@ -127,7 +127,21 @@ class A2AAgent(BaseAgent):
)
factory = ClientFactory(config)
interceptors = [auth_interceptor] if auth_interceptor is not None else None
self.client = factory.create(agent_card, interceptors=interceptors) # type: ignore
# Attempt transport negotiation with the provided agent card
try:
self.client = factory.create(agent_card, interceptors=interceptors) # type: ignore
except Exception as transport_error:
# Transport negotiation failed - fall back to minimal agent card with JSONRPC
fallback_card = minimal_agent_card(agent_card.url, [TransportProtocol.jsonrpc])
try:
self.client = factory.create(fallback_card, interceptors=interceptors) # type: ignore
except Exception as fallback_error:
raise RuntimeError(
f"A2A transport negotiation failed. "
f"Primary error: {transport_error}. "
f"Fallback error: {fallback_error}"
) from transport_error
async def __aenter__(self) -> "A2AAgent":
"""Async context manager entry."""
+41 -2
View File
@@ -2,10 +2,22 @@
from collections.abc import AsyncIterator
from typing import Any
from unittest.mock import AsyncMock, MagicMock
from unittest.mock import AsyncMock, MagicMock, patch
from uuid import uuid4
from a2a.types import Artifact, DataPart, FilePart, FileWithUri, Message, Part, Task, TaskState, TaskStatus, TextPart
from a2a.types import (
AgentCard,
Artifact,
DataPart,
FilePart,
FileWithUri,
Message,
Part,
Task,
TaskState,
TaskStatus,
TextPart,
)
from a2a.types import Role as A2ARole
from agent_framework import (
AgentRunResponse,
@@ -515,3 +527,30 @@ def test_auth_interceptor_parameter() -> None:
# Verify the agent was created successfully
assert agent.name == "test-agent"
assert agent.client is not None
def test_transport_negotiation_both_fail() -> None:
"""Test that RuntimeError is raised when both primary and fallback transport negotiation fail."""
# Create a mock agent card
mock_agent_card = MagicMock(spec=AgentCard)
mock_agent_card.url = "http://test-agent.example.com"
# Mock the factory to simulate both primary and fallback failures
mock_factory = MagicMock()
# Both calls to factory.create() fail
primary_error = Exception("no compatible transports found")
fallback_error = Exception("fallback also failed")
mock_factory.create.side_effect = [primary_error, fallback_error]
with (
patch("agent_framework_a2a._agent.ClientFactory", return_value=mock_factory),
patch("agent_framework_a2a._agent.minimal_agent_card"),
patch("agent_framework_a2a._agent.httpx.AsyncClient"),
raises(RuntimeError, match="A2A transport negotiation failed"),
):
# Attempt to create A2AAgent - should raise RuntimeError
A2AAgent(
name="test-agent",
agent_card=mock_agent_card,
)