Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ requires-python = ">=3.13"
dependencies = [
"httpx>=0.28.1",
"httpx-sse>=0.4.0",
"mypy>=1.15.0",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this was moved to dev dependencies.

"opentelemetry-api>=1.33.0",
"opentelemetry-sdk>=1.33.0",
"pydantic>=2.11.3",
Expand Down
2 changes: 2 additions & 0 deletions src/a2a/client/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@

import httpx

from httpx_sse import SSEError, aconnect_sse

Check failure on line 9 in src/a2a/client/client.py

View workflow job for this annotation

GitHub Actions / Check Spelling

`aconnect` is not a recognized word. (unrecognized-spelling)

from a2a.client.errors import A2AClientHTTPError, A2AClientJSONError

Check failure on line 11 in src/a2a/client/client.py

View workflow job for this annotation

GitHub Actions / Check Spelling

`AClient` is not a recognized word. (unrecognized-spelling)

Check failure on line 11 in src/a2a/client/client.py

View workflow job for this annotation

GitHub Actions / Check Spelling

`AClient` is not a recognized word. (unrecognized-spelling)

Check warning on line 11 in src/a2a/client/client.py

View workflow job for this annotation

GitHub Actions / Check Spelling

`AClient` is not a recognized word. (unrecognized-spelling)
from a2a.types import (
AgentCard,
CancelTaskRequest,
Expand All @@ -24,9 +24,10 @@
SetTaskPushNotificationConfigRequest,
SetTaskPushNotificationConfigResponse,
)
from a2a.utils.telemetry import SpanKind, trace_class


class A2ACardResolver:

Check failure on line 30 in src/a2a/client/client.py

View workflow job for this annotation

GitHub Actions / Check Spelling

`ACard` is not a recognized word. (unrecognized-spelling)
"""Agent Card resolver."""

def __init__(
Expand All @@ -50,15 +51,16 @@
response.raise_for_status()
return AgentCard.model_validate(response.json())
except httpx.HTTPStatusError as e:
raise A2AClientHTTPError(e.response.status_code, str(e)) from e

Check failure on line 54 in src/a2a/client/client.py

View workflow job for this annotation

GitHub Actions / Check Spelling

`AClient` is not a recognized word. (unrecognized-spelling)

Check warning on line 54 in src/a2a/client/client.py

View workflow job for this annotation

GitHub Actions / Check Spelling

`AClient` is not a recognized word. (unrecognized-spelling)
except json.JSONDecodeError as e:
raise A2AClientJSONError(str(e)) from e

Check failure on line 56 in src/a2a/client/client.py

View workflow job for this annotation

GitHub Actions / Check Spelling

`AClient` is not a recognized word. (unrecognized-spelling)

Check warning on line 56 in src/a2a/client/client.py

View workflow job for this annotation

GitHub Actions / Check Spelling

`AClient` is not a recognized word. (unrecognized-spelling)
except httpx.RequestError as e:
raise A2AClientHTTPError(

Check failure on line 58 in src/a2a/client/client.py

View workflow job for this annotation

GitHub Actions / Check Spelling

`AClient` is not a recognized word. (unrecognized-spelling)

Check warning on line 58 in src/a2a/client/client.py

View workflow job for this annotation

GitHub Actions / Check Spelling

`AClient` is not a recognized word. (unrecognized-spelling)
503, f'Network communication error: {e}'
) from e


@trace_class(kind=SpanKind.CLIENT)
class A2AClient:
"""A2A Client."""

Expand All @@ -85,7 +87,7 @@
http_kwargs: dict[str, Any] | None = None,
) -> 'A2AClient':
"""Get a A2A client for provided agent card URL."""
agent_card: AgentCard = await A2ACardResolver(

Check warning on line 90 in src/a2a/client/client.py

View workflow job for this annotation

GitHub Actions / Check Spelling

`ACard` is not a recognized word. (unrecognized-spelling)
httpx_client, base_url=base_url, agent_card_path=agent_card_path
).get_agent_card(http_kwargs=http_kwargs)
return A2AClient(httpx_client=httpx_client, agent_card=agent_card)
Expand Down Expand Up @@ -121,7 +123,7 @@
**(http_kwargs or {}),
}

async with aconnect_sse(

Check warning on line 126 in src/a2a/client/client.py

View workflow job for this annotation

GitHub Actions / Check Spelling

`aconnect` is not a recognized word. (unrecognized-spelling)
self.httpx_client,
'POST',
self.url,
Expand Down
2 changes: 2 additions & 0 deletions src/a2a/server/events/event_consumer.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,13 @@
TaskStatusUpdateEvent,
)
from a2a.utils.errors import ServerError
from a2a.utils.telemetry import SpanKind, trace_class


logger = logging.getLogger(__name__)


@trace_class(kind=SpanKind.SERVER)
class EventConsumer:
"""Consumer to read events from the agent event queue."""

Expand Down
2 changes: 2 additions & 0 deletions src/a2a/server/events/event_queue.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
TaskArtifactUpdateEvent,
TaskStatusUpdateEvent,
)
from a2a.utils.telemetry import SpanKind, trace_class


logger = logging.getLogger(__name__)
Expand All @@ -26,6 +27,7 @@
)


@trace_class(kind=SpanKind.SERVER)
class EventQueue:
"""Event queue for A2A responses from agent."""

Expand Down
2 changes: 2 additions & 0 deletions src/a2a/server/events/in_memory_queue_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@
QueueManager,
TaskQueueExists,
)
from a2a.utils.telemetry import SpanKind, trace_class


@trace_class(kind=SpanKind.SERVER)
class InMemoryQueueManager(QueueManager):
"""InMemoryQueueManager is used for a single binary management.

Expand Down
6 changes: 4 additions & 2 deletions src/a2a/server/request_handlers/default_request_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,12 @@
UnsupportedOperationError,
)
from a2a.utils.errors import ServerError
from a2a.utils.telemetry import SpanKind, trace_class

logger = logging.getLogger(__name__)


@trace_class(kind=SpanKind.SERVER)
class DefaultRequestHandler(RequestHandler):
"""Default request handler for all incoming requests."""

Expand Down Expand Up @@ -128,7 +130,7 @@ async def on_message_send(
# agents.
queue = await self._queue_manager.create_or_tap(task_id)
result_aggregator = ResultAggregator(task_manager)
# TODO to manage the non-blocking flows.
# TODO: to manage the non-blocking flows.
producer_task = asyncio.create_task(
self._run_event_stream(
request_context,
Expand All @@ -144,7 +146,7 @@ async def on_message_send(
(
result,
interrupted,
) = await result_aggregator.consume_and_break_on_interrupt(consumer)
) = await result_aggregator.consume_and_break_on_interrupt(consumer)
if not result:
raise ServerError(error=InternalError())
finally:
Expand Down
6 changes: 4 additions & 2 deletions src/a2a/server/request_handlers/jsonrpc_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,15 @@
)
from a2a.utils.errors import ServerError
from a2a.utils.helpers import validate
from a2a.utils.telemetry import SpanKind, trace_class


logger = logging.getLogger(__name__)


@trace_class(kind=SpanKind.SERVER)
class JSONRPCHandler:
"""A handler that maps the JSONRPC Objects to the request handler and back."""
"""Maps the JSONRPC Objects to the request handler and back."""

def __init__(
self,
Expand All @@ -53,7 +55,7 @@ def __init__(
Args:
agent_card: The AgentCard describing the agent's capabilities.
request_handler: The handler instance responsible for processing A2A requests.
request_handler: The handler instance to process A2A requests.
"""
self.agent_card = agent_card
self.request_handler = request_handler
Expand Down
5 changes: 5 additions & 0 deletions src/a2a/utils/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# type: ignore
from opentelemetry.trace import SpanKind as OTelSpanKind

from a2a.utils.artifact import new_text_artifact
from a2a.utils.helpers import (
append_artifact_to_task,
Expand All @@ -12,7 +15,9 @@
from a2a.utils.task import new_task


SpanKind = OTelSpanKind
__all__ = [
'SpanKind',
'append_artifact_to_task',
'build_text_artifact',
'create_task_obj',
Expand Down
3 changes: 3 additions & 0 deletions src/a2a/utils/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,13 @@
TextPart,
)
from a2a.utils.errors import ServerError, UnsupportedOperationError
from a2a.utils.telemetry import trace_function


logger = logging.getLogger(__name__)


@trace_function()
def create_task_obj(message_send_params: MessageSendParams) -> Task:
"""Create a new task object from message send params."""
if not message_send_params.message.contextId:
Expand All @@ -31,6 +33,7 @@
)


@trace_function()
def append_artifact_to_task(task: Task, event: TaskArtifactUpdateEvent) -> None:
"""Helper method for updating Task with new artifact data."""
if not task.artifacts:
Expand Down Expand Up @@ -74,7 +77,7 @@
# We received a chunk to append, but we don't have an existing artifact.
# we will ignore this chunk
logger.warning(
f'Received append=True for non-existent artifact index {artifact_id} in task {task.id}. Ignoring chunk.'

Check failure on line 80 in src/a2a/utils/helpers.py

View workflow job for this annotation

GitHub Actions / Check Spelling

`non-existent` matches a line_forbidden.patterns entry: `\b[Nn]o[nt][- ]existent\b`. (forbidden-pattern)
)


Expand Down
12 changes: 10 additions & 2 deletions src/a2a/utils/telemetry.py
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,11 @@
return async_wrapper if is_async_func else sync_wrapper


def trace_class(include_list: list[str] = None, exclude_list: list[str] = None):
def trace_class(
include_list: list[str] = None,
exclude_list: list[str] = None,
kind=SpanKind.INTERNAL,
):
"""A class decorator to automatically trace specified methods of a class.

This decorator iterates over the methods of a class and applies the
Expand Down Expand Up @@ -261,10 +265,10 @@
logger.debug(f'Trace all class {include_list}, {exclude_list}')
exclude_list = exclude_list or []

def decorator(cls):

Check failure on line 268 in src/a2a/utils/telemetry.py

View workflow job for this annotation

GitHub Actions / Check Spelling

`cls` is not a recognized word. (unrecognized-spelling)
all_methods = {}
for name, method in inspect.getmembers(cls, inspect.isfunction):

Check warning on line 270 in src/a2a/utils/telemetry.py

View workflow job for this annotation

GitHub Actions / Check Spelling

`cls` is not a recognized word. (unrecognized-spelling)
# Skip Dunders

Check failure on line 271 in src/a2a/utils/telemetry.py

View workflow job for this annotation

GitHub Actions / Check Spelling

`Dunders` is not a recognized word. (unrecognized-spelling)
if name.startswith('__') and name.endswith('__'):
continue

Expand All @@ -276,9 +280,13 @@
continue

all_methods[name] = method
span_name = f'{cls.__module__}.{cls.__name__}.{name}'

Check warning on line 283 in src/a2a/utils/telemetry.py

View workflow job for this annotation

GitHub Actions / Check Spelling

`cls` is not a recognized word. (unrecognized-spelling)

Check warning on line 283 in src/a2a/utils/telemetry.py

View workflow job for this annotation

GitHub Actions / Check Spelling

`cls` is not a recognized word. (unrecognized-spelling)
# Set the decorator on the method.
setattr(cls, name, trace_function(span_name=span_name)(method))
setattr(
cls,

Check warning on line 286 in src/a2a/utils/telemetry.py

View workflow job for this annotation

GitHub Actions / Check Spelling

`cls` is not a recognized word. (unrecognized-spelling)
name,
trace_function(span_name=span_name, kind=kind)(method),
)
return cls

return decorator
8 changes: 5 additions & 3 deletions uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.