# A2A (Agent2Agent) Protocol - Full Documentation This file is a consolidated version of all documentation, specifications, and API references for the A2A (Agent2Agent) Protocol project, optimized for LLM consumption. ## Project Summary # A2A (Agent2Agent) Protocol High-Level Summary This project defines the **Agent2Agent (A2A) protocol**, an open standard initiated by Google and donated to the Linux Foundation, designed to enable communication and interoperability between disparate AI agent systems. It allows agents built on different frameworks (e.g., LangGraph, CrewAI, Google ADK, Genkit) to discover each other's capabilities, negotiate interaction modes, and collaborate on tasks securely without exposing internal state. The repository contains: 1. **Formal Specification:** The normative Protobuf definition (`specification/a2a.proto`). A non-normative JSON Schema (`a2a.json`, JSON Schema 2020-12) is generated from it at build time and published at `docs/spec/a2a.json`. 2. **Core Concepts Documentation:** Conceptual guides in `docs/topics/` (What is A2A, A2A & MCP, Core Concepts, Life of a Task, Agent Discovery, Enterprise Features, Streaming & Async, Multi-Tenancy, and the Extensions group). 3. **SDKs:** Production-ready SDKs for Python, JS/TS, Java, Go, .NET, and Rust. 4. **Sample Implementations:** Real-world examples integrated with various agent frameworks. ## Key Files & Directories - `specification/a2a.proto`: The authoritative, normative Protobuf definition of the protocol (source of truth). - `docs/specification.md`: The human-readable protocol specification (current released version `1.0.0`). - `docs/definitions.md`: Protocol Definition reference embedding the normative proto and the generated JSON Schema. - `docs/whats-new-v1.md`: Summary of changes from v0.3.0 to v1.0. - `docs/topics/`: Conceptual guides — `what-is-a2a`, `a2a-and-mcp`, `key-concepts`, `life-of-a-task`, `agent-discovery`, `enterprise-ready`, `streaming-and-async`, `multi-tenancy`, plus the Extensions group (`extensions`, `custom-protocol-bindings`, `extension-and-binding-governance`). - `docs/tutorials/`: Step-by-step Python quickstart for building A2A-compliant agents. - `docs/sdk/`: SDK overview and Python API reference. - `scripts/`: Utility scripts for building docs, JSON Schema generation, and formatting. # A2A (Agent2Agent) Protocol Reference ## 1. Overview - **Purpose:** Open standard for agent-to-agent interoperability. - **Current Version:** 1.0. The Protobuf definition (`specification/a2a.proto`) is the normative source of truth; each `AgentInterface` advertises its own `protocol_version`. - **Communication Bindings:** Supports JSON-RPC 2.0 (HTTP/SSE), gRPC, and HTTP/REST. - **Key Concepts:** Agent Cards for discovery, Task-based execution, Multi-turn Messages, and Artifact outputs. ## 2. Core Data Objects ### 2.1 AgentCard (`/.well-known/agent-card.json`) Describes an agent's identity and capabilities. - `name`, `description`, `version`: Identity metadata. - `supported_interfaces`: List of `AgentInterface` (URL, protocol binding, tenant, protocol version). - `capabilities`: `streaming`, `push_notifications`, `extended_agent_card`, `extensions`. - `skills`: List of `AgentSkill` (id, name, description, tags, examples). - `security_schemes`, `security_requirements`: Authentication configuration (API Key, OAuth2, OIDC, mTLS, HTTP Auth). - `default_input_modes`, `default_output_modes`: Supported MIME types (e.g., `text/plain`, `application/json`). ### 2.2 Task Represents a stateful unit of work. - `id`, `context_id`: Identifiers for the task and its conversational context. - `status`: `TaskStatus` (state, message, timestamp). - `artifacts`: List of `Artifact` (outputs produced). - `history`: List of `Message` (conversation history). - `metadata`: Custom structured data. ### 2.3 TaskState (Enum) - `SUBMITTED`, `WORKING`, `COMPLETED` (terminal), `FAILED` (terminal), `CANCELED` (terminal), `REJECTED` (terminal), `INPUT_REQUIRED` (interrupted), `AUTH_REQUIRED` (interrupted). ### 2.4 Message & Part - `Message`: Contains `message_id`, `role` (USER/AGENT), `parts`, `context_id`, `task_id`, `reference_task_ids`. - `Part`: Union type containing `text`, `raw` (bytes), `url`, or `data` (JSON). Includes `media_type` and `filename`. ### 2.5 Artifact - A tangible output from a task, containing one or more `Part`s and metadata. ## 3. RPC Methods | Method | Request | Response | Description | | :--- | :--- | :--- | :--- | | `SendMessage` | `SendMessageRequest` | `SendMessageResponse` | Initiates or continues a task. | | `SendStreamingMessage` | `SendMessageRequest` | `stream StreamResponse` | Sends message and receives real-time SSE updates. | | `GetTask` | `GetTaskRequest` | `Task` | Retrieves current task state. | | `ListTasks` | `ListTasksRequest` | `ListTasksResponse` | Filter and paginate tasks. | | `CancelTask` | `CancelTaskRequest` | `Task` | Requests cancellation of a task. | | `SubscribeToTask` | `SubscribeToTaskRequest` | `stream StreamResponse` | Subscribes to updates for an existing task. | | `GetExtendedAgentCard` | `GetExtendedAgentCardRequest` | `AgentCard` | Fetches detailed metadata after authentication. | | `CreateTaskPushNotificationConfig` | `TaskPushNotificationConfig` | `TaskPushNotificationConfig` | Registers a push notification (webhook) config for a task. | | `GetTaskPushNotificationConfig` | `GetTaskPushNotificationConfigRequest` | `TaskPushNotificationConfig` | Retrieves a task's push notification config. | | `ListTaskPushNotificationConfigs` | `ListTaskPushNotificationConfigsRequest` | `ListTaskPushNotificationConfigsResponse` | Lists push notification configs for a task. | | `DeleteTaskPushNotificationConfig` | `DeleteTaskPushNotificationConfigRequest` | `Empty` | Deletes a task's push notification config. | ### 3.1 Streaming Events (`StreamResponse`) Streams return a payload containing one of: - `task`: Full task state. - `message`: A discrete message part. - `status_update`: `TaskStatusUpdateEvent` (taskId, contextId, status). - `artifact_update`: `TaskArtifactUpdateEvent` (taskId, artifact, append, last_chunk). ## 4. Security & Authentication - **Transport:** HTTPS/TLS required for production. - **Authentication:** Declared in `AgentCard` via OpenAPI-style security schemes. - **Push Notifications:** Webhooks secured via authentication tokens/schemes configured per task. ## 5. Implementation Status - **Official SDKs:** Python (`a2a-sdk`), JS/TS (`@a2a-js/sdk`), Java, Go, C#/.NET (`A2A`), and Rust (`a2a-rs`). - **Integrations:** LangGraph, CrewAI, Google ADK, Genkit, AG2, BeeAI, PydanticAI, and more. --- ## File Index - README.md - docs/announcing-1.0.md - docs/community.md - docs/definitions.md - docs/index.md - docs/partners.md - docs/roadmap.md - docs/sdk/index.md - docs/specification.md - docs/topics/a2a-and-mcp.md - docs/topics/agent-discovery.md - docs/topics/custom-protocol-bindings.md - docs/topics/enterprise-ready.md - docs/topics/extension-and-binding-governance.md - docs/topics/extensions.md - docs/topics/key-concepts.md - docs/topics/life-of-a-task.md - docs/topics/multi-tenancy.md - docs/topics/streaming-and-async.md - docs/topics/what-is-a2a.md - docs/tutorials/index.md - docs/tutorials/python/1-introduction.md - docs/tutorials/python/2-setup.md - docs/tutorials/python/3-agent-skills-and-card.md - docs/tutorials/python/4-agent-executor.md - docs/tutorials/python/5-start-server.md - docs/tutorials/python/6-interact-with-server.md - docs/tutorials/python/7-streaming-and-multiturn.md - docs/tutorials/python/8-next-steps.md - docs/whats-new-v1.md - sdk/python/a2a.a2a_db_cli.txt - sdk/python/a2a.auth.txt - sdk/python/a2a.auth.user.txt - sdk/python/a2a.client.auth.credentials.txt - sdk/python/a2a.client.auth.interceptor.txt - sdk/python/a2a.client.auth.txt - sdk/python/a2a.client.base_client.txt - sdk/python/a2a.client.card_resolver.txt - sdk/python/a2a.client.client.txt - sdk/python/a2a.client.client_factory.txt - sdk/python/a2a.client.errors.txt - sdk/python/a2a.client.interceptors.txt - sdk/python/a2a.client.optionals.txt - sdk/python/a2a.client.service_parameters.txt - sdk/python/a2a.client.transports.base.txt - sdk/python/a2a.client.transports.grpc.txt - sdk/python/a2a.client.transports.http_helpers.txt - sdk/python/a2a.client.transports.jsonrpc.txt - sdk/python/a2a.client.transports.rest.txt - sdk/python/a2a.client.transports.tenant_decorator.txt - sdk/python/a2a.client.transports.txt - sdk/python/a2a.client.txt - sdk/python/a2a.compat.txt - sdk/python/a2a.compat.v0_3.a2a_v0_3_pb2.txt - sdk/python/a2a.compat.v0_3.a2a_v0_3_pb2_grpc.txt - sdk/python/a2a.compat.v0_3.context_builders.txt - sdk/python/a2a.compat.v0_3.conversions.txt - sdk/python/a2a.compat.v0_3.extension_headers.txt - sdk/python/a2a.compat.v0_3.grpc_handler.txt - sdk/python/a2a.compat.v0_3.grpc_transport.txt - sdk/python/a2a.compat.v0_3.jsonrpc_adapter.txt - sdk/python/a2a.compat.v0_3.jsonrpc_transport.txt - sdk/python/a2a.compat.v0_3.model_conversions.txt - sdk/python/a2a.compat.v0_3.proto_utils.txt - sdk/python/a2a.compat.v0_3.request_handler.txt - sdk/python/a2a.compat.v0_3.rest_adapter.txt - sdk/python/a2a.compat.v0_3.rest_handler.txt - sdk/python/a2a.compat.v0_3.rest_transport.txt - sdk/python/a2a.compat.v0_3.txt - sdk/python/a2a.compat.v0_3.types.txt - sdk/python/a2a.compat.v0_3.versions.txt - sdk/python/a2a.extensions.common.txt - sdk/python/a2a.extensions.txt - sdk/python/a2a.helpers.agent_card.txt - sdk/python/a2a.helpers.proto_helpers.txt - sdk/python/a2a.helpers.txt - sdk/python/a2a.migrations.env.txt - sdk/python/a2a.migrations.migration_utils.txt - sdk/python/a2a.migrations.txt - sdk/python/a2a.migrations.versions.38ce57e08137_add_column_protocol_version.txt - sdk/python/a2a.migrations.versions.6419d2d130f6_add_columns_owner_last_updated.txt - sdk/python/a2a.migrations.versions.txt - sdk/python/a2a.server.agent_execution.active_task.txt - sdk/python/a2a.server.agent_execution.active_task_registry.txt - sdk/python/a2a.server.agent_execution.agent_executor.txt - sdk/python/a2a.server.agent_execution.context.txt - sdk/python/a2a.server.agent_execution.request_context_builder.txt - sdk/python/a2a.server.agent_execution.simple_request_context_builder.txt - sdk/python/a2a.server.agent_execution.txt - sdk/python/a2a.server.context.txt - sdk/python/a2a.server.events.event_consumer.txt - sdk/python/a2a.server.events.event_queue.txt - sdk/python/a2a.server.events.event_queue_v2.txt - sdk/python/a2a.server.events.in_memory_queue_manager.txt - sdk/python/a2a.server.events.queue_manager.txt - sdk/python/a2a.server.events.txt - sdk/python/a2a.server.id_generator.txt - sdk/python/a2a.server.jsonrpc_models.txt - sdk/python/a2a.server.models.txt - sdk/python/a2a.server.owner_resolver.txt - sdk/python/a2a.server.request_handlers.default_request_handler.txt - sdk/python/a2a.server.request_handlers.default_request_handler_v2.txt - sdk/python/a2a.server.request_handlers.grpc_handler.txt - sdk/python/a2a.server.request_handlers.request_handler.txt - sdk/python/a2a.server.request_handlers.response_helpers.txt - sdk/python/a2a.server.request_handlers.txt - sdk/python/a2a.server.routes.agent_card_routes.txt - sdk/python/a2a.server.routes.common.txt - sdk/python/a2a.server.routes.fastapi_routes.txt - sdk/python/a2a.server.routes.jsonrpc_dispatcher.txt - sdk/python/a2a.server.routes.jsonrpc_routes.txt - sdk/python/a2a.server.routes.rest_dispatcher.txt - sdk/python/a2a.server.routes.rest_routes.txt - sdk/python/a2a.server.routes.txt - sdk/python/a2a.server.tasks.base_push_notification_sender.txt - sdk/python/a2a.server.tasks.copying_task_store.txt - sdk/python/a2a.server.tasks.database_push_notification_config_store.txt - sdk/python/a2a.server.tasks.database_task_store.txt - sdk/python/a2a.server.tasks.inmemory_push_notification_config_store.txt - sdk/python/a2a.server.tasks.inmemory_task_store.txt - sdk/python/a2a.server.tasks.push_notification_config_store.txt - sdk/python/a2a.server.tasks.push_notification_sender.txt - sdk/python/a2a.server.tasks.result_aggregator.txt - sdk/python/a2a.server.tasks.task_manager.txt - sdk/python/a2a.server.tasks.task_store.txt - sdk/python/a2a.server.tasks.task_updater.txt - sdk/python/a2a.server.tasks.txt - sdk/python/a2a.server.txt - sdk/python/a2a.txt - sdk/python/a2a.types.a2a_pb2.txt - sdk/python/a2a.types.a2a_pb2_grpc.txt - sdk/python/a2a.types.txt - sdk/python/a2a.utils.constants.txt - sdk/python/a2a.utils.error_handlers.txt - sdk/python/a2a.utils.errors.txt - sdk/python/a2a.utils.json_utils.txt - sdk/python/a2a.utils.proto_utils.txt - sdk/python/a2a.utils.signing.txt - sdk/python/a2a.utils.task.txt - sdk/python/a2a.utils.telemetry.txt - sdk/python/a2a.utils.txt - sdk/python/a2a.utils.version_validator.txt - sdk/python/index.txt - sdk/python/modules.txt - specification/a2a.proto --- # Agent2Agent (A2A) Protocol [![PyPI - Version](https://img.shields.io/pypi/v/a2a-sdk)](https://pypi.org/project/a2a-sdk) [![Apache License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](LICENSE) Ask Code Wiki
🌐 Language
English | 简体中文 | 繁體中文 | 日本語 | 한국어 | हिन्दी | ไทย | Français | Deutsch | Español | Italiano | Русский | Português | Nederlands | Polski | العربية | فارسی | Türkçe | Tiếng Việt | Bahasa Indonesia | অসমীয়া
Agent2Agent Protocol Logo

Agent2Agent (A2A) Protocol

**An open protocol enabling communication and interoperability between opaque agentic applications.** The Agent2Agent (A2A) protocol addresses a critical challenge in the AI landscape: enabling gen AI agents, built on diverse frameworks by different companies running on separate servers, to communicate and collaborate effectively - as agents, not just as tools. A2A aims to provide a common language for agents, fostering a more interconnected, powerful, and innovative AI ecosystem. With A2A, agents can: - Discover each other's capabilities. - Negotiate interaction modalities (text, forms, media). - Securely collaborate on long-running tasks. - Operate without exposing their internal state, memory, or tools. ## DeepLearning.AI Course [![A2A DeepLearning.AI](https://img.youtube.com/vi/4gYm0Rp7VHc/maxresdefault.jpg)](https://goo.gle/dlai-a2a) Join this short course on [A2A: The Agent2Agent Protocol](https://goo.gle/dlai-a2a), built in partnership with Google Cloud and IBM Research, and taught by [Holt Skinner](https://github.com/holtskinner), [Ivan Nardini](https://github.com/inardini), and [Sandi Besen](https://github.com/sandijean90). **What you'll learn:** - **Make agents A2A-compliant:** Expose agents built with frameworks like Google ADK, LangGraph, or BeeAI as A2A servers. - **Connect agents:** Create A2A clients from scratch or using integrations to connect to A2A-compliant agents. - **Orchestrate workflows:** Build sequential and hierarchical workflows of A2A-compliant agents. - **Multi-agent systems:** Build a healthcare multi-agent system using different frameworks and see how A2A enables collaboration. - **A2A and MCP:** Learn how A2A complements MCP by enabling agents to collaborate with each other. ## Why A2A? As AI agents become more prevalent, their ability to interoperate is crucial for building complex, multi-functional applications. A2A aims to: - **Break Down Silos:** Connect agents across different ecosystems. - **Enable Complex Collaboration:** Allow specialized agents to work together on tasks that a single agent cannot handle alone. - **Promote Open Standards:** Foster a community-driven approach to agent communication, encouraging innovation and broad adoption. - **Preserve Opacity:** Allow agents to collaborate without needing to share internal memory, proprietary logic, or specific tool implementations, enhancing security and protecting intellectual property. ### Key Features - **Standardized Communication:** JSON-RPC 2.0 over HTTP(S). - **Agent Discovery:** Via "Agent Cards" detailing capabilities and connection info. - **Flexible Interaction:** Supports synchronous request/response, streaming (SSE), and asynchronous push notifications. - **Rich Data Exchange:** Handles text, files, and structured JSON data. - **Enterprise-Ready:** Designed with security, authentication, and observability in mind. ## Getting Started - 📚 **Explore the Documentation:** Visit the [Agent2Agent Protocol Documentation Site](https://a2a-protocol.org) for a complete overview, the full protocol specification, tutorials, and guides. - 📝 **View the Specification:** [A2A Protocol Specification](https://a2a-protocol.org/latest/specification/) - Use the SDKs: - [🐍 A2A Python SDK](https://github.com/a2aproject/a2a-python) `pip install a2a-sdk` - [🐿️ A2A Go SDK](https://github.com/a2aproject/a2a-go) `go get github.com/a2aproject/a2a-go` - [🧑‍💻 A2A JS SDK](https://github.com/a2aproject/a2a-js) `npm install @a2a-js/sdk` - [☕️ A2A Java SDK](https://github.com/a2aproject/a2a-java) using maven - [🔷 A2A .NET SDK](https://github.com/a2aproject/a2a-dotnet) using [NuGet](https://www.nuget.org/packages/A2A) `dotnet add package A2A` - [🦀 A2A Rust SDK](https://github.com/a2aproject/a2a-rs) `cargo add a2a-lf` - 🎬 Use our [samples](https://github.com/a2aproject/a2a-samples) to see A2A in action ## Contributing We welcome community contributions to enhance and evolve the A2A protocol! - **Questions & Discussions:** Join our [GitHub Discussions](https://github.com/a2aproject/A2A/discussions). - **Issues & Feedback:** Report issues or suggest improvements via [GitHub Issues](https://github.com/a2aproject/A2A/issues). - **Contribution Guide:** See our [CONTRIBUTING.md](CONTRIBUTING.md) for details on how to contribute. - **Private Feedback:** Use this [Google Form](https://goo.gle/a2a-feedback). - **Partner Program:** Google Cloud customers can join our partner program via this [form](https://goo.gle/a2a-partner). ## What's next ### Protocol Enhancements - **Agent Discovery:** - Formalize inclusion of authorization schemes and optional credentials directly within the `AgentCard`. - **Agent Collaboration:** - Investigate a `QuerySkill()` method for dynamically checking unsupported or unanticipated skills. - **Task Lifecycle & UX:** - Support for dynamic UX negotiation _within_ a task (e.g., agent adding audio/video mid-conversation). - **Client Methods & Transport:** - Explore extending support to client-initiated methods (beyond task management). - Improvements to streaming reliability and push notification mechanisms. ## About The A2A Protocol is an open source project under the Linux Foundation, contributed by Google. It is licensed under the [Apache License 2.0](LICENSE) and is open to contributions from the community.
# A2A Protocol Ships v1.0: Production-Ready Standard for Agent-to-Agent Communication The A2A Protocol community today are announcing the release of A2A Protocol v1.0, marking the first stable, production-ready version of the open standard for communication between AI agents. The protocol is guided by a technical steering committee with representatives from eight major technology companies. As organizations build increasingly sophisticated multi-agent systems, interoperability has become the defining challenge. Teams can coordinate agents effectively within a single platform, but connecting those systems across technology stacks and organizational boundaries remains difficult. A2A addresses that challenge by combining support for multiple protocol bindings, seamless version negotiation, and a common semantic model so agents can interoperate across systems with predictable behavior. The v1.0 release emphasizes maturity rather than reinvention: the core ideas remain intact, while rough edges have been removed, ambiguous areas clarified, and enterprise deployment requirements addressed more directly. The official SDKs ensure v1.0 A2A agents work seamlessly with older versions. ## Delivering on enterprise requirements The v1.0 release introduces several capabilities aimed at production environments where trust, scale, and operational control are non-negotiable. - **Heterogeneous environment support** enables interoperability across diverse technology stacks through multi-protocol bindings and version negotiation, so enterprises are not tied to a single vendor or platform. - **Multi-tenancy support** allows a single endpoint to securely host many agents. - **Signed Agent Cards** provide cryptographic verification of agent identity and metadata, establishing trust before interaction across organizational boundaries. - **Improved security posture** modernizes security flows and removes legacy patterns that are no longer aligned with current best practices. Together, these changes move A2A from early adopter implementations toward broader enterprise confidence, especially in regulated or multi-party scenarios. ## Web-aligned architecture for scale A2A v1.0 aligns with core architectural principles of the web: stateless, layered architecture, standard protocol bindings, and infrastructure-friendly communication patterns. That alignment matters operationally because organizations can scale agent interactions with the same proven load balancing, gateway, security and observability patterns they already use for web systems. The standard builds on industry-proven protocols, including JSON+HTTP, gRPC, and JSON-RPC. It also keeps the barrier to entry low: in its simplest form, an A2A interaction can begin with a single HTTP request. A2A also gives consumers flexibility in how they receive results. Depending on workload and operational needs, clients can use polling, streaming, or webhooks to consume task updates and responses. ## Complementary to MCP, not a replacement The release also reinforces A2A's relationship with the Model Context Protocol (MCP), a point that has generated confusion in early ecosystem discussions. MCP and A2A solve different layers of the problem. MCP is commonly used for tool and context integration at the individual agent level. A2A focuses on communication and coordination between agents. In practice, many systems will use both: MCP inside agents, A2A between agents. ## Smooth migration from earlier versions The v1.0 release tightens specification behavior, which includes breaking changes in the interaction protocol. AgentCard, however, has evolved in a backward-compatible way and now allows agents to advertise support for both existing v0.3 protocol behavior and v1.0 simultaneously. This enables clients to migrate progressively rather than through a single cutover. That approach is intended to protect current investments while still delivering the benefits of a cleaner, more durable standard. ## Why this release matters now AI agents are increasingly deployed across departments, products, and partner ecosystems. At that scale, the key question is no longer whether agents can coordinate within one stack, but whether they can collaborate reliably across organizational and platform boundaries. Open protocols determine whether organizations can compose best-of-breed systems or become locked into isolated stacks. A2A v1.0 gives the market a stronger foundation for open multi-agent collaboration. The community is now focused on delivering multi-language v1.0 SDK support to help developers build conformant solutions with ease. The complete v1.0 materials, including specification and migration documentation, are available at [a2a-protocol.org](https://a2a-protocol.org) and on [GitHub](https://github.com/a2aproject/A2A). --- **About A2A Protocol** The Agent-to-Agent (A2A) Protocol is an open standard that enables AI agents to discover capabilities, communicate, and delegate tasks across teams, products, and organizations. The A2A Technical Steering Committee includes representatives from AWS, Cisco, Google, IBM Research, Microsoft, Salesforce, SAP, and ServiceNow. **Media Contact** A2A Protocol Community [https://a2a-protocol.org](https://a2a-protocol.org) # A2A Community Hub Welcome to the official community hub for the **Agent2Agent (A2A) protocol**! A2A is an open, standardized protocol that enables seamless interoperability and collaboration between AI agents across all frameworks and vendors. --- ## Recent News & Blog Posts Stay up-to-date with the latest announcements, tutorials, and insights from the A2A team and our community. - **[Announcing Agent Payments Protocol (AP2)](https://cloud.google.com/blog/products/ai-machine-learning/announcing-agent-payments-protocol-ap2)** - *September 16* - **[A2A Extensions Empowering Custom Agent Functionality](https://developers.googleblog.com/en/a2a-extensions-empowering-custom-agent-functionality/)** - *September 9* - **[A2A protocol: Demystifying Tasks vs Messages](https://discuss.google.dev/t/a2a-protocol-demystifying-tasks-vs-messages/255879)** - *August 18* - **[End-to-end evaluation of multi-agent systems on Vertex AI](https://discuss.google.dev/t/end-to-end-evaluation-of-multi-agent-systems-on-vertex-ai-with-cloud-run-deployment-for-a2a-agents/250552)** - *August 7* - **[Agent2Agent (A2A) protocol is getting an upgrade](https://cloud.google.com/blog/products/ai-machine-learning/agent2agent-protocol-is-getting-an-upgrade?e=48754805)** - *July 26* --- ## Use Case Highlights A2A unlocks powerful new ways for AI agents to collaborate and solve complex problems. Here are a few examples of what's possible: - **Multi-Agent Workflows:** Chain specialized agents together to automate complex processes, like candidate sourcing for hiring or streamlining supply chain logistics. - **Agent Marketplaces:** Create platforms where agents can discover and utilize the capabilities of other agents from different providers. - **Cross-Platform Integration:** Connect agents built on different frameworks—like LangGraph, BeeAI, and more—to work together seamlessly. - **Evaluating Multi-Agent Systems:** Use frameworks like Vertex AI to assess the performance and success of collaborative agent trajectories. --- ## Community Spotlight ### Featured Contributions A2A is an open-source protocol, and we thrive on community contributions. A huge thank you to everyone who has helped build and improve A2A! Here are some recent highlights: - [Python Quickstart Tutorial (PR#202)](https://github.com/a2aproject/A2A/pull/202) - [LlamaIndex sample implementation (PR#179)](https://github.com/a2aproject/A2A/pull/179) - [Autogen sample server (PR#232)](https://github.com/a2aproject/A2A/pull/232) - [AG2 + MCP example (PR#230)](https://github.com/a2aproject/A2A/pull/230) - [PydanticAI example (PR#127)](https://github.com/a2aproject/A2A/pull/127) ### The Word on the Street The launch of A2A has sparked lively discussions and positive reactions across various social and video platforms. - **Microsoft's Semantic Kernel:** Asha Sharma, Head of AI Platform Product at Microsoft, [announced on LinkedIn](https://www.linkedin.com/posts/aboutasha_a2a-ugcPost-7318649411704602624-0C_8) that "Semantic Kernel now speaks A2A," enabling instant, secure interoperability. - **Matt Pocock's Diagramming:** Well-known developer educator Matt Pocock [shared diagrams on X](https://x.com/mattpocockuk/status/1910002033018421400) explaining the A2A protocol, which were liked and reposted hundreds of times. - **Craig McLuckie's "Hot Take":** Craig McLuckie shared his thoughts on [LinkedIn](https://www.linkedin.com/posts/craigmcluckie_hot-take-on-agent2agent-vs-mcp-google-just-activity-7315939233792176128-4rGQ), highlighting A2A's focus on interactions *between* agentic systems as a sensible approach. - **Zachary Huang's Deep Dive:** In his [YouTube video](https://www.youtube.com/watch?v=wrCF8MoXC_I), Zachary explains how A2A complements MCP, with A2A handling communication between agents and MCP connecting agents to tools. --- ## A2A Integrations These agentic frameworks have built-in A2A integration, making it easy to get started: - [Agent Development Kit (ADK)](https://google.github.io/adk-docs/a2a/) - [Agno](https://docs.agno.com/agent-os/interfaces/a2a/introduction) - [AG2](https://docs.ag2.ai/latest/docs/user-guide/a2a/) - [BeeAI Framework](https://framework.beeai.dev/integrations/a2a) - [CrewAI](https://docs.crewai.com/en/learn/a2a-agent-delegation) - [Hector](https://github.com/kadirpekel/hector) - [LangGraph](https://docs.langchain.com/langsmith/server-a2a) - [LiteLLM](https://docs.litellm.ai/docs/a2a) - [Microsoft Agent Framework](https://learn.microsoft.com/en-us/agent-framework/user-guide/agents/agent-types/a2a-agent) - [Pydantic AI](https://ai.pydantic.dev/a2a/) - [Slide (Tyler)](https://slide.mintlify.app/guides/a2a-integration) - [Strands Agents](https://strandsagents.com/latest/documentation/docs/user-guide/concepts/multi-agent/agent-to-agent/) ## Community SDKs Building an A2A agent in a language not covered by the [official SDKs](./sdk/index.md)? These community-maintained implementations have you covered. ### 🦀 Rust — a2a-rust ![Stars](https://img.shields.io/github/stars/tomtom215/a2a-rust?style=flat-square) [![Crate](https://img.shields.io/crates/v/a2a-protocol-sdk?style=flat-square)](https://crates.io/crates/a2a-protocol-sdk) [tomtom215/a2a-rust](https://github.com/tomtom215/a2a-rust) · A2A spec v1.0.0 · Full SDK with JSON-RPC, REST, WebSocket, and gRPC transports. ### 🦀 Rust — a2a-rs ![Stars](https://img.shields.io/github/stars/EmilLindfors/a2a-rs?style=flat-square) [![Crate](https://img.shields.io/crates/v/a2a-rs?style=flat-square)](https://crates.io/crates/a2a-rs) [EmilLindfors/a2a-rs](https://github.com/EmilLindfors/a2a-rs) · A2A spec v0.3.0 · Modular workspace with core protocol, AP2 extension, and agent framework. ### 🍎 Swift — A2AClient ![Stars](https://img.shields.io/github/stars/tolgaki/a2a-client-swift?style=flat-square) [tolgaki/a2a-client-swift](https://github.com/tolgaki/a2a-client-swift) · A2A spec v1.0.0 · Swift Package Manager. iOS 15+, macOS 12+, watchOS 8+, tvOS 15+. ### 💧 Elixir — a2a ![Stars](https://img.shields.io/github/stars/actioncard/a2a-elixir?style=flat-square) [![Hex](https://img.shields.io/hexpm/v/a2a?style=flat-square)](https://hex.pm/packages/a2a) [actioncard/a2a-elixir](https://github.com/actioncard/a2a-elixir) · A2A spec v0.2.0 · OTP-native with Agent behaviour, TaskStore, and supervision tree. ### ⚙️ C++ — a2a-cpp ![Stars](https://img.shields.io/github/stars/MisterVVP/a2a-cpp?style=flat-square) [![TCK conformance](https://img.shields.io/github/actions/workflow/status/MisterVVP/a2a-cpp/tck.yml?branch=main&label=TCK%20conformance&style=flat-square)](https://github.com/MisterVVP/a2a-cpp/actions/workflows/tck.yml) [![Docs](https://img.shields.io/badge/docs-GitHub%20Pages-blue?style=flat-square)](https://mistervvp.github.io/a2a-cpp/) [![vcpkg overlay](https://img.shields.io/badge/vcpkg-overlay%20port-blue?style=flat-square)](https://github.com/MisterVVP/a2a-cpp/tree/main/vcpkg-overlay-ports) [MisterVVP/a2a-cpp](https://github.com/MisterVVP/a2a-cpp) · A2A spec v1.0.0 · C++20 SDK with client/server APIs, discovery, REST/JSON-RPC/gRPC transports, streaming, authentication hooks, CMake/vcpkg build integration, and a TCK conformance workflow. !!! tip "Want to add your SDK?" Open an issue on [a2aproject/A2A](https://github.com/a2aproject/A2A/issues/new?title=Community%20SDK%20Submission) with a link to your repository and published package. **Requirements:** Spec compliance, published package on standard registry, documentation, tests with CI, Apache 2.0 license, and active maintenance. ## The Future is Interoperable The excitement surrounding Google's A2A protocol clearly indicates a strong belief in its potential to revolutionize multi-agent AI systems. By providing a standardized way for AI agents to communicate and collaborate, A2A is poised to unlock new levels of automation and innovation. As enterprises increasingly adopt AI agents, A2A represents a crucial step towards realizing the full power of interconnected AI ecosystems. **Join the growing community building the future of AI interoperability with A2A!** # A2A Definition/Schema === "Protobuf"

Protobuf

The normative A2A protocol definition in Protocol Buffers (proto3 syntax). This is the source of truth for the A2A protocol specification.

Download

You can download the proto file directly: [`a2a.proto`](spec/a2a.proto)

Definition

```protobuf --8<-- "docs/spec/a2a.proto" ``` === "JSON"

JSON

The A2A protocol JSON Schema definition (JSON Schema 2020-12 compliant). This schema is automatically generated from the protocol buffer definitions and bundled into a single file with all message definitions.

Download

You can download the schema file directly: [`a2a.json`](spec/a2a.json)

Definition

```json --8<-- "docs/spec/a2a.json" ```
--- hide: - toc - navigation ---

Agent2Agent Protocol Logo

An open protocol enabling communication and interoperability between opaque agentic applications.

[Get started](./tutorials/python/1-introduction.md){ .md-button .md-button--primary } [Read the spec](./specification.md){ .md-button }
## What is A2A Protocol? The **Agent2Agent (A2A) Protocol** is an open standard for seamless communication and collaboration between AI agents. In a world where agents are built using diverse frameworks and by different vendors, A2A provides the definitive common language for agent interoperability. !!! abstract "" Build with **[![ADK Logo](https://google.github.io/adk-docs/assets/agent-development-kit.png){class="twemoji lg middle"} ADK](https://google.github.io/adk-docs/)** _(or any framework)_, equip with **[![MCP Logo](https://modelcontextprotocol.io/mcp.png){class="twemoji lg middle"} MCP](https://modelcontextprotocol.io)** _(or any tool)_, and communicate with **![A2A Logo](./assets/a2a_logo/icon/color/SVG/a2a_icon_color.svg){class="twemoji lg middle"} A2A**, to remote agents, local agents, and humans. ## Key Features
- :material-account-group-outline:{ .lg .middle } **Interoperability** Connect agents built on different platforms (LangGraph, CrewAI, Semantic Kernel, custom solutions) to create powerful, composite AI systems. - :material-lan-connect:{ .lg .middle } **Complex Workflows** Enable agents to delegate sub-tasks, exchange information, and coordinate actions to solve complex problems that a single agent cannot. - :material-shield-key-outline:{ .lg .middle } **Secure & Opaque** Agents interact without needing to share internal memory, tools, or proprietary logic, ensuring security and preserving intellectual property. - :material-puzzle-outline:{ .lg .middle } **Extensible** Add capabilities through formal protocol [extensions and custom bindings](./topics/extension-and-binding-governance.md), governed by a tiered promotion process so the core stays stable.
## Get started with A2A
- :material-book-open:{ .lg .middle } **Read the Introduction** Understand the core ideas behind A2A. [:octicons-arrow-right-24: What is A2A?](./topics/what-is-a2a.md) [:octicons-arrow-right-24: Key Concepts](./topics/key-concepts.md) - :material-file-document-outline:{ .lg .middle } **Dive into the Specification** Explore the detailed technical definition of the A2A protocol. [:octicons-arrow-right-24: Protocol Specification](./specification.md) - :material-application-cog-outline:{ .lg .middle } **Follow the Tutorials** Build your first A2A-compliant agent with our step-by-step Python quickstart. [:octicons-arrow-right-24: Hands-on-Tutorial](./tutorials/python/1-introduction.md) - :material-code-braces:{ .lg .middle } **Explore Code Samples** See A2A in action with sample clients, servers, and agent framework integrations. [:fontawesome-brands-github: GitHub Samples](https://github.com/a2aproject/a2a-samples) - :material-code-braces:{ .lg .middle } **Download the Official SDKs** [:fontawesome-brands-python: Python](https://github.com/a2aproject/a2a-python) [:fontawesome-brands-js: JavaScript](https://github.com/a2aproject/a2a-js) [:fontawesome-brands-java: Java](https://github.com/a2aproject/a2a-java) [:material-language-csharp: C#/.NET](https://github.com/a2aproject/a2a-dotnet) [:fontawesome-brands-golang: Golang](https://github.com/a2aproject/a2a-go) [:fontawesome-brands-rust: Rust](https://github.com/a2aproject/a2a-rust) - :material-play-circle:{ .lg .middle } **Video** Intro in under 8 min - :material-play-circle:{ .lg .middle } **Course** [DeepLearning.AI](https://deeplearning.ai) - Intro to A2A [![A2A DeepLearning.AI](https://img.youtube.com/vi/4gYm0Rp7VHc/maxresdefault.jpg)](https://goo.gle/dlai-a2a)
## How A2A Works with MCP The Model Context Protocol (MCP) and the A2A Protocol are not competitors — they are highly complementary. They solve two different problems and are designed to work together. - **MCP is for agent-to-tool communication:** it standardizes how an agent connects to its tools, APIs, and resources to get information. See [Model Context Protocol](https://modelcontextprotocol.io/). - **A2A is for agent-to-agent communication:** as a universal, decentralized standard, A2A lets independent agents — including those using MCP — discover each other, delegate tasks, and share results. Use MCP to equip an individual agent with the specific tools it needs to do its job (e.g., access to a GitHub repository or a SQL database). Use A2A to let that specialized agent securely collaborate with other agents across different frameworks.
```mermaid flowchart LR User(🧑‍💻 User) <--> ClientAgent(🤖 Client Agent) RemoteAgent(🤖 Remote Agent) RemoteTool(⚙️ Remote Tool) ClientAgent -- Using Agent2Agent Protocol Logo --> RemoteAgent ClientAgent -- Using Agent2Agent Protocol Logo --> RemoteTool style User fill:#fdebd0,stroke:#e67e22,stroke-width:2px style ClientAgent fill:#d6eaf8,stroke:#3498db,stroke-width:2px style RemoteAgent fill:#d6eaf8,stroke:#3498db,stroke-width:2px style RemoteTool fill:#d6eaf8,stroke:#3498db,stroke-width:2px ```
[:octicons-arrow-right-24: A2A and MCP — deeper dive](./topics/a2a-and-mcp.md) ## What A2A Is Not A2A is a focused protocol. To set expectations, here is what it explicitly does not try to be: - **Not an agent development kit** like LangGraph, CrewAI, or ADK for building agentic applications. A2A is the communication layer between agents built with any of these. - **Not a sub-agent or tool-call protocol.** A2A does not specify how an agent talks to its own sub-agents or how it invokes tools — use your framework's native primitives, or MCP, for those. - **Not a replacement for [MCP](https://modelcontextprotocol.io/).** MCP standardizes agent-to-tool communication; A2A standardizes agent-to-agent communication. They are complementary (see [above](#how-a2a-works-with-mcp)). - **Not an interactive messaging app** like Slack, Discord, WhatsApp, or Telegram. A2A is a machine-to-machine protocol for autonomous agents. ## Governance & Open Source A2A was originally developed by Google and donated to the Linux Foundation. It is maintained by a Technical Steering Committee with representatives from AWS, Cisco, Google, IBM Research, Microsoft, Salesforce, SAP, and ServiceNow, and supported by a broad community of [partners](./partners.md). For details on how the project is run, see [`GOVERNANCE.md`](https://github.com/a2aproject/A2A/blob/main/GOVERNANCE.md) and [`MAINTAINERS.md`](https://github.com/a2aproject/A2A/blob/main/MAINTAINERS.md). ## License The A2A Protocol is licensed under the [Apache License 2.0](https://github.com/a2aproject/A2A/blob/main/LICENSE) and welcomes [contributions](https://github.com/a2aproject/A2A/blob/main/CONTRIBUTING.md) from the community.
# Partners Below is a list of partners (and a link to their A2A announcement or blog post, if available) who are part of the A2A community and are helping build, codify, and adopt A2A as the standard protocol for AI agents to communicate and collaborate effectively with each other and with users. - [A2A Net](https://a2anet.com) - [Accelirate Inc](https://www.accelirate.com) - [Accenture](https://www.accenture.com) - [Activeloop](https://www.activeloop.ai/) - [Adobe](https://www.adobe.com) - [AG2AI](https://ag2.ai) - [AgentTrust](https://agenttrust.ai/) - [AI21 Labs](https://www.ai21.com/) - [AI71](https://ai71.ai/) - [Airia](https://airia.com) - [Aisera](https://aisera.com/) - [AlgoVoi](https://algovoi.co.uk) - [AliCloud](http://www.alibabacloud.com) - [Almawave.it](https://www.almawave.com/it/) - [AmikoNet](https://amikonet.ai) - [ArcBlock](http://www.arcblock.io) - [Arize](https://arize.com/blog/arize-ai-and-future-of-agent-interoperability-embracing-googles-a2a-protocol/) - [Articul8](https://www.articul8.ai/blog/unleashing-the-next-frontier-of-enterprise-ai-introducing-model-mesh-dock-and-inter-lock-and-our-a2-a-partnership-with-google) - [ask-ai.com](https://ask-ai.com) - [Atlassian](https://www.atlassian.com) - [Auth0](https://auth0.com/blog/auth0-google-a2a/) - [Autodesk](https://www.autodesk.com) - [Auto Agent Protocol](https://autoagentprotocol.org/) - [AWS](https://aws.amazon.com/) - [Beekeeper](http://beekeeper.io) - [BCG](https://www.bcg.com) - [Block Inc](https://block.xyz/) - [Bloomberg LP](https://techatbloomberg.com/) - [BLUEISH Inc](https://www.blueish.co.jp/) - [BMC Software Inc](https://www.bmc.com/it-solutions/bmc-helix.html) - [Boomi](https://boomi.com/) - [Box](https://www.box.com) - [Bridge2Things Automation Process GmbH](http://bridge2things.at) - [Cafe 24](https://www.cafe24corp.com/en/company/about) - [C3 AI](https://c3.ai) - [Capgemini](https://www.capgemini.com) - [Chronosphere](https://chronosphere.io) - [Cisco](https://www.cisco.com/) - [Codimite PTE LTD](https://codimite.ai/) - [Cognigy](https://www.cognigy.com/) - [Cognizant](https://www.cognizant.com) - [Cohere](https://cohere.com) - [Collibra](https://www.collibra.com) - [Confluent](https://developer.confluent.io) - [Contextual](https://contextual.ai) - [Cotality](https://cotality.com) (fka Corelogic) - [Crubyt](https://www.crubyt.com) - [Cyderes](http://www.cyderes.com) - [Datadog](https://www.datadoghq.com) - [DataRobot](https://www.datarobot.com) - [DataStax](https://www.datastax.com) - [Decagon.ai](https://decagon.ai) - [Deloitte](https://www.prnewswire.com/news-releases/deloitte-expands-alliances-with-google-cloud-and-servicenow-to-accelerate-agentic-ai-adoption-in-the-enterprise-302423941.html) - [Devnagri](https://devnagri.com) - [Deutsche Telekom](https://www.telekom.com/en) - [Dexter Tech Labs](http://www.dextertechlabs.com) - [Distyl.ai](https://distyl.ai) - [Elastic](https://www.elastic.co) - [Ema.co](https://ema.co) - [EPAM](https://www.epam.com) - [Eviden (Atos Group)](https://atos.net/) - [fractal.ai](https://fractal.ai/new) - [GenAI Nebula9.ai Solutions Pvt Ltd](http://nebula9.ai) - [Glean](https://www.glean.com) - [Global Logic](https://www.globallogic.com/) - [Gravitee](https://www.gravitee.io/) - [GrowthLoop](https://growthloop.com) - [Guru](http://www.getguru.com) - [Harness](https://harness.io) - [HCLTech](https://www.hcltech.com) - [Headwaters](https://www.headwaters.co.jp) - [Hellotars](https://hellotars.com) - [Hexaware](https://hexaware.com/) - [HUMAN](https://www.humansecurity.com/) - [IBM Research](https://lfaidata.foundation/communityblog/2025/08/29/acp-joins-forces-with-a2a-under-the-linux-foundations-lf-ai-data/) - [Incorta](https://www.incorta.com) - [Infinitus](https://www.infinitus.ai/) - [InfoSys](https://www.infosys.com) - [Intuit](https://www.intuit.com) - [Iron Mountain](https://www.ironmountain.com/) - [JamJet](https://github.com/jamjet-labs/jamjet) - [JetBrains](https://www.jetbrains.com) - [JFrog](https://jfrog.com) - [Kakao](https://www.kakaocorp.com) - [King's College London](https://www.kcl.ac.uk/informatics) - [KPMG](https://kpmg.com/us/en/media/news/kpmg-google-cloud-alliance-expansion-agentspace-adoption.html) - [Kyndryl](http://www.kyndryl.com) - [LabelBox](https://labelbox.com) - [LangChain](https://www.langchain.com) - [LG CNS](http://www.lgcns.com) - [Livex.ai](https://livex.ai) - [LlamaIndex](https://x.com/llama_index/status/1912949446322852185) - [LTIMindTtree](https://www.ltimindtree.com) - [Lumeris](https://www.lumeris.com/) - [Lumika](https://lumika.ai) - [Lyzr.ai](https://lyzr.ai) - [Magyar Telekom](https://www.telekom.hu/) - [MasOrange](https://masorange.es/en/) - [Microsoft](https://www.microsoft.com/en-us/microsoft-cloud/blog/2025/05/07/empowering-multi-agent-apps-with-the-open-agent2agent-a2a-protocol/) - [MindsDB](https://mindsdb.com/blog/mindsdb-now-supports-the-agent2agent-(a2a)-protocol) - [McKinsey](https://www.mckinsey.com) - [MongoDB](https://www.mongodb.com) - [Monite](https://monite.com/) - [Neo4j](https://neo4j.com) - [New Relic](https://newrelic.com) - [Nisum](http://www.nisum.com) - [Noorle Inc](http://www.noorle.com) - [NTT DATA](https://www.nttdata.com) - [Optimizely Inc](https://www.optimizely.com/) - [Oracle / NetSuite](https://www.oracle.com/netsuite) - [Palo Alto Networks](https://www.paloaltonetworks.com/) - [PancakeAI](https://www.pancakeai.tech/) - [ParkourSC](https://www.parkoursc.com/) - [Pendo](https://www.pendo.io) - [PerfAI.ai](https://perfai.ai) - [Personal AI](https://personal.ai) - [Poppulo](https://www.poppulo.com/blog/poppulo-google-a2a-the-future-of-workplace-communication) - [Productive Edge](https://www.productiveedge.com/) - [Proofs](https://proofs.io) - [Publicis Sapient](https://www.publicissapient.com/) - [PWC](https://www.pwc.com) - [Quantiphi](https://www.quantiphi.com) - [Radix](https://radix.website/) - [RagaAI Inc](https://raga.ai/) - [Red Hat](https://www.redhat.com) - [Reltio Inc](http://www.reltio.com) - [S&P](https://www.spglobal.com) - [Sage](https://www.sage.com/en-us/) - [Salesforce](https://www.salesforce.com) - [SAP](https://news.sap.com/2025/04/sap-google-cloud-enterprise-ai-open-agent-collaboration-model-choice-multimodal-intelligence/) - [Sayone Technologies](https://www.sayonetech.com/) - [ServiceNow](https://www.servicenow.com) - [Siemens AG](https://siemens.com/) - [SoftBank Corp](https://www.softbank.jp/en//) - [Solace](https://solace.com/products/agent-mesh/) - [Solo.io](https://www.solo.io/) - [Space Auto](https://space.auto/) - [Stacklok, Inc](https://stacklok.com) - [Strale](https://strale.dev) - [Supertab](https://www.supertab.co/post/supertab-connect-partners-with-google-cloud-to-enable-ai-agents) - [Suzega](https://suzega.com/) - [TCS](https://www.tcs.com) - [Tech Mahindra](https://www.techmahindra.com/) - [Telefonica](https://www.telefonica.com/) - [Test Innovation Technology](https://www.test-it.com) - [the artinet project](https://artinet.io/) - [Think41](http://www.think41.com) - [Thoughtworks](https://www.thoughtworks.com/) - [Tredence](http://www.tredence.com) - [Two Tall Totems Ltd. DBA TTT Studios](https://ttt.studio) - [Typeface](https://typeface.ai) - [UKG](https://www.ukg.com) - [UiPath](https://www.uipath.com/newsroom/uipath-launches-first-enterprise-grade-platform-for-agentic-automation) - [Upwork, Inc.](https://www.upwork.com/) - [Ushur, Inc.](http://ushur.ai) - [Valle AI](http://www.valleai.com.br) - [Valtech](https://www.valtech.com/) - [Vervelo](https://www.vervelo.com/) - [VoltAgent](https://voltagent.dev/) - [Weights & Biases](https://wandb.ai/wandb_fc/product-announcements-fc/reports/Powering-Agent-Collaboration-Weights-Biases-Partners-with-Google-Cloud-on-Agent2Agent-Interoperability-Protocol---VmlldzoxMjE3NDg3OA) - [Wipro](https://www.wipro.com) - [Workday](https://www.workday.com) - [WritBase](https://github.com/Writbase/writbase) - [Writer](https://writer.com) - [Zenity](https://zenity.io) - [Zeotap](https://www.zeotap.com) - [Zocket Technologies , Inc.](https://zocket.ai) - [Zoom](https://www.zoom.us) - [zyprova](http://www.zyprova.com) # A2A protocol roadmap **Last updated:** March 10, 2026 ## Near-term initiatives - Release `1.0` version of the protocol which represents significant maturation of the protocol with enhanced clarity, stronger specifications, and important structural improvements. - [What's New in A2A Protocol v1.0](https://a2a-protocol.org/latest/whats-new-v1/) has further updates. - Continue to support additional [A2A extensions](topics/extensions.md) with SDK support. - Prioritize community-led development with standardized processes for contributing to the specification, SDKs and tooling. To review recent protocol changes see [Release Notes](https://github.com/a2aproject/A2A/releases). ## Longer term (3-6 month period) roadmap ### Governance The TSC looks to streamline opportunities for contribution through [A2A extensions](topics/extensions.md), [Samples](https://github.com/a2aproject/a2a-samples) and participation. ### Validation As the A2A ecosystem matures, it becomes critical for the A2A community to have tools to validate their agents. The community has launched two efforts to help with validation. Learn more about [A2A Inspector](https://github.com/a2aproject/a2a-inspector) and the [A2A Protocol Technology Compatibility Kit](https://github.com/a2aproject/a2a-tck) (TCK). ### SDKs A2A Project currently hosts SDKs in six languages (Python, Go, JS, Java, .NET, and Rust). ### Community best practices As companies and individuals deploy A2A systems at an increasing pace, we are looking to accelerate the learning of the community by collecting and sharing the best practices and success stories that A2A enabled. # A2A SDK The following table lists the supported languages for official A2A SDKs and their repositories. | Language | Repository | |------------|----------------------------------------------------------| | Python | [`a2a-python`](https://github.com/a2aproject/a2a-python) | | Go | [`a2a-go`](https://github.com/a2aproject/a2a-go) | | Java | [`a2a-java`](https://github.com/a2aproject/a2a-java) | | JavaScript | [`a2a-js`](https://github.com/a2aproject/a2a-js) | | C#/.NET | [`a2a-dotnet`](https://github.com/a2aproject/a2a-dotnet) | | Rust | [`a2a-rs`](https://github.com/a2aproject/a2a-rs) | The A2A project provides numerous samples across supported languages in the [a2a-samples repository](https://github.com/a2aproject/a2a-samples). # Agent2Agent (A2A) Protocol Specification ??? note "**Latest Released Version** [`1.0.0`](https://a2a-protocol.org/v1.0.0/specification)" **Previous Versions** - [`0.3.0`](https://a2a-protocol.org/v0.3.0/specification) - [`0.2.6`](https://a2a-protocol.org/v0.2.6/specification) - [`0.1.0`](https://a2a-protocol.org/v0.1.0/specification) See [Release Notes](https://github.com/a2aproject/A2A/releases) for changes made between versions. ## 1. Introduction The Agent2Agent (A2A) Protocol is an open standard designed to facilitate communication and interoperability between independent, potentially opaque AI agent systems. In an ecosystem where agents might be built using different frameworks, languages, or by different vendors, A2A provides a common language and interaction model. This document provides the detailed technical specification for the A2A protocol. Its primary goal is to enable agents to: - Discover each other's capabilities. - Negotiate interaction modalities (text, files, structured data). - Manage collaborative tasks. - Securely exchange information to achieve user goals **without needing access to each other's internal state, memory, or tools.** ### 1.1. Key Goals of A2A - **Interoperability:** Bridge the communication gap between disparate agentic systems. - **Collaboration:** Enable agents to delegate tasks, exchange context, and work together on complex user requests. - **Discovery:** Allow agents to dynamically find and understand the capabilities of other agents. - **Flexibility:** Support various interaction modes including synchronous request/response, streaming for real-time updates, and asynchronous push notifications for long-running tasks. - **Security:** Facilitate secure communication patterns suitable for enterprise environments, relying on standard web security practices. - **Asynchronicity:** Natively support long-running tasks and interactions that may involve human-in-the-loop scenarios. ### 1.2. Guiding Principles - **Simple:** Reuse existing, well-understood standards (HTTP, JSON-RPC 2.0, Server-Sent Events). - **Enterprise Ready:** Address authentication, authorization, security, privacy, tracing, and monitoring by aligning with established enterprise practices. - **Async First:** Designed for (potentially very) long-running tasks and human-in-the-loop interactions. - **Modality Agnostic:** Support exchange of diverse content types including text, audio/video (via file references), structured data/forms, and potentially embedded UI components (e.g., iframes referenced in parts). - **Opaque Execution:** Agents collaborate based on declared capabilities and exchanged information, without needing to share their internal thoughts, plans, or tool implementations. For a broader understanding of A2A's purpose and benefits, see [What is A2A?](./topics/what-is-a2a.md). ### 1.3. Specification Structure This specification is organized into three distinct layers that work together to provide a complete protocol definition: ```mermaid graph TB subgraph L1 ["A2A Data Model"] direction LR A[Task] ~~~ B[Message] ~~~ C[AgentCard] ~~~ D[Part] ~~~ E[Artifact] ~~~ F[Extension] end subgraph L2 ["A2A Operations"] direction LR G[Send Message] ~~~ H[Send Streaming Message] ~~~ I[Get Task] ~~~ J[List Tasks] ~~~ K[Cancel Task] ~~~ L[Get Agent Card] end subgraph L3 ["Protocol Bindings"] direction LR M[JSON-RPC Methods] ~~~ N[gRPC RPCs] ~~~ O[HTTP/REST Endpoints] ~~~ P[Custom Bindings] end %% Dependencies between layers L1 --> L2 L2 --> L3 style A fill:#e1f5fe style B fill:#e1f5fe style C fill:#e1f5fe style D fill:#e1f5fe style E fill:#e1f5fe style F fill:#e1f5fe style G fill:#f3e5f5 style H fill:#f3e5f5 style I fill:#f3e5f5 style J fill:#f3e5f5 style K fill:#f3e5f5 style L fill:#f3e5f5 style M fill:#e8f5e8 style N fill:#e8f5e8 style O fill:#e8f5e8 style L1 fill:#f0f8ff,stroke:#333,stroke-width:2px style L2 fill:#faf0ff,stroke:#333,stroke-width:2px style L3 fill:#f0fff0,stroke:#333,stroke-width:2px ``` **Layer 1: Canonical Data Model** defines the core data structures and message formats that all A2A implementations must understand. These are protocol agnostic definitions expressed as Protocol Buffer messages. **Layer 2: Abstract Operations** describes the fundamental capabilities and behaviors that A2A agents must support, independent of how they are exposed over specific protocols. **Layer 3: Protocol Bindings** provides concrete mappings of the abstract operations and data structures to specific protocol bindings (JSON-RPC, gRPC, HTTP/REST), including method names, endpoint patterns, and protocol-specific behaviors. This layered approach ensures that: - Core semantics remain consistent across all protocol bindings - New protocol bindings can be added without changing the fundamental data model - Developers can reason about A2A operations independently of binding concerns - Interoperability is maintained through shared understanding of the canonical data model ### 1.4 Normative Content In addition to the protocol requirements defined in this document, the file `spec/a2a.proto` is the single authoritative normative definition of all protocol data objects and request/response messages. A generated JSON artifact (`spec/a2a.json`, produced at build time and not committed) MAY be published for convenience to tooling and the website, but it is a non-normative build artifact. SDK language bindings, schemas, and any other derived forms **MUST** be regenerated from the proto (directly or via code generation) rather than edited manually. **Change Control and Deprecation Lifecycle:** - Introduction: When a proto message or field is renamed, the new name is added while existing published names remain available, but marked deprecated, until the next major release. - Documentation: Migration guidance MUST be provided via an ancillary document when introducing major breaking changes. - Anchors: Legacy documentation anchors MUST be preserved (as hidden HTML anchors) to avoid breaking inbound links. - SDK/Schema Aliases: SDKs and JSON Schemas SHOULD provide deprecated alias types/definitions to maintain backward compatibility. - Removal: A deprecated name SHOULD NOT be removed earlier than the next major version after introduction of its replacement. **Automated Generation:** The documentation build generates `specification/json/a2a.json` on-the-fly (the file is not tracked in source control). Future improvements may publish an OpenAPI v3 + JSON Schema bundle for enhanced tooling. **Rationale:** Centering the proto file as the normative source ensures protocol neutrality, reduces specification drift, and provides a deterministic evolution path for the ecosystem. ## 2. Terminology ### 2.1. Requirements Language The keywords "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in [RFC 2119](https://tools.ietf.org/html/rfc2119). ### 2.2. Core Concepts A2A revolves around several key concepts. For detailed explanations, please refer to the [Key Concepts guide](./topics/key-concepts.md). - **A2A Client:** An application or agent that initiates requests to an A2A Server on behalf of a user or another system. - **A2A Server (Remote Agent):** An agent or agentic system that exposes an A2A-compliant endpoint, processing tasks and providing responses. - **Agent Card:** A JSON metadata document published by an A2A Server, describing its identity, capabilities, skills, service endpoint, and authentication requirements. - **Message:** A communication turn between a client and a remote agent, having a `role` ("user" or "agent") and containing one or more `Parts`. - **Task:** The fundamental unit of work managed by A2A, identified by a unique ID. Tasks are stateful and progress through a defined lifecycle. - **Part:** The smallest unit of content within a Message or Artifact. Parts can contain text, file references, or structured data. - **Artifact:** An output (e.g., a document, image, structured data) generated by the agent as a result of a task, composed of `Parts`. - **Streaming:** Real-time, incremental updates for tasks (status changes, artifact chunks) delivered via protocol-specific streaming mechanisms. - **Push Notifications:** Asynchronous task updates delivered via server-initiated HTTP POST requests to a client-provided webhook URL, for long-running or disconnected scenarios. - **Context:** An optional identifier to logically group related tasks and messages. - **Extension:** A mechanism for agents to provide additional functionality or data beyond the core A2A specification. ## 3. A2A Protocol Operations This section describes the core operations of the A2A protocol in a binding-independent manner. These operations define the fundamental capabilities that all A2A implementations must support, regardless of the underlying binding mechanism. ### 3.1. Core Operations The following operations define the fundamental capabilities that all A2A implementations must support, independent of the specific protocol binding used. For a quick reference mapping of these operations to protocol-specific method names and endpoints, see [Section 5.3 (Method Mapping Reference)](#53-method-mapping-reference). For detailed protocol-specific implementation details, see: - [Section 9: JSON-RPC Protocol Binding](#9-json-rpc-protocol-binding) - [Section 10: gRPC Protocol Binding](#10-grpc-protocol-binding) - [Section 11: HTTP+JSON/REST Protocol Binding](#11-httpjsonrest-protocol-binding) #### 3.1.1. Send Message The primary operation for initiating agent interactions. Clients send a message to an agent and receive either a task that tracks the processing or a direct response message. **Inputs:** - [`SendMessageRequest`](#321-sendmessagerequest): Request object containing the message, configuration, and metadata **Outputs:** - [`Task`](#411-task): A task object representing the processing of the message, OR - [`Message`](#414-message): A direct response message (for simple interactions that don't require task tracking) **Errors:** - [`ContentTypeNotSupportedError`](#332-error-handling): A Media Type provided in the request's message parts is not supported by the agent. - [`UnsupportedOperationError`](#332-error-handling): Messages sent to Tasks that are in a terminal state (`TASK_STATE_COMPLETED`, `TASK_STATE_FAILED`, `TASK_STATE_CANCELED`, `TASK_STATE_REJECTED`) cannot accept further messages. - [`TaskNotFoundError`](#332-error-handling): The task ID does not exist or is not accessible. **Behavior:** The agent MAY create a new `Task` to process the provided message asynchronously or MAY return a direct `Message` response for simple interactions. The operation MUST return immediately with either task information or response message. Task processing MAY continue asynchronously after the response when a [`Task`](#411-task) is returned. #### 3.1.2. Send Streaming Message Similar to Send Message but with real-time streaming of updates during processing. **Inputs:** - [`SendMessageRequest`](#321-sendmessagerequest): Request object containing the message, configuration, and metadata **Outputs:** - [`Stream Response`](#323-stream-response) object containing: - Initial response: [`Task`](#411-task) object OR [`Message`](#414-message) object - Subsequent events following a `Task` MAY include stream of [`TaskStatusUpdateEvent`](#421-taskstatusupdateevent) and [`TaskArtifactUpdateEvent`](#422-taskartifactupdateevent) objects - Final completion indicator **Errors:** - [`UnsupportedOperationError`](#332-error-handling): Streaming is not supported by the agent (see [Capability Validation](#334-capability-validation)). - [`UnsupportedOperationError`](#332-error-handling): Messages sent to Tasks that are in a terminal state (`TASK_STATE_COMPLETED`, `TASK_STATE_FAILED`, `TASK_STATE_CANCELED`, `TASK_STATE_REJECTED`) cannot accept further messages. - [`ContentTypeNotSupportedError`](#332-error-handling): A Media Type provided in the request's message parts is not supported by the agent. - [`TaskNotFoundError`](#332-error-handling): The task ID does not exist or is not accessible. **Behavior:** The operation MUST establish a streaming connection for real-time updates. The stream MUST follow one of these patterns: 1. **Message-only stream:** If the agent returns a [`Message`](#414-message), the stream MUST contain exactly one `Message` object and then close immediately. No task tracking or updates are provided. 2. **Task lifecycle stream:** If the agent returns a [`Task`](#411-task), the stream MUST begin with the Task object, followed by zero or more [`TaskStatusUpdateEvent`](#421-taskstatusupdateevent) or [`TaskArtifactUpdateEvent`](#422-taskartifactupdateevent) objects. The stream MUST close when the task reaches a terminal state (`TASK_STATE_COMPLETED`, `TASK_STATE_FAILED`, `TASK_STATE_CANCELED`, `TASK_STATE_REJECTED`). The agent MAY return a `Task` for complex processing with status/artifact updates or MAY return a `Message` for direct streaming responses without task overhead. The implementation MUST provide immediate feedback on progress and intermediate results. #### 3.1.3. Get Task Retrieves the current state (including status, artifacts, and optionally history) of a previously initiated task. This is typically used for polling the status of a task initiated with Send Message, or for fetching the final state of a task after being notified via a push notification or after a stream has ended. **Inputs:** {{ proto_to_table("GetTaskRequest") }} See [History Length Semantics](#324-history-length-semantics) for details about `historyLength`. **Outputs:** - [`Task`](#411-task): Current state and artifacts of the requested task **Errors:** - [`TaskNotFoundError`](#332-error-handling): The task ID does not exist or is not accessible. #### 3.1.4. List Tasks Retrieves a list of tasks with optional filtering and pagination capabilities. This method allows clients to discover and manage multiple tasks across different contexts or with specific status criteria. **Inputs:** {{ proto_to_table("ListTasksRequest") }} When `includeArtifacts` is false (the default), the artifacts field MUST be omitted entirely from each Task object in the response. The field should not be present as an empty array or null value. When `includeArtifacts` is true, the artifacts field should be included with its actual content (which may be an empty array if the task has no artifacts). **Outputs:** {{ proto_to_table("ListTasksResponse") }} Note on `nextPageToken`: The `nextPageToken` field MUST always be present in the response. When there are no more results to retrieve (i.e., this is the final page), the field MUST be set to an empty string (""). Clients should check for an empty string to determine if more pages are available. **Errors:** None specific to this operation beyond standard protocol errors. **Behavior:** The operation MUST return only tasks visible to the authenticated client and MUST use cursor-based pagination for performance and consistency. Tasks MUST be sorted by last update time in descending order. Implementations MUST implement appropriate authorization scoping to ensure clients can only access authorized tasks. See [Section 13.1 Data Access and Authorization Scoping](#131-data-access-and-authorization-scoping) for detailed security requirements. ***Pagination Strategy:*** This method uses cursor-based pagination (via `pageToken`/`nextPageToken`) rather than offset-based pagination for better performance and consistency, especially with large datasets. Cursor-based pagination avoids the "deep pagination problem" where skipping large numbers of records becomes inefficient for databases. This approach is consistent with the gRPC specification, which also uses cursor-based pagination (page_token/next_page_token). ***Ordering:*** Implementations MUST return tasks sorted by their status timestamp time in descending order (most recently updated tasks first). This ensures consistent pagination and allows clients to efficiently monitor recent task activity. #### 3.1.5. Cancel Task Requests the cancellation of an ongoing task. The server will attempt to cancel the task, but success is not guaranteed (e.g., the task might have already completed or failed, or cancellation might not be supported at its current stage). **Inputs:** {{ proto_to_table("CancelTaskRequest") }} **Outputs:** - Updated [`Task`](#411-task) with cancellation status **Errors:** - [`TaskNotCancelableError`](#332-error-handling): The task is not in a cancelable state (e.g., already completed, failed, or canceled). - [`TaskNotFoundError`](#332-error-handling): The task ID does not exist or is not accessible. **Behavior:** The operation attempts to cancel the specified task and returns its updated state. #### 3.1.6. Subscribe to Task Establishes a streaming connection to receive updates for an existing task. **Inputs:** {{ proto_to_table("SubscribeToTaskRequest") }} **Outputs:** - [`Stream Response`](#323-stream-response) object containing: - Initial response: [`Task`](#411-task) object with current state - Stream of [`TaskStatusUpdateEvent`](#421-taskstatusupdateevent) and [`TaskArtifactUpdateEvent`](#422-taskartifactupdateevent) objects **Errors:** - [`UnsupportedOperationError`](#332-error-handling): Streaming is not supported by the agent (see [Capability Validation](#334-capability-validation)). - [`TaskNotFoundError`](#332-error-handling): The task ID does not exist or is not accessible. - [`UnsupportedOperationError`](#332-error-handling): The operation is attempted on a task that is in a terminal state (`TASK_STATE_COMPLETED`, `TASK_STATE_FAILED`, `TASK_STATE_CANCELED`, `TASK_STATE_REJECTED`). **Behavior:** The operation enables real-time monitoring of task progress and can be used with any task that is not in a terminal state. The stream MUST terminate when the task reaches a terminal state (`TASK_STATE_COMPLETED`, `TASK_STATE_FAILED`, `TASK_STATE_CANCELED`, `TASK_STATE_REJECTED`). The operation MUST return a `Task` object as the first event in the stream, representing the current state of the task at the time of subscription. This prevents a potential loss of information between a call to `GetTask` and calling `SubscribeToTask`. #### 3.1.7. Create Push Notification Config Creates a push notification configuration for a task to receive asynchronous updates via webhook. **Inputs:** {{ proto_to_table("TaskPushNotificationConfig") }} **Outputs:** - [`PushNotificationConfig`](#431-pushnotificationconfig): Created configuration with assigned ID **Errors:** - [`PushNotificationNotSupportedError`](#332-error-handling): Push notifications are not supported by the agent (see [Capability Validation](#334-capability-validation)). - [`TaskNotFoundError`](#332-error-handling): The task ID does not exist or is not accessible. **Behavior:** The operation MUST establish a webhook endpoint for task update notifications. When task updates occur, the agent will send HTTP POST requests to the configured webhook URL with [`StreamResponse`](#323-stream-response) payloads (see [Push Notification Payload](#433-push-notification-payload) for details). This operation is only available if the agent supports push notifications capability. The configuration MUST persist until task completion or explicit deletion. #### 3.1.8. Get Push Notification Config Retrieves an existing push notification configuration for a task. **Inputs:** {{ proto_to_table("GetTaskPushNotificationConfigRequest") }} **Outputs:** - [`PushNotificationConfig`](#431-pushnotificationconfig): The requested configuration **Errors:** - [`PushNotificationNotSupportedError`](#332-error-handling): Push notifications are not supported by the agent (see [Capability Validation](#334-capability-validation)). - [`TaskNotFoundError`](#332-error-handling): The push notification configuration does not exist. **Behavior:** The operation MUST return configuration details including webhook URL and notification settings. The operation MUST fail if the configuration does not exist or the client lacks access. #### 3.1.9. List Push Notification Configs Retrieves all push notification configurations for a task. **Inputs:** {{ proto_to_table("ListTaskPushNotificationConfigsRequest") }} **Outputs:** {{ proto_to_table("ListTaskPushNotificationConfigsResponse") }} **Errors:** - [`PushNotificationNotSupportedError`](#332-error-handling): Push notifications are not supported by the agent (see [Capability Validation](#334-capability-validation)). - [`TaskNotFoundError`](#332-error-handling): The task ID does not exist or is not accessible. **Behavior:** The operation MUST return all active push notification configurations for the specified task and MAY support pagination for tasks with many configurations. #### 3.1.10. Delete Push Notification Config Removes a push notification configuration for a task. **Inputs:** {{ proto_to_table("DeleteTaskPushNotificationConfigRequest") }} **Outputs:** - Confirmation of deletion (implementation-specific) **Errors:** - [`PushNotificationNotSupportedError`](#332-error-handling): Push notifications are not supported by the agent (see [Capability Validation](#334-capability-validation)). - [`TaskNotFoundError`](#332-error-handling): The task ID does not exist. **Behavior:** The operation MUST permanently remove the specified push notification configuration. No further notifications will be sent to the configured webhook after deletion. This operation MUST be idempotent - multiple deletions of the same config have the same effect. #### 3.1.11. Get Extended Agent Card Retrieves a potentially more detailed version of the Agent Card after the client has authenticated. This endpoint is available only if `AgentCard.capabilities.extendedAgentCard` is `true`. **Inputs:** {{ proto_to_table("GetExtendedAgentCardRequest") }} **Outputs:** - [`AgentCard`](#441-agentcard): A complete Agent Card object, which may contain additional details or skills not present in the public card **Errors:** - [`UnsupportedOperationError`](#332-error-handling): The agent does not support authenticated extended cards (see [Capability Validation](#334-capability-validation)). - [`ExtendedAgentCardNotConfiguredError`](#332-error-handling): The agent declares support but does not have an extended agent card configured. **Behavior:** - **Authentication**: The client MUST authenticate the request using one of the schemes declared in the public `AgentCard.securitySchemes` and `AgentCard.security` fields. - **Extended Information**: The operation MAY return different details based on client authentication level, including additional skills, capabilities, or configuration not available in the public Agent Card. - **Card Replacement**: Clients retrieving this extended card SHOULD replace their cached public Agent Card with the content received from this endpoint for the duration of their authenticated session or until the card's version changes. - **Availability**: This operation is only available if the public Agent Card declares `capabilities.extendedAgentCard: true`. For detailed security guidance on extended agent cards, see [Section 13.3 Extended Agent Card Access Control](#133-extended-agent-card-access-control). ### 3.2. Operation Parameter Objects This section defines common parameter objects used across multiple operations. #### 3.2.1. SendMessageRequest {{ proto_to_table("SendMessageRequest") }} #### 3.2.2. SendMessageConfiguration {{ proto_to_table("SendMessageConfiguration") }} **Execution Mode:** The `return_immediately` field in [`SendMessageConfiguration`](#322-sendmessageconfiguration) controls whether the operation returns immediately or waits for task completion. Operations are blocking by default: - **Blocking (`return_immediately: false` or unset)**: The operation MUST wait until the task reaches a terminal state (`TASK_STATE_COMPLETED`, `TASK_STATE_FAILED`, `TASK_STATE_CANCELED`, `TASK_STATE_REJECTED`) or an interrupted state (`TASK_STATE_INPUT_REQUIRED`, `TASK_STATE_AUTH_REQUIRED`) before returning. The response MUST include the latest task state with all artifacts and status information. This is the default behavior. - **Non-Blocking (`return_immediately: true`)**: The operation MUST return immediately after creating the task, even if processing is still in progress. The returned task will have an in-progress state (e.g., `TASK_STATE_WORKING`, `TASK_STATE_INPUT_REQUIRED`). It is the caller's responsibility to poll for updates using [Get Task](#313-get-task), subscribe via [Subscribe to Task](#316-subscribe-to-task), or receive updates via push notifications. The `return_immediately` field has no effect: - when the operation returns a direct [`Message`](#414-message) response instead of a task. - for streaming operations, which always return updates in real-time. - on configured push notification configurations, which operates independently of execution mode. #### 3.2.3. Stream Response {{ proto_to_table("StreamResponse") }} This wrapper allows streaming endpoints to return different types of updates through a single response stream while maintaining type safety. #### 3.2.4. History Length Semantics The `historyLength` parameter appears in multiple operations and controls how much task history is returned in responses. This parameter follows consistent semantics across all operations: - **Unset/undefined**: No limit imposed; server returns its default amount of history (implementation-defined, may be all history) - **0**: No history should be returned; the `history` field SHOULD be omitted - **> 0**: Return at most this many recent messages from the task's history #### 3.2.5. Metadata A flexible key-value map for passing additional context or parameters with operations. Metadata keys and are strings and values can be any valid value that can be represented in JSON. [`Extensions`](#46-extensions) can be used to strongly type metadata values for specific use cases. #### 3.2.6 Service Parameters A key-value map for passing horizontally applicable context or parameters with case-insensitive string keys and case-sensitive string values. The transmission mechanism for these service parameter key-value pairs is defined by the specific protocol binding (e.g., HTTP headers for HTTP-based bindings, gRPC metadata for gRPC bindings). Custom protocol bindings **MUST** specify how service parameters are transmitted in their binding specification. **Standard A2A Service Parameters:** | Name | Description | Example Value | | :--------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------ | :-------------------------------------------------------------------------------------------- | | `A2A-Extensions` | Comma-separated list of extension URIs that the client wants to use for the request | `https://example.com/extensions/geolocation/v1,https://standards.org/extensions/citations/v1` | | `A2A-Version` | The A2A protocol version that the client is using. If the version is not supported, the agent returns [`VersionNotSupportedError`](#332-error-handling) | `0.3` | As service parameter names MAY need to co-exist with other parameters defined by the underlying transport protocol or infrastructure, all service parameters defined by this specification will be prefixed with `a2a-`. ### 3.3. Operation Semantics #### 3.3.1. Idempotency - **Get operations** (Get Task, List Tasks, Get Extended Agent Card) are naturally idempotent - **Send Message** operations MAY be idempotent. Agents may utilize the messageId to detect duplicate messages. - **Cancel Task** operations are idempotent - multiple cancellation requests have the same effect. A duplicate cancellation request MAY return `TaskNotFoundError` if the task has already been canceled and purged. #### 3.3.2. Error Handling All operations may return errors in the following categories. Servers **MUST** return appropriate errors and **SHOULD** provide actionable information to help clients resolve issues. **Error Categories and Server Requirements:** - **Authentication Errors**: Invalid or missing credentials - Servers **MUST** reject requests with invalid or missing authentication credentials - Servers **SHOULD** include authentication challenge information in the error response - Servers **SHOULD** specify which authentication scheme is required - Example error codes: HTTP `401 Unauthorized`, gRPC `UNAUTHENTICATED`, JSON-RPC custom error - Example scenarios: Missing bearer token, expired API key, invalid OAuth token - **Authorization Errors**: Insufficient permissions for requested operation - Servers **MUST** return an authorization error when the authenticated client lacks required permissions - Servers **SHOULD** indicate what permission or scope is missing (without leaking sensitive information about resources the client cannot access) - Servers **MUST NOT** reveal the existence of resources the client is not authorized to access - Example error codes: HTTP `403 Forbidden`, gRPC `PERMISSION_DENIED`, JSON-RPC custom error - Example scenarios: Attempting to access a task created by another user, insufficient OAuth scopes - **Validation Errors**: Invalid input parameters or message format - Servers **MUST** validate all input parameters before processing - Servers **SHOULD** specify which parameter(s) failed validation and why - Servers **SHOULD** provide guidance on valid parameter values or formats - Example error codes: HTTP `400 Bad Request`, gRPC `INVALID_ARGUMENT`, JSON-RPC `-32602 Invalid params` - Example scenarios: Invalid task ID format, missing required message parts, unsupported content type - **Resource Errors**: Requested task not found or not accessible - Servers **MUST** return a not found error when a requested resource does not exist or is not accessible to the authenticated client - Servers **SHOULD NOT** distinguish between "does not exist" and "not authorized" to prevent information leakage - Example error codes: HTTP `404 Not Found`, gRPC `NOT_FOUND`, JSON-RPC custom error (see A2A-specific errors) - Example scenarios: Task ID does not exist, task has been deleted, configuration not found - **System Errors**: Internal agent failures or temporary unavailability - Servers **SHOULD** return appropriate error codes for temporary failures vs. permanent errors - Servers **MAY** include retry guidance (e.g., Retry-After header in HTTP) - Servers **SHOULD** log system errors for diagnostic purposes - Example error codes: HTTP `500 Internal Server Error` or `503 Service Unavailable`, gRPC `INTERNAL` or `UNAVAILABLE`, JSON-RPC `-32603 Internal error` - Example scenarios: Database connection failure, downstream service timeout, rate limit exceeded **Error Payload Structure:** All error responses in the A2A protocol, regardless of binding, **MUST** convey the following information: 1. **Error Code**: A machine-readable identifier for the error type (e.g., string code, numeric code, or protocol-specific status) 2. **Error Message**: A human-readable description of the error 3. **Error Details** (optional): An array of objects providing additional structured information about the error. Each object in the array **MUST** include a `@type` key that identifies the object's type (using [ProtoJSON `Any` representation](https://protobuf.dev/programming-guides/json)). Well-known types from the [`google.rpc` error model](https://cloud.google.com/apis/design/errors#error_model) (e.g., `ErrorInfo`, `BadRequest`) **SHOULD** be used where applicable. Error details may be used for: - Affected fields or parameters - Contextual information (e.g., task ID, timestamp) - Suggestions for resolution Protocol bindings **MUST** map these elements to their native error representations while preserving semantic meaning. See binding-specific sections for concrete error format examples: [JSON-RPC Error Handling](#95-error-handling), [gRPC Error Handling](#106-error-handling), and [HTTP/REST Error Handling](#116-error-handling). **A2A-Specific Errors:** | Error Name | Description | | :------------------------------------ | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `TaskNotFoundError` | The specified task ID does not correspond to an existing or accessible task. It might be invalid, expired, or already completed and purged. | | `TaskNotCancelableError` | An attempt was made to cancel a task that is not in a cancelable state (e.g., it has already reached a terminal state like `TASK_STATE_COMPLETED`, `TASK_STATE_FAILED`, `TASK_STATE_CANCELED`, `TASK_STATE_REJECTED`). | | `PushNotificationNotSupportedError` | Client attempted to use push notification features but the server agent does not support them (i.e., `AgentCard.capabilities.pushNotifications` is `false`). | | `UnsupportedOperationError` | The requested operation or a specific aspect of it is not supported by this server agent implementation. | | `ContentTypeNotSupportedError` | A Media Type provided in the request's message parts or implied for an artifact is not supported by the agent or the specific skill being invoked. | | `InvalidAgentResponseError` | An agent returned a response that does not conform to the specification for the current method. | | `ExtendedAgentCardNotConfiguredError` | The agent does not have an extended agent card configured when one is required for the requested operation. | | `ExtensionSupportRequiredError` | Server requested use of an extension marked as `required: true` in the Agent Card but the client did not declare support for it in the request. | | `VersionNotSupportedError` | The A2A protocol version specified in the request (via `A2A-Version` service parameter) is not supported by the agent. | #### 3.3.3. Asynchronous Processing A2A operations are designed for asynchronous task execution. Operations return immediately with either [`Task`](#411-task) objects or [`Message`](#414-message) objects, and when a Task is returned, processing continues in the background. Clients retrieve task updates through polling, streaming, or push notifications (see [Section 3.5](#35-task-update-delivery-mechanisms)). Agents MAY accept additional messages for tasks in non-terminal states to enable multi-turn interactions (see [Section 3.4](#34-multi-turn-interactions)). #### 3.3.4. Capability Validation Agents declare optional capabilities in their [`AgentCard`](#441-agentcard). When clients attempt to use operations or features that require capabilities not declared as supported in the Agent Card, the agent **MUST** return an appropriate error response: - **Push Notifications**: If `AgentCard.capabilities.pushNotifications` is `false` or not present, operations related to push notification configuration (Create, Get, List, Delete) **MUST** return [`PushNotificationNotSupportedError`](#332-error-handling). - **Streaming**: If `AgentCard.capabilities.streaming` is `false` or not present, attempts to use `SendStreamingMessage` or `SubscribeToTask` operations **MUST** return [`UnsupportedOperationError`](#332-error-handling). - **Extended Agent Card**: If `AgentCard.capabilities.extendedAgentCard` is `false` or not present, attempts to call the Get Extended Agent Card operation **MUST** return [`UnsupportedOperationError`](#332-error-handling). If the agent declares support but has not configured an extended card, it **MUST** return [`ExtendedAgentCardNotConfiguredError`](#332-error-handling). - **Extensions**: When a server requests use of an extension marked as `required: true` in the Agent Card but the client does not declare support for it, the agent **MUST** return [`ExtensionSupportRequiredError`](#332-error-handling). Clients **SHOULD** validate capability support by examining the Agent Card before attempting operations that require optional capabilities. ### 3.4. Multi-Turn Interactions The A2A protocol supports multi-turn conversations through context identifiers and task references, enabling agents to maintain conversational continuity across multiple interactions. #### 3.4.1. Context Identifier Semantics A `contextId` is an identifier that logically groups multiple related [`Task`](#411-task) and [`Message`](#414-message) objects, providing continuity across a series of interactions. **Generation and Assignment:** - Agents **MAY** generate a new `contextId` when processing a [`Message`](#414-message) that does not include a `contextId` field - If an agent generates a new `contextId`, it **MUST** be included in the response (either [`Task`](#411-task) or [`Message`](#414-message)) - Agents **MAY** accept and preserve client-provided `contextId` values - If an agent cannot accept a client-provided `contextId`, it **MUST** reject the request with an error and **MUST NOT** generate a new `contextId` for the response - Clients **SHOULD NOT** provide a client-generated `contextId` to a server unless they understand how the server will process that `contextId` - Server-generated `contextId` values **SHOULD** be treated as opaque identifiers by clients **Grouping and Scope:** - A `contextId` logically groups multiple [`Task`](#411-task) objects and [`Message`](#414-message) objects that are part of the same conversational context - All tasks and messages with the same `contextId` **SHOULD** be treated as part of the same conversational session - Agents **MAY** use the `contextId` to maintain internal state, conversational history, or LLM context across multiple interactions - Agents **MAY** implement context expiration or cleanup policies and **SHOULD** document any such policies #### 3.4.2. Task Identifier Semantics A `taskId` is a unique identifier for a [`Task`](#411-task) object, representing a stateful unit of work with a defined lifecycle. **Generation and Assignment:** - Task IDs are **server-generated** when a new task is created in response to a [`Message`](#414-message) - Agents **MUST** generate a unique `taskId` for each new task they create - The generated `taskId` **MUST** be included in the [`Task`](#411-task) object returned to the client - When a client includes a `taskId` in a [`Message`](#414-message), it **MUST** reference an existing task - Agents **MUST** return a [`TaskNotFoundError`](#332-error-handling) if the provided `taskId` does not correspond to an existing task - Client-provided `taskId` values for creating new tasks is **NOT** supported #### 3.4.3. Multi-Turn Conversation Patterns The A2A protocol supports several patterns for multi-turn interactions: **Context Continuity:** - [`Task`](#411-task) objects maintain conversation context through the `contextId` field - Clients **MAY** include the `contextId` in subsequent messages to indicate continuation of a previous interaction - Clients **MAY** use `taskId` (with or without `contextId`) to continue or refine a specific task - Clients **MAY** use `contextId` without `taskId` to start a new task within an existing conversation context - Agents **MUST** infer `contextId` from the task if only `taskId` is provided - Agents **MUST** reject messages containing mismatching `contextId` and `taskId` (i.e., the provided `contextId` is different from that of the referenced [`Task`](#411-task)). **Input Required State:** - Agents can request additional input mid-processing by transitioning a task to the `input-required` state - The client continues the interaction by sending a new message with the same `taskId` and `contextId` **Follow-up Messages:** - Clients can send additional messages with `taskId` references to continue or refine existing tasks - Clients **SHOULD** use the `referenceTaskIds` field in [`Message`](#414-message) to explicitly reference related tasks - Agents **SHOULD** use referenced tasks to understand the context and intent of follow-up requests **Context Inheritance:** - New tasks created within the same `contextId` can inherit context from previous interactions - Agents **SHOULD** leverage the shared `contextId` to provide contextually relevant responses ### 3.5. Task Update Delivery Mechanisms The A2A protocol provides three complementary mechanisms for clients to receive updates about task progress and completion. #### 3.5.1. Overview of Update Mechanisms **Polling (Get Task):** - Client periodically calls Get Task ([Section 3.1.3](#313-get-task)) to check task status - Simple to implement, works with all protocol bindings - Higher latency, potential for unnecessary requests - Best for: Simple integrations, infrequent updates, clients behind restrictive firewalls **Streaming:** - Real-time delivery of events as they occur - Operations: Send Streaming Message ([Section 3.1.2](#312-send-streaming-message)) and Subscribe to Task ([Section 3.1.6](#316-subscribe-to-task)) - Low latency, efficient for frequent updates - Requires persistent connection support - Best for: Interactive applications, real-time dashboards, live progress monitoring - Requires `AgentCard.capabilities.streaming` to be `true` **Push Notifications (WebHooks):** - Agent sends HTTP POST requests to client-registered endpoints when task state changes - Client does not maintain persistent connection - Asynchronous delivery, client must be reachable via HTTP - Best for: Server-to-server integrations, long-running tasks, event-driven architectures - Operations: Create ([Section 3.1.7](#317-create-push-notification-config)), Get ([Section 3.1.8](#76-taskspushnotificationconfigget)), List ([Section 3.1.9](#319-list-push-notification-configs)), Delete ([Section 3.1.10](#3110-delete-push-notification-config)) - Event types: TaskStatusUpdateEvent ([Section 4.2.1](#421-taskstatusupdateevent)), TaskArtifactUpdateEvent ([Section 4.2.2](#422-taskartifactupdateevent)), WebHook payloads ([Section 4.3](#43-push-notification-objects)) - Requires `AgentCard.capabilities.pushNotifications` to be `true` - Regardless of the protocol binding being used by the agent, WebHook calls use plain HTTP and the JSON payloads as defined in the HTTP protocol binding #### 3.5.2. Streaming Event Delivery **Event Ordering:** All implementations MUST deliver events in the order they were generated. Events MUST NOT be reordered during transmission, regardless of protocol binding. **Multiple Streams Per Task:** An agent MAY serve multiple concurrent streams to one or more clients for the same task. This allows multiple clients (or the same client with multiple connections) to independently subscribe to and receive updates about a task's progress. When multiple streams are active for a task: - Events MUST be broadcast to all active streams for that task - Each stream MUST receive the same events in the same order - Closing one stream MUST NOT affect other active streams for the same task - The task lifecycle is independent of any individual stream's lifecycle This capability enables scenarios such as: - Multiple team members monitoring the same long-running task - A client reconnecting to a task after a network interruption by opening a new stream - Different applications or dashboards displaying real-time updates for the same task #### 3.5.3. Push Notification Delivery Push notifications are delivered via HTTP POST to client-registered webhook endpoints. The delivery semantics and reliability guarantees are defined in [Section 4.3](#43-push-notification-objects). ### 3.6 Versioning The specific version of the A2A protocol in use is identified using the `Major.Minor` elements (e.g. `1.0`) of the corresponding A2A specification version. Patch version numbers used by the specification, do not affect protocol compatibility. Patch version numbers SHOULD NOT be used in requests, responses and Agent Cards, and MUST not be considered when clients and servers negotiate protocol versions. #### 3.6.1 Client Responsibilities Clients MUST send the `A2A-Version` header with each request to maintain compatibility after an agent upgrades to a new version of the protocol (except for 0.3 Clients - 0.3 will be assumed for empty header). Sending the `A2A-Version` header also provides visibility to agents about version usage in the ecosystem, which can help inform the risks of inplace version upgrades. **Example of HTTP GET Request with Version Header:** ```http GET /tasks/task-123 HTTP/1.1 Host: agent.example.com A2A-Version: 1.0 Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... Accept: application/json ``` Clients MAY provide the `A2A-Version` as a request parameter instead of a header. **Example of HTTP GET Request with Version request parameter:** ```http GET /tasks/task-123?A2A-Version=1.0 HTTP/1.1 Host: agent.example.com Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... Accept: application/json ``` #### 3.6.2 Server Responsibilities Agents MUST process requests using the semantics of the requested `A2A-Version` (matching `Major.Minor`). If the version is not supported by the interface, agents MUST return a [`VersionNotSupportedError`](#332-error-handling). Agents MUST interpret empty value as 0.3 version. Agents CAN expose multiple interfaces for the same transport with different versions under the same or different URLs. #### 3.6.3 Tooling support Tooling libraries and SDKs that implement the A2A protocol MUST provide mechanisms to help clients manage protocol versioning, such as negotiation of the transport and protocol version used. Client Agents that require the latest features of the protocol should be configured to request specific versions and avoid automatic fallback to older versions, to prevent silently losing functionality. ### 3.7 Messages and Artifacts Messages and Artifacts serve distinct purposes within the A2A protocol. The core interaction model defined by A2A is for clients to send messages to initiate a task that produces one or more artifacts. Messages play several key roles: - **Task Initiation**: Clients send Messages to agents to initiate new tasks. - **Clarification Messages**: Agents may send Messages back to the client to request clarification prior to initiating a task. - **Status Messages**: Agents attach Messages to status update events to inform clients about task progress, request additional input, or provide informational updates. - **Task Interaction**: Clients send Messages to provide additional input or instructions for ongoing tasks. Messages SHOULD NOT be used to deliver task outputs. Results SHOULD BE returned using Artifacts associated with a Task. This separation allows for a clear distinction between communication (Messages) and data output (Artifacts). The Task History field contains Messages exchanged during task execution. However, not all Messages are guaranteed to be persisted in the Task history; for example, transient informational messages may not be stored. Messages exchanged prior to task creation may not be stored in Task history. The agent is responsible to determine which Messages are persisted in the Task History. Clients using streaming to retrieve task updates MAY not receive all status update messages if the client is disconnected and then reconnects. Messages MUST NOT be considered a reliable delivery mechanism for critical information. Agents MAY choose to persist all Messages that contain important information in the Task history to ensure clients can retrieve it later. However, clients MUST NOT rely on this behavior unless negotiated out-of-band. ## 4. Protocol Data Model The A2A protocol defines a canonical data model using Protocol Buffers. All protocol bindings **MUST** provide functionally equivalent representations of these data structures. ### 4.1. Core Objects #### 4.1.1. Task {{ proto_to_table("Task") }} #### 4.1.2. TaskStatus {{ proto_to_table("TaskStatus") }} #### 4.1.3. TaskState {{ proto_enum_to_table("TaskState") }} #### 4.1.4. Message {{ proto_to_table("Message") }} #### 4.1.5. Role {{ proto_enum_to_table("Role") }} #### 4.1.6. Part {{ proto_to_table("Part") }} #### 4.1.7. Artifact {{ proto_to_table("Artifact") }} ### 4.2. Streaming Events #### 4.2.1. TaskStatusUpdateEvent {{ proto_to_table("TaskStatusUpdateEvent") }} #### 4.2.2. TaskArtifactUpdateEvent {{ proto_to_table("TaskArtifactUpdateEvent") }} ### 4.3. Push Notification Objects #### 4.3.1. PushNotificationConfig {{ proto_to_table("PushNotificationConfig") }} #### 4.3.2. AuthenticationInfo {{ proto_to_table("AuthenticationInfo") }} #### 4.3.3. Push Notification Payload When a task update occurs, the agent sends an HTTP POST request to the configured webhook URL. The payload uses the same [`StreamResponse`](#323-stream-response) format as streaming operations, allowing push notifications to deliver the same event types as real-time streams. **Request Format:** ```http POST {webhook_url} Authorization: {authentication_scheme} {credentials} Content-Type: application/a2a+json { /* StreamResponse object - one of: */ "task": { /* Task object */ }, "message": { /* Message object */ }, "statusUpdate": { /* TaskStatusUpdateEvent object */ }, "artifactUpdate": { /* TaskArtifactUpdateEvent object */ } } ``` **Payload Structure:** The webhook payload is a [`StreamResponse`](#323-stream-response) object containing exactly one of the following: - **task**: A [`Task`](#411-task) object with the current task state - **message**: A [`Message`](#414-message) object containing a message response - **statusUpdate**: A [`TaskStatusUpdateEvent`](#421-taskstatusupdateevent) indicating a status change - **artifactUpdate**: A [`TaskArtifactUpdateEvent`](#422-taskartifactupdateevent) indicating artifact updates **Authentication:** The agent MUST include authentication credentials in the request headers as specified in the [`PushNotificationConfig.authentication`](#432-authenticationinfo) field. The format follows standard HTTP authentication patterns (Bearer tokens, Basic auth, etc.). **Client Responsibilities:** - Clients MUST respond with HTTP 2xx status codes to acknowledge successful receipt - Clients SHOULD process notifications idempotently, as duplicate deliveries may occur - Clients MUST validate the task ID matches an expected task - Clients SHOULD implement appropriate security measures to verify the notification source **Server Guarantees:** - Agents MUST attempt delivery at least once for each configured webhook - Agents MAY implement retry logic with exponential backoff for failed deliveries - Agents SHOULD include a reasonable timeout for webhook requests (recommended: 10-30 seconds) - Agents MAY stop attempting delivery after a configured number of consecutive failures For detailed security guidance on push notifications, see [Section 13.2 Push Notification Security](#132-push-notification-security). ### 4.4. Agent Discovery Objects #### 4.4.1. AgentCard {{ proto_to_table("AgentCard") }} #### 4.4.2. AgentProvider {{ proto_to_table("AgentProvider") }} #### 4.4.3. AgentCapabilities {{ proto_to_table("AgentCapabilities") }} #### 4.4.4. AgentExtension {{ proto_to_table("AgentExtension") }} #### 4.4.5. AgentSkill {{ proto_to_table("AgentSkill") }} #### 4.4.6. AgentInterface {{ proto_to_table("AgentInterface") }} #### 4.4.7. AgentCardSignature {{ proto_to_table("AgentCardSignature") }} ### 4.5. Security Objects #### 4.5.1. SecurityScheme {{ proto_to_table("SecurityScheme") }} #### 4.5.2. APIKeySecurityScheme {{ proto_to_table("APIKeySecurityScheme") }} #### 4.5.3. HTTPAuthSecurityScheme {{ proto_to_table("HTTPAuthSecurityScheme") }} #### 4.5.4. OAuth2SecurityScheme {{ proto_to_table("OAuth2SecurityScheme") }} #### 4.5.5. OpenIdConnectSecurityScheme {{ proto_to_table("OpenIdConnectSecurityScheme") }} #### 4.5.6. MutualTlsSecurityScheme {{ proto_to_table("MutualTlsSecurityScheme") }} #### 4.5.7. OAuthFlows {{ proto_to_table("OAuthFlows") }} #### 4.5.8. AuthorizationCodeOAuthFlow {{ proto_to_table("AuthorizationCodeOAuthFlow") }} #### 4.5.9. ClientCredentialsOAuthFlow {{ proto_to_table("ClientCredentialsOAuthFlow") }} #### 4.5.10. DeviceCodeOAuthFlow {{ proto_to_table("DeviceCodeOAuthFlow") }} ### 4.6. Extensions The A2A protocol supports extensions to provide additional functionality or data beyond the core specification while maintaining backward compatibility and interoperability. Extensions allow agents to declare additional capabilities such as protocol enhancements or vendor-specific features, maintain compatibility with clients that don't support specific extensions, enable innovation through experimental or domain-specific features without modifying the core protocol, and facilitate standardization by providing a pathway for community-developed features to become part of the core specification. #### 4.6.1. Extension Declaration Agents declare their supported extensions in the [`AgentCard`](#441-agentcard) using the `extensions` field, which contains an array of [`AgentExtension`](#444-agentextension) objects. *Example: Agent declaring extension support in AgentCard:* ```json { "name": "Research Assistant Agent", "description": "AI agent for academic research and fact-checking", "supportedInterfaces": [ { "url": "https://research-agent.example.com/a2a/v1", "protocolBinding": "HTTP+JSON", "protocolVersion": "0.3", } ], "capabilities": { "streaming": false, "pushNotifications": false, "extensions": [ { "uri": "https://standards.org/extensions/citations/v1", "description": "Provides citation formatting and source verification", "required": false }, { "uri": "https://example.com/extensions/geolocation/v1", "description": "Location-based search capabilities", "required": false } ] }, "defaultInputModes": ["text/plain"], "defaultOutputModes": ["text/plain"], "skills": [ { "id": "academic-research", "name": "Academic Research Assistant", "description": "Provides research assistance with citations and source verification", "tags": ["research", "citations", "academic"], "examples": ["Find peer-reviewed articles on climate change"], "inputModes": ["text/plain"], "outputModes": ["text/plain"] } ] } ``` Clients indicate their desire to opt into the use of specific extensions through binding-specific mechanisms such as HTTP headers, gRPC metadata, or JSON-RPC request parameters that identify the extension identifiers they wish to utilize during the interaction. *Example: HTTP client opting into extensions using headers:* ```http POST /message:send HTTP/1.1 Host: agent.example.com Content-Type: application/a2a+json Authorization: Bearer token A2A-Extensions: https://example.com/extensions/geolocation/v1,https://standards.org/extensions/citations/v1 { "message": { "role": "ROLE_USER", "parts": [{"text": "Find restaurants near me"}], "extensions": ["https://example.com/extensions/geolocation/v1"], "metadata": { "https://example.com/extensions/geolocation/v1": { "latitude": 37.7749, "longitude": -122.4194 } } } } ``` #### 4.6.2. Extensions Points Extensions can be integrated into the A2A protocol at several well-defined extension points: **Message Extensions:** Messages can be extended to allow clients to provide additional strongly typed context or parameters relevant to the message being sent, or TaskStatus Messages to include extra information about the task's progress. *Example: A location extension using the extensions and metadata arrays:* ```json { "role": "ROLE_USER", "parts": [ {"text": "Find restaurants near me"} ], "extensions": ["https://example.com/extensions/geolocation/v1"], "metadata": { "https://example.com/extensions/geolocation/v1": { "latitude": 37.7749, "longitude": -122.4194, "accuracy": 10.0, "timestamp": "2025-10-21T14:30:00Z" } } } ``` **Artifact Extensions:** Artifacts can include extension data to provide strongly typed context or metadata about the generated content. *Example: An artifact with citation extension for research sources:* ```json { "artifactId": "research-summary-001", "name": "Climate Change Summary", "parts": [ { "text": "Global temperatures have risen by 1.1°C since pre-industrial times, with significant impacts on weather patterns and sea levels." } ], "extensions": ["https://standards.org/extensions/citations/v1"], "metadata": { "https://standards.org/extensions/citations/v1": { "sources": [ { "title": "Global Temperature Anomalies - 2023 Report", "authors": ["Smith, J.", "Johnson, M."], "url": "https://climate.gov/reports/2023-temperature", "accessDate": "2025-10-21", "relevantText": "Global temperatures have risen by 1.1°C" } ] } } } ``` #### 4.6.3. Extension Versioning and Compatibility Extensions **SHOULD** include version information in their URI identifier. This allows clients and agents to negotiate compatible versions of extensions during interactions. A new URI **MUST** be created for breaking changes to an extension. If a client requests a versions of an extension that the agent does not support, the agent **SHOULD** ignore the extension for that interaction and proceed without it, unless the extension is marked as `required` in the AgentCard, in which case the agent **MUST** return an error indicating unsupported extension. It **MUST NOT** fall back to a previous version of the extension automatically. ## 5. Protocol Binding Requirements and Interoperability ### 5.1. Functional Equivalence Requirements When an agent supports multiple protocols, all supported protocols **MUST**: - **Identical Functionality**: Provide the same set of operations and capabilities - **Consistent Behavior**: Return semantically equivalent results for the same requests - **Same Error Handling**: Map errors consistently using appropriate protocol-specific codes - **Equivalent Authentication**: Support the same authentication schemes declared in the AgentCard ### 5.2. Protocol Selection and Negotiation - **Agent Declaration**: Agents **MUST** declare all supported protocols in their AgentCard - **Client Choice**: Clients **MAY** choose any protocol declared by the agent - **Fallback Behavior**: Clients **SHOULD** implement fallback logic for alternative protocols ### 5.3. Method Mapping Reference | Functionality | JSON-RPC Method | gRPC Method | REST Endpoint | | :------------------------------ | :--------------------------------- | :--------------------------------- | :------------------------------------------------------ | | Send message | `SendMessage` | `SendMessage` | `POST /message:send` | | Send streaming message | `SendStreamingMessage` | `SendStreamingMessage` | `POST /message:stream` | | Get task | `GetTask` | `GetTask` | `GET /tasks/{id}` | | List tasks | `ListTasks` | `ListTasks` | `GET /tasks` | | Cancel task | `CancelTask` | `CancelTask` | `POST /tasks/{id}:cancel` | | Subscribe to task | `SubscribeToTask` | `SubscribeToTask` | `POST /tasks/{id}:subscribe` | | Create push notification config | `CreateTaskPushNotificationConfig` | `CreateTaskPushNotificationConfig` | `POST /tasks/{id}/pushNotificationConfigs` | | Get push notification config | `GetTaskPushNotificationConfig` | `GetTaskPushNotificationConfig` | `GET /tasks/{id}/pushNotificationConfigs/{configId}` | | List push notification configs | `ListTaskPushNotificationConfigs` | `ListTaskPushNotificationConfigs` | `GET /tasks/{id}/pushNotificationConfigs` | | Delete push notification config | `DeleteTaskPushNotificationConfig` | `DeleteTaskPushNotificationConfig` | `DELETE /tasks/{id}/pushNotificationConfigs/{configId}` | | Get extended Agent Card | `GetExtendedAgentCard` | `GetExtendedAgentCard` | `GET /extendedAgentCard` | ### 5.4. Error Code Mappings All A2A-specific errors defined in [Section 3.3.2](#332-error-handling) **MUST** be mapped to binding-specific error representations. The following table provides the canonical mappings for each standard protocol binding: | A2A Error Type | JSON-RPC Code | gRPC Status | HTTP Status | | :------------------------------------ | :------------ | :-------------------- | :-------------------------- | | `TaskNotFoundError` | `-32001` | `NOT_FOUND` | `404 Not Found` | | `TaskNotCancelableError` | `-32002` | `FAILED_PRECONDITION` | `400 Bad Request` | | `PushNotificationNotSupportedError` | `-32003` | `FAILED_PRECONDITION` | `400 Bad Request` | | `UnsupportedOperationError` | `-32004` | `FAILED_PRECONDITION` | `400 Bad Request` | | `ContentTypeNotSupportedError` | `-32005` | `INVALID_ARGUMENT` | `400 Bad Request` | | `InvalidAgentResponseError` | `-32006` | `INTERNAL` | `500 Internal Server Error` | | `ExtendedAgentCardNotConfiguredError` | `-32007` | `FAILED_PRECONDITION` | `400 Bad Request` | | `ExtensionSupportRequiredError` | `-32008` | `FAILED_PRECONDITION` | `400 Bad Request` | | `VersionNotSupportedError` | `-32009` | `FAILED_PRECONDITION` | `400 Bad Request` | **Custom Binding Requirements:** Custom protocol bindings **MUST** define equivalent error code mappings that preserve the semantic meaning of each A2A error type. The binding specification **SHOULD** provide a similar mapping table showing how each A2A error type is represented in the custom binding's native error format. For binding-specific error structures and examples, see: - [JSON-RPC Error Handling](#95-error-handling) - [gRPC Error Handling](#106-error-handling) - [HTTP/REST Error Handling](#116-error-handling) ### 5.5. JSON Field Naming Convention All JSON serializations of the A2A protocol data model **MUST** use **camelCase** naming for field names, not the snake_case convention used in Protocol Buffer definitions. **Naming Convention:** - Protocol Buffer field: `protocol_version` → JSON field: `protocolVersion` - Protocol Buffer field: `context_id` → JSON field: `contextId` - Protocol Buffer field: `default_input_modes` → JSON field: `defaultInputModes` - Protocol Buffer field: `push_notification_config` → JSON field: `pushNotificationConfig` **Enum Values:** - Enum values **MUST** be represented according to the [ProtoJSON specification](https://protobuf.dev/programming-guides/json/), which serializes enums as their string names **as defined in the Protocol Buffer definition** (typically SCREAMING_SNAKE_CASE). **Examples:** - Protocol Buffer enum: `TASK_STATE_INPUT_REQUIRED` → JSON value: `"TASK_STATE_INPUT_REQUIRED"` - Protocol Buffer enum: `ROLE_USER` → JSON value: `"ROLE_USER"` **Note:** This follows the ProtoJSON specification as adopted in [ADR-001](../adrs/adr-001-protojson-serialization.md). ### 5.6. Data Type Conventions This section documents conventions for common data types used throughout the A2A protocol, particularly as they apply to protocol bindings. #### 5.6.1. Timestamps The A2A protocol uses [`google.protobuf.Timestamp`](https://protobuf.dev/reference/protobuf/google.protobuf/#timestamp) for all timestamp fields in the Protocol Buffer definitions. When serialized to JSON (in JSON-RPC, HTTP/REST, or other JSON-based bindings), these timestamps **MUST** be represented as ISO 8601 formatted strings in UTC timezone. **Format Requirements:** - **Format:** ISO 8601 combined date and time representation - **Timezone:** UTC (denoted by 'Z' suffix) - **Precision:** Millisecond precision **SHOULD** be used where available - **Pattern:** `YYYY-MM-DDTHH:mm:ss.sssZ` **Examples:** ```json { "timestamp": "2025-10-28T10:30:00.000Z", "createdAt": "2025-10-28T14:25:33.142Z", "lastModified": "2025-10-31T17:45:22.891Z" } ``` **Implementation Notes:** - Protocol Buffer's `google.protobuf.Timestamp` represents time as seconds since Unix epoch (January 1, 1970, 00:00:00 UTC) plus nanoseconds - JSON serialization automatically converts this to ISO 8601 format when using standard Protocol Buffer JSON encoding - Clients and servers **MUST** parse and generate ISO 8601 timestamps correctly - When millisecond precision is not available, the fractional seconds portion **MAY** be omitted or zero-filled - Timestamps **MUST NOT** include timezone offsets other than 'Z' (all times are UTC) ### 5.7. Field Presence and Optionality The Protocol Buffer definition in `specification/a2a.proto` uses [`google.api.field_behavior`](https://github.com/googleapis/googleapis/blob/master/google/api/field_behavior.proto) annotations to indicate whether fields are `REQUIRED`. These annotations serve as both documentation and validation hints for implementations. **Required Fields:** Fields marked with `[(google.api.field_behavior) = REQUIRED]` indicate that the field **MUST** be present and set in valid messages. Implementations **SHOULD** validate these requirements and reject messages with missing required fields. Arrays marked as required **MUST** contain at least one element. **Optional Field Presence:** The Protocol Buffer `optional` keyword is used to distinguish between a field being explicitly set versus omitted. This distinction is critical for two scenarios: 1. **Explicit Default Values:** Some fields in the specification define default values that differ from Protocol Buffer's implicit defaults. Implementations should apply the default value when the field is not explicitly provided. 2. **Agent Card Canonicalization:** When creating cryptographic signatures of Agent Cards, it is required to produce a canonical JSON representation. The `optional` keyword enables implementations to distinguish between fields that were explicitly set (and should be included in the canonical form) versus fields that were omitted (and should be excluded from canonicalization). This ensures Agent Cards can be reconstructed to accurately match their signature. **Unrecognized Fields:** Implementations **SHOULD** ignore unrecognized fields in messages, allowing for forward compatibility as the protocol evolves. ### 5.8. Custom Binding Identification Custom protocol bindings **SHOULD** be identified by a URI. Using a URI as the identifier provides globally unique identification across all implementers. The `protocolBinding` field in the Agent Card's `supportedInterfaces` entry **SHOULD** be a URI: ```json { "supportedInterfaces": [ { "url": "wss://agent.example.com/a2a/websocket", "protocolBinding": "https://example.com/bindings/websocket/v1", "protocolVersion": "1.0" } ] } ``` When a breaking change is introduced to a binding, a new URI **MUST** be used so that clients can distinguish between incompatible versions: ```text https://example.com/bindings/websocket/v1 → https://example.com/bindings/websocket/v2 ``` ## 6. Common Workflows & Examples This section provides illustrative examples of common A2A interactions across different bindings. ### 6.1. Basic Task Execution **Scenario:** Client asks a question and receives a completed task response. **Request:** ```http POST /message:send HTTP/1.1 Host: agent.example.com Content-Type: application/a2a+json Authorization: Bearer token { "message": { "role": "ROLE_USER", "parts": [{"text": "What is the weather today?"}], "messageId": "msg-uuid" } } ``` **Response:** ```http HTTP/1.1 200 OK Content-Type: application/a2a+json { "task": { "id": "task-uuid", "contextId": "context-uuid", "status": {"state": "TASK_STATE_COMPLETED"}, "artifacts": [{ "artifactId": "artifact-uuid", "name": "Weather Report", "parts": [{"text": "Today will be sunny with a high of 75°F"}] }] } } ``` ### 6.2. Streaming Task Execution **Scenario:** Client requests a long-running task with real-time updates. **Request:** ```http POST /message:stream HTTP/1.1 Host: agent.example.com Content-Type: application/a2a+json Authorization: Bearer token { "message": { "role": "ROLE_USER", "parts": [{"text": "Write a detailed report on climate change"}], "messageId": "msg-uuid" } } ``` **SSE Response Stream:** ```http HTTP/1.1 200 OK Content-Type: text/event-stream data: {"task": {"id": "task-uuid", "status": {"state": "TASK_STATE_WORKING"}}} data: {"artifactUpdate": {"taskId": "task-uuid", "artifact": {"parts": [{"text": "# Climate Change Report\n\n"}]}}} data: {"statusUpdate": {"taskId": "task-uuid", "status": {"state": "TASK_STATE_COMPLETED"}}} ``` ### 6.3. Multi-Turn Interaction **Scenario:** Agent requires additional input to complete a task. **Initial Request:** ```http POST /message:send HTTP/1.1 Host: agent.example.com Content-Type: application/a2a+json Authorization: Bearer token { "message": { "role": "ROLE_USER", "parts": [{"text": "Book me a flight"}], "messageId": "msg-1" } } ``` **Response (Input Required):** ```http HTTP/1.1 200 OK Content-Type: application/a2a+json { "task": { "id": "task-uuid", "status": { "state": "TASK_STATE_INPUT_REQUIRED", "message": { "role": "ROLE_AGENT", "parts": [{"text": "I need more details. Where would you like to fly from and to?"}] } } } } ``` **Follow-up Request:** ```http POST /message:send HTTP/1.1 Host: agent.example.com Content-Type: application/a2a+json Authorization: Bearer token { "message": { "taskId": "task-uuid", "role": "ROLE_USER", "parts": [{"text": "From San Francisco to New York"}], "messageId": "msg-2" } } ``` ### 6.4. Version Negotiation Error **Scenario:** Client requests an unsupported protocol version. **Request:** ```http POST /message:send HTTP/1.1 Host: agent.example.com Content-Type: application/a2a+json Authorization: Bearer token A2A-Version: 0.5 { "message": { "role": "ROLE_USER", "parts": [{"text": "Hello"}], "messageId": "msg-uuid" } } ``` **Response:** ```http HTTP/1.1 400 Bad Request Content-Type: application/problem+json { "type": "https://a2a-protocol.org/errors/version-not-supported", "title": "Protocol Version Not Supported", "status": 400, "detail": "The requested A2A protocol version 0.5 is not supported by this agent", "supportedVersions": ["0.3"] } ``` ### 6.5. Task Listing and Management **Scenario:** Client wants to see all tasks from a specific context or all tasks with a particular status. #### Request: All tasks from a specific context **Request:** ```http GET /tasks?contextId=c295ea44-7543-4f78-b524-7a38915ad6e4&pageSize=10&historyLength=3 HTTP/1.1 Host: agent.example.com Authorization: Bearer token ``` **Response:** ```http HTTP/1.1 200 OK Content-Type: application/a2a+json { "tasks": [ { "id": "3f36680c-7f37-4a5f-945e-d78981fafd36", "contextId": "c295ea44-7543-4f78-b524-7a38915ad6e4", "status": { "state": "TASK_STATE_COMPLETED", "timestamp": "2024-03-15T10:15:00Z" } } ], "totalSize": 5, "pageSize": 10, "nextPageToken": "" } ``` #### Request: All working tasks across all contexts **Request:** ```http GET /tasks?status=TASK_STATE_WORKING&pageSize=20 HTTP/1.1 Host: agent.example.com Authorization: Bearer token ``` **Response:** ```http HTTP/1.1 200 OK Content-Type: application/a2a+json { "tasks": [ { "id": "789abc-def0-1234-5678-9abcdef01234", "contextId": "another-context-id", "status": { "state": "TASK_STATE_WORKING", "message": { "role": "ROLE_AGENT", "parts": [ { "text": "Processing your document analysis..." } ], "messageId": "msg-status-update" }, "timestamp": "2024-03-15T10:20:00Z" } } ], "totalSize": 1, "pageSize": 20, "nextPageToken": "" } ``` #### Pagination Example **Request:** ```http GET /tasks?contextId=c295ea44-7543-4f78-b524-7a38915ad6e4&pageSize=10&pageToken=base64-encoded-cursor-token HTTP/1.1 Host: agent.example.com Authorization: Bearer token ``` **Response:** ```http HTTP/1.1 200 OK Content-Type: application/a2a+json { "tasks": [ /* ... additional tasks */ ], "totalSize": 15, "pageSize": 10, "nextPageToken": "base64-encoded-next-cursor-token" } ``` #### Validation Error Example **Request:** ```http GET /tasks?pageSize=150&historyLength=-5&status=TASK_STATE_RUNNING HTTP/1.1 Host: agent.example.com Authorization: Bearer token ``` **Response:** ```http HTTP/1.1 400 Bad Request Content-Type: application/problem+json { "status": 400, "detail": "Invalid parameters", "errors": [ { "field": "pageSize", "message": "Must be between 1 and 100 inclusive, got 150" }, { "field": "historyLength", "message": "Must be non-negative integer, got -5" }, { "field": "status", "message": "Invalid status value 'TASK_STATE_RUNNING'. Must be one of: TASK_STATE_SUBMITTED, TASK_STATE_WORKING, TASK_STATE_COMPLETED, TASK_STATE_FAILED, TASK_STATE_CANCELED, TASK_STATE_REJECTED, TASK_STATE_INPUT_REQUIRED, TASK_STATE_AUTH_REQUIRED" } ] } ``` ### 6.6. Push Notification Setup and Usage **Scenario:** Client requests a long-running report generation and wants to be notified via webhook when it's done. **Initial Request with Push Notification Config:** ```http POST /message:send HTTP/1.1 Host: agent.example.com Content-Type: application/a2a+json Authorization: Bearer token { "message": { "role": "ROLE_USER", "parts": [ { "text": "Generate the Q1 sales report. This usually takes a while. Notify me when it's ready." } ], "messageId": "6dbc13b5-bd57-4c2b-b503-24e381b6c8d6" }, "configuration": { "taskPushNotificationConfig": { "url": "https://client.example.com/webhook/a2a-notifications", "authentication": { "scheme": "Bearer", "credentials": "secure-client-token-for-task-aaa" } } } } ``` **Response (Task Submitted):** ```http HTTP/1.1 200 OK Content-Type: application/a2a+json { "task": { "id": "43667960-d455-4453-b0cf-1bae4955270d", "contextId": "c295ea44-7543-4f78-b524-7a38915ad6e4", "status": { "state": "TASK_STATE_SUBMITTED", "timestamp": "2024-03-15T11:00:00Z" } } } ``` **Later: Server POSTs Notification to Webhook:** ```http POST /webhook/a2a-notifications HTTP/1.1 Host: client.example.com Authorization: Bearer secure-client-token-for-task-aaa Content-Type: application/a2a+json { "statusUpdate": { "taskId": "43667960-d455-4453-b0cf-1bae4955270d", "contextId": "c295ea44-7543-4f78-b524-7a38915ad6e4", "status": { "state": "TASK_STATE_COMPLETED", "timestamp": "2024-03-15T18:30:00Z" } } } ``` ### 6.7. File Exchange (Upload and Download) **Scenario:** Client sends an image for analysis, and the agent returns a modified image. **Request with File Upload:** ```http POST /message:send HTTP/1.1 Host: agent.example.com Content-Type: application/a2a+json Authorization: Bearer token { "message": { "role": "ROLE_USER", "parts": [ { "text": "Analyze this image and highlight any faces." }, { "raw": "iVBORw0KGgoAAAANSUhEUgAAAAUA..." "filename": "input_image.png", "mediaType": "image/png", } ], "messageId": "6dbc13b5-bd57-4c2b-b503-24e381b6c8d6" } } ``` **Response with File Reference:** ```http HTTP/1.1 200 OK Content-Type: application/a2a+json { "task": { "id": "43667960-d455-4453-b0cf-1bae4955270d", "contextId": "c295ea44-7543-4f78-b524-7a38915ad6e4", "status": { "state": "TASK_STATE_COMPLETED", "timestamp": "2024-03-15T12:05:00Z" }, "artifacts": [ { "artifactId": "9b6934dd-37e3-4eb1-8766-962efaab63a1", "name": "processed_image_with_faces.png", "parts": [ { "url": "https://storage.example.com/processed/task-bbb/output.png?token=xyz", "filename": "output.png", "mediaType": "image/png" } ] } ] } } ``` ### 6.8. Structured Data Exchange **Scenario:** Client asks for a list of open support tickets in a specific JSON format. **Request:** ```http POST /message:send HTTP/1.1 Host: agent.example.com Content-Type: application/a2a+json Authorization: Bearer token { "message": { "role": "ROLE_USER", "parts": [ { "text": "Show me a list of my open IT tickets", "metadata": { "mediaType": "application/json", "schema": { "type": "array", "items": { "type": "object", "properties": { "ticketNumber": { "type": "string" }, "description": { "type": "string" } } } } } } ], "messageId": "85b26db5-ffbb-4278-a5da-a7b09dea1b47" } } ``` **Response with Structured Data:** ```http HTTP/1.1 200 OK Content-Type: application/a2a+json { "task": { "id": "d8c6243f-5f7a-4f6f-821d-957ce51e856c", "contextId": "c295ea44-7543-4f78-b524-7a38915ad6e4", "status": { "state": "TASK_STATE_COMPLETED", "timestamp": "2025-04-17T17:47:09.680794Z" }, "artifacts": [ { "artifactId": "c5e0382f-b57f-4da7-87d8-b85171fad17c", "parts": [ { "text": "[{\"ticketNumber\":\"REQ12312\",\"description\":\"request for VPN access\"},{\"ticketNumber\":\"REQ23422\",\"description\":\"Add to DL - team-gcp-onboarding\"}]" } ] } ] } } ``` ### 6.9. Fetching Authenticated Extended Agent Card **Scenario:** A client discovers a public Agent Card indicating support for an authenticated extended card and wants to retrieve the full details. **Step 1: Client fetches the public Agent Card:** ```http GET /.well-known/agent-card.json HTTP/1.1 Host: example.com ``` **Response includes:** ```json { "capabilities": { "extendedAgentCard": true }, "securitySchemes": { "google": { "openIdConnectSecurityScheme": { "openIdConnectUrl": "https://accounts.google.com/.well-known/openid-configuration" } } } } ``` ### Step 2: Client obtains credentials (out-of-band OAuth 2.0 flow) ### Step 3: Client fetches authenticated extended Agent Card ```http GET /extendedAgentCard HTTP/1.1 Host: agent.example.com Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... ``` **Response:** ```http HTTP/1.1 200 OK Content-Type: application/a2a+json { "name": "Extended Agent with Additional Skills", "skills": [ /* Extended skills available to authenticated users */ ] } ``` ## 7. Authentication and Authorization A2A treats agents as standard enterprise applications, relying on established web security practices. Identity information is handled at the protocol layer, not within A2A semantics. For a comprehensive guide on enterprise security aspects, see [Enterprise-Ready Features](./topics/enterprise-ready.md). ### 7.1. Protocol Security Production deployments **MUST** use encrypted communication (HTTPS for HTTP-based bindings, TLS for gRPC). Implementations **SHOULD** use modern TLS configurations (TLS 1.3+ recommended) with strong cipher suites. ### 7.2. Server Identity Verification A2A Clients **SHOULD** verify the A2A Server's identity by validating its TLS certificate against trusted certificate authorities (CAs) during the TLS handshake. ### 7.3. Client Authentication Process 1. **Discovery of Requirements:** The client discovers the server's required authentication schemes via the `securitySchemes` field in the AgentCard. 2. **Credential Acquisition (Out-of-Band):** The client obtains the necessary credentials through an out-of-band process specific to the required authentication scheme. 3. **Credential Transmission:** The client includes these credentials in protocol-appropriate headers or metadata for every A2A request. ### 7.4. Server Authentication Responsibilities The A2A Server: - **MUST** authenticate every incoming request based on the provided credentials and its declared authentication requirements. - **SHOULD** use appropriate binding-specific error codes for authentication challenges or rejections. - **SHOULD** provide relevant authentication challenge information with error responses. ### 7.5. Server Authorization Responsibilities Once authenticated, the A2A Server authorizes requests based on the authenticated identity and its own policies. Authorization logic is implementation-specific and **MAY** consider: - Specific skills requested - Actions attempted within tasks - Data access policies - OAuth scopes (if applicable) ### 7.6. In-Task Authorization In the course of performing a task, an agent may require authorization to perform some action. Examples include: - An agent requiring an OAuth access token to call an API or another agent - An agent requiring human approval before a destructive action is taken In the sections below, we refer to the object that represents the approved authorization as a credential. Agents may have multiple means for retrieving this authorization, such as via directly sending messages to a human. A2A provides the capability for agents to delegate the fulfillment of this authorization to the client via the `TASK_STATE_AUTH_REQUIRED` Task state. This provides agents a fallback path for requesting authorization by passing the responsibility to the client. #### 7.6.1 In-Task Authorization Agent Responsibilities To request that a client fulfills an authorization request, the agent: 1. MUST use a Task to track the operation it is performing 2. MUST transition the TaskState to `TASK_STATE_AUTH_REQUIRED` 3. MUST include a TaskStatus message explaining the required authorization, unless the details of the authorization have been negotiated out-of-band or via an extension Agents MUST arrange to receive credentials via an out-of-band means, unless an in-band mechanism has been negotiated out-of-band or via an extension. If the credential is received out-of-band, the agent SHOULD maintain any active response streams with the client after setting the TaskState to `TASK_STATE_AUTH_REQUIRED`. The agent MAY immediately continue Task processing after receiving the credential, without a requirement that clients send a follow-up message. Agents SHOULD support receiving messages directed to the Task while the Task remains in `TASK_STATE_AUTH_REQUIRED`. This enables clients to negotiate, correct, or reject an authorization request. #### 7.6.2 In-Task Authorization Client Responsibilities Upon receiving a Task in `TASK_STATE_AUTH_REQUIRED`, a client is expected to take action in some way to resolve the agent's request for authorization. A client may: - Send a response message to the Task to negotiate, correct, or reject the authorization request. - Contact another human, agent, or service to fulfill the authorization request - Directly fulfill the authorization request via an out-of-band or extension negotiated means If the client is itself an A2A agent actively processing a Task, the client may further delegate the authorization request to its client by transitioning its own Task to `TASK_STATE_AUTH_REQUIRED`. The client SHOULD follow all [In-Task Authorization Agent Responsibilities](#761-in-task-authorization-agent-responsibilities). This enables forming a chain of Tasks in `TASK_STATE_AUTH_REQUIRED`. Clients may not be aware of when the agent receives credentials out-of-band and subsequently continues Task processing. If a client does not have an active response stream open with the agent, the client risks missing Task updates. To avoid this, a client SHOULD perform one of the following: - Subscribe to a stream of events for the Task using the [Subscribe to Task](#316-subscribe-to-task) operation - Register a webhook to receive events, if supported by the agent, using the [Create Push Notification Config](#317-create-push-notification-config) operation - Begin polling the Task using the [Get Task](#313-get-task) operation #### 7.6.3 In-Task Authorization Security Considerations Agents SHOULD receive credentials for in-task authorization requests out of band via a secure channel, such as HTTPS. This ensures that credentials are provided directly to the agent. In-band credential exchange may be negotiated via out-of-band means or by using extensions. In-band credential exchange can allow credentials to be passed across chains of multiple A2A agents, exposing those credentials to each agent participating in the chain. If using in-band credential exchange, we recommend adhering to the following security practices: - Credentials SHOULD be bound to the agent which originated the request, such that only this agent is able to use the credentials. This ensures that credentials propagating through a chain of A2A requests are only usable by the requesting agent. - Credentials containing sensitive information SHOULD be only readable by the agent which originated the request, such as by encrypting the credential. ## 8. Agent Discovery: The Agent Card ### 8.1. Purpose A2A Servers **MUST** make an Agent Card available. The Agent Card describes the server's identity, capabilities, skills, and interaction requirements. Clients use this information for discovering suitable agents and configuring interactions. For more on discovery strategies, see the [Agent Discovery guide](./topics/agent-discovery.md). ### 8.2. Discovery Mechanisms Clients can find Agent Cards through: - **Well-Known URI:** Accessing `https://{server_domain}/.well-known/agent-card.json` (see [Section 8.6](#86-caching) for caching guidance) - **Registries/Catalogs:** Querying curated catalogs of agents - **Direct Configuration:** Pre-configured Agent Card URLs or content ### 8.3. Protocol Declaration Requirements The AgentCard **MUST** properly declare supported protocols: #### 8.3.1. Supported Interfaces Declaration - The `supportedInterfaces` field **SHOULD** declare all supported protocol combinations in preference order - The first entry in `supportedInterfaces` represents the preferred interface - Each interface **MUST** accurately declare its transport protocol and URL - URLs **MAY** be reused if multiple transports are available at the same endpoint #### 8.3.2. Client Protocol Selection Clients **MUST** follow these rules: 1. Parse `supportedInterfaces` if present, and select the first supported transport 2. Prefer earlier entries in the ordered list when multiple options are supported 3. Use the correct URL for the selected transport 4. Set the `tenant` field in every request message to exactly the value declared in the selected `AgentInterface` entry (omit the field if `tenant` is not set in that entry) ### 8.4. Agent Card Signing Agent Cards **MAY** be digitally signed using JSON Web Signature (JWS) as defined in [RFC 7515](https://tools.ietf.org/html/rfc7515) to ensure authenticity and integrity. Signatures allow clients to verify that an Agent Card has not been tampered with and originates from the claimed provider. #### 8.4.1. Canonicalization Requirements Before signing, the Agent Card content **MUST** be canonicalized using the JSON Canonicalization Scheme (JCS) as defined in [RFC 8785](https://tools.ietf.org/html/rfc8785). This ensures consistent signature generation and verification across different JSON implementations. **Canonicalization Rules:** 1. **Field Presence and Default Value Handling**: Before canonicalization, the JSON representation **MUST** respect Protocol Buffer field presence semantics as defined in [Section 5.7](#57-field-presence-and-optionality). This ensures that the canonical form accurately reflects which fields were explicitly provided versus which were omitted, enabling signature verification when Agent Cards are reconstructed: - **Optional fields not explicitly set**: Fields marked with the `optional` keyword that were not explicitly set **MUST** be omitted from the JSON object - **Optional fields explicitly set to defaults**: Fields marked with `optional` that were explicitly set to a value (even if that value matches a default) **MUST** be included in the JSON object - **Required fields**: Fields marked with `REQUIRED` **MUST** always be present, even if the field value matches the default. - **Default values**: Fields with default values **MUST** be omitted unless the field is marked as `REQUIRED` or has the `optional` keyword. 2. **RFC 8785 Compliance**: The Agent Card JSON **MUST** be canonicalized according to RFC 8785, which specifies: - Predictable ordering of object properties (lexicographic by key) - Consistent representation of numbers, strings, and other primitive values - Removal of insignificant whitespace 3. **Signature Field Exclusion**: The `signatures` field itself **MUST** be excluded from the content being signed to avoid circular dependencies. **Example of Default Value Removal:** Original Agent Card fragment: ```json { "name": "Example Agent", "description": "", "capabilities": { "streaming": false, "pushNotifications": false, "extensions": [] }, "skills": [] } ``` Applying the canonicalization rules: - `name`: "Example Agent" - REQUIRED field → **include** - `description`: "" - REQUIRED field → **include** - `capabilities`: object - REQUIRED field → **include** (after processing children) - `streaming`: false - optional field, present in JSON (explicitly set) → **include** - `pushNotifications`: false - optional field, present in JSON (explicitly set) → **include** - `extensions`: [] - repeated field (not REQUIRED) with empty array → **omit** - `skills`: [] - REQUIRED field → **include** After applying RFC 8785: ```json {"capabilities":{"pushNotifications":false,"streaming":false},"description":"","name":"Example Agent","skills":[]} ``` #### 8.4.2. Signature Format Signatures use the JSON Web Signature (JWS) format as defined in [RFC 7515](https://tools.ietf.org/html/rfc7515). The [`AgentCardSignature`](#447-agentcardsignature) object represents JWS components using three fields: - **`protected`** (required, string): Base64url-encoded JSON object containing the JWS Protected Header - **`signature`** (required, string): Base64url-encoded signature value - **`header`** (optional, object): JWS Unprotected Header as a JSON object (not base64url-encoded) **JWS Protected Header Parameters:** The protected header **MUST** include: - `alg`: Algorithm used for signing (e.g., "ES256", "RS256") - `typ`: **SHOULD** be set to "JOSE" for JWS - `kid`: Key ID for identifying the signing key The protected header **MAY** include: - `jku`: URL to JSON Web Key Set (JWKS) containing the public key **Signature Generation Process:** 1. **Prepare the payload:** - Remove properties with default values from the Agent Card - Exclude the `signatures` field - Canonicalize the resulting JSON using RFC 8785 to produce the canonical payload 2. **Create the protected header:** - Construct a JSON object with the required header parameters (`alg`, `typ`, `kid`) and any optional parameters (`jku`) - Serialize the header to JSON - Base64url-encode the serialized header to produce the `protected` field value 3. **Compute the signature:** - Construct the JWS Signing Input: `ASCII(BASE64URL(UTF8(JWS Protected Header)) || '.' || BASE64URL(JWS Payload))` - Sign the JWS Signing Input using the algorithm specified in the `alg` header parameter and the private key - Base64url-encode the resulting signature bytes to produce the `signature` field value 4. **Assemble the AgentCardSignature:** - Set `protected` to the base64url-encoded protected header from step 2 - Set `signature` to the base64url-encoded signature value from step 3 - Optionally set `header` to a JSON object containing any unprotected header parameters. **Example:** Given a canonical Agent Card payload and signing key, the signature generation produces: ```json { "protected": "eyJhbGciOiJFUzI1NiIsInR5cCI6IkpPU0UiLCJraWQiOiJrZXktMSIsImprdSI6Imh0dHBzOi8vZXhhbXBsZS5jb20vYWdlbnQvandrcy5qc29uIn0", "signature": "QFdkNLNszlGj3z3u0YQGt_T9LixY3qtdQpZmsTdDHDe3fXV9y9-B3m2-XgCpzuhiLt8E0tV6HXoZKHv4GtHgKQ" } ``` Where the `protected` value decodes to: ```json {"alg":"ES256","typ":"JOSE","kid":"key-1","jku":"https://example.com/agent/jwks.json"} ``` #### 8.4.3. Signature Verification Clients verifying Agent Card signatures **MUST**: 1. Extract the signature from the `signatures` array 2. Retrieve the public key using the `kid` and `jku` (or from a trusted key store) 3. Remove properties with default values from the received Agent Card 4. Exclude the `signatures` field 5. Canonicalize the resulting JSON using RFC 8785 6. Verify the signature against the canonicalized payload **Security Considerations:** - Clients **SHOULD** verify at least one signature before trusting an Agent Card - Public keys **SHOULD** be retrieved over secure channels (HTTPS) - Clients **MAY** maintain a trusted key store for known agent providers - Expired or revoked keys **MUST NOT** be used for verification - Multiple signatures **MAY** be present to support key rotation ### 8.5. Sample Agent Card ```json { "name": "GeoSpatial Route Planner Agent", "description": "Provides advanced route planning, traffic analysis, and custom map generation services. This agent can calculate optimal routes, estimate travel times considering real-time traffic, and create personalized maps with points of interest.", "supportedInterfaces": [ {"url": "https://georoute-agent.example.com/a2a/v1", "protocolBinding": "JSONRPC", "protocolVersion": "1.0"}, {"url": "https://georoute-agent.example.com/a2a/grpc", "protocolBinding": "GRPC", "protocolVersion": "1.0"}, {"url": "https://georoute-agent.example.com/a2a/json", "protocolBinding": "HTTP+JSON", "protocolVersion": "1.0"} ], "provider": { "organization": "Example Geo Services Inc.", "url": "https://www.examplegeoservices.com" }, "iconUrl": "https://georoute-agent.example.com/icon.png", "version": "1.2.0", "documentationUrl": "https://docs.examplegeoservices.com/georoute-agent/api", "capabilities": { "streaming": true, "pushNotifications": true, "extendedAgentCard": true }, "securitySchemes": { "google": { "openIdConnectSecurityScheme": { "openIdConnectUrl": "https://accounts.google.com/.well-known/openid-configuration" } } }, "security": [{ "google": ["openid", "profile", "email"] }], "defaultInputModes": ["application/json", "text/plain"], "defaultOutputModes": ["application/json", "image/png"], "skills": [ { "id": "route-optimizer-traffic", "name": "Traffic-Aware Route Optimizer", "description": "Calculates the optimal driving route between two or more locations, taking into account real-time traffic conditions, road closures, and user preferences (e.g., avoid tolls, prefer highways).", "tags": ["maps", "routing", "navigation", "directions", "traffic"], "examples": [ "Plan a route from '1600 Amphitheatre Parkway, Mountain View, CA' to 'San Francisco International Airport' avoiding tolls.", "{\"origin\": {\"lat\": 37.422, \"lng\": -122.084}, \"destination\": {\"lat\": 37.7749, \"lng\": -122.4194}, \"preferences\": [\"avoid_ferries\"]}" ], "inputModes": ["application/json", "text/plain"], "outputModes": [ "application/json", "application/vnd.geo+json", "text/html" ] }, { "id": "custom-map-generator", "name": "Personalized Map Generator", "description": "Creates custom map images or interactive map views based on user-defined points of interest, routes, and style preferences. Can overlay data layers.", "tags": ["maps", "customization", "visualization", "cartography"], "examples": [ "Generate a map of my upcoming road trip with all planned stops highlighted.", "Show me a map visualizing all coffee shops within a 1-mile radius of my current location." ], "inputModes": ["application/json"], "outputModes": [ "image/png", "image/jpeg", "application/json", "text/html" ] } ], "signatures": [ { "protected": "eyJhbGciOiJFUzI1NiIsInR5cCI6IkpPU0UiLCJraWQiOiJrZXktMSIsImprdSI6Imh0dHBzOi8vZXhhbXBsZS5jb20vYWdlbnQvandrcy5qc29uIn0", "signature": "QFdkNLNszlGj3z3u0YQGt_T9LixY3qtdQpZmsTdDHDe3fXV9y9-B3m2-XgCpzuhiLt8E0tV6HXoZKHv4GtHgKQ" } ] } ``` ### 8.6. Caching Agent Card content changes infrequently relative to the frequency at which clients may fetch it. Servers and clients **SHOULD** use standard HTTP caching mechanisms to reduce unnecessary network overhead. #### 8.6.1. Server Requirements - Agent Card HTTP endpoints **SHOULD** include a `Cache-Control` response header with a `max-age` directive appropriate for the agent's expected update frequency - Agent Card HTTP endpoints **SHOULD** include an `ETag` response header derived from the Agent Card's `version` field or a hash of the card content - Agent Card HTTP endpoints **MAY** include a `Last-Modified` response header #### 8.6.2. Client Requirements - Clients **SHOULD** honor HTTP caching semantics as defined in [RFC 9111](https://www.rfc-editor.org/rfc/rfc9111) when fetching Agent Cards - When a cached Agent Card has expired, clients **SHOULD** use conditional requests (`If-None-Match` with the stored `ETag`, or `If-Modified-Since`) to avoid re-downloading unchanged cards - When the server does not include caching headers, clients **MAY** apply an implementation-specific default cache duration ## 9. JSON-RPC Protocol Binding The JSON-RPC protocol binding provides a simple, HTTP-based interface using JSON-RPC 2.0 for method calls and Server-Sent Events for streaming. ### 9.1. Protocol Requirements - **Protocol:** JSON-RPC 2.0 over HTTP(S) - **Content-Type:** `application/json` for requests and responses - **Method Naming:** PascalCase method names matching gRPC conventions (e.g., `SendMessage`, `GetTask`) - **Streaming:** Server-Sent Events (`text/event-stream`) ### 9.2. Service Parameter Transmission A2A service parameters defined in [Section 3.2.6](#326-service-parameters) **MUST** be transmitted using standard HTTP request headers, as JSON-RPC 2.0 operates over HTTP(S). **Service Parameter Requirements:** - Service parameter names **MUST** be transmitted as HTTP header fields - Service parameter keys are case-insensitive per HTTP specification (RFC 7230) - Multiple values for the same service parameter (e.g., `A2A-Extensions`) **SHOULD** be comma-separated in a single header field **Example Request with A2A Service Parameters:** ```http POST /rpc HTTP/1.1 Host: agent.example.com Content-Type: application/json Authorization: Bearer token A2A-Version: 0.3 A2A-Extensions: https://example.com/extensions/geolocation/v1,https://standards.org/extensions/citations/v1 { "jsonrpc": "2.0", "id": 1, "method": "SendMessage", "params": { /* SendMessageRequest */ } } ``` ### 9.3. Base Request Structure All JSON-RPC requests **MUST** follow the standard JSON-RPC 2.0 format: ```json { "jsonrpc": "2.0", "id": "unique-request-id", "method": "category/action", "params": { /* method-specific parameters */ } } ``` ### 9.4. Core Methods #### 9.4.1. `SendMessage` Sends a message to initiate or continue a task. **Request:** ```json { "jsonrpc": "2.0", "id": 1, "method": "SendMessage", "params": { /* SendMessageRequest object */ } } ``` **Referenced Objects:** [`SendMessageRequest`](#321-sendmessagerequest), [`Message`](#414-message) **Response:** ```json { "jsonrpc": "2.0", "id": 1, "result": { /* SendMessageResponse object, contains one of: * "task": { Task object } * "message": { Message object } */ } ``` **Referenced Objects:** [`Task`](#411-task), [`Message`](#414-message) #### 9.4.2. `SendStreamingMessage` Sends a message and subscribes to real-time updates via Server-Sent Events. **Request:** Same as `SendMessage` **Response:** HTTP 200 with `Content-Type: text/event-stream` ```text data: {"jsonrpc": "2.0", "id": 1, "result": { /* StreamResponse object */ }} data: {"jsonrpc": "2.0", "id": 1, "result": { /* StreamResponse object */ }} ``` **Referenced Objects:** [`StreamResponse`](#323-stream-response) #### 9.4.3. `GetTask` Retrieves the current state of a task. **Request:** ```json { "jsonrpc": "2.0", "id": 2, "method": "GetTask", "params": { "id": "task-uuid", "historyLength": 10 } } ``` #### 9.4.4. `ListTasks` Lists tasks with optional filtering and pagination. **Request:** ```json { "jsonrpc": "2.0", "id": 3, "method": "ListTasks", "params": { "contextId": "context-uuid", "status": "TASK_STATE_WORKING", "pageSize": 50, "pageToken": "cursor-token" } } ``` #### 9.4.5. `CancelTask` Cancels an ongoing task. **Request:** ```json { "jsonrpc": "2.0", "id": 4, "method": "CancelTask", "params": { "id": "task-uuid" } } ``` #### 9.4.6. `SubscribeToTask` Subscribes to a task stream for receiving updates on a task that is not in a terminal state. **Request:** ```json { "jsonrpc": "2.0", "id": 5, "method": "SubscribeToTask", "params": { "id": "task-uuid" } } ``` **Response:** SSE stream (same format as `SendStreamingMessage`) **Error:** Returns `UnsupportedOperationError` if the task is in a terminal state (`TASK_STATE_COMPLETED`, `TASK_STATE_FAILED`, `TASK_STATE_CANCELED`, or `TASK_STATE_REJECTED`). #### 9.4.7. Push Notification Configuration Methods - `CreateTaskPushNotificationConfig` - Create push notification configuration - `GetTaskPushNotificationConfig` - Get push notification configuration - `ListTaskPushNotificationConfigs` - List push notification configurations - `DeleteTaskPushNotificationConfig` - Delete push notification configuration #### 9.4.8. `GetExtendedAgentCard` Retrieves an extended Agent Card. **Request:** ```json { "jsonrpc": "2.0", "id": 6, "method": "GetExtendedAgentCard" } ``` ### 9.5. Error Handling JSON-RPC error responses use the standard [JSON-RPC 2.0 error object](https://www.jsonrpc.org/specification#error_object) structure, which maps to the generic A2A error model defined in [Section 3.3.2](#332-error-handling) as follows: - **Error Code**: Mapped to `error.code` (numeric JSON-RPC error code) - **Error Message**: Mapped to `error.message` (human-readable string) - **Error Details**: Mapped to `error.data` (array of objects, each containing a `@type` key, using ProtoJSON `Any` representation) **Standard JSON-RPC Error Codes:** | JSON-RPC Error Code | Error Name | Standard Message | Description | | :------------------ | :-------------------- | :--------------------------------- | :------------------------------------------------------ | | `-32700` | `JSONParseError` | "Invalid JSON payload" | The server received invalid JSON | | `-32600` | `InvalidRequestError` | "Request payload validation error" | The JSON sent is not a valid Request object | | `-32601` | `MethodNotFoundError` | "Method not found" | The requested method does not exist or is not available | | `-32602` | `InvalidParamsError` | "Invalid parameters" | The method parameters are invalid | | `-32603` | `InternalError` | "Internal error" | An internal error occurred on the server | **A2A-Specific Error Codes:** A2A-specific errors use codes in the range `-32001` to `-32099`. For the complete mapping of A2A error types to JSON-RPC error codes, see [Section 5.4 (Error Code Mappings)](#54-error-code-mappings). **Error Detail Objects:** Each object in the `data` array **MUST** include a `@type` key that identifies the object's type. Implementations **SHOULD** use well-known types such as `google.rpc.ErrorInfo` to refine error reporting, or `google.rpc.BadRequest` to attach structured data to validation errors. Additional error context **MAY** be included as further objects in the `data` array. **Error Response Structure:** ```json { "jsonrpc": "2.0", "id": 1, "error": { "code": -32602, "message": "Invalid parameters", "data": [ { "@type": "type.googleapis.com/google.rpc.BadRequest", "fieldViolations": [ { "field": "message.parts", "description": "At least one part is required" } ] } ] } } ``` **Example A2A-Specific Error Response:** ```json { "jsonrpc": "2.0", "id": 2, "error": { "code": -32001, "message": "Task not found", "data": [ { "@type": "type.googleapis.com/google.rpc.ErrorInfo", "reason": "TASK_NOT_FOUND", "domain": "a2a-protocol.org", "metadata": { "taskId": "nonexistent-task-id", "timestamp": "2025-11-09T10:30:00.000Z" } } ] } } ``` ## 10. gRPC Protocol Binding The gRPC Protocol Binding provides a high-performance, strongly-typed interface using Protocol Buffers over HTTP/2. The gRPC Protocol Binding leverages the [API guidelines](https://google.aip.dev/general) to simplify gRPC to HTTP mapping. ### 10.1. Protocol Requirements - **Protocol:** gRPC over HTTP/2 with TLS - **Definition:** Use the normative Protocol Buffers definition in `specification/a2a.proto` - **Serialization:** Protocol Buffers version 3 - **Service:** Implement the `A2AService` gRPC service ### 10.2. Service Parameter Transmission A2A service parameters defined in [Section 3.2.6](#326-service-parameters) **MUST** be transmitted using gRPC metadata (headers). **Service Parameter Requirements:** - Service parameter names **MUST** be transmitted as gRPC metadata keys - Metadata keys are case-insensitive and automatically converted to lowercase by gRPC - Multiple values for the same service parameter (e.g., `A2A-Extensions`) **SHOULD** be comma-separated in a single metadata entry **Example gRPC Request with A2A Service Parameters:** ```go // Go example using gRPC metadata md := metadata.Pairs( "authorization", "Bearer token", "a2a-version", "0.3", "a2a-extensions", "https://example.com/extensions/geolocation/v1,https://standards.org/extensions/citations/v1", ) ctx := metadata.NewOutgoingContext(context.Background(), md) // Make the RPC call with the context containing metadata response, err := client.SendMessage(ctx, request) ``` **Metadata Handling:** - Implementations **MUST** extract A2A service parameters from gRPC metadata for processing - Servers **SHOULD** validate required service parameters (e.g., `A2A-Version`) from metadata - Service parameter keys in metadata are normalized to lowercase per gRPC conventions ### 10.3. Service Definition {{ proto_service_to_table("A2AService") }} ### 10.4. Core Methods #### 10.4.1. SendMessage Sends a message to an agent. **Request:** {{ proto_to_table("SendMessageRequest") }} **Response:** {{ proto_to_table("SendMessageResponse") }} #### 10.4.2. SendStreamingMessage Sends a message with streaming updates. **Request:** {{ proto_to_table("SendMessageRequest") }} **Response:** Server streaming [`StreamResponse`](#stream-response) objects. #### 10.4.3. GetTask Retrieves task status. **Request:** {{ proto_to_table("GetTaskRequest") }} **Response:** See [`Task`](#411-task) object definition. #### 10.4.4. ListTasks Lists tasks with filtering. **Request:** {{ proto_to_table("ListTasksRequest") }} **Response:** {{ proto_to_table("ListTasksResponse") }} #### 10.4.5. CancelTask Cancels a running task. **Request:** {{ proto_to_table("CancelTaskRequest") }} **Response:** See [`Task`](#411-task) object definition. #### 10.4.6. SubscribeToTask Subscribe to task updates via streaming. Returns `UnsupportedOperationError` if the task is in a terminal state. **Request:** {{ proto_to_table("SubscribeToTaskRequest") }} **Response:** Server streaming [`StreamResponse`](#stream-response) objects. #### 10.4.7. CreateTaskPushNotificationConfig Creates a push notification configuration for a task. **Request:** {{ proto_to_table("CreateTaskPushNotificationConfigRequest") }} **Response:** See [`PushNotificationConfig`](#431-pushnotificationconfig) object definition. #### 10.4.8. GetTaskPushNotificationConfig Retrieves an existing push notification configuration for a task. **Request:** {{ proto_to_table("GetTaskPushNotificationConfigRequest") }} **Response:** See [`PushNotificationConfig`](#431-pushnotificationconfig) object definition. #### 10.4.9. ListTaskPushNotificationConfigs Lists all push notification configurations for a task. **Request:** {{ proto_to_table("ListTaskPushNotificationConfigsRequest") }} **Response:** {{ proto_to_table("ListTaskPushNotificationConfigsResponse") }} #### 10.4.10. DeleteTaskPushNotificationConfig Removes a push notification configuration for a task. **Request:** {{ proto_to_table("DeleteTaskPushNotificationConfigRequest") }} **Response:** `google.protobuf.Empty` #### 10.4.11. GetExtendedAgentCard Retrieves the agent's extended capability card after authentication. **Request:** {{ proto_to_table("GetExtendedAgentCardRequest") }} **Response:** See [`AgentCard`](#441-agentcard) object definition. ### 10.5. gRPC-Specific Data Types #### 10.5.1. TaskPushNotificationConfig Resource wrapper for push notification configurations. This is a gRPC-specific type used in resource-oriented operations to provide the full resource name along with the configuration data. {{ proto_to_table("TaskPushNotificationConfig") }} ### 10.6. Error Handling gRPC error responses use the standard [gRPC status](https://grpc.io/docs/guides/error/) structure with [google.rpc.Status](https://github.com/googleapis/googleapis/blob/master/google/rpc/status.proto), which maps to the generic A2A error model defined in [Section 3.3.2](#332-error-handling) as follows: - **Error Code**: Mapped to `status.code` (gRPC status code enum) - **Error Message**: Mapped to `status.message` (human-readable string) - **Error Details**: Mapped to `status.details` (repeated google.protobuf.Any messages) **A2A Error Representation:** For A2A-specific errors, implementations **MUST** include a `google.rpc.ErrorInfo` message in the `status.details` array with: - `reason`: The A2A error type in UPPER_SNAKE_CASE without the "Error" suffix (e.g., `TASK_NOT_FOUND`) - `domain`: Set to `"a2a-protocol.org"` - `metadata`: Optional map of additional error context For the complete mapping of A2A error types to gRPC status codes, see [Section 5.4 (Error Code Mappings)](#54-error-code-mappings). **Error Response Example:** ```proto // Standard gRPC invalid argument error status { code: INVALID_ARGUMENT message: "Invalid request parameters" details: [ { type: "type.googleapis.com/google.rpc.BadRequest" field_violations: [ { field: "message.parts" description: "At least one part is required" } ] } ] } ``` **Example A2A-Specific Error Response:** ```proto // A2A-specific task not found error status { code: NOT_FOUND message: "Task with ID 'task-123' not found" details: [ { type: "type.googleapis.com/google.rpc.ErrorInfo" reason: "TASK_NOT_FOUND" domain: "a2a-protocol.org" metadata: { task_id: "task-123" timestamp: "2025-11-09T10:30:00Z" } } ] } ``` ### 10.7. Streaming gRPC streaming uses server streaming RPCs for real-time updates. The `StreamResponse` message provides a union of possible streaming events: {{ proto_to_table("StreamResponse") }} ## 11. HTTP+JSON/REST Protocol Binding The HTTP+JSON protocol binding provides a RESTful interface using standard HTTP methods and JSON payloads. ### 11.1. Protocol Requirements - **Protocol:** HTTP(S) with JSON payloads - **Content-Type:** application/a2a+json **SHOULD** be used for requests and responses - **Methods:** Standard HTTP verbs (GET, POST, PUT, DELETE) - **URL Patterns:** RESTful resource-based URLs - **Streaming:** Server-Sent Events for real-time updates ### 11.2. Service Parameter Transmission A2A service parameters defined in [Section 3.2.6](#326-service-parameters) **MUST** be transmitted using standard HTTP request headers. **Service Parameter Requirements:** - Service parameter names **MUST** be transmitted as HTTP header fields - Service parameter keys are case-insensitive per HTTP specification (RFC 9110) - Multiple values for the same service parameter (e.g., `A2A-Extensions`) **SHOULD** be comma-separated in a single header field **Example Request with A2A Service Parameters:** ```http POST /message:send HTTP/1.1 Host: agent.example.com Content-Type: application/a2a+json Authorization: Bearer token A2A-Version: 0.3 A2A-Extensions: https://example.com/extensions/geolocation/v1,https://standards.org/extensions/citations/v1 { "message": { "role": "ROLE_USER", "parts": [{"text": "Find restaurants near me"}] } } ``` ### 11.3. URL Patterns and HTTP Methods #### 11.3.1. Message Operations - `POST /message:send` - Send message - `POST /message:stream` - Send message with streaming (SSE response) #### 11.3.2. Task Operations - `GET /tasks/{id}` - Get task status - `GET /tasks` - List tasks (with query parameters) - `POST /tasks/{id}:cancel` - Cancel task - `POST /tasks/{id}:subscribe` - Subscribe to task updates (SSE response, returns error for terminal tasks) #### 11.3.3. Push Notification Configuration - `POST /tasks/{id}/pushNotificationConfigs` - Create configuration - `GET /tasks/{id}/pushNotificationConfigs/{configId}` - Get configuration - `GET /tasks/{id}/pushNotificationConfigs` - List configurations - `DELETE /tasks/{id}/pushNotificationConfigs/{configId}` - Delete configuration #### 11.3.4. Agent Card - `GET /extendedAgentCard` - Get authenticated extended Agent Card ### 11.4. Request/Response Format All requests and responses use JSON objects structurally equivalent to the Protocol Buffer definitions. **Example Send Message:** ```http POST /message:send Content-Type: application/a2a+json { "message": { "messageId": "uuid", "role": "ROLE_USER", "parts": [{"text": "Hello"}] }, "configuration": { "acceptedOutputModes": ["text/plain"] } } ``` **Referenced Objects:** [`SendMessageRequest`](#321-sendmessagerequest), [`Message`](#414-message) **Response:** ```http HTTP/1.1 200 OK Content-Type: application/a2a+json { "task": { "id": "task-uuid", "contextId": "context-uuid", "status": { "state": "TASK_STATE_COMPLETED" } } } ``` **Referenced Objects:** [`Task`](#411-task) ### 11.5. Query Parameter Naming for Request Parameters HTTP methods that do not support request bodies (GET, DELETE) **MUST** transmit operation request parameters as path parameters or query parameters. This section defines how to map Protocol Buffer field names to query parameter names. **Naming Convention:** Query parameter names **MUST** use `camelCase` to match the JSON serialization of Protocol Buffer field names. This ensures consistency with request bodies used in POST operations. **Example Mappings:** | Protocol Buffer Field | Query Parameter Name | Example Usage | | --------------------- | -------------------- | ------------------- | | `context_id` | `contextId` | `?contextId=uuid` | | `page_size` | `pageSize` | `?pageSize=50` | | `page_token` | `pageToken` | `?pageToken=cursor` | | `task_id` | `taskId` | `?taskId=uuid` | **Usage Examples:** List tasks with filtering: ```http GET /tasks?contextId=uuid&status=TASK_STATE_WORKING&pageSize=50&pageToken=cursor ``` Get task with history: ```http GET /tasks/{id}?historyLength=10 ``` **Field Type Handling:** - **Strings**: Passed directly as query parameter values - **Booleans**: Represented as lowercase strings (`true`, `false`) - **Numbers**: Represented as decimal strings - **Enums**: Represented using their string values (e.g., `status=TASK_STATE_WORKING`) - **Repeated Fields**: Multiple values **MAY** be passed by repeating the parameter name (e.g., `?tag=value1&tag=value2`) or as comma-separated values (e.g., `?tag=value1,value2`) - **Nested Objects**: Not supported in query parameters; operations requiring nested objects **MUST** use POST with a request body - **Datetimes/Timestamps**: Represented as ISO 8601 strings (e.g., `2025-11-09T10:30:00Z`) **URL Encoding:** All query parameter values **MUST** be properly URL-encoded per [RFC 3986](https://www.rfc-editor.org/rfc/rfc3986.html). ### 11.6. Error Handling HTTP error responses use the [google.rpc.Status](https://github.com/googleapis/googleapis/blob/master/google/rpc/status.proto) JSON representation, which maps to the generic A2A error model defined in [Section 3.3.2](#332-error-handling) as follows: - **Error Code**: Mapped to the HTTP status code and the `error.code` field - **Error Message**: Mapped to the `error.message` field (human-readable string) - **Error Details**: Mapped to the `error.details` array (array of objects, each containing a `@type` key, using ProtoJSON `Any` representation) **Error Detail Objects:** Each object in the `details` array **MUST** include a `@type` key that identifies the object's type. Implementations **SHOULD** use well-known types such as `google.rpc.BadRequest` to attach structured data to validation errors. Additional error context **MAY** be included as further objects in the `details` array. **A2A Error Representation:** Since multiple A2A error types may map to the same HTTP status code (e.g., `TaskNotCancelableError` and `PushNotificationNotSupportedError` both map to `400 Bad Request`), implementations **MUST** include a `google.rpc.ErrorInfo` object in the `details` array for A2A-specific errors with: - `@type`: Set to `"type.googleapis.com/google.rpc.ErrorInfo"` - `reason`: The A2A error type in UPPER_SNAKE_CASE without the "Error" suffix (e.g., `TASK_NOT_FOUND`, `TASK_NOT_CANCELABLE`) - `domain`: Set to `"a2a-protocol.org"` For the complete mapping of A2A error types to HTTP status codes, see [Section 5.4 (Error Code Mappings)](#54-error-code-mappings). **Error Response Example:** ```http HTTP/1.1 404 Not Found Content-Type: application/a2a+json { "error": { "code": 404, "status": "NOT_FOUND", "message": "The specified task ID does not exist or is not accessible", "details": [ { "@type": "type.googleapis.com/google.rpc.ErrorInfo", "reason": "TASK_NOT_FOUND", "domain": "a2a-protocol.org", "metadata": { "taskId": "task-123", "timestamp": "2025-11-09T10:30:00.000Z" } } ] } } ``` Extension fields like `taskId` and `timestamp` provide additional context to help diagnose the error. ### 11.7. Streaming REST streaming uses Server-Sent Events with the `data` field containing JSON serializations of the protocol data objects: ```http POST /message:stream Content-Type: application/a2a+json { /* SendMessageRequest object */ } ``` **Referenced Objects:** [`SendMessageRequest`](#321-sendmessagerequest) **Response:** ```http HTTP/1.1 200 OK Content-Type: text/event-stream data: { /* StreamResponse object */ } data: { /* StreamResponse object */ } ``` **Referenced Objects:** [`StreamResponse`](#323-stream-response) Streaming responses are simple, linearly ordered sequences: first a `Task` (or single `Message`), then zero or more status or artifact update events until the task reaches a terminal or interrupted state, at which point the stream closes. Implementations SHOULD avoid re-ordering events and MAY optionally resend a final `Task` snapshot before closing. ## 12. Custom Binding Guidelines While the A2A protocol provides three standard bindings (JSON-RPC, gRPC, and HTTP+JSON/REST), implementers **MAY** create custom protocol bindings to support additional transport mechanisms or communication patterns. Custom bindings **MUST** comply with all requirements defined in [Section 5 (Protocol Binding Requirements and Interoperability)](#5-protocol-binding-requirements-and-interoperability). This section provides additional guidelines specific to developing custom bindings. ### 12.1. Binding Requirements Custom protocol bindings **MUST**: 1. **Implement All Core Operations**: Support all operations defined in [Section 3 (A2A Protocol Operations)](#3-a2a-protocol-operations) 2. **Preserve Data Model**: Use data structures functionally equivalent to those defined in [Section 4 (Protocol Data Model)](#4-protocol-data-model) 3. **Maintain Semantics**: Ensure operations behave consistently with the abstract operation definitions 4. **Document Completely**: Provide comprehensive documentation of the binding specification ### 12.2. Data Type Mappings Custom bindings **MUST** provide clear mappings for: - **Protocol Buffer Types**: Define how each Protocol Buffer message type is represented - **Timestamps**: Follow the conventions in [Section 5.6.1 (Timestamps)](#561-timestamps) - **Binary Data**: Specify encoding for binary content (e.g., base64 for text-based protocols) - **Enumerations**: Define representation of enum values (e.g., strings, integers) ### 12.3. Service Parameter Transmission As specified in [Section 3.2.6 (Service Parameters)](#326-service-parameters), custom protocol bindings **MUST** document how service parameters are transmitted. The binding specification **MUST** address: 1. **Transmission Mechanism**: The protocol-specific method for transmitting service parameter key-value pairs 2. **Value Constraints**: Any limitations on service parameter values (e.g., character encoding, size limits) 3. **Reserved Names**: Any service parameter names reserved by the binding itself 4. **Fallback Strategy**: What happens when the protocol lacks native header support (e.g., passing service parameters in metadata) **Example Documentation Requirements:** - **For native header support**: "Service parameters are transmitted using HTTP request headers. Service parameter keys are case-insensitive and must conform to RFC 7230. Service parameter values must be UTF-8 strings." - **For protocols without headers**: "Service parameters are serialized as a JSON object and transmitted in the request metadata field `a2a-service-parameters`." ### 12.4. Error Mapping Custom bindings **MUST**: 1. **Map Standard Errors**: Provide mappings for all A2A-specific error types defined in [Section 3.2.2 (Error Handling)](#332-error-handling) 2. **Preserve Error Information**: Ensure error details are accessible to clients 3. **Use Appropriate Codes**: Map to protocol-native error codes where applicable 4. **Document Error Format**: Specify the structure of error responses ### 12.5. Streaming Support If the binding supports streaming operations: 1. **Define Stream Mechanism**: Document how streaming is implemented (e.g., WebSockets, long-polling, chunked encoding) 2. **Event Ordering**: Specify ordering guarantees for streaming events 3. **Reconnection**: Define behavior for connection interruption and resumption 4. **Stream Termination**: Specify how stream completion is signaled If streaming is not supported, the binding **MUST** clearly document this limitation in the Agent Card. ### 12.6. Authentication and Authorization Custom bindings **MUST**: 1. **Support Standard Schemes**: Implement authentication schemes declared in the Agent Card 2. **Document Integration**: Specify how credentials are transmitted in the protocol 3. **Handle Challenges**: Define how authentication challenges are communicated 4. **Maintain Security**: Follow security best practices for the transport protocol ### 12.7. Agent Card Declaration Custom bindings **MUST** be declared in the Agent Card: 1. **Transport Identifier**: Use a URI to identify the binding (see [Section 5.8](#58-custom-binding-identification)) 2. **Endpoint URL**: Provide the full URL where the binding is available **Example:** ```json { "supportedInterfaces": [ { "url": "wss://agent.example.com/a2a/websocket", "protocolBinding": "https://example.com/bindings/websocket/v1" } ] } ``` ### 12.8. Interoperability Testing Custom binding implementers **SHOULD**: 1. **Test Against Reference**: Verify behavior matches standard bindings 2. **Document Differences**: Clearly note any deviations from standard binding behavior 3. **Provide Examples**: Include sample requests and responses 4. **Test Edge Cases**: Verify handling of error conditions, large payloads, and long-running tasks ## 13. Security Considerations This section consolidates security guidance and best practices for implementing and operating A2A agents. For additional enterprise security considerations, see [Enterprise-Ready Features](./topics/enterprise-ready.md). ### 13.1. Data Access and Authorization Scoping Implementations **MUST** ensure appropriate scope limitation based on the authenticated caller's authorization boundaries. This applies to all operations that access or list tasks and other resources. **Authorization Principles:** - Servers **MUST** implement authorization checks on every [A2A Protocol Operations](#3-a2a-protocol-operations) request - Implementations **MUST** scope results to the caller's authorized access boundaries as defined by the agent's authorization model - Even when `contextId` or other filter parameters are not specified in requests, implementations **MUST** scope results to the caller's authorized access boundaries - Authorization models are agent-defined and **MAY** be based on: - User identity (user-based authorization) - Organizational roles or groups (role-based authorization) - Project or workspace membership (project-based authorization) - Organizational or tenant boundaries (multi-tenant authorization) - Custom authorization logic specific to the agent's domain **Operations Requiring Scope Limitation:** - [`List Tasks`](#314-list-tasks): **MUST** only return tasks visible to the authenticated client according to the agent's authorization model - [`Get Task`](#313-get-task): **MUST** verify the authenticated client has access to the requested task according to the agent's authorization model - Task-related operations (Cancel, Subscribe, Push Notification Config): **MUST** verify the client has appropriate access rights according to the agent's authorization model **Implementation Requirements:** - Authorization boundaries are defined by each agent's authorization model, not prescribed by the protocol - Authorization checks **MUST** occur before any database queries or operations that could leak information about the existence of resources outside the caller's authorization scope - Agents **SHOULD** document their authorization model and access control policies See also: [Section 3.1.4 List Tasks (Security Note)](#314-list-tasks) for operation-specific requirements. ### 13.2. Push Notification Security When implementing push notifications, both agents (as webhook callers) and clients (as webhook receivers) have security responsibilities. **Agent (Webhook Caller) Requirements:** - Agents **MUST** include authentication credentials in webhook requests as specified in [`PushNotificationConfig.authentication`](#432-authenticationinfo) - Agents **SHOULD** implement reasonable timeout values for webhook requests (recommended: 10-30 seconds) - Agents **SHOULD** implement retry logic with exponential backoff for failed deliveries - Agents **MAY** stop attempting delivery after a configured number of consecutive failures - Agents **SHOULD** validate webhook URLs to prevent SSRF (Server-Side Request Forgery) attacks: - Reject private IP ranges (127.0.0.0/8, 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16) - Reject localhost and link-local addresses - Implement URL allowlists where appropriate **Client (Webhook Receiver) Requirements:** - Clients **MUST** validate webhook authenticity using the provided authentication credentials - Clients **SHOULD** verify the task ID in the payload matches an expected task they created - Clients **MUST** respond with HTTP 2xx status codes to acknowledge successful receipt - Clients **SHOULD** process notifications idempotently, as duplicate deliveries may occur - Clients **SHOULD** implement rate limiting to prevent webhook flooding - Clients **SHOULD** use HTTPS endpoints for webhook URLs to ensure confidentiality **Configuration Security:** - Webhook URLs **SHOULD** use HTTPS to protect payload confidentiality in transit - Authentication tokens in [`PushNotificationConfig`](#431-pushnotificationconfig) **SHOULD** be treated as secrets and rotated periodically - Agents **SHOULD** securely store push notification configurations and credentials - Clients **SHOULD** use unique, single-purpose tokens for each push notification configuration See also: [Section 4.3 Push Notification Objects](#43-push-notification-objects) and [Section 4.3.3 Push Notification Payload](#433-push-notification-payload). ### 13.3. Extended Agent Card Access Control The extended Agent Card feature allows agents to provide additional capabilities or information to authenticated clients beyond what is available in the public Agent Card. **Access Control Requirements:** - The [`Get Extended Agent Card`](#3111-get-extended-agent-card) operation **MUST** require authentication - Agents **MUST** authenticate requests using one of the schemes declared in the public `AgentCard.securitySchemes` and `AgentCard.security` fields - Agents **MAY** return different extended card content based on the authenticated client's identity or authorization level - Agents **SHOULD** implement appropriate caching headers to control client-side caching of extended cards **Capability-Based Access:** - Extended cards **MAY** include additional skills not present in the public card - Extended cards **MAY** expose more detailed capability information (e.g., rate limits, quotas) - Extended cards **MAY** include organization-specific or user-specific configuration - Agents **SHOULD** document which capabilities are available at different authentication levels **Security Considerations:** - Extended cards **SHOULD NOT** include sensitive information that could be exploited if leaked (e.g., internal service URLs, unmasked credentials) - Agents **MUST** validate that clients have appropriate permissions before returning privileged information in extended cards - Clients retrieving extended cards **SHOULD** replace their cached public Agent Card with the extended version for the duration of their authenticated session - Agents **SHOULD** version extended cards appropriately and honor client cache invalidation **Availability Declaration:** - Agents declare extended card support via `AgentCard.capabilities.extendedAgentCard` - When `capabilities.extendedAgentCard` is `false` or not present, the operation **MUST** return [`UnsupportedOperationError`](#332-error-handling) - When support is declared but no extended card is configured, the operation **MUST** return [`ExtendedAgentCardNotConfiguredError`](#332-error-handling) See also: [Section 3.1.11 Get Extended Agent Card](#3111-get-extended-agent-card) and [Section 3.3.4 Capability Validation](#334-capability-validation). ### 13.4. General Security Best Practices **Transport Security:** - Production deployments **MUST** use encrypted communication (HTTPS for HTTP-based bindings, TLS for gRPC) - Implementations **SHOULD** use modern TLS configurations (TLS 1.3+ recommended) with strong cipher suites - Agents **SHOULD** enforce HSTS (HTTP Strict Transport Security) headers when using HTTP-based bindings - Implementations **SHOULD** disable support for deprecated SSL/TLS versions (SSLv3, TLS 1.0, TLS 1.1) **Input Validation:** - Agents **MUST** validate all input parameters before processing - Agents **SHOULD** implement appropriate limits on message sizes, file sizes, and request complexity - Agents **SHOULD** sanitize or validate file content types and reject unexpected media types **Credential Management:** - API keys, tokens, and other credentials **MUST** be treated as secrets - Credentials **SHOULD** be rotated periodically - Credentials **SHOULD** be transmitted only over encrypted connections - Agents **SHOULD** implement credential revocation mechanisms - Agents **SHOULD** log authentication failures and implement rate limiting to prevent brute-force attacks **Audit and Monitoring:** - Agents **SHOULD** log security-relevant events (authentication failures, authorization denials, suspicious requests) - Agents **SHOULD** implement monitoring for unusual patterns (rapid task creation, excessive cancellations) - Agents **SHOULD** provide audit trails for sensitive operations - Logs **MUST NOT** include sensitive information (credentials, personal data) unless required and properly protected **Rate Limiting and Abuse Prevention:** - Agents **SHOULD** implement rate limiting on all operations - Agents **SHOULD** return appropriate error responses when rate limits are exceeded - Agents **MAY** implement different rate limits for different operations or user tiers **Data Privacy:** - Agents **MUST** comply with applicable data protection regulations - Agents **SHOULD** provide mechanisms for users to request deletion of their data - Agents **SHOULD** implement appropriate data retention policies - Agents **SHOULD** minimize logging of sensitive or personal information **Custom Binding Security:** - Custom protocol bindings **MUST** address security considerations in their specification - Custom bindings **SHOULD** follow the same security principles as standard bindings - Custom bindings **MUST** document authentication integration and credential transmission See also: [Section 12.6 Authentication and Authorization (Custom Bindings)](#126-authentication-and-authorization). ## 14. IANA Considerations This section provides registration templates for the A2A protocol's media type, HTTP headers, and well-known URI, intended for submission to the Internet Assigned Numbers Authority (IANA). ### 14.1. Media Type Registration #### 14.1.1. application/a2a+json **Type name:** `application` **Subtype name:** `a2a+json` **Required parameters:** None **Optional parameters:** - None **Encoding considerations:** Binary (UTF-8 encoding MUST be used for JSON text) **Security considerations:** This media type shares security considerations common to all JSON-based formats as described in RFC 8259, Section 12. Additionally: - Content MUST be validated against the A2A protocol schema before processing - Implementations MUST sanitize user-provided content to prevent injection attacks - File references within A2A messages MUST be validated to prevent server-side request forgery (SSRF) - Authentication and authorization MUST be enforced as specified in Section 7 of the A2A specification - Sensitive information in task history and artifacts MUST be protected according to applicable data protection regulations **Interoperability considerations:** The A2A protocol supports multiple protocol bindings. This media type is intended for the HTTP+JSON/REST binding. **Published specification:** Agent2Agent (A2A) Protocol Specification, available at: **Applications that use this media type:** AI agent platforms, agentic workflow systems, multi-agent collaboration tools, and enterprise automation systems that implement the A2A protocol for agent-to-agent communication. **Fragment identifier considerations:** None **Additional information:** - **Deprecated alias names for this type:** None - **Magic number(s):** None - **File extension(s):** .a2a.json - **Macintosh file type code(s):** TEXT **Person & email address to contact for further information:** A2A Protocol Working Group, **Intended usage:** COMMON **Restrictions on usage:** None **Author:** A2A Protocol Working Group **Change controller:** A2A Protocol Working Group **Provisional registration:** No ### 14.2. HTTP Header Field Registrations **Note:** The following HTTP headers represent the HTTP-based protocol binding implementation of the abstract A2A service parameters defined in [Section 3.2.6](#326-service-parameters). These registrations are specific to HTTP/HTTPS transports. #### 14.2.1. A2A-Version Header **Header field name:** A2A-Version **Applicable protocol:** HTTP **Status:** Standard **Author/Change controller:** A2A Protocol Working Group **Specification document:** Section 3.2.5 of the A2A Protocol Specification **Related information:** The A2A-Version header field indicates the A2A protocol version that the client is using. The value MUST be in the format `Major.Minor` (e.g., "0.3"). If the version is not supported by the agent, the agent returns a `VersionNotSupportedError`. **Example:** ```text A2A-Version: 0.3 ``` #### 14.2.2. A2A-Extensions Header **Header field name:** A2A-Extensions **Applicable protocol:** HTTP **Status:** Standard **Author/Change controller:** A2A Protocol Working Group **Specification document:** Section 3.2.5 of the A2A Protocol Specification **Related information:** The A2A-Extensions header field contains a comma-separated list of extension URIs that the client wants to use for the request. Extensions allow agents to provide additional functionality beyond the core A2A specification while maintaining backward compatibility. **Example:** ```text A2A-Extensions: https://example.com/extensions/geolocation/v1,https://standards.org/extensions/citations/v1 ``` ### 14.3. Well-Known URI Registration **URI suffix:** agent-card.json **Change controller:** A2A Protocol Working Group **Specification document:** Section 8.2 of the A2A Protocol Specification **Related information:** The `.well-known/agent-card.json` URI provides a standardized location for discovering an A2A agent's capabilities, supported protocols, authentication requirements, and available skills. The resource at this URI MUST return an AgentCard object as defined in Section 4.4.1 of the A2A specification. **Status:** Permanent **Security considerations:** - The Agent Card MAY contain public information about an agent's capabilities and SHOULD NOT include sensitive credentials or internal implementation details - Implementations SHOULD support HTTPS to ensure authenticity and integrity of the Agent Card - Agent Cards MAY be signed using JSON Web Signatures (JWS) as specified in the AgentCardSignature object (Section 4.4.7) - Clients SHOULD verify signatures when present to ensure the Agent Card has not been tampered with - Extended Agent Cards retrieved via authenticated endpoints (Section 3.1.11) MAY contain additional information and MUST enforce appropriate access controls **Example:** ```text https://agent.example.com/.well-known/agent-card.json ``` --- ## Appendix A. Migration & Legacy Compatibility This appendix catalogs renamed protocol messages and objects, their legacy identifiers, and the planned deprecation/removal schedule. All legacy names and anchors MUST remain resolvable until the stated earliest removal version. | Legacy Name | Current Name | Earliest Removal Version | Notes | | ----------------------------------------------- | ----------------------------------------- | ------------------------ | ------------------------------------------------------ | | `MessageSendParams` | `SendMessageRequest` | >= 0.5.0 | Request payload rename for clarity (request vs params) | | `SendMessageSuccessResponse` | `SendMessageResponse` | >= 0.5.0 | Unified success response naming | | `SendStreamingMessageSuccessResponse` | `StreamResponse` | >= 0.5.0 | Shorter, binding-agnostic streaming response | | `SetTaskPushNotificationConfigRequest` | `CreateTaskPushNotificationConfigRequest` | >= 0.5.0 | Explicit creation intent | | `ListTaskPushNotificationConfigSuccessResponse` | `ListTaskPushNotificationConfigsResponse` | >= 0.5.0 | Consistent response suffix removal | | `GetAuthenticatedExtendedCardRequest` | `GetExtendedAgentCardRequest` | >= 0.5.0 | Removed "Authenticated" from naming | Planned Lifecycle (example timeline; adjust per release strategy): 1. 0.3.x: New names introduced; legacy names documented; aliases added. 2. 0.4.x: Legacy names marked "deprecated" in SDKs and schemas; warning notes added. 3. ≥0.5.0: Legacy names eligible for removal after review; migration appendix updated. ### A.1 Legacy Documentation Anchors Hidden anchor spans preserve old inbound links: Each legacy span SHOULD be placed adjacent to the current object's heading (to be inserted during detailed object section edits). If an exact numeric-prefixed anchor existed (e.g., `#414-message`), add an additional span matching that historical form if known. ### A.2 Migration Guidance Client Implementations SHOULD: - Prefer new names immediately for all new integrations. - Implement dual-handling where schemas/types permit (e.g., union type or backward-compatible decoder). - Log a warning when receiving legacy-named objects after the first deprecation announcement release. Server Implementations MAY: - Accept both legacy and current request message forms during the overlap period. - Emit only current form in responses (recommended) while providing explicit upgrade notes. #### A.2.1 Breaking Change: Kind Discriminator Removed **Version 1.0 introduces a breaking change** in how polymorphic objects are represented in the protocol. This affects `Part` types and streaming event types. **Legacy Pattern (v0.3.x):** Objects used an inline `kind` field as a discriminator to identify the object type: **Example 1 - TextPart:** ```json { "kind": "text", "text": "Hello, world!" } ``` **Example 2 - FilePart:** ```json { "kind": "file", "file": { "name": "diagram.png", "mimeType": "image/png", "fileWithBytes": "iVBORw0KGgo..." } } ``` **Current Pattern (v1.0):** Objects now use the **JSON member name** itself to identify the type. The member name acts as the discriminator, and the value structure depends on the specific type: **Example 1 - TextPart:** ```json { "text": "Hello, world!" } ``` **Example 2 - FilePart:** ```json { "raw": "iVBORw0KGgo...", "filename": "diagram.png", "mediaType": "image/png" } ``` **Affected Types:** 1. **Part Union Types**: - **TextPart**: - **Legacy:** `{ "kind": "text", "text": "..." }` - **Current:** `{ "text": "..." }` (member presence acts as discriminator) - **FilePart**: - **Legacy:** `{ "kind": "file", "file": { "name": "...", "mimeType": "...", "fileWithBytes": "..." } }` - **Current:** `{ "raw": "...", "filename": "...", "mediaType": "..." }` (or `url` instead of `raw`) - **DataPart**: - **Legacy:** `{ "kind": "data", "data": {...} }` - **Current:** `{ "data": {...}, "mediaType": "application/json" }` 2. **Streaming Event Types**: - **TaskStatusUpdateEvent**: - **Legacy:** `{ "kind": "status-update", "taskId": "...", "status": {...} }` - **Current:** `{ "statusUpdate": { "taskId": "...", "status": {...} } }` - **TaskArtifactUpdateEvent**: - **Legacy:** `{ "kind": "artifact-update", "taskId": "...", "artifact": {...} }` - **Current:** `{ "artifactUpdate": { "taskId": "...", "artifact": {...} } }` **Migration Strategy:** For **Clients** upgrading from pre-0.3.x: 1. Update parsers to expect wrapper objects with member names as discriminators 2. When constructing requests, use the new wrapper format 3. Implement version detection based on the agent's `protocolVersions` in the `AgentCard` 4. Consider maintaining backward compatibility by detecting and handling both formats during a transition period For **Servers** upgrading from pre-0.3.x: 1. Update serialization logic to emit wrapper objects 2. **Breaking:** The `kind` field is no longer part of the protocol and should not be emitted 3. Update deserialization to expect wrapper objects with member names 4. Ensure the `AgentCard` declares the correct `protocolVersions` (e.g., ["1.0"] or later) **Rationale:** This change aligns with modern API design practices and Protocol Buffers' `oneof` semantics, where the field name itself serves as the type discriminator. This approach: - Reduces redundancy (no need for both a field name and a `kind` value) - Aligns JSON-RPC and gRPC representations more closely - Simplifies code generation from schema definitions - Eliminates the need for representing inheritance structures in schema languages - Improves type safety in strongly-typed languages #### A.2.2 Breaking Change: Extended Agent Card Field Relocated **Version 1.0 relocates the extended agent card capability** from a top-level field to the capabilities object for architectural consistency. **Legacy Structure (pre-1.0):** ```json { "supportsExtendedAgentCard": true, "capabilities": { "streaming": true } } ``` **Current Structure (1.0+):** ```json { "capabilities": { "streaming": true, "extendedAgentCard": true } } ``` **Proto Changes:** - Removed: `AgentCard.supports_extended_agent_card` (field 13) - Added: `AgentCapabilities.extended_agent_card` (field 5) **Migration Steps:** For **Agent Implementations**: 1. Remove `supportsExtendedAgentCard` from top-level AgentCard 2. Add `extendedAgentCard` to `capabilities` object 3. Update validation: `agentCard.capabilities?.extendedAgentCard` For **Client Implementations**: 1. Update capability checks: `agentCard.capabilities?.extendedAgentCard` 2. Temporary fallback (transition period): ```javascript const supported = agentCard.capabilities?.extendedAgentCard || agentCard.supportsExtendedAgentCard; ``` 3. Remove fallback after agent ecosystem migrates For **SDK Developers**: 1. Regenerate code from updated proto 2. Update type definitions 3. Document breaking change in release notes **Rationale:** All optional features enabling specific operations (`streaming`, `pushNotifications`) reside in `AgentCapabilities`. Moving `extendedAgentCard` achieves: - Architectural consistency - Improved discoverability - Semantic correctness (it is a capability) ### A.3 Future Automation Once the proto→schema generation pipeline lands, this appendix will be partially auto-generated (legacy mapping table sourced from a maintained manifest). Until then, edits MUST be manual and reviewed in PRs affecting `a2a.proto`. ## Appendix B. Relationship to MCP (Model Context Protocol) A2A and MCP are complementary protocols designed for different aspects of agentic systems: - **[Model Context Protocol (MCP)](https://modelcontextprotocol.io/):** Focuses on standardizing how AI models and agents connect to and interact with **tools, APIs, data sources, and other external resources.** It defines structured ways to describe tool capabilities (like function calling in LLMs), pass inputs, and receive structured outputs. Think of MCP as the "how-to" for an agent to *use* a specific capability or access a resource. - **Agent2Agent Protocol (A2A):** Focuses on standardizing how independent, often opaque, **AI agents communicate and collaborate with each other as peers.** A2A provides an application-level protocol for agents to discover each other, negotiate interaction modalities, manage shared tasks, and exchange conversational context or complex results. It's about how agents *partner* or *delegate* work. **How they work together:** An A2A Client agent might request an A2A Server agent to perform a complex task. The Server agent, in turn, might use MCP to interact with several underlying tools, APIs, or data sources to gather information or perform actions necessary to fulfill the A2A task. For a more detailed comparison, see the [A2A and MCP guide](./topics/a2a-and-mcp.md). --- # A2A and MCP: Detailed Comparison In AI agent development, two key protocol types emerge to facilitate interoperability. One connects agents to tools and resources. The other enables agent-to-agent collaboration. The Agent2Agent (A2A) Protocol and the [Model Context Protocol](https://modelcontextprotocol.io/) (MCP) address these distinct but highly complementary needs. ## Model Context Protocol The Model Context Protocol (MCP) defines how an AI agent interacts with and utilizes individual tools and resources, such as a database or an API. This protocol offers the following capabilities: - Standardizes how AI models and agents connect to and interact with tools, APIs, and other external resources. - Defines a structured way to describe tool capabilities, similar to function calling in Large Language Models. - Passes inputs to tools and receives structured outputs. - Supports common use cases, such as an LLM calling an external API, an agent querying a database, or an agent connecting to predefined functions. ## Agent2Agent Protocol The Agent2Agent Protocol focuses on enabling different agents to collaborate with one another to achieve a common goal. This protocol offers the following capabilities: - Standardizes how independent, often opaque, AI agents communicate and collaborate as peers. - Provides an application-level protocol for agents to discover each other, negotiate interactions, manage shared tasks, and exchange conversational context and complex data. - Supports typical use cases, including a customer service agent delegating an inquiry to a billing agent, or a travel agent coordinating with flight, hotel, and activity agents. ## Why Different Protocols? Both the MCP and A2A protocols are essential for building complex AI systems, and they address distinct but highly complementary needs. The distinction between A2A and MCP depends on what an agent interacts with. - **Tools and Resources (MCP Domain)**: - **Characteristics:** These are typically primitives with well-defined, structured inputs and outputs. They perform specific, often stateless, functions. Examples include a calculator, a database query API, or a weather lookup service. - **Purpose:** Agents use tools to gather information and perform discrete functions. - **Agents (A2A domain)**: - **Characteristics:** These are more autonomous systems. They reason, plan, use multiple tools, maintain state over longer interactions, and engage in complex, often multi-turn dialogues to achieve novel or evolving tasks. - **Purpose:** Agents collaborate with other agents to tackle broader, more complex goals. ## A2A ❤️ MCP: Complementary Protocols for Agentic Systems An agentic application might primarily use A2A to communicate with other agents. Each individual agent internally uses MCP to interact with its specific tools and resources.
![Diagram showing A2A and MCP working together. A User interacts with Agent A using A2A. Agent A interacts with Agent B using A2A. Agent B uses MCP to interact with Tool 1 and Tool 2.](../assets/a2a-mcp.png){width="80%"} _An agentic application might use A2A to communicate with other agents, while each agent internally uses MCP to interact with its specific tools and resources._
### Example Scenario: The Auto Repair Shop Consider an auto repair shop staffed by autonomous AI agent "mechanics". These mechanics use special-purpose tools, such as vehicle diagnostic scanners, repair manuals, and platform lifts, to diagnose and repair problems. The repair process can involve extensive conversations, research, and interaction with part suppliers. - **Customer Interaction (User-to-Agent using A2A)**: A customer (or their primary assistant agent) uses A2A to communicate with the "Shop Manager" agent. For example, the customer might say, "My car is making a rattling noise". - **Multi-turn Diagnostic Conversation (Agent-to-Agent using A2A)**: The Shop Manager agent uses A2A for a multi-turn diagnostic conversation. For example, the Manager might ask, "Can you send a video of the noise?" or "I see some fluid leaking. How long has this been happening?". - **Internal Tool Usage (Agent-to-Tool using MCP)**: The Mechanic agent, assigned the task by the Shop Manager, needs to diagnose the issue. The Mechanic agent uses MCP to interact with its specialized tools. For example: - MCP call to a "Vehicle Diagnostic Scanner" tool: `scan_vehicle_for_error_codes(vehicle_id='XYZ123')` - MCP call to a "Repair Manual Database" tool: `get_repair_procedure(error_code='P0300', vehicle_make='Toyota', vehicle_model='Camry')` - MCP call to a "Platform Lift" tool: `raise_platform(height_meters=2)` - **Supplier Interaction (Agent-to-Agent using A2A)**: The Mechanic agent determines that a specific part is needed. The Mechanic agent uses A2A to communicate with a "Parts Supplier" agent to order a part. For example, the Mechanic agent might ask, "Do you have part #12345 in stock for a Toyota Camry 2018?" - **Order processing (Agent-to-Agent using A2A)**: The Parts Supplier agent, which is also an A2A-compliant system, responds, potentially leading to an order. In this example: - A2A facilitates the higher-level, conversational, and task-oriented interactions between the customer and the shop, and between the shop's agents and external supplier agents. - MCP enables the mechanic agent to use its specific, structured tools to perform its diagnostic and repair functions. An A2A server could expose some of its skills as MCP-compatible resources. However, A2A's primary strength lies in its support for more flexible, stateful, and collaborative interactions. These interactions go beyond a typical tool invocation. A2A focuses on agents partnering on tasks, whereas MCP focuses on agents using capabilities. ## Representing A2A Agents as MCP Resources An A2A Server (a remote agent) could expose some of its skills as MCP-compatible resources, especially if those skills are well-defined and can be invoked in a more tool-like, stateless manner. In such a case, another agent might "discover" this A2A agent's specific skill through an MCP-style tool description (perhaps derived from its Agent Card). However, the primary strength of A2A lies in its support for more flexible, stateful, and collaborative interactions that go beyond typical tool invocation. A2A is about agents _partnering_ on tasks, while MCP is more about agents _using_ capabilities. By leveraging both A2A for inter-agent collaboration and MCP for tool integration, developers can build more powerful, flexible, and interoperable AI systems.
# Agent Discovery in A2A To collaborate using the Agent2Agent (A2A) protocol, AI agents need to first find each other and understand their capabilities. A2A standardizes agent self-descriptions through the **[Agent Card](../specification.md#5-agent-discovery-the-agent-card)**. However, discovery methods for these Agent Cards vary by environment and requirements. The Agent Card defines what an agent offers. Various strategies exist for a client agent to discover these cards. The choice of strategy depends on the deployment environment and security requirements. ## The Role of the Agent Card The Agent Card is a JSON document that serves as a digital "business card" for an A2A Server (the remote agent). It is crucial for agent discovery and interaction. The key information included in an Agent Card is as follows: - **Identity:** Includes `name`, `description`, and `provider` information. - **Service Endpoint:** Specifies the `url` for the A2A service. - **A2A Capabilities:** Lists supported features such as `streaming` or `pushNotifications`. - **Authentication:** Details the required `schemes` (e.g., "Bearer", "OAuth2"). - **Skills:** Describes the agent's tasks using `AgentSkill` objects, including `id`, `name`, `description`, `inputModes`, `outputModes`, and `examples`. Client agents use the Agent Card to determine an agent's suitability, structure requests, and ensure secure communication. ## Discovery Strategies The following sections detail common strategies used by client agents to discover remote Agent Cards: ### 1. Well-Known URI This approach is recommended for public agents or agents intended for broad discovery within a specific domain. - **Mechanism:** A2A Servers make their Agent Card discoverable by hosting it at a standardized, `well-known` URI on their domain. The standard path is `https://{agent-server-domain}/.well-known/agent-card.json`, following the principles of [RFC 8615](https://datatracker.ietf.org/doc/html/rfc8615). - **Process:** 1. A client agent knows or programmatically discovers the domain of a potential A2A Server (e.g., `smart-thermostat.example.com`). 2. The client performs an HTTP GET request to `https://smart-thermostat.example.com/.well-known/agent-card.json`. 3. If the Agent Card exists and is accessible, the server returns it as a JSON response. - **Advantages:** - Ease of implementation - Adheres to standards - Facilitates automated discovery - **Considerations:** - Best suited for open or domain-controlled discovery scenarios. - Authentication is necessary at the endpoint serving the Agent Card if it contains sensitive details. ### 2. Curated Registries (Catalog-Based Discovery) This approach is employed in enterprise environments or public marketplaces, where Agent Cards are often managed by a central registry. The curated registry acts as a central repository, allowing clients to query and discover agents based on criteria like "skills" or "tags". - **Mechanism:** An intermediary service (the registry) maintains a collection of Agent Cards. Clients query this registry to find agents based on various criteria (e.g., skills offered, tags, provider name, capabilities). - **Process:** 1. A2A Servers publish their Agent Cards to the registry. 2. Client agents query the registry's API, and search by criteria such as "specific skills". 3. The registry returns matching Agent Cards or references. - **Advantages:** - Centralized management and governance. - Capability-based discovery (e.g., by skill). - Support for access controls and trust frameworks. - Applicable in both private and public marketplaces. - **Considerations:** - Requires deployment and maintenance of a registry service. - The current A2A specification does not prescribe a standard API for curated registries. ### 3. Direct Configuration / Private Discovery This approach is used for tightly coupled systems, private agents, or development purposes, where clients are directly configured with Agent Card information or URLs. - **Mechanism:** Client applications utilize hardcoded details, configuration files, environment variables, or proprietary APIs for discovery. - **Process:** The process is specific to the application's deployment and configuration strategy. - **Advantages:** This method is straightforward for establishing connections within known, static relationships. - **Considerations:** - Inflexible for dynamic discovery scenarios. - Changes to Agent Card information necessitate client reconfiguration. - Proprietary API-based discovery also lacks standardization. ## Securing Agent Cards Agent Cards include sensitive information, such as: - URLs for internal or restricted agents. - Descriptions of sensitive skills. ### Protection Mechanisms To mitigate risks, the following protection mechanisms should be considered: - **Authenticated Agent Cards:** We recommend the use of [authenticated extended agent cards](../specification.md#3111-get-extended-agent-card) for sensitive information or for serving a more detailed version of the card. - **Secure Endpoints:** Implement access controls on the HTTP endpoint serving the Agent Card (e.g., `/.well-known/agent-card.json` or registry API). The methods include: - Mutual TLS (mTLS) - Network restrictions (e.g., IP ranges) - HTTP Authentication (e.g., OAuth 2.0) - **Registry Selective Disclosure:** Registries return different Agent Cards based on the client's identity and permissions. Any Agent Card containing sensitive data must be protected with authentication and authorization mechanisms. The A2A specification strongly recommends the use of out-of-band dynamic credentials rather than embedding static secrets within the Agent Card. ## Caching Considerations Agent Cards describe an agent's capabilities and typically change infrequently — for example, when skills are added or authentication requirements are updated. Applying standard HTTP caching practices to Agent Card endpoints reduces unnecessary network requests while ensuring clients eventually receive updated information. ### Server Guidance Servers hosting Agent Card endpoints should include HTTP caching headers in their responses. The `Cache-Control` header with an appropriate `max-age` directive allows clients and intermediaries to cache the card for a specified duration. Including an `ETag` header — derived from the card's `version` field or a content hash — enables clients to make conditional requests and avoid re-downloading unchanged cards. ### Client Guidance Clients fetching Agent Cards should honor standard HTTP caching semantics. When a cached card expires, clients should use conditional requests (for example, `If-None-Match` with the stored `ETag` or `If-Modified-Since`) rather than unconditionally re-fetching the full card. When the server does not provide caching headers, clients may apply a reasonable default cache duration. For Extended Agent Cards, clients should also follow the session-scoped caching guidance described in the [specification](../specification.md#133-extended-agent-card-access-control). For normative requirements, see [Section 8.6](../specification.md#86-caching) of the specification. ## Future Considerations The A2A community explores standardizing registry interactions or advanced discovery protocols. # Custom Protocol Bindings The A2A protocol ships with three standard bindings (JSON-RPC, gRPC, and HTTP+JSON/REST) that cover the majority of deployment scenarios. Custom protocol bindings let implementers expose A2A operations over additional transport mechanisms not covered by the standard set. Custom protocol bindings are a complementary but distinct concept to [Extensions](extensions.md). Extensions modify the *behavior* of protocol interactions by adding new data, methods, or state transitions on top of an existing transport. Custom protocol bindings change the *transport layer* itself—for example, exposing A2A over WebSockets for low-latency bidirectional communication, or over MQTT for IoT environments with constrained connectivity. ## Declaration in the Agent Card Custom protocol bindings are declared in the Agent Card's `supportedInterfaces` list. Each entry identifies the transport by URI, the endpoint URL, and the A2A protocol version it implements. The `protocolBinding` field should be a URI that uniquely identifies the binding (see [Section 5.8 of the specification](../specification.md#58-custom-binding-identification) for the normative requirement and versioning guidance). ```json { "supportedInterfaces": [ { "url": "wss://agent.example.com/a2a/websocket", "protocolBinding": "https://a2a-protocol.org/bindings/websocket", "protocolVersion": "1.0" } ] } ``` Agents that support multiple bindings list all of them. Clients parse `supportedInterfaces` in order and select the first transport they support, so entries should be listed in preference order. ## Requirements Custom protocol bindings must comply with all requirements in the [Protocol Binding Requirements and Interoperability](../specification.md#5-protocol-binding-requirements-and-interoperability) section of the specification. In particular: - **All core operations must be supported.** The binding must expose every operation defined in the abstract operations layer (send message, get task, cancel task, streaming, push notifications, etc.). - **The data model must be preserved.** All data structures must be functionally equivalent to the canonical Protocol Buffer definitions. JSON serializations must use camelCase field names, and timestamps must be ISO 8601 strings in UTC. - **Behavior must be consistent.** Semantically equivalent requests must produce semantically equivalent results regardless of which binding is used. ## Key Areas to Specify A custom binding specification must address each of the following areas. ### Data Type Mappings Document how each Protocol Buffer type is represented in the custom transport, including: - Binary data encoding (e.g., base64 for text-based transports) - Enum representation (strings, integers, or named constants) - Timestamp format (ISO 8601 strings in UTC per the core convention) ### Service Parameters Service parameters are key-value pairs used to carry horizontally applicable context such as tracing identifiers or authentication hints. The binding specification must state: - The mechanism used to carry service parameters (e.g., custom message headers, a top-level metadata field) - Any character encoding or size constraints on keys and values - Any names reserved by the binding itself For transports that lack native header support, a common pattern is to embed service parameters as a JSON object in a dedicated metadata field, for example `a2a-service-parameters`. ### Error Mapping The binding must map all A2A error types to transport-native error representations while preserving their semantic meaning. Provide a mapping table equivalent to the one in the specification's [Error Code Mappings](../specification.md#54-error-code-mappings) section, showing how each A2A error type (e.g., `TaskNotFoundError`, `UnsupportedOperationError`) is expressed in the custom binding's native error format. ### Streaming If the transport supports streaming, document: - The stream mechanism (e.g., WebSocket frames, chunked encoding, long polling) - Ordering guarantees (events must be delivered in the order they were generated) - Reconnection behavior when a connection is interrupted - How stream completion or termination is signaled to the client If the transport does not support streaming, state this limitation clearly in the Agent Card so clients can fall back to polling. ### Authentication and Authorization Document how authentication credentials declared in the Agent Card are transmitted using the custom transport. Define how authentication challenges are communicated to clients and ensure the custom binding does not inadvertently bypass the agent's primary security controls. ## Interoperability Testing Before publishing a custom binding, verify that: - All operations behave identically to the standard bindings for the same logical requests - Error conditions, large payloads, and long-running tasks are handled correctly - Any intentional deviations from standard binding behavior are clearly documented - Sample requests and responses are included in the specification to help implementers ## Governance The A2A organization uses a formal governance framework for how custom protocol bindings are proposed, developed, promoted, and maintained. Official bindings use the `https://a2a-protocol.org/bindings/` URI prefix and are hosted under the `a2aproject` organization with the `cpb-` repository prefix (experimental bindings use `experimental-cpb-`). A2A SDKs SHOULD implement official custom protocol bindings. !!! note "URI Namespaces" The `https://a2a-protocol.org/bindings/` prefix is a canonical namespace for globally unique binding identifiers used in Agent Cards. Individual URIs under this prefix, such as `https://a2a-protocol.org/bindings/{name}/v1` identify a specific binding and version. These URIs are identifiers, HTTP access is not expected. See [URI namespaces](extension-and-binding-governance.md#uri-namespaces) in the governance documentation for details. For the full governance process—including tiers, lifecycle, SDK support, and legal requirements—see the [Extension and Protocol Binding Governance](extension-and-binding-governance.md) page. # Enterprise Implementation of A2A The Agent2Agent (A2A) protocol is designed with enterprise requirements at its core. Rather than inventing new, proprietary standards for security and operations, A2A aims to integrate seamlessly with existing enterprise infrastructure and widely adopted best practices. This approach allows organizations to use their existing investments and expertise in security, monitoring, governance, and identity management. A key principle of A2A is that agents are typically **opaque** because they don't share internal memory, tools, or direct resource access with each other. This opacity naturally aligns with standard client-server security paradigms, treating remote agents as standard HTTP-based enterprise applications. ## Transport Level Security (TLS) Ensuring the confidentiality and integrity of data in transit is fundamental for any enterprise application. - **HTTPS Mandate**: All A2A communication in production environments must occur over `HTTPS`. - **Modern TLS Standards**: Implementations should use modern TLS versions. TLS 1.2 or higher is recommended. Strong, industry-standard cipher suites should be used to protect data from eavesdropping and tampering. - **Server Identity Verification**: A2A clients should verify the A2A server's identity by validating its TLS certificate against trusted certificate authorities during the TLS handshake. This prevents man-in-the-middle attacks. ## Authentication A2A delegates authentication to standard web mechanisms. It primarily relies on HTTP headers and established standards like OAuth2 and OpenID Connect. Authentication requirements are advertised by the A2A server in its Agent Card. - **No Identity in Payload**: A2A protocol payloads, such as `JSON-RPC` messages, don't carry user or client identity information directly. Identity is established at the transport/HTTP layer. - **Agent Card Declaration**: The A2A server's Agent Card describes the authentication schemes it supports in its `security` field and aligns with those defined in the OpenAPI Specification for authentication. - **Out-of-Band Credential Acquisition**: The A2A Client obtains the necessary credentials, such as OAuth 2.0 tokens or API keys, through processes external to the A2A protocol itself. Examples include OAuth flows or secure key distribution. - **HTTP Header Transmission**: Credentials **must** be transmitted in standard HTTP headers as per the requirements of the chosen authentication scheme. Examples include `Authorization: Bearer ` or `API-Key: `. - **Server-Side Validation**: The A2A server **must** authenticate every incoming request using the credentials provided in the HTTP headers. - If authentication fails or credentials are missing, the server **should** respond with a standard HTTP status code: - `401 Unauthorized`: If the credentials are missing or invalid. This response **should** include a `WWW-Authenticate` header to inform the client about the supported authentication methods. - `403 Forbidden`: If the credentials are valid, but the authenticated client does not have permission to perform the requested action. - **In-Task Authentication (Secondary Credentials)**: If an agent needs additional credentials to access a different system or service during a task (for example, to use a specific tool on the user's behalf), the A2A server indicates to the client that more information is needed. The client is then responsible for obtaining these secondary credentials through a process outside of the A2A protocol itself (for example, an OAuth flow) and providing them back to the A2A server to continue the task. ## Authorization Once a client is authenticated, the A2A server is responsible for authorizing the request. Authorization logic is specific to the agent's implementation, the data it handles, and applicable enterprise policies. - **Granular Control**: Authorization **should** be applied based on the authenticated identity, which could represent an end user, a client application, or both. - **Skill-Based Authorization**: Access can be controlled on a per-skill basis, as advertised in the Agent Card. For example, specific OAuth scopes **should** grant an authenticated client access to invoke certain skills but not others. - **Data and Action-Level Authorization**: Agents that interact with backend systems, databases, or tools **must** enforce appropriate authorization before performing sensitive actions or accessing sensitive data through those underlying resources. The agent acts as a gatekeeper. - **Principle of Least Privilege**: Agents **must** grant only the necessary permissions required for a client or user to perform their intended operations through the A2A interface. ## Data Privacy and Confidentiality Protecting sensitive data exchanged between agents is paramount, requiring strict adherence to privacy regulations and best practices. - **Sensitivity Awareness**: Implementers must be acutely aware of the sensitivity of data exchanged in Message and Artifact parts of A2A interactions. - **Compliance**: Ensure compliance with relevant data privacy regulations such as GDPR, CCPA, and HIPAA, based on the domain and data involved. - **Data Minimization**: Avoid including or requesting unnecessarily sensitive information in A2A exchanges. - **Secure Handling**: Protect data both in transit, using TLS as mandated, and at rest if persisted by agents, according to enterprise data security policies and regulatory requirements. ## Tracing, Observability, and Monitoring A2A's reliance on HTTP allows for straightforward integration with standard enterprise tracing, logging, and monitoring tools, providing critical visibility into inter-agent workflows. - **Distributed Tracing**: A2A Clients and Servers **should** participate in distributed tracing systems. For example, use OpenTelemetry to propagate trace context, including trace IDs and span IDs, through standard HTTP headers, such as W3C Trace Context headers. This enables end-to-end visibility for debugging and performance analysis. - **Comprehensive Logging**: Log details on both client and server, including taskId, sessionId, correlation IDs, and trace context for troubleshooting and auditing. - **Metrics**: A2A servers should expose key operational metrics, such as request rates, error rates, task processing latency, and resource utilization, to enable performance monitoring, alerting, and capacity planning. - **Auditing**: Audit significant events, such as task creation, critical state changes, and agent actions, especially when involving sensitive data or high-impact operations. ## API Management and Governance For A2A servers exposed externally, across organizational boundaries, or even within large enterprises, integration with API Management solutions is highly recommended, as this provides: - **Centralized Policy Enforcement**: Consistent application of security policies such as authentication and authorization, rate limiting, and quotas. - **Traffic Management**: Load balancing, routing, and mediation. - **Analytics and Reporting**: Insights into agent usage, performance, and trends. - **Developer Portals**: Facilitate discovery of A2A-enabled agents, provide documentation such as Agent Cards, and streamline onboarding for client developers. By adhering to these enterprise-grade practices, A2A implementations can be deployed securely, reliably, and manageably within complex organizational environments. This fosters trust and enables scalable inter-agent collaboration. # Extension and Protocol Binding Governance The A2A organization uses a unified governance framework for both [Extensions](extensions.md) and [Custom Protocol Bindings](custom-protocol-bindings.md). This document defines the formal process for proposing, developing, promoting, and maintaining these artifacts within the A2A organization. Anyone may develop and publish extensions or custom protocol bindings independently. The tiers and lifecycle described here apply specifically to those hosted under the `a2aproject` GitHub organization. ## Tiers Both extensions and custom protocol bindings use a two-tier system within the `a2aproject` organization. Repository naming and URI prefixes differ by type: | | Extensions | Custom Protocol Bindings | | :----------------------- | :---------------------------------------------- | :--------------------------------------------- | | Official repo prefix | `ext-{name}` | `cpb-{name}` | | Experimental repo prefix | `experimental-ext-{name}` | `experimental-cpb-{name}` | | Official URI prefix | `https://a2a-protocol.org/extensions/` | `https://a2a-protocol.org/bindings/` | ### URI namespaces The official URI prefixes are canonical namespace identifiers used to assign globally unique URIs to extensions and custom protocol bindings. Agents and clients reference these URIs in Agent Cards, headers, and protocol messages to declare and negotiate support. Individual URIs under a prefix identify a specific artifact and, where applicable, its version—for example, `https://a2a-protocol.org/extensions/{name}/v1` or `https://a2a-protocol.org/bindings/{name}/v1`. These URIs are identifiers, HTTP access is not expected. ### Official Official artifacts are developed and maintained under the `a2aproject` GitHub organization, officially recommended by the TSC. Each repository has designated maintainers identified in `MAINTAINERS.md`. **Requirements:** - Specifications MUST use the same language as the core specification ([RFC 2119](https://tools.ietf.org/html/rfc2119)) - MUST be licensed under Apache 2.0 - MUST have at least one reference implementation - SHOULD have associated documentation on the A2A website ### Experimental Experimental artifacts provide an incubation pathway for community contributors to prototype and collaborate on ideas before graduation to official status. **Creation Requirements:** - An experimental repository can ONLY be created with sponsorship from an A2A Maintainer - The sponsoring Maintainer is responsible for initial oversight of the experimental artifact - Experimental repositories MUST clearly indicate their experimental/non-official status in the README - Any published packages MUST use naming that clearly indicates experimental status - The TSC retains oversight, including the ability to archive or remove experimental repositories ## Lifecycle Extensions and custom protocol bindings progress through the following phases. ### Proposal Phase Any community member may propose an extension or custom protocol binding: 1. **Open an Issue**: Create an issue in the main `a2aproject/A2A` repository describing: - An abstract describing the extension's purpose or the binding's transport and use case - Motivation explaining why this cannot be achieved with the core protocol or existing standard bindings - An initial technical approach or specification draft 2. **Community Discussion**: The proposal is open for community feedback and refinement ### Maintainer Sponsorship For a proposal to proceed to experimental status: 1. **Secure a Sponsor**: An A2A Maintainer must agree to sponsor the proposal 2. **Repository Creation**: The sponsoring Maintainer creates the `experimental-ext-*` or `experimental-cpb-*` repository under `a2aproject` 3. **Oversight**: The sponsoring Maintainer provides initial oversight and ensures alignment with A2A design principles ### Experimental Development While in experimental status: - Contributors iterate on the specification and reference implementations - The experimental artifact MAY be used by early adopters with the understanding that breaking changes are expected - Community feedback is gathered and incorporated - The experimental repository MUST clearly indicate its non-official status ### Graduation to Official Status To graduate an experimental extension or binding to official status: 1. **Maturity Requirements**: - At least one production-quality reference implementation - Documentation meeting A2A standards - Evidence of community adoption or interest - Clear maintainer commitment for ongoing maintenance 2. **Graduation Proposal**: Open an issue in `a2aproject/A2A` with: - Reference to the experimental repository and its implementations - Summary of community feedback and adoption - Proposed maintainers for the official artifact 3. **TSC Vote**: - The proposal is added to the TSC meeting agenda - **Quorum Requirement**: At least 50% of TSC voting members must be present - **Approval**: Requires majority vote of those in attendance (per A2A governance) - The TSC may request revisions before a final vote 4. **Acceptance**: - (Extensions) The repository is renamed from `experimental-ext-*` to `ext-*`; documentation is added to the A2A website's extensions page - (Custom Protocol Bindings) The repository is renamed from `experimental-cpb-*` to `cpb-*`; documentation is added to the A2A website's custom protocol bindings page ### Official Iteration Once official, extensions and bindings may be iterated on: - Repository maintainers are responsible for day-to-day governance - Changes SHOULD be coordinated via the relevant working group if one exists - Breaking changes require a new identifier - Breaking changes require TSC review - Maintainers SHOULD coordinate with SDK maintainers for implementation updates ### Promotion to Core Protocol Some extensions may eventually transition to core protocol features, and some custom protocol bindings may transition to core bindings. This is governed through the existing A2A specification enhancement process: - A proposal is submitted following the standard specification change process - The proposal references the official extension or binding and its adoption - TSC vote with standard quorum and majority requirements applies - Not all extensions or bindings are suitable for core inclusion; many will remain as extensions or custom bindings indefinitely ## SDK Support SDK support requirements differ between extensions and official custom protocol bindings, reflecting their different roles in the protocol ecosystem. **Extensions**: A2A SDKs MAY implement extensions. Where implemented: - Extensions MUST be disabled by default and require explicit opt-in - SDK documentation SHOULD list supported extensions - SDK maintainers have full autonomy over extension support decisions - Extension support is not required for protocol conformance **Official Custom Protocol Bindings**: A2A SDKs SHOULD implement official custom protocol bindings. Where implemented: - Custom protocol bindings MUST be disabled by default and require explicit opt-in - SDK documentation SHOULD list supported custom protocol bindings - SDK maintainers have full autonomy over binding support decisions - Custom protocol binding support is not required for protocol conformance ## Legal Requirements ### Licensing Official extensions and custom protocol bindings MUST be available under the Apache 2.0 license, consistent with the core A2A project. ### Contributor License Grant By submitting a contribution to an official A2A extension or custom protocol binding repository, contributors represent that: 1. They have the legal authority to grant the rights 2. The contribution is original work or they have sufficient rights to submit it 3. They grant to the Linux Foundation and recipients a perpetual, worldwide, non-exclusive, royalty-free license to use, reproduce, modify, and distribute the contribution ### Antitrust Extension and custom protocol binding developers acknowledge that: - They may compete with other participants - They have no obligation to implement any extension or binding - They are free to develop competing extensions or bindings - Status as an official extension or binding does not create an exclusive relationship # Extensions in A2A The Agent2Agent (A2A) protocol provides a strong foundation for inter-agent communication. However, specific domains or advanced use cases often require additional structure, custom data, or new interaction patterns beyond the generic methods. Extensions are A2A's powerful mechanism for layering new capabilities onto the base protocol. Extensions allow for extending the A2A protocol with new data, requirements, RPC methods, and state machines. Agents declare their support for specific extensions in their Agent Card, and clients can then opt in to the behavior offered by an extension as part of requests they make to the agent. Extensions are identified by a URI and defined by their own specification. Anyone is able to define, publish, and implement an extension. The flexibility of extensions allows for customizing A2A without fragmenting the core standard, fostering innovation and domain-specific optimizations. ## Scope of Extensions The exact set of possible ways to use extensions is intentionally broad, facilitating the ability to expand A2A beyond known use cases. However, some foreseeable applications include: - **Data-only Extensions**: Exposing new, structured information in the Agent Card that doesn't impact the request-response flow. For example, an extension could add structured data about an agent's GDPR compliance. - **Profile Extensions**: Overlaying additional structure and state change requirements on the core request-response messages. This type effectively acts as a profile on the core A2A protocol, narrowing the space of allowed values (for example, requiring all messages to use `DataParts` adhering to a specific schema). This can also include augmenting existing states in the task state machine by using metadata. For example, an extension could define a 'generating-image' substate when `TaskStatus.state` is 'working' and `TaskStatus.message.metadata["generating-image"]` is true. - **Method Extensions (Extended Skills)**: Adding entirely new RPC methods beyond the core set defined by the protocol. An Extended Skill refers to a capability or function an agent gains or exposes specifically through the implementation of an extension that defines new RPC methods. For example, a `task-history` extension might add a `tasks/search` RPC method to retrieve a list of previous tasks, effectively providing the agent with a new, extended skill. - **State Machine Extensions**: Adding new states or transitions to the task state machine. ## List of Example Extensions | Extension | Description | | :-------- | :------------ | | [Secure Passport Extension](https://github.com/a2aproject/a2a-samples/tree/main/extensions/secure-passport) | Adds a trusted, contextual layer for immediate personalization and reduced overhead (v1). | | [Hello World or Timestamp Extension](https://github.com/a2aproject/a2a-samples/tree/main/extensions/timestamp) | A simple extension demonstrating how to augment base A2A types by adding timestamps to the `metadata` field of `Message` and `Artifact` objects (v1). | | [Traceability Extension](https://github.com/a2aproject/a2a-samples/tree/main/samples/python/extensions/traceability) | Explore the Python implementation and basic usage of the Traceability Extension (v1). | | [Agent Gateway Protocol (AGP) Extension](https://github.com/a2aproject/a2a-samples/tree/main/extensions/agp) | A Core Protocol Layer or Routing Extension that introduces Autonomous Squads (ASq) and routes Intent payloads based on declared Capabilities, enhancing scalability (v1). | ## Extension Governance The A2A organization uses a formal governance framework for how extensions are proposed, developed, promoted, and maintained. Official extensions use the `https://a2a-protocol.org/extensions/` URI prefix and are hosted under the `a2aproject` organization with the `ext-` repository prefix (experimental extensions use `experimental-ext-`). !!! note "URI Namespaces" The `https://a2a-protocol.org/extensions/` prefix is a canonical namespace for globally unique extension identifiers used in Agent Cards and protocol messages. Individual URIs under this prefix, such as `https://a2a-protocol.org/extensions/{name}/v1` identify a specific extension and version. These URIs are identifiers, HTTP access is not expected. See [URI namespaces](extension-and-binding-governance.md#uri-namespaces) in the governance documentation for details. For the full governance process—including tiers, lifecycle, SDK support, and legal requirements—see the [Extension and Protocol Binding Governance](extension-and-binding-governance.md) page. ## Limitations There are some changes to the protocol that extensions don't allow, primarily to prevent breaking core type validations: - **Changing the Definition of Core Data Structures**: For example, adding new fields or removing required fields to protocol-defined data structures. Extensions should place custom attributes in the `metadata` map present on core data structures. - **Adding New Values to Enum Types**: Extensions should use existing enum values and annotate additional semantic meaning in the `metadata` field. ## Extension Declaration Agents declare their support for extensions in their Agent Card by including `AgentExtension` objects within their `AgentCapabilities` object. {{ proto_to_table("AgentExtension") }} The following is an example of an Agent Card with an extension: ```json { "name": "Magic 8-ball", "description": "An agent that can tell your future... maybe.", "version": "0.1.0", "url": "https://example.com/agents/eightball", "capabilities": { "streaming": true, "extensions": [ { "uri": "https://example.com/ext/konami-code/v1", "description": "Provide cheat codes to unlock new fortunes", "required": false, "params": { "hints": [ "When your sims need extra cash fast", "You might deny it, but we've seen the evidence of those cows." ] } } ] }, "defaultInputModes": ["text/plain"], "defaultOutputModes": ["text/plain"], "skills": [ { "id": "fortune", "name": "Fortune teller", "description": "Seek advice from the mystical magic 8-ball", "tags": ["mystical", "untrustworthy"] } ] } ``` ## Required Extensions While extensions generally offer optional functionality, some agents may have stricter requirements. When an Agent Card declares an extension as `required: true`, it signals to clients that some aspect of the extension impacts how requests are structured or processed, and that the client must abide by it. Agents shouldn't mark data-only extensions as required. If a client does not request activation of a required extension, or fails to follow its protocol, the agent should reject the incoming request with an appropriate error. ## Extension Specification The detailed behavior and structure of an extension are defined by its **specification**. While the exact format is not mandated, it should contain at least: - The specific URI(s) that identify the extension. - The schema and meaning of objects specified in the `params` field of the `AgentExtension` object. - Schemas of any additional data structures communicated between client and agent. - Details of new request-response flows, additional endpoints, or any other logic required to implement the extension. ## Extension Dependencies Extensions might depend on other extensions. This can be a required dependency (where the extension cannot function without the dependent) or an optional one (where additional functionality is enabled if another extension is present). Extension specifications should document these dependencies. It is the client's responsibility to activate an extension and all its required dependencies as listed in the extension's specification. ## Extension Activation Extensions default to being inactive, providing a baseline experience for extension-unaware clients. Clients and agents perform negotiation to determine which extensions are active for a specific request. 1. **Client Request**: A client requests extension activation by including the `A2A-Extensions` header in the HTTP request to the agent. The value is a comma-separated list of extension URIs the client intends to activate. 2. **Agent Processing**: Agents are responsible for identifying supported extensions in the request and performing the activation. Any requested extensions not supported by the agent can be ignored. 3. **Response**: Once the agent has identified all activated extensions, the response SHOULD include the `A2A-Extensions` header, listing all extensions that were successfully activated for that request. ![A2A Extension Flow Diagram](https://storage.googleapis.com/gweb-developer-goog-blog-assets/images/Screenshot_2025-09-04_at_13.03.31.original.png){ width="70%" style="margin:20px auto;display:block;" } **Example request showing extension activation:** ```http POST /agents/eightball HTTP/1.1 Host: example.com Content-Type: application/json A2A-Extensions: https://example.com/ext/konami-code/v1 Content-Length: 519 { "jsonrpc": "2.0", "method": "SendMessage", "id": "1", "params": { "message": { "messageId": "1", "role": "ROLE_USER", "parts": [{"text": "Oh magic 8-ball, will it rain today?"}] }, "metadata": { "https://example.com/ext/konami-code/v1/code": "motherlode" } } } ``` **Corresponding response echoing activated extensions:** ```http HTTP/1.1 200 OK Content-Type: application/json A2A-Extensions: https://example.com/ext/konami-code/v1 Content-Length: 338 { "jsonrpc": "2.0", "id": "1", "result": { "message": { "messageId": "2", "role": "ROLE_AGENT", "parts": [{"text": "That's a bingo!"}] } } } ``` ## Implementation Considerations While the A2A protocol defines the functionality of extensions, this section provides guidance on their implementation—best practices for authoring, versioning, and distributing extension implementations. - **Versioning**: Extension specifications evolve. It is crucial to have a clear versioning strategy to ensure that clients and agents can negotiate compatible implementations. - **Recommendation**: Use the extension's URI as the primary version identifier, ideally including a version number (for example, `https://example.com/ext/my-extension/v1`). - **Breaking Changes**: A new URI MUST be used when introducing a breaking change to an extension's logic, data structures, or required parameters. - Handling Mismatches: If a client requests a version not supported by the agent, the agent SHOULD ignore the activation request for that extension; it MUST NOT fall back to a different version. - **Discoverability and Publication**: - **Specification Hosting**: The extension specification document **should** be hosted at the extension's URI. - **Permanent Identifiers**: Authors are encouraged to use a permanent identifier service, such as `w3id.org`, for their extension URIs to prevent broken links. - **Community Registry**: The A2A [Extension Governance](#extension-governance) framework defines a tiered system for official and experimental extensions hosted under the `a2aproject` organization, including a lifecycle for proposing and promoting extensions. - **Packaging and Reusability (A2A SDKs and Libraries)**: To promote adoption, extension logic should be packaged into reusable libraries that can be integrated into existing A2A client and server applications. - An extension implementation should be distributed as a standard package for its language ecosystem (for example, a PyPI package for Python, an npm package for TypeScript/JavaScript). - The objective is to provide a streamlined integration experience for developers. A well-designed extension package should allow a developer to add it to their server with minimal code, for example: ```python --8<-- "https://raw.githubusercontent.com/a2aproject/a2a-samples/refs/heads/main/samples/python/agents/adk_expense_reimbursement/__main__.py" ``` This example showcases how A2A SDKs or libraries such as `a2a.server` in Python facilitate the implementation of A2A agents and extensions. - **Security**: Extensions modify the core behavior of the A2A protocol, and therefore introduce new security considerations: - **Input Validation**: Any new data fields, parameters, or methods introduced by an extension MUST be rigorously validated. Treat all extension-related data from an external party as untrusted input. - **Scope of Required Extensions**: Be mindful when marking an extension as `required: true` in an Agent Card. This creates a hard dependency for all clients and should only be used for extensions fundamental to the agent's core function and security (for example, a message signing extension). - **Authentication and Authorization**: If an extension adds new methods, the implementation MUST ensure these methods are subject to the same authentication and authorization checks as the core A2A methods. An extension MUST NOT provide a way to bypass the agent's primary security controls. For more information, see the [A2A Extensions: Empowering Custom Agent Functionality](https://developers.googleblog.com/en/a2a-extensions-empowering-custom-agent-functionality/) blog post. # Core Concepts and Components in A2A A2A uses a set of core concepts that define how agents interact. Understand these core building blocks to develop or integrate with A2A-compliant systems. ![A2A Actors showing a User, A2A Client (Client Agent), and A2A Server (Remote Agent)](../assets/a2a-actors.png){ width="70%" style="margin:20px auto;display:block;" } ## Core Actors in A2A Interactions - **User**: The end user, which can be a human operator or an automated service. The user initiates a request or defines a goal that requires assistance from one or more AI agents. - **A2A Client (Client Agent)**: An application, service, or another AI agent that acts on behalf of the user. The client initiates communication using the A2A protocol. - **A2A Server (Remote Agent)**: An AI agent or an agentic system that exposes an HTTP endpoint implementing the A2A protocol. It receives requests from clients, processes tasks, and returns results or status updates. From the client's perspective, the remote agent operates as an _opaque_ (black-box) system, meaning its internal workings, memory, or tools are not exposed. ## Fundamental Communication Elements The following table describes the fundamental communication elements in A2A: | Element | Description | Key Purpose | | :------ | :---------- | :---------- | | Agent Card | A JSON metadata document describing an agent's identity, capabilities, endpoint, skills, and authentication requirements. | Enables clients to discover agents and understand how to interact with them securely and effectively. | | Task | A stateful unit of work initiated by an agent, with a unique ID and defined lifecycle. | Facilitates tracking of long-running operations and enables multi-turn interactions and collaboration. | | Message | A single turn of communication between a client and an agent, containing content and a role ("user" or "agent"). | Conveys instructions, context, questions, answers, or status updates that are not necessarily formal artifacts. | | Part | The fundamental content container used within Messages and Artifacts. A Part holds one of: text content, a file reference (URL or inline bytes), or structured data. | Provides flexibility for agents to exchange various content types within messages and artifacts. | | Artifact | A tangible output generated by an agent during a task (for example, a document, image, or structured data). | Delivers the concrete results of an agent's work, ensuring structured and retrievable outputs. | ## Interaction Mechanisms The A2A Protocol supports various interaction patterns to accommodate different needs for responsiveness and persistence. These mechanisms ensure that agents can exchange information efficiently and reliably, regardless of the task's complexity or duration: - **Request/Response (Polling)**: Clients send a request and the server responds. For long-running tasks, the client periodically polls the server for updates. - **Streaming with Server-Sent Events (SSE)**: Clients initiate a stream to receive real-time, incremental results or status updates from the server over an open HTTP connection. - **Push Notifications**: For very long-running tasks or disconnected scenarios, the server can actively send asynchronous notifications to a client-provided webhook when significant task updates occur. For a detailed exploration of streaming and push notifications, refer to the [Streaming & Asynchronous Operations](./streaming-and-async.md) document. ## Agent Cards The Agent Card is a JSON document that serves as a digital business card for initial discovery and interaction setup. It provides essential metadata about an agent. Clients parse this information to determine if an agent is suitable for a given task, how to structure requests, and how to communicate securely. Key information includes identity, service endpoint (URL), A2A capabilities, authentication requirements, and a list of skills. ## Messages and Parts A message represents a single turn of communication between a client and an agent. It includes a role ("user" or "agent") and a unique `messageId`. It contains one or more Part objects, which are granular containers for the actual content. This design allows A2A to be modality independent. The `Part` object is a flexible container that can hold different types of content using a `oneof` field structure. A Part must contain exactly one of the following content fields: - `text`: A string containing plain textual content. - `raw`: A byte array containing binary file data (inline). - `url`: A string URI referencing external file content. - `data`: A structured JSON value (e.g., object, array) for machine-readable data. Additionally, every `Part` can include: - `mediaType`: The MIME type of the content (e.g., `"text/plain"`, `"image/png"`, `"application/json"`). - `filename`: An optional name for the file or content. - `metadata`: A key-value map for additional context. ## Artifacts An artifact represents a tangible output or a concrete result generated by a remote agent during task processing. Unlike general messages, artifacts are the actual deliverables. An artifact has a unique `artifactId`, a human-readable name, and consists of one or more part objects. Artifacts are closely tied to the task lifecycle and can be streamed incrementally to the client. ## Agent Response: Task or Message The agent response can be a new `Task` (when the agent needs to perform a long-running operation) or a `Message` (when the agent can respond immediately). For more details, see [Life of a Task](./life-of-a-task.md). ## Other Important Concepts - **Context (`contextId`):** A server-generated identifier that can be used to logically group multiple related `Task` objects, providing context across a series of interactions. - **Transport and Format:** A2A communication occurs over HTTP(S). JSON-RPC 2.0 is used as the payload format for all requests and responses. - **Authentication & Authorization:** A2A relies on standard web security practices. Authentication requirements are declared in the Agent Card, and credentials (e.g., OAuth tokens, API keys) are typically passed through HTTP headers, separate from the A2A protocol messages themselves. For more information, see [Enterprise-Ready Features](./enterprise-ready.md). - **Agent Discovery:** The process by which clients find Agent Cards to learn about available A2A Servers and their capabilities. For more information, see [Agent Discovery](./agent-discovery.md). - **Extensions:** A2A allows agents to declare custom protocol extensions as part of their AgentCard. For more information, see [Extensions](./extensions.md). # Life of a Task In the Agent2Agent (A2A) Protocol, interactions can range from simple, stateless exchanges to complex, long-running processes. When an agent receives a message from a client, it can respond in one of two fundamental ways: - **Respond with a Stateless `Message`**: This type of response is typically used for immediate, self-contained interactions that conclude without requiring further state management. - **Initiate a Stateful `Task`**: If the response is a `Task`, the agent will process it through a defined lifecycle, communicating progress and requiring input as needed, until it reaches an interrupted state (e.g., `input-required`, `auth-required`) or a terminal state (e.g., `completed`, `canceled`, `rejected`, `failed`). ## Group Related Interactions A `contextId` is a crucial identifier that logically groups multiple `Task` objects and independent `Message` objects, providing continuity across a series of interactions. - When a client sends a message for the first time, the agent responds with a new `contextId`. If a task is initiated, it will also have a `taskId`. - Clients can send subsequent messages and include the same `contextId` to indicate that they are continuing their previous interaction within the same context. - Clients optionally attach the `taskId` to a subsequent message to indicate that it continues that specific task. The `contextId` enables collaboration towards a common goal or a shared contextual session across multiple, potentially concurrent tasks. Internally, an A2A agent (especially one using an LLM) uses the `contextId` to manage its internal conversational state or its LLM context. ## Agent Response: Message or Task The choice between responding with a `Message` or a `Task` depends on the nature of the interaction and the agent's capabilities: - **Messages for Trivial Interactions**: `Message` objects are suitable for transactional interactions that don't require long-running processing or complex state management. An agent might use messages to negotiate the acceptance or scope of a task before committing to a `Task` object. - **Tasks for Stateful Interactions**: Once an agent maps the intent of an incoming message to a supported capability that requires substantial, trackable work over an extended period, the agent responds with a `Task` object. Conceptually, agents operate at different levels of complexity: - **Message-only Agents**: Always respond with `Message` objects. They typically don't manage complex state or long-running executions, and use `contextId` to tie messages together. These agents might directly wrap LLM invocations and simple tools. - **Task-generating Agents**: Always respond with `Task` objects, even for responses, which are then modeled as completed tasks. Once a task is created, the agent will only return `Task` objects in response to messages sent, and once a task is complete, no more messages can be sent. This approach avoids deciding between `Task` versus `Message`, but creates completed task objects for even simple interactions. - **Hybrid Agents**: Generate both `Message` and `Task` objects. These agents use messages to negotiate agent capability and the scope of work for a task, then send a `Task` object to track execution and manage states like `input-required` or error handling. Once a task is created, the agent will only return `Task` objects in response to messages sent, and once a task is complete, no more messages can be sent. A hybrid agent uses messages to negotiate the scope of a task, and then generate a task to track its execution. For more information about hybrid agents, see [A2A protocol: Demystifying Tasks vs Messages](https://discuss.google.dev/t/a2a-protocol-demystifying-tasks-vs-messages/255879). ## Task Refinements Clients often need to send new requests based on task results or refine the outputs of previous tasks. This is modeled by starting another interaction using the same `contextId` as the original task. Clients further hint the agent by providing references to the original task using `referenceTaskIds` in the `Message` object. The agent then responds with either a new `Task` or a `Message`. ## Task Immutability Once a task reaches a terminal state (completed, canceled, rejected, or failed), it cannot restart. Any subsequent interaction related to that task, such as a refinement, must initiate a new task within the same `contextId`. This principle offers several benefits: - **Task Immutability.** Clients reliably reference tasks and their associated state, artifacts, and messages, providing a clean mapping of inputs to outputs. This is valuable for orchestration and traceability. - **Clear Unit of Work.** Every new request, refinement, or follow-up becomes a distinct task. This simplifies bookkeeping, allows for granular tracking of an agent's work, and enables tracing each artifact to a specific unit of work. - **Easier Implementation.** This removes ambiguity for agent developers regarding whether to create a new task or restart an existing one. ## Parallel Follow-ups A2A supports parallel work by enabling agents to create distinct, parallel tasks for each follow-up message sent within the same `contextId`. This allows clients to track individual tasks and create new dependent tasks as soon as a prerequisite task is complete. For example: - Task 1: Book a flight to Helsinki. - Task 2: Based on Task 1, book a hotel. - Task 3: Based on Task 1, book a snowmobile activity. - Task 4: Based on Task 2, add a spa reservation to the hotel booking. ## Referencing Previous Artifacts The serving agent infers the relevant artifact from a referenced task or from the `contextId`. As the domain expert, the serving agent is best suited to resolve ambiguity or identify missing information. If there is ambiguity, the agent asks the client for clarification by returning an `input-required` state. The client then specifies the artifact in its response, optionally populating artifact references (`artifactId`, `taskId`) in `Part` metadata. ## Tracking Artifact Mutation Follow-up or refinement tasks often lead to the creation of new artifacts based on older ones. Tracking these mutations is important to ensure that only the most recent version of an artifact is used in subsequent interactions. This could be conceptualized as a version history, where each new artifact is linked to its predecessor. However, the client is in the best position to manage this artifact linkage. The client determines what constitutes an acceptable result and has the ability to accept or reject new versions. Therefore, the serving agent shouldn't be responsible for tracking artifact mutations, and this linkage is not part of the A2A protocol specification. Clients should maintain this version history on their end and present the latest acceptable version to the user. To facilitate client-side tracking, serving agents should use a consistent `artifact-name` when generating a refined version of an existing artifact. When initiating follow-up or refinement tasks, the client should explicitly reference the specific artifact they intend to refine, ideally the "latest" version from their perspective. If the artifact reference is not provided, the serving agent can: - Attempt to infer the intended artifact based on the current `contextId`. - If there is ambiguity or insufficient context, the agent should respond with an `input-required` task state to request clarification from the client. ## Example Follow-up Scenario The following example illustrates a typical task flow with a follow-up: 1. Client sends a message to the agent: ```json { "jsonrpc": "2.0", "id": "req-001", "method": "SendMessage", "params": { "message": { "role": "user", "parts": [ { "text": "Generate an image of a sailboat on the ocean." } ], "messageId": "msg-user-001" } } } ``` 2. Agent responds with a boat image (completed task): ```json { "jsonrpc": "2.0", "id": "req-001", "result": { "task": { "id": "task-boat-gen-123", "contextId": "ctx-conversation-abc", "status": { "state": "TASK_STATE_COMPLETED" }, "artifacts": [ { "artifactId": "artifact-boat-v1-xyz", "name": "sailboat_image.png", "description": "A generated image of a sailboat on the ocean.", "parts": [ { "filename": "sailboat_image.png", "mediaType": "image/png", "raw": "base64_encoded_png_data_of_a_sailboat" } ] } ] } } } ``` 3. Client asks to color the boat red. This refinement request refers to the previous `taskId` and uses the same `contextId`. ```json { "jsonrpc": "2.0", "id": "req-002", "method": "SendMessage", "params": { "message": { "role": "user", "messageId": "msg-user-002", "contextId": "ctx-conversation-abc", "referenceTaskIds": [ "task-boat-gen-123" ], "parts": [ { "text": "Please modify the sailboat to be red." } ] } } } ``` 4. Agent responds with a new image artifact (new task, same context, same artifact name): The agent creates a new task within the same `contextId`. The new boat image artifact retains the same name but has a new `artifactId`. ```json { "jsonrpc": "2.0", "id": "req-002", "result": { "task": { "id": "task-boat-color-456", "contextId": "ctx-conversation-abc", "status": { "state": "TASK_STATE_COMPLETED" }, "artifacts": [ { "artifactId": "artifact-boat-v2-red-pqr", "name": "sailboat_image.png", "description": "A generated image of a red sailboat on the ocean.", "parts": [ { "filename": "sailboat_image.png", "mediaType": "image/png", "raw": "base64_encoded_png_data_of_a_RED_sailboat" } ] } ] } } } ``` # Multi-Tenancy and Multi-Agent Routing A single A2A endpoint can serve multiple agents or tenants. The A2A protocol does not prescribe a specific routing implementation — operators are free to choose the approach that best fits their infrastructure. This document describes the routing mechanisms the protocol supports and the rules clients must follow when a routing identifier is advertised in an Agent Card. ## Overview A common deployment pattern is to place several agents behind a single host or reverse-proxy. From the outside the agents are reachable at the same domain, but each individual agent needs to be distinguished so that requests are delivered to the right backend. Three complementary approaches are available: ### 1. URL-Based Routing (Sub-Path) Each agent is assigned a distinct URL prefix. The Agent Card for each agent advertises its own `url` in `supportedInterfaces`, so clients automatically send requests to the correct path. Agent Card for the "billing" agent: ```json { "name": "Billing Agent", "supportedInterfaces": [ { "url": "https://agents.example.com/billing", "protocolBinding": "HTTP+JSON", "protocolVersion": "1.0" } ] } ``` Agent Card for the "support" agent: ```json { "name": "Support Agent", "supportedInterfaces": [ { "url": "https://agents.example.com/support", "protocolBinding": "HTTP+JSON", "protocolVersion": "1.0" } ] } ``` The gateway or reverse-proxy routes `/billing/*` and `/support/*` to the appropriate backend. This is the simplest approach and requires no special client awareness beyond reading the Agent Card. ### 2. Authentication Header-Based Routing When multiple agents share the same URL, a gateway can use the authentication credentials already present in the request to determine which agent to route to. Authentication requirements are declared in the Agent Card's `securitySchemes` and `security` fields, making this approach fully discoverable by clients. Examples: - A bearer token whose claims (such as audience or scope) identify the target agent. - An API key that maps to a particular agent in the gateway's configuration. The gateway inspects the credential and forwards the request to the appropriate backend without any changes to the A2A protocol messages themselves. ### 3. Body-Based Routing Using the `tenant` Field Every A2A request message contains an optional `tenant` field. This is an **opaque string** whose value is defined entirely by the server operator; the protocol does not impose any format or semantics on it. A gateway or agent implementation can inspect this field and forward the request to the appropriate backend. The `tenant` value that a client should use for a particular agent is advertised in the `AgentInterface` entry inside `supportedInterfaces`: ```json { "name": "Billing Agent", "supportedInterfaces": [ { "url": "https://agents.example.com/a2a", "protocolBinding": "HTTP+JSON", "protocolVersion": "1.0", "tenant": "billing" } ] } ``` **Client requirement**: The client **MUST** always echo the `tenant` value from the selected `AgentInterface` entry back in every request message. If the `AgentInterface` does not set `tenant`, the field **MUST** be omitted from the request. See [Section 8.3.2](../specification.md#832-client-protocol-selection) of the specification for the normative rule. A server MAY use the `tenant` field to represent any routing key that suits its deployment — agent identifiers, workspace slugs, organization IDs, or any other opaque discriminator. ## Combining Approaches The three approaches are not mutually exclusive. For example, a deployment could use URL-based routing to distinguish between major product lines and rely on the `tenant` field to distinguish individual customers within each product line. The appropriate combination depends on the operator's architecture and the capabilities of the gateway in use. ## Discovering Multiple Agents When multiple agents are deployed behind a shared domain, each agent **SHOULD** have its own Agent Card published at an appropriate location (see [Agent Discovery](./agent-discovery.md)). Clients retrieve each agent's card independently and use the `supportedInterfaces` information it contains — including any `tenant` value — to communicate with the correct agent. # Streaming and Asynchronous Operations for Long-Running Tasks The Agent2Agent (A2A) protocol is explicitly designed to handle tasks that might not complete immediately. Many AI-driven operations are often long-running, involve multiple steps, produce incremental results, or require human intervention. A2A provides mechanisms for managing such asynchronous interactions, ensuring that clients receive updates effectively, whether they remain continuously connected or operate in a more disconnected fashion. ## Streaming with Server-Sent Events (SSE) For tasks that produce incremental results (like generating a long document or streaming media) or provide ongoing status updates, A2A supports real-time communication using Server-Sent Events (SSE). This approach is ideal when the client is able to maintain an active HTTP connection with the A2A Server. The following key features detail how SSE streaming is implemented and managed within the A2A protocol: - **Server Capability:** The A2A Server must indicate its support for streaming by setting `capabilities.streaming: true` in its Agent Card. - **Initiating a Stream:** The client uses the `SendStreamingMessage` RPC method to send an initial message (for example, a prompt or command) and simultaneously subscribe to updates for that task. - **Server Response and Connection:** If the subscription is successful, the server responds with an HTTP 200 OK status and a `Content-Type: text/event-stream`. This HTTP connection remains open for the server to push events to the client. - **Event Structure and Types:** The server sends events over this stream. Each event's `data` field contains a JSON-RPC 2.0 Response object, typically a `SendStreamingMessageResponse`. The `result` field of the `SendStreamingMessageResponse` contains: - [`Task`](../specification.md#61-task-object): Represents the current state of the work. - [`TaskStatusUpdateEvent`](../specification.md#taskstatusupdateevent): Communicates changes in the task's lifecycle state (for example, from `working` to `input-required` or `completed`). It also provides intermediate messages from the agent. - [`TaskArtifactUpdateEvent`](../specification.md#taskartifactupdateevent): Delivers new or updated Artifacts generated by the task. This is used to stream large files or data structures in chunks, with fields like `append` and `lastChunk` to help reassemble. - **Stream Termination:** When a task reaches a terminal or interrupted state (e.g., `COMPLETED`, `FAILED`, `CANCELED`, `REJECTED`, or `INPUT_REQUIRED`), the server closes the stream and sends no further updates. - **Resubscription:** If a client's SSE connection breaks prematurely while a task is still active, the client is able to attempt to reconnect to the stream using the `SubscribeToTask` RPC method. ### When to Use Streaming Streaming with SSE is best suited for: - Real-time progress monitoring of long-running tasks. - Receiving large results (artifacts) incrementally. - Interactive, conversational exchanges where immediate feedback or partial responses are beneficial. - Applications requiring low-latency updates from the agent. ### Protocol Specification References Refer to the Protocol Specification for detailed structures: - [`SendStreamingMessage`](../specification.md#72-messagestream) - [`SubscribeToTask`](../specification.md#79-taskssubscribe) ## Push Notifications for Disconnected Scenarios For very long-running tasks (for example, lasting minutes, hours, or even days) or when clients are unable to or prefer not to maintain persistent connections (like mobile clients or serverless functions), A2A supports asynchronous updates using push notifications. This allows the A2A Server to actively notify a client-provided webhook when a significant task update occurs. The following key features detail how push notifications are implemented and managed within the A2A protocol: - **Server Capability:** The A2A Server must indicate its support for this feature by setting `capabilities.pushNotifications: true` in its Agent Card. - **Configuration:** The client provides a [`PushNotificationConfig`](../specification.md#pushnotificationconfig) to the server. This configuration is supplied: - Within the initial `SendMessage` or `SendStreamingMessage` request, or - Separately, using the `CreateTaskPushNotificationConfig` RPC method for an existing task. The `PushNotificationConfig` includes a `url` (the HTTPS webhook URL), an optional `token` (for client-side validation), and optional `authentication` details (for the A2A Server to authenticate to the webhook). - **Notification Trigger:** The A2A Server decides when to send a push notification, typically when a task reaches a significant state change (for example, terminal state, `input-required`, or `auth-required`). - **Notification Payload:** The A2A protocol defines the HTTP body payload as a [`StreamResponse`](../specification.md#323-stream-response) object, matching the format used in streaming operations. The payload contains one of: `task`, `message`, `statusUpdate`, or `artifactUpdate`. See [Push Notification Payload](../specification.md#pushnotificationpayload) for detailed structure. - **Client Action:** Upon receiving a push notification (and successfully verifying its authenticity), the client typically uses the `GetTask` RPC method with the `taskId` from the notification to retrieve the complete, updated `Task` object, including any new artifacts. ### When to Use Push Notifications Push notifications are ideal for: - Very long-running tasks that can take minutes, hours, or days to complete. - Clients that cannot or prefer not to maintain persistent connections, such as mobile applications or serverless functions. - Scenarios where clients only need to be notified of significant state changes rather than continuous updates. ### Protocol Specification References Refer to the Protocol Specification for detailed structures: - [`CreateTaskPushNotificationConfig`](../specification.md#317-create-push-notification-config) - [`GetTask`](../specification.md#76-taskspushnotificationconfigget) ### Client-Side Push Notification Service The `url` specified in `PushNotificationConfig.url` points to a client-side Push Notification Service. This service is responsible for receiving the HTTP POST notification from the A2A Server. Its responsibilities include authenticating the incoming notification, validating its relevance, and relaying the notification or its content to the appropriate client application logic or system. ### Security Considerations for Push Notifications Security is paramount for push notifications due to their asynchronous and server-initiated outbound nature. Both the A2A Server (sending the notification) and the client's webhook receiver have critical responsibilities. #### A2A Server Security (when sending notifications to client webhook) - **Webhook URL Validation:** Servers SHOULD NOT blindly trust and send POST requests to any URL provided by a client. Malicious clients could provide URLs pointing to internal services or unrelated third-party systems, leading to Server-Side Request Forgery (SSRF) attacks or acting as Distributed Denial of Service (DDoS) amplifiers. - **Mitigation strategies:** Allowlisting of trusted domains, ownership verification (for example, challenge-response mechanisms), and network controls (e.g., egress firewalls). - **Authenticating to the Client's Webhook:** The A2A Server MUST authenticate itself to the client's webhook URL according to the scheme specified in `PushNotificationConfig.authentication`. Common schemes include Bearer Tokens (OAuth 2.0), API keys, HMAC signatures, or mutual TLS (mTLS). #### Client Webhook Receiver Security (when receiving notifications from A2A server) - **Authenticating the A2A Server:** The webhook endpoint MUST rigorously verify the authenticity of incoming notification requests to ensure they originate from the legitimate A2A Server and not an imposter. - **Verification methods:** Verify signatures/tokens (for example, JWT signatures against the A2A Server's trusted public keys, HMAC signatures, or API key validation). Also, validate the `PushNotificationConfig.token` if provided. - **Preventing Replay Attacks:** - **Timestamps:** Notifications SHOULD include a timestamp. The webhook SHOULD reject notifications that are too old. - **Nonces/unique IDs:** For critical notifications, consider using unique, single-use identifiers (for example, JWT's `jti` claim or event IDs) to prevent processing duplicate notifications. - **Secure Key Management and Rotation:** Implement secure key management practices, including regular key rotation, especially for cryptographic keys. Protocols like JWKS (JSON Web Key Set) facilitate key rotation for asymmetric keys. #### Example Asymmetric Key Flow (JWT + JWKS) 1. Client creates a `PushNotificationConfig` specifying `authentication.scheme: "Bearer"` and possibly an expected `issuer` or `audience` for the JWT. 2. A2A Server, when sending a notification: - Generates a JWT, signing it with its private key. The JWT includes claims like `iss` (issuer), `aud` (audience), `iat` (issued at), `exp` (expires), `jti` (JWT ID), and `taskId`. - The JWT header indicates the signing algorithm and key ID (`kid`). - The A2A Server makes its public keys available through a JWKS endpoint. 3. Client Webhook, upon receiving the notification: - Extracts the JWT from the Authorization header. - Inspects the `kid` (key ID) in the JWT header. - Fetches the corresponding public key from the A2A Server's JWKS endpoint (caching keys is recommended). - Verifies the JWT signature using the public key. - Validates claims (`iss`, `aud`, `iat`, `exp`, `jti`). - Checks the `PushNotificationConfig.token` if provided. This comprehensive, layered approach to security for push notifications helps ensure that messages are authentic, integral, and timely, protecting both the sending A2A Server and the receiving client webhook infrastructure. # What is A2A? The A2A protocol is an open standard that enables seamless communication and collaboration between AI agents. It provides a common language for agents built using diverse frameworks and by different vendors, fostering interoperability and breaking down silos. Agents are autonomous problem-solvers that act independently within their environment. A2A allows agents from different developers, built on different frameworks, and owned by different organizations to unite and work together. ## Why Use the A2A Protocol A2A addresses key challenges in AI agent collaboration. It provides a standardized approach for agents to interact. This section explains the problems A2A solves and the benefits it offers. ### Problems that A2A Solves Consider a user request for an AI assistant to plan an international trip. This task involves orchestrating multiple specialized agents, such as: - A flight booking agent - A hotel reservation agent - An agent for local tour recommendations - A currency conversion agent Without A2A, integrating these diverse agents presents several challenges: - **Agent Exposure**: Developers often wrap agents as tools to expose them to other agents, similar to how tools are exposed through the Model Context Protocol (MCP). However, this approach is inefficient because agents are designed to negotiate directly. Wrapping agents as tools limits their capabilities. A2A allows agents to be exposed as they are, without requiring this wrapping. - **Custom Integrations**: Each interaction requires custom, point-to-point solutions, creating significant engineering overhead. - **Slow Innovation**: Bespoke development for each new integration slows innovation. - **Scalability Issues**: Systems become difficult to scale and maintain as the number of agents and interactions grows. - **Interoperability**: This approach limits interoperability, preventing the organic formation of complex AI ecosystems. - **Security Gaps**: Ad hoc communication often lacks consistent security measures. The A2A protocol addresses these challenges by establishing interoperability for AI agents to interact reliably and securely. ### A2A Example Scenario This section provides an example scenario to illustrate the benefits of using an A2A (Agent2Agent) protocol for complex interactions between AI agents. #### A User's Complex Request A user interacts with an AI assistant, giving it a complex prompt like "Plan an international trip." ```mermaid graph LR User --> Prompt --> AI_Assistant[AI Assistant] ``` #### The Need for Collaboration The AI assistant receives the prompt and realizes it needs to call upon multiple specialized agents to fulfill the request. These agents include a Flight Booking Agent, a Hotel Reservation Agent, a Currency Conversion Agent, and a Local Tours Agent. ```mermaid graph LR subgraph "Specialized Agents" FBA[✈️ Flight Booking Agent] HRA[🏨 Hotel Reservation Agent] CCA[💱 Currency Conversion Agent] LTA[🚌 Local Tours Agent] end AI_Assistant[🤖 AI Assistant] --> FBA AI_Assistant --> HRA AI_Assistant --> CCA AI_Assistant --> LTA ``` #### The Interoperability Challenge The core problem: The agents are unable to work together because each has its own bespoke development and deployment. The consequence of a lack of a standardized protocol is that these agents cannot collaborate with each other let alone discover what they can do. The individual agents (Flight, Hotel, Currency, and Tours) are isolated. #### The "With A2A" Solution The A2A Protocol provides standard methods and data structures for agents to communicate with one another, regardless of their underlying implementation, so the same agents can be used as an interconnected system, communicating seamlessly through the standardized protocol. The AI assistant, now acting as an orchestrator, receives the cohesive information from all the A2A-enabled agents. It then presents a single, complete travel plan as a seamless response to the user's initial prompt. ![A2A Actors showing a User, A2A Client (Client Agent), and A2A Server (Remote Agent)](../assets/a2a-actors.png){ width="70%" style="margin:20px auto;display:block;" } ### Core Benefits of A2A Implementing the A2A protocol offers significant advantages across the AI ecosystem: - **Secure collaboration**: Without a standard, it's difficult to ensure secure communication between agents. A2A uses HTTPS for secure communication and maintains opaque operations, so agents can't see the inner workings of other agents during collaboration. - **Interoperability**: A2A breaks down silos between different AI agent ecosystems, enabling agents from various vendors and frameworks to work together seamlessly. - **Agent autonomy**: A2A allows agents to retain their individual capabilities and act as autonomous entities while collaborating with other agents. - **Reduced integration complexity**: The protocol standardizes agent communication, enabling teams to focus on the unique value their agents provide. - **Support for LRO**: The protocol supports long-running operations (LRO) and streaming with Server-Sent Events (SSE) and asynchronous execution. ### Key Design Principles of A2A A2A development follows principles that prioritize broad adoption, enterprise-grade capabilities, and future-proofing. - **Simplicity**: A2A leverages existing standards like HTTP, JSON-RPC, and Server-Sent Events (SSE). This avoids reinventing core technologies and accelerates developer adoption. - **Enterprise Readiness**: A2A addresses critical enterprise needs. It aligns with standard web practices for robust authentication, authorization, security, privacy, tracing, and monitoring. - **Asynchronous**: A2A natively supports long-running tasks. It handles scenarios where agents or users might not remain continuously connected. It uses mechanisms like streaming and push notifications. - **Modality Independent**: The protocol allows agents to communicate using a wide variety of content types. This enables rich and flexible interactions beyond plain text. - **Opaque Execution**: Agents collaborate effectively without exposing their internal logic, memory, or proprietary tools. Interactions rely on declared capabilities and exchanged context. This preserves intellectual property and enhances security. ### Understanding the Agent Stack: A2A, MCP, Agent Frameworks and Models A2A is situated within a broader agent stack, which includes: - **A2A:** Standardizes communication among agents deployed in different organizations and developed using diverse frameworks. - **MCP:** Connects models to data and external resources. - **Frameworks (like ADK):** Provide toolkits for constructing agents. - **Models:** Fundamental to an agent's reasoning, these can be any Large Language Model (LLM). ![ADK versus MCP](../assets/agentic-stack.png){ width="70%" style="margin:20px auto;display:block;" } #### A2A and MCP In the broader ecosystem of AI communication, you might be familiar with protocols designed to facilitate interactions between agents, models, and tools. Notably, the Model Context Protocol (MCP) is an emerging standard focused on connecting Large Language Models (LLMs) with data and external resources. The Agent2Agent (A2A) protocol is designed to standardize communication between AI agents, particularly those deployed in external systems. A2A is positioned to complement MCP, addressing a distinct yet related aspect of agent interaction. - **MCP's Focus:** Reducing the complexity involved in connecting agents with tools and data. Tools are typically stateless and perform specific, predefined functions (e.g., a calculator, a database query). - **A2A's Focus:** Enabling agents to collaborate within their native modalities, allowing them to communicate as agents (or as users) rather than being constrained to tool-like interactions. This enables complex, multi-turn interactions where agents reason, plan, and delegate tasks to other agents. For example, this facilitates multi-turn interactions, such as those involving negotiation or clarification when placing an order. ![ADK + MCP](../assets/a2a-mcp-readme.png){ width="70%" style="margin:20px auto;display:block;" } The practice of encapsulating an agent as a simple tool is fundamentally limiting, as it fails to capture the agent's full capabilities. This critical distinction is explored in the post, [Why Agents Are Not Tools](https://discuss.google.dev/t/agents-are-not-tools/192812). For a more in-depth comparison, refer to the [A2A and MCP Comparison](a2a-and-mcp.md) document. #### A2A and ADK The [Agent Development Kit (ADK)](https://google.github.io/adk-docs) is an open-source agent development toolkit developed by Google. A2A is a communication protocol for agents that enables inter-agent communication, regardless of the framework used for their construction (e.g., ADK, LangGraph, or Crew AI). ADK is a flexible and modular framework for developing and deploying AI agents. While optimized for Gemini AI and the Google ecosystem, ADK is model-agnostic, deployment-agnostic, and built for compatibility with other frameworks. ### A2A Request Lifecycle The A2A request lifecycle is a sequence that details the four main steps a request follows: agent discovery, authentication, `sendMessage` API, and `sendMessageStream` API. The following diagram provides a deeper look into the operational flow, illustrating the interactions between the client, A2A server, and auth server. ```mermaid sequenceDiagram participant Client participant A2A Server participant Auth Server rect rgb(240, 240, 240) Note over Client, A2A Server: 1. Agent Discovery Client->>A2A Server: GET agent card eg: (/.well-known/agent-card) A2A Server-->>Client: Returns Agent Card end rect rgb(240, 240, 240) Note over Client, Auth Server: 2. Authentication Client->>Client: Parse Agent Card for securitySchemes alt securityScheme is "openIdConnect" Client->>Auth Server: Request token based on "authorizationUrl" and "tokenUrl". Auth Server-->>Client: Returns JWT end end rect rgb(240, 240, 240) Note over Client, A2A Server: 3. sendMessage API Client->>Client: Parse Agent Card for "url" param to send API requests to. Client->>A2A Server: POST /sendMessage (with JWT) A2A Server->>A2A Server: Process message and create task A2A Server-->>Client: Returns Task Response end rect rgb(240, 240, 240) Note over Client, A2A Server: 4. sendMessageStream API Client->>A2A Server: POST /sendMessageStream (with JWT) A2A Server-->>Client: Stream: Task (Submitted) A2A Server-->>Client: Stream: TaskStatusUpdateEvent (Working) A2A Server-->>Client: Stream: TaskArtifactUpdateEvent (artifact A) A2A Server-->>Client: Stream: TaskArtifactUpdateEvent (artifact B) A2A Server-->>Client: Stream: TaskStatusUpdateEvent (Completed) end ``` ## What's Next Learn about the [Key Concepts](./key-concepts.md) that form the foundation of the A2A protocol. # Tutorials ## Python Tutorial | Description | Difficulty :-------- | :------------ | :----------- [A2A and Python Quickstart](./python/1-introduction.md) | Learn to build a simple Python-based "echo" A2A server and client. | Easy [ADK facts](https://github.com/a2aproject/a2a-samples/tree/main/samples/python/agents/adk_facts) | Build and test a simple Personal Assistant agent using the Agent Development Kit (ADK) that can provide interesting facts. | Easy [ADK agent on Cloud Run](https://github.com/a2aproject/a2a-samples/tree/main/samples/python/agents/adk_cloud_run) | Deploy, manage, and observe an ADK-based agent as a scalable, serverless service on Google Cloud Run. | Easy [Multi-agent collaboration using A2A](https://github.com/a2aproject/a2a-samples/tree/main/demo) | Learn how to set up an orchestrator (host agent) that routes and manages requests among several specialized A2A-compatible agents. | Easy [Airbnb and weather multi-agent](https://github.com/a2aproject/a2a-samples/tree/main/samples/python/agents/airbnb_planner_multiagent) | Build a complex multi-agent system where agents collaborate using A2A to plan a trip, finding both Airbnb accommodations and weather information. | Medium [A2A Client-Server example using remote ADK agent](https://goo.gle/adk-a2a) | Learn how a local A2A client agent discovers and consumes the capabilities of a separate, remote ADK-based agent (for example, a prime number checker). | Easy [Colab Notebook](https://github.com/a2aproject/a2a-samples/blob/main/notebooks/multi_agents_eval_with_cloud_run_deployment.ipynb) | Use Colab Notebook to deploy A2A agents to Cloud Run from your browser, and then evaluate their performance with Vertex AI. | Easy ## Java Tutorial | Description | Difficulty :-------- | :------------ | :----------- [Weather Agent](https://github.com/a2aproject/a2a-samples/tree/main/samples/java/agents/weather_mcp) | Build a weather information agent using an MCP server.

**To make use of this agent in a multi-language, multi-agent system, check out the [weather_and_airbnb_planner sample](https://github.com/a2aproject/a2a-samples/tree/main/samples/python/hosts/weather_and_airbnb_planner).** | Easy [Content Writer Agent](https://github.com/a2aproject/a2a-samples/tree/main/samples/java/agents/content_writer) | Build a content writer agent that generates engaging pieces of content from outlines.

**To make use of this agent in a content creation multi-language, multi-agent system, check out the [content_creation sample](https://github.com/a2aproject/a2a-samples/tree/main/samples/python/hosts/content_creation).** | Easy [Content Editor Agent](https://github.com/a2aproject/a2a-samples/tree/main/samples/java/agents/content_editor) | Build a content editor agent that proof-reads and polishes content.

**To make use of this agent in a content creation multi-language, multi-agent system, check out the [content_creation sample](https://github.com/a2aproject/a2a-samples/tree/main/samples/python/hosts/content_creation).** | Easy [Dice Agent (Multi-Transport)](https://github.com/a2aproject/a2a-samples/tree/main/samples/java/agents/dice_agent_multi_transport) | Build a multi-transport agent that rolls dice and checks for prime numbers. | Medium [Magic 8 Ball Agent (Security)](https://github.com/a2aproject/a2a-samples/tree/main/samples/java/agents/magic_8_ball_security) | Build a Magic 8 Ball agent to learn how to secure A2A servers with Keycloak using bearer token authentication and configure an A2A client to obtain and pass the required token. | Medium ## JavaScript Tutorial | Description :-------- | :------------ [Movie research agent using JavaScript](https://github.com/a2aproject/a2a-samples/tree/main/samples/js) | Build an A2A agent with Node.js that uses the TMDB (The Movie Database) API to handle movie searches and queries. ## C#/.NET Tutorial | Description :-------- | :------------ [All .NET samples](https://github.com/a2aproject/a2a-dotnet/tree/main/samples) | Repository of foundational samples showing how to build A2A clients and servers, including an Echo Agent, using the C#/.NET SDK.
# Python Quickstart Tutorial: Building an A2A Agent Welcome to the Agent2Agent (A2A) Python Quickstart Tutorial! In this tutorial, you will explore a simple "echo" A2A server using the Python SDK. This will introduce you to the fundamental concepts and components of an A2A server. You will then look at a more advanced example that integrates a Large Language Model (LLM). This hands-on guide will help you understand: - The basic concepts behind the A2A protocol. - How to set up a Python environment for A2A development using the SDK. - How Agent Skills and Agent Cards describe an agent. - How an A2A server handles tasks. - How to interact with an A2A server using a client. - How streaming capabilities and multi-turn interactions work. - How an LLM can be integrated into an A2A agent. By the end of this tutorial, you will have a functional understanding of A2A agents and a solid foundation for building or integrating A2A-compliant applications. ## Tutorial Sections The tutorial is broken down into the following steps: 1. **[Introduction (This Page)](./1-introduction.md)** 2. **[Setup](./2-setup.md)**: Prepare your Python environment and the A2A SDK. 3. **[Agent Skills & Agent Card](./3-agent-skills-and-card.md)**: Define what your agent can do and how it describes itself. 4. **[The Agent Executor](./4-agent-executor.md)**: Understand how the agent logic is implemented. 5. **[Starting the Server](./5-start-server.md)**: Run the Helloworld A2A server. 6. **[Interacting with the Server](./6-interact-with-server.md)**: Send requests to your agent. 7. **[Streaming & Multi-Turn Interactions](./7-streaming-and-multiturn.md)**: Explore advanced capabilities with the LangGraph example. 8. **[Next Steps](./8-next-steps.md)**: Explore further possibilities with A2A. Let's get started! # 2. Set Up Your Environment ## Prerequisites - Python 3.10 or higher. - Access to a terminal or command prompt. - Git, for cloning the repository. - A code editor (e.g., Visual Studio Code) is recommended. ## Clone the Repository If you haven't already, clone the A2A Samples repository: ```bash git clone https://github.com/a2aproject/a2a-samples.git -b main --depth 1 cd a2a-samples ``` ## Python Environment & SDK Installation We recommend using a virtual environment for Python projects. The A2A Python SDK uses `uv` for dependency management, but you can use `pip` with `venv` as well. 1. **Create and activate a virtual environment:** Using `venv` (standard library): === "Mac/Linux" ```sh python -m venv .venv source .venv/bin/activate ``` === "Windows" ```powershell python -m venv .venv .venv\Scripts\activate ``` 2. **Install the A2A SDK and its required Python dependencies:** ```bash pip install -r samples/python/requirements.txt ``` ## Verify Installation After installation, you should be able to import the `a2a` package in a Python interpreter: ```bash python -c "import a2a; print('A2A SDK imported successfully')" ``` If this command runs without error and prints the success message, your environment is set up correctly. # 3. Agent Skills & Agent Card Before an A2A agent can do anything, it needs to define what it _can_ do (its skills) and how other agents or clients can find out about these capabilities (its Agent Card). We'll use the `helloworld` example located in [`a2a-samples/samples/python/agents/helloworld/`](https://github.com/a2aproject/a2a-samples/tree/main/samples/python/agents/helloworld). ## Agent Skills An **Agent Skill** describes a specific capability or function the agent can perform. It's a building block that tells clients what kinds of tasks the agent is good for. Attributes of an `AgentSkill` (defined in `a2a.types`): - `id`: A unique identifier for the skill. - `name`: A human-readable name. - `description`: A more detailed explanation of what the skill does. - `tags`: Keywords for categorization and discovery. - `examples`: Sample prompts or use cases. - `input_modes` / `output_modes`: Supported Media Types for input and output (e.g., "text/plain", "application/json"). - `security_requirements`: Security schemes necessary for this skill. In `__main__.py`, you can see how a skill for the Helloworld agent is defined: ```python { .no-copy } --8<-- "https://raw.githubusercontent.com/a2aproject/a2a-samples/refs/heads/main/samples/python/agents/helloworld/__main__.py:AgentSkill" ``` This skill is very simple: it's named "Returns hello world" and primarily deals with text. ## Agent Card The **Agent Card** is a JSON document that an A2A Server makes available, typically at a `.well-known/agent-card.json` endpoint. It's like a digital business card for the agent. Key attributes of an `AgentCard` (defined in `a2a.types`): - `name`, `description`, `version`: Basic identity information. - `supported_interfaces`: Ordered list of endpoints and protocols where the A2A service can be reached. - `capabilities`: Supported A2A features like `streaming` or `extended_agent_card`. - `default_input_modes` / `default_output_modes`: Default Media Types for the agent. - `skills`: A list of `AgentSkill` objects that the agent offers. The `helloworld` example defines its Agent Card like this: ```python { .no-copy } --8<-- "https://raw.githubusercontent.com/a2aproject/a2a-samples/refs/heads/main/samples/python/agents/helloworld/__main__.py:AgentCard" ``` This card tells us the agent is named "Hello World Agent", can be run at `http://127.0.0.1:9999/`, supports text interactions, and has the `hello_world` skill. # 4. The Agent Executor The core logic of how an A2A agent processes requests and generates responses/events is handled by an **Agent Executor**. The A2A Python SDK provides an abstract base class `a2a.server.agent_execution.AgentExecutor` that you implement. ## `AgentExecutor` Interface The `AgentExecutor` class defines two primary methods: - `async def execute(self, context: RequestContext, event_queue: EventQueue)`: Handles incoming requests that expect a response or a stream of events. It processes the user's input (available via `context`) and uses the `event_queue` to send back `Message`, `Task`, `TaskStatusUpdateEvent`, or `TaskArtifactUpdateEvent` objects. - `async def cancel(self, context: RequestContext, event_queue: EventQueue)`: Handles requests to cancel an ongoing task. The `RequestContext` provides information about the incoming request, such as the user's message and any existing task details. The `EventQueue` is used by the executor to send events back to the client. ## Helloworld Agent Executor Let's look at `agent_executor.py`. It defines `HelloWorldAgentExecutor`. 1. **The Agent (`HelloWorldAgent`)**: This is a simple helper class that encapsulates the actual "business logic". ```python { .no-copy } --8<-- "https://raw.githubusercontent.com/a2aproject/a2a-samples/refs/heads/main/samples/python/agents/helloworld/agent_executor.py:HelloWorldAgent" ``` It has a simple `invoke` method that returns the string "Hello, World!". 2. **The Executor (`HelloWorldAgentExecutor`)**: This class implements the `AgentExecutor` interface. - **`__init__`**: ```python { .no-copy } --8<-- "https://raw.githubusercontent.com/a2aproject/a2a-samples/refs/heads/main/samples/python/agents/helloworld/agent_executor.py:HelloWorldAgentExecutor_init" ``` It instantiates the `HelloWorldAgent`. - **`execute`**: ```python { .no-copy } --8<-- "https://raw.githubusercontent.com/a2aproject/a2a-samples/refs/heads/main/samples/python/agents/helloworld/agent_executor.py:HelloWorldAgentExecutor_execute" ``` When a `Send Message` or `Send Streaming Message` request comes in (both are handled by `execute` in this simplified executor), the following steps occur: **Step 1.** The `A2A instance` (server) retrieves the current task from the context. If there is no task in context, then it creates a new task and adds it to the `EventQueue`. **Step 2.** It enqueues a `TaskStatusUpdateEvent` with a state of `TASK_STATE_WORKING` to indicate the agent has begun processing. **Step 3.** It calls `self.agent.invoke()` to execute the actual business logic (which simply returns "Hello, World!"). **Step 4.** It enqueues a `TaskArtifactUpdateEvent` containing the result text from the agent. **Step 5.** Finally, it enqueues a `TaskStatusUpdateEvent` with a state of `TASK_STATE_COMPLETED` to conclude the task. The `AgentExecutor` acts as the bridge between the A2A protocol (managed by the request handler and server application) and your agent's specific logic. It receives context about the request and uses an event queue to communicate results or updates back. # 5. Starting the Server Now that we have an Agent Card and an Agent Executor, we can set up and start the A2A server. To set up an A2A server, the Python SDK provides a route factory and helper functions (`create_agent_card_routes`, `create_jsonrpc_routes`, `create_rest_routes`). Use the route factory to create routes for the A2A server's services. These routes can be attached natively to popular frameworks like [Starlette](https://www.starlette.io/) and [FastAPI](https://fastapi.tiangolo.com/), which give you better control over authentication, logging, and other features. In this tutorial, we will use Starlette with [Uvicorn](https://www.uvicorn.org/). ## Server Setup in Helloworld Let's look at `__main__.py` again to see how the server is initialized and started. ```python { .no-copy } --8<-- "https://raw.githubusercontent.com/a2aproject/a2a-samples/refs/heads/main/samples/python/agents/helloworld/__main__.py" ``` Let's break this down: 1. **`DefaultRequestHandler`**: - The SDK provides `DefaultRequestHandler`. This handler takes your `AgentExecutor` implementation (`HelloWorldAgentExecutor`), a `TaskStore` (`InMemoryTaskStore`), and the public and extended `AgentCard` objects. - It routes incoming A2A RPC calls to the appropriate methods on your executor (like `execute` or `cancel`). - The `TaskStore` is used by the `DefaultRequestHandler` to manage the lifecycle of tasks, especially for stateful interactions, streaming, and resubscription. Even if your agent executor is simple, the handler needs a task store. - `agent_card` is passed to the handler so it can verify the agent's declared capabilities when processing incoming requests. For example, it checks whether streaming or push notifications are supported before handling those request types. - `extended_agent_card` is passed so the handler can serve it via the `GetExtendedAgentCard` RPC method to authenticated clients. 2. **`create_agent_card_routes` and `create_jsonrpc_routes`**: - `create_agent_card_routes(public_agent_card)` returns Starlette routes that expose the Agent Card at the `/.well-known/agent-card.json` endpoint for public discovery. - `create_jsonrpc_routes(request_handler, '/')` returns Starlette routes that handle all incoming A2A JSON-RPC method calls by delegating to the `request_handler`. - These route lists are combined and passed to a standard `Starlette` application. 3. **`uvicorn.run(app, ...)`**: - The constructed `Starlette` app is run using `uvicorn.run()`, making your agent accessible over HTTP. - `host='127.0.0.1'` makes the server accessible only from your local machine. - `port=9999` specifies the port to listen on. This matches the endpoints defined in the `AgentCard`'s `supported_interfaces`. ## Running the Helloworld Server Navigate to the `a2a-samples` directory in your terminal (if you're not already there) and ensure your virtual environment is activated. To run the Helloworld server: ```bash # from the a2a-samples directory python samples/python/agents/helloworld/__main__.py ``` You should see output similar to this, indicating the server is running: ```console { .no-copy } INFO: Started server process [xxxxx] INFO: Waiting for application startup. INFO: Application startup complete. INFO: Uvicorn running on http://127.0.0.1:9999 (Press CTRL+C to quit) ``` Your A2A Helloworld agent is now live and listening for requests! In the next step, we'll interact with it. # 6. Interacting with the Server With the Helloworld A2A server running, let's send some requests to it. ## The Helloworld Test Client The `test_client.py` script demonstrates how to: 1. Fetch the Agent Card from the server. 2. Create a client using `create_client`. 3. Send both `Send Message` and `Send Streaming Message` requests. Open a **new terminal window**, activate your virtual environment, and navigate to the `a2a-samples` directory. Activate the virtual environment (be sure to do this in the same directory where you created it): === "Mac/Linux" ```sh source .venv/bin/activate ``` === "Windows" ```powershell .venv\Scripts\activate ``` Run the test client: ```bash # from the a2a-samples directory python samples/python/agents/helloworld/test_client.py ``` ## Understanding the Client Code Let's look at key parts of `test_client.py`: 1. **Fetching the Agent Card**: ```python { .no-copy } --8<-- "https://raw.githubusercontent.com/a2aproject/a2a-samples/refs/heads/main/samples/python/agents/helloworld/test_client.py:A2ACardResolver" ``` The `A2ACardResolver` class is a convenience. When `get_agent_card()` is called, it fetches the `AgentCard` from the server's `/.well-known/agent-card.json` endpoint (based on the provided base URL), which is then used to initialize the client. 2. **Initializing the Client & Sending a Non-Streaming Message**: ```python { .no-copy } --8<-- "https://raw.githubusercontent.com/a2aproject/a2a-samples/refs/heads/main/samples/python/agents/helloworld/test_client.py:message_send" ``` - The `create_client` function creates a `Client` based on the information provided by the `AgentCard` and a `ClientConfig`. - We construct a `Message` using the `new_text_message` helper (passing `role=Role.ROLE_USER`), then wrap it in a `SendMessageRequest`. - The client's `send_message` method returns an async iterator that yields a single final `Task` or `Message` response from the agent. In this example, it is a `Task`. 3. **Initializing the Client & Sending a Streaming Message**: ```python { .no-copy } --8<-- "https://raw.githubusercontent.com/a2aproject/a2a-samples/refs/heads/main/samples/python/agents/helloworld/test_client.py:message_stream" ``` - A separate streaming client is created via `create_client` with `streaming=True` in its `ClientConfig`. - We again call `send_message`, which now streams events: each iteration of the loop prints a discrete chunk as it arrives over the network. - Call `await streaming_client.close()` after the loop to release the underlying HTTP connection. ## Expected Output When you run `test_client.py`, you'll see output for: - The public agent card, displayed in a formatted summary. - The non-streaming response: a single `task` in protobuf text format containing the completed status, the generated artifact with "Hello, World!", and the agent's intermediate status message in history. - The streaming response: four chunks — the initial `task`, a `status_update` for WORKING, an `artifact_update` with the result, and a final `status_update` for COMPLETED. - The extended agent card, displayed in a formatted summary (with an additional `super_hello_world` skill). The `id` fields in the output will vary with each run. ```console { .no-copy } AgentCard --- General --- Name : Hello World Agent Description : Just a hello world agent Version : 0.0.1 --- Interfaces --- [0] http://127.0.0.1:9999 (JSONRPC) --- Capabilities --- Streaming : True Push notifications : False Extended agent card : True --- I/O Modes --- Input : text/plain Output : text/plain --- Skills --- ---------------------------------------------------- ID : hello_world Name : Returns hello world Description : just returns hello world Tags : hello world Example : hi Example : hello world --- Non-Streaming Call --- Non-streaming Client initialized. Response: // Non-streaming response task { id: "xxxxxxxx" context_id: "yyyyyyyy" status { state: TASK_STATE_COMPLETED } artifacts { artifact_id: "zzzzzzzz" name: "result" parts { text: "Hello, World!" } } history { message_id: "vvvvvvvv" context_id: "yyyyyyyy" task_id: "xxxxxxxx" role: ROLE_USER parts { text: "Say hello." } } history { message_id: "wwwwwwww" role: ROLE_AGENT parts { text: "Processing request..." } } } // Streaming response task { id: "xxxxxxxx-s" context_id: "yyyyyyyy-s" status { state: TASK_STATE_SUBMITTED } history { message_id: "vvvvvvvv" context_id: "yyyyyyyy-s" task_id: "xxxxxxxx-s" role: ROLE_USER parts { text: "Say hello." } } } Response chunk: status_update { task_id: "xxxxxxxx-s" context_id: "yyyyyyyy-s" status { state: TASK_STATE_WORKING message { message_id: "zzzzzzzz-s" role: ROLE_AGENT parts { text: "Processing request..." } } } } Response chunk: artifact_update { task_id: "xxxxxxxx-s" context_id: "yyyyyyyy-s" artifact { artifact_id: "wwwwwwww-s" name: "result" parts { text: "Hello, World!" } } } Response chunk: status_update { task_id: "xxxxxxxx-s" context_id: "yyyyyyyy-s" status { state: TASK_STATE_COMPLETED } } AgentCard --- General --- Name : Hello World Agent - Extended Edition Description : The full-featured hello world agent for authenticated users. Version : 0.0.2 --- Interfaces --- [0] http://127.0.0.1:9999 (JSONRPC) --- Capabilities --- Streaming : True Push notifications : False Extended agent card : True --- I/O Modes --- Input : text/plain Output : text/plain --- Skills --- ---------------------------------------------------- ID : hello_world Name : Returns hello world Description : just returns hello world Tags : hello world Example : hi Example : hello world ---------------------------------------------------- ID : super_hello_world Name : Returns a SUPER Hello World Description : A more enthusiastic greeting, only for authenticated users. Tags : hello world, super, extended Example : super hi Example : give me a super hello ``` _(Actual IDs like `xxxxxxxx`, `yyyyyyyy`, `zzzzzzzz`, `wwwwwwww`, and `vvvvvvvv` will be different UUIDs in each run.)_ This confirms your server is correctly handling basic A2A interactions with the updated SDK structure. You can now shut down the server by pressing Ctrl+C in the terminal window where `__main__.py` is running. # 7. Streaming & Multi-Turn Interactions (LangGraph Example) The Hello World example demonstrates the basic mechanics of A2A. For more advanced features like robust streaming, task state management, and multi-turn conversations powered by an LLM, we'll turn to the LangGraph example located in [`a2a-samples/samples/python/agents/langgraph/`](https://github.com/a2aproject/a2a-samples/tree/main/samples/python/agents/langgraph). This example features a "Currency Agent" that uses the Gemini model via LangChain and LangGraph to answer currency conversion questions. ## Setting up the LangGraph Example 1. Create a [Gemini API Key](https://ai.google.dev/gemini-api/docs/api-key) if you don't already have one. 2. **Environment Variable:** Create a `.env` file in the `a2a-samples/samples/python/agents/langgraph/` directory: ```bash echo "GOOGLE_API_KEY=YOUR_API_KEY_HERE" > .env ``` Replace `YOUR_API_KEY_HERE` with your actual Gemini API key. 3. **Install Dependencies (if not already covered):** The `langgraph` example has its own `pyproject.toml` which includes dependencies like `langchain-google-genai` and `langgraph`. When you installed the SDK from the `a2a-samples` root using `pip install -e .[dev]`, this should have also installed the dependencies for the workspace examples, including `langgraph-example`. If you encounter import errors, ensure your primary SDK installation from the root directory was successful. ## Running the LangGraph Server Navigate to the `a2a-samples/samples/python/agents/langgraph/app` directory in your terminal and ensure your virtual environment (from the SDK root) is activated. Start the LangGraph agent server: ```bash python __main__.py ``` This will start the server, usually on `http://localhost:10000`. ## Interacting with the LangGraph Agent Open a **new terminal window**, activate your virtual environment, and navigate to `a2a-samples/samples/python/agents/langgraph/app`. Run its test client: ```bash python test_client.py ``` Now, you can shut down the server by typing Ctrl+C in the terminal window where `__main__.py` is running. ## Key Features Demonstrated The `langgraph` example showcases several important A2A concepts: 1. **LLM Integration**: - `agent.py` defines `CurrencyAgent`. It uses `ChatGoogleGenerativeAI` and LangGraph's `create_react_agent` to process user queries. - This demonstrates how a real LLM can power the agent's logic. 2. **Task State Management**: - `samples/langgraph/__main__.py` initializes a `DefaultRequestHandler` with an `InMemoryTaskStore`. ```python { .no-copy } --8<-- "https://raw.githubusercontent.com/a2aproject/a2a-samples/refs/heads/main/samples/python/agents/langgraph/app/__main__.py:DefaultRequestHandler" ``` - The `CurrencyAgentExecutor` (in `samples/langgraph/agent_executor.py`), when its `execute` method is called by the `DefaultRequestHandler`, interacts with the `RequestContext` which contains the current task (if any). - For `Send Message`, the `DefaultRequestHandler` uses the `TaskStore` to persist and retrieve task state across interactions. The response to `Send Message` will be a full `Task` object if the agent's execution flow involves multiple steps or results in a persistent task. - The `test_client.py`'s `run_single_turn_test` demonstrates getting a `Task` object back and then querying it using `get_task`. 3. **Streaming with `TaskStatusUpdateEvent` and `TaskArtifactUpdateEvent`**: - The `execute` method in `CurrencyAgentExecutor` is responsible for handling both non-streaming and streaming requests, orchestrated by the `DefaultRequestHandler`. - As the LangGraph agent processes the request (which might involve calling tools like `get_exchange_rate`), the `CurrencyAgentExecutor` enqueues different types of events onto the `EventQueue`: - `TaskStatusUpdateEvent`: For intermediate updates (e.g., "Looking up exchange rates...", "Processing the exchange rates..."). - `TaskArtifactUpdateEvent`: When the final answer is ready, it's enqueued as an artifact. The `lastChunk` flag is `True`. - A final `TaskStatusUpdateEvent` with `state=TaskState.completed` is sent to signify the end of the task, closing the stream. - The `test_client.py`'s `run_streaming_test` function will print these individual event chunks as they are received from the server. 4. **Multi-Turn Conversation (`TaskState.input_required`)**: - The `CurrencyAgent` can ask for clarification if a query is ambiguous (e.g., user asks "how much is 100 USD?"). - When this happens, the `CurrencyAgentExecutor` will enqueue a `TaskStatusUpdateEvent` where `status.state` is `TaskState.input_required` and `status.message` contains the agent's question (e.g., "To which currency would you like to convert?"). The stream closes after this event. - The `test_client.py`'s `run_multi_turn_test` function demonstrates this: - It sends an initial ambiguous query. - The agent responds (via the `DefaultRequestHandler` processing the enqueued events) with a `Task` whose status is `input_required`. - The client then sends a second message, including the `taskId` and `contextId` from the first turn's `Task` response, to provide the missing information ("in GBP"). This continues the same task. ## Exploring the Code Take some time to look through these files: - `__main__.py`: Server setup using `A2AStarletteApplication` and `DefaultRequestHandler`. Note the `AgentCard` definition includes `capabilities.streaming=True`. - `agent.py`: The `CurrencyAgent` with LangGraph, LLM model, and tool definitions. - `agent_executor.py`: The `CurrencyAgentExecutor` implementing the `execute` (and `cancel`) method. It uses the `RequestContext` to understand the ongoing task and the `EventQueue` to send back various events (`TaskStatusUpdateEvent`, `TaskArtifactUpdateEvent`, new `Task` object implicitly via the first event if no task exists). - `test_client.py`: Demonstrates various interaction patterns, including retrieving task IDs and using them for multi-turn conversations. This example provides a much richer illustration of how A2A facilitates complex, stateful, and asynchronous interactions between agents. # Next Steps Congratulations on completing the A2A Python SDK Tutorial! You've learned how to: - Set up your environment for A2A development. - Define Agent Skills and Agent Cards using the SDK's types. - Implement a basic HelloWorld A2A server and client. - Understand and implement streaming capabilities. - Integrate a more complex agent using LangGraph, demonstrating task state management and tool use. You now have a solid foundation for building and integrating your own A2A-compliant agents. ## Where to Go From Here? Here are some ideas and resources to continue your A2A journey: - **Explore Other Examples:** - Check out the other examples in the [a2a-samples GitHub repository](https://github.com/a2aproject/a2a-samples/tree/main/samples) for more complex agent integrations and features. - **Deepen Your Protocol Understanding:** - 📚 Read the complete [A2A Protocol Documentation site](https://a2a-protocol.org) for a comprehensive overview. - 📝 Review the detailed [A2A Protocol Specification](../../specification.md) to understand the nuances of all data structures and RPC methods. - **Review Key A2A Topics:** - [A2A and MCP](../../topics/a2a-and-mcp.md): Understand how A2A complements the Model Context Protocol for tool usage. - [Enterprise-Ready Features](../../topics/enterprise-ready.md): Learn about security, observability, and other enterprise considerations. - [Streaming & Asynchronous Operations](../../topics/streaming-and-async.md): Get more details on SSE and push notifications. - [Agent Discovery](../../topics/agent-discovery.md): Explore different ways agents can find each other. - **Build Your Own Agent:** - Try creating a new A2A agent using your favorite Python agent framework (like LangChain, CrewAI, AutoGen, Semantic Kernel, or a custom solution). - Implement the `a2a.server.agent_execution.AgentExecutor` interface to bridge your agent's logic with the A2A protocol. - Think about what unique skills your agent could offer and how its Agent Card would represent them. - **Experiment with Advanced Features:** - Implement robust task management with a persistent `TaskStore` if your agent handles long-running or multi-session tasks. - Explore implementing push notifications if your agent's tasks are very long-lived. - Consider more complex input and output modalities (e.g., handling file uploads/downloads via file Parts, or structured data via data Parts). - **Contribute to the A2A Community:** - Join the discussions on the [A2A GitHub Discussions page](https://github.com/a2aproject/A2A/discussions). - Report issues or suggest improvements via [GitHub Issues](https://github.com/a2aproject/A2A/issues). - Consider contributing code, examples, or documentation. See the [CONTRIBUTING.md](https://github.com/a2aproject/A2A/blob/main/CONTRIBUTING.md) guide. The A2A protocol aims to foster an ecosystem of interoperable AI agents. By building and sharing A2A-compliant agents, you can be a part of this exciting development! # What's New in A2A Protocol v1.0 This document provides a comprehensive overview of changes from A2A Protocol v0.3.0 to v1.0. The v1.0 release represents a significant maturation of the protocol with enhanced clarity, stronger specifications, and important structural improvements. ## Overview of Major Themes The v1.0 release focuses on four major themes: ### 1. **Protocol Maturity and Standardization** - Elevate a2a.proto from being a gRPC-specific implementation file to the universal, normative source of truth - Leverage formal specification standards (RFC 8785, RFC 7515) and google.rpc.Status where possible - Stricter adherence to industry-standard patterns for REST, gRPC, and JSON-RPC bindings - Enhanced versioning strategy with explicit backward compatibility rules - Comprehensive error taxonomy with protocol-specific mappings ### 2. **Enhanced Type Safety and Clarity** - Removal of discriminator `kind` fields in favor of JSON member-based polymorphism - **Breaking:** Enum values changed from `kebab-case` to `SCREAMING_SNAKE_CASE` for compliance with the ProtoJSON specification - Stricter field naming conventions (`camelCase` for JSON) - More precise timestamp specifications (ISO 8601 with millisecond precision) - Better-defined data types with clearer Optional vs Required semantics ### 3. **Improved Developer Experience** - Renamed operations for consistency and clarity - Reorganized Agent Card structure for better logical grouping - Enhanced extension mechanism with versioning and requirement declarations - More explicit service parameter handling (A2A-Version, A2A-Extensions headers) - **Simplified ID format** - Removed complex compound IDs (e.g., `tasks/{id}`) in favor of simple UUIDs - **Protocol versioning per interface** - Each AgentInterface specifies its own protocol version for better backward compatibility - **Multi-tenancy support** - Native tenant scoping in gRPC requests ### 4. **Enterprise-Ready Features** - Agent Card signature verification using JWS and JSON Canonicalization - Formal specification of all three protocol bindings with equivalence guarantees - Enhanced security scheme declarations with mutual TLS support - **Modern OAuth 2.0 flows** - Added Device Code flow (RFC 8628), removed deprecated implicit/password flows - **PKCE support** - Added `pkce_required` field to Authorization Code flow for enhanced security - Cursor-based pagination for scalable task listing --- ## Behavioral Changes for Core Operations ### Send Message (`message/send` → **`SendMessage`**) **v0.3.0 Behavior:** - Operation named `message/send` - Less formal specification of when `Task` vs `Message` is returned **v1.0 Changes:** - **✅ RENAMED:** Operation now **`SendMessage`** - **✅ CLARIFIED:** More precise specification of Task vs Message return semantics ### Send Streaming Message (`message/stream` → **SendStreamingMessage**) **v0.3.0 Behavior:** - Operation named `message/stream` - Stream events had `kind` discriminator field **v1.0 Changes:** - **✅ RENAMED:** Operation now **`SendStreamingMessage`** - **✅ BREAKING:** Stream events no longer have `kind` field - Use JSON member names to discriminate between `TaskStatusUpdateEvent` and `TaskArtifactUpdateEvent` - **✅ REMOVED:** `final` boolean field removed from TaskStatusUpdateEvent. Leverage protocol binding specific stream closure mechanism instead. - **✅ CLARIFIED:** Multiple concurrent streams allowed; all receive same ordered events ### Get Task (`tasks/get` → **GetTask**) **v0.3.0 Behavior:** - Operation named `tasks/get` - Returns task with status, artifacts, and optionally history - Less formal specification of what "include history" means **v1.0 Changes:** - **✅ RENAMED:** Operation now **GetTask** - **✅ NEW:** `createdAt` and `lastModified` timestamp fields added to Task object - **✅ CLARIFIED:** More precise specification of history inclusion behavior - **✅ NEW:** Task object now includes `extensions[]` array in messages and artifacts - **✅ CLARIFIED:** Authentication/authorization scoping - servers MUST only return tasks visible to caller ### List Tasks (`tasks/list` → **ListTasks**) **v0.3.0 Behavior:** - Operation unavailable. **v1.0 Changes:** - **✅ NEW:** New operation **ListTasks** with filtering capabilities - **✅ CLARIFIED:** Task visibility scoped to authenticated caller ### Cancel Task (`tasks/cancel` → **CancelTask**) **v0.3.0 Behavior:** - Operation named `tasks/cancel` - Request with taskId, returns Task **v1.0 Changes:** - **✅ RENAMED:** Operation now **CancelTask** - **✅ CLARIFIED:** More precise specification of when cancellation is allowed - **✅ CLARIFIED:** Task state transitions for cancellation scenarios ### Get Agent Card (Well-known URI and **GetExtendedAgentCard**) **v0.3.0 Behavior:** - Discovery via `/.well-known/agent-card.json` - Extended card via `agent/getAuthenticatedExtendedCard` - `supportsAuthenticatedExtendedCard` boolean at top level **v1.0 Changes:** - **✅ RENAMED:** `agent/getAuthenticatedExtendedCard` → **GetExtendedAgentCard** - **✅ BREAKING:** `supportsAuthenticatedExtendedCard` moved to `capabilities.extendedAgentCard` - **✅ NEW:** Canonicalization (RFC 8785) clarified for Agent Card signature - **✅ BREAKING:** `protocolVersion` moved from AgentCard to individual AgentInterface objects - **✅ BREAKING:** `preferredTransport` and `additionalInterfaces` consolidated into `supportedInterfaces[]` - Each interface has `url`, `protocolBinding`, and `protocolVersion` ### Subscribe to task (`tasks/resubscribe` → **SubscribeToTask**) **v0.3.0 Behavior:** - Used `tasks/resubscribe` to reconnect interrupted SSE streams - Backfill behavior implementation-dependent **v1.0 Changes:** - **✅ RENAMED:** Operation now **SubscribeToTask** - **✅ CLARIFIED:** Formal specification of streaming subscription lifecycle - **✅ CLARIFIED:** Stream closure behavior when task reaches terminal state - **✅ CLARIFIED:** Multiple concurrent subscriptions supported per task ### Push Notification Operations **v0.3.0 Operations:** - `tasks/pushNotificationConfig/set` - `tasks/pushNotificationConfig/get` - `tasks/pushNotificationConfig/list` - `tasks/pushNotificationConfig/delete` **v1.0 Changes:** - **✅ RENAMED:** Operations now **CreateTaskPushNotificationConfig**, **GetTaskPushNotificationConfig**, **ListTaskPushNotificationConfigs**, **DeleteTaskPushNotificationConfig** - **✅ NEW:** `createdAt` timestamp field added to PushNotificationConfig - **✅ CLARIFIED:** Push notification payloads now use StreamResponse format - **✅ BREAKING:** model changed for all methods, with TaskPushNotificationConfig flattened ### NEW: Multi-Tenancy Support **v0.3.0:** - No native multi-tenancy support in protocol - Tenants handled implicitly via authentication or URL paths **v1.0 Changes:** - **✅ NEW:** `tenant` field added to all request messages - **✅ NEW:** `tenant` field added to `AgentInterface` to specify default tenant - **✅ CLARIFIED:** Tenant provided per-request, inherited from AgentInterface - **✅ USE CASE:** Enables to serve multiple agents from a single endpoint ### Protocol Simplifications #### ID Format Simplification (#1389) **v0.3.0:** - Some operations used complex compound IDs like `tasks/{taskId}` - Required clients/servers to construct/deconstruct resource names **v1.0 Changes:** - **✅ BREAKING:** All IDs are now simple literals - **✅ BREAKING:** Operations that previously used compound IDs now separate parent and resource ID - Example: `tasks/{taskId}/pushNotificationConfigs/{configId}` → separate `task_id` and `config_id` fields - **✅ BENEFIT:** Simpler to implement - IDs map directly to database keys #### HTTP URL Path Simplification (#1269) **v0.3.0:** - HTTP+JSON binding used `/v1/` prefix in URLs - Example: `POST /v1/message:send` **v1.0 Changes:** - **✅ BREAKING:** Removed `/v1` prefix from HTTP+JSON URL paths - **✅ NEW:** Examples: `POST /message:send`, `GET /tasks/{id}` - **✅ RATIONALE:** Version can be part of the base url if required by agent owner - **✅ BENEFIT:** Cleaner URLs, version management at interface level --- ## Structural Changes in Core Model Objects ### TaskStatus Object **Modified Fields:** - ✅ `state`: **BREAKING** - Enum values changed from lowercase to `SCREAMING_SNAKE_CASE` with `TASK_STATE_` prefix - v0.3.0: `"submitted"`, `"working"`, `"completed"`, `"failed"`, `"canceled"`, `"rejected"`, `"input-required"`, `"auth-required"` - v1.0: `"TASK_STATE_SUBMITTED"`, `"TASK_STATE_WORKING"`, `"TASK_STATE_COMPLETED"`, `"TASK_STATE_FAILED"`, `"TASK_STATE_CANCELED"`, `"TASK_STATE_REJECTED"`, `"TASK_STATE_INPUT_REQUIRED"`, `"TASK_STATE_AUTH_REQUIRED"` - ✅ `timestamp`: Now explicitly ISO 8601 UTC with millisecond precision (`YYYY-MM-DDTHH:mm:ss.sssZ`) **Removed Fields:** - None **Example Migration:** ```json // v0.3.0 { "status": { "state": "completed", "timestamp": "2024-03-15T10:15:00Z" } } // v1.0 { "status": { "state": "TASK_STATE_COMPLETED", "timestamp": "2024-03-15T10:15:00.000Z" } } ``` ### Message Object **Added Fields:** - ✅ `extensions[]`: Array of extension URIs applicable to this message **Modified Fields:** - ✅ `role`: **BREAKING** - Enum values changed from lowercase to `SCREAMING_SNAKE_CASE` with `ROLE_` prefix - v0.3.0: `"user"`, `"agent"` - v1.0: `"ROLE_USER"`, `"ROLE_AGENT"` **Example Migration:** ```json // v0.3.0 { "role": "user", "parts": [{"kind": "text", "text": "Hello"}] } // v1.0 { "role": "ROLE_USER", "parts": [{"text": "Hello"}], } ``` **Behavior Changes:** - Parts array now uses member-based discrimination instead of `kind` field ### Part Object **BREAKING CHANGE - Complete Redesign:** The Part structure has been completely redesigned in v1.0. Instead of separate TextPart, FilePart, and DataPart message types, there is now a single unified `Part` message. **v0.3.0 Structure (Separate Types):** ```json // Text example { "kind": "text", "text": "Hello world" } // File example { "kind": "file", "file": { "fileWithUri": "https://example.com/doc.pdf", "mimeType": "application/pdf" } } // Data example { "kind": "data", "data": {"key": "value"} } ``` **v1.0 Structure (Unified Part):** ```json // Text example { "text": "Hello world", "mediaType": "text/plain" } // File with URL example { "url": "https://example.com/doc.pdf", "filename": "doc.pdf", "mediaType": "application/pdf" } // File with raw bytes example { "raw": "base64encodedcontent==", "filename": "image.png", "mediaType": "image/png" } // Data example { "data": {"key": "value"}, "mediaType": "application/json" } ``` **Changes:** - ⛔ **REMOVED:** Separate `TextPart`, `FilePart`, and `DataPart` types - ⛔ **REMOVED:** `kind` discriminator field - ⛔ **REMOVED:** Nested `file` object structure - ✅ **NEW:** Single unified `Part` message with `oneof content` field - ✅ **NEW:** Content type determined by which field is present: `text`, `raw`, `url`, or `data` - ✅ **NEW:** `mediaType` field (replaces `mimeType`) - available for all part types - ✅ **NEW:** `filename` field - available for all part types (not just files) - ✅ **NEW:** `raw` field for inline binary content (base64 in JSON) - ✅ **NEW:** `url` field for file references (replaces `file.fileWithUri`) **Migration Examples:** ```typescript // v0.3.0 const textPart = { kind: "text", text: "Hello" }; const filePart = { kind: "file", file: { fileWithUri: "https://...", mimeType: "image/png" } }; const dataPart = { kind: "data", data: { key: "value" } }; // v1.0 const textPart = { text: "Hello", mediaType: "text/plain" }; const filePart = { url: "https://...", mediaType: "image/png", filename: "image.png" }; const dataPart = { data: { key: "value" }, mediaType: "application/json" }; // Discrimination changed from kind field to member presence if (part.kind === "text") { ... } // v0.3.0 if ("text" in part) { ... } // v1.0 ``` ### Artifact Object **Added Fields:** - ✅ `extensions[]`: Array of extension URIs **Modified Fields:** - ✅ `parts[]`: Now uses member-based Part discrimination (see Part changes above) ### AgentCard Object **Added Fields:** - ✅ `supportedInterfaces[]`: Array of `AgentInterface` objects **Removed Fields:** - ⛔ `protocolVersion`: Removed from AgentCard (now in each AgentInterface) - ⛔ `preferredTransport`: Consolidated into `supportedInterfaces` - ⛔ `additionalInterfaces`: Consolidated into `supportedInterfaces` - ⛔ `supportsAuthenticatedExtendedCard`: Moved to `capabilities.extendedAgentCard` - ⛔ `url`: Primary endpoint now in `supportedInterfaces[0].url` **Structure Example:** **v0.3.0:** ```json { "protocolVersion": "0.3", "url": "https://agent.example.com/a2a", "preferredTransport": "JSONRPC", "supportsAuthenticatedExtendedCard": true, "additionalInterfaces": [...] } ``` **v1.0:** ```json { "supportedInterfaces": [ { "url": "https://agent.example.com/a2a", "protocolBinding": "JSONRPC", "protocolVersion": "1.0" } ], "capabilities": { "extendedAgentCard": true }, "signatures": [...] } ``` ### AgentCapabilities Object **Modified Fields:** - ✅ `extendedAgentCard`: Moved from top-level `supportsAuthenticatedExtendedCard` field ### PushNotificationConfig Object **Added Fields:** - ✅ `configId`: Unique identifier for the configuration - ✅ `createdAt`: Timestamp - Configuration creation time **Modified Fields:** - ✅ `authentication`: Enhanced PushNotificationAuthenticationInfo structure ### Stream Event Objects **TaskStatusUpdateEvent:** **v0.3.0:** ```json { "kind": "taskStatusUpdate", "taskId": "...", "contextId": "...", "status": {...}, "final": true } ``` **v1.0:** ```json { "taskStatusUpdate": { "taskId": "...", "contextId": "...", "status": {...} } } ``` **Changes:** - ⛔ **REMOVED:** `kind` discriminator - ⛔ **REMOVED:** `final` boolean field (stream closure indicates completion instead) - ✅ **NEW PATTERN:** Event type determined by JSON member name (`taskStatusUpdate` or `taskArtifactUpdate`) - ✅ **CLARIFIED:** Terminal state indicated by protocol-specific stream closure mechanism **TaskArtifactUpdateEvent:** **v0.3.0:** ```json { "kind": "taskArtifactUpdate", "taskId": "...", "contextId": "...", "artifact": {...} } ``` **v1.0:** ```json { "taskArtifactUpdate": { "taskId": "...", "contextId": "...", "artifact": {...}, "index": 0 } } ``` **Changes:** - ⛔ **REMOVED:** `kind` discriminator - ✅ **NEW PATTERN:** Wrapped in `taskArtifactUpdate` object - ✅ **NEW:** `index` field indicates artifact position in task's artifacts array ### OAuth 2.0 Security Updates (#1303) v1.0 modernizes OAuth 2.0 support in alignment with OAuth 2.0 Security Best Current Practice (BCP). **Removed Flows (Deprecated by OAuth BCP):** - ⛔ `ImplicitOAuthFlow` - Deprecated due to token leakage risks in browser history/logs - ⛔ `PasswordOAuthFlow` - Deprecated due to credential exposure risks **Added Flows:** - ✅ `DeviceCodeOAuthFlow` (RFC 8628) - For CLI tools, IoT devices, and input-constrained scenarios - Provides `device_authorization_url` endpoint - Supports `verification_uri`, `user_code` pattern - Ideal for headless environments **Enhanced Security:** - ✅ `pkce_required` field added to `AuthorizationCodeOAuthFlow` (RFC 7636) - Indicates whether PKCE (Proof Key for Code Exchange) is mandatory - Protects against authorization code interception attacks - Recommended for all OAuth clients, required for public clients **Migration Guide:** ```typescript // v0.3.0 - Implicit Flow (now removed) { "implicitFlow": { "authorizationUrl": "https://auth.example.com/authorize", "scopes": {"read": "Read access"} } } // v1.0 - Use Authorization Code + PKCE instead { "authorizationCodeFlow": { "authorizationUrl": "https://auth.example.com/authorize", "tokenUrl": "https://auth.example.com/token", "pkceRequired": true, "scopes": {"read": "Read access"} } } ``` --- ## New Dependencies on Other Specifications v1.0 introduces several new formal dependencies on industry-standard specifications: ### Added Specifications #### ✅ google.rpc.Status / google.rpc.ErrorInfo - **Purpose:** Standardized error response model with ProtoJSON representation - **Usage:** Error responses for HTTP+JSON and JSON-RPC bindings - **Impact:** Replaces RFC 9457 for HTTP errors. Enforces structured `ErrorInfo` with `reason` and `domain` for A2A-specific errors. #### ✅ RFC 8785 - JSON Canonicalization Scheme (JCS) - **Purpose:** Deterministic JSON serialization for signing - **Usage:** Agent Card signature verification - **Impact:** Enables cryptographic verification of Agent Card integrity - **Details:** Canonical form used before JWS signing (excludes `signatures` field) #### ✅ RFC 7515 - JSON Web Signature (JWS) - **Purpose:** Cryptographic signing standard - **Usage:** Agent Card signatures field - **Impact:** Industry-standard signature format for trust verification - **Details:** Supports detached signatures with public key retrieval via `jku` or trusted keystores #### ✅ Google API Design Guidelines - **Purpose:** gRPC best practices and conventions - **Usage:** gRPC binding design patterns - **Impact:** Better alignment with gRPC ecosystem expectations #### ✅ ISO 8601 - **Purpose:** Timestamp format standard - **Usage:** All timestamp fields (createdAt, lastModified, timestamp) - **Impact:** Explicit format requirement: UTC with millisecond precision (`YYYY-MM-DDTHH:mm:ss.sssZ`) ### Existing Dependencies (Retained from v0.3.0) - JSON-RPC 2.0 - gRPC / Protocol Buffers 3 - HTTP/HTTPS (various RFCs) - Server-Sent Events (SSE) - W3C specification - RFC 8615 - Well-known URIs - OAuth 2.0, OpenID Connect (for authentication) - TLS (RFC 8446 recommended) ### Complementary Protocol **Model Context Protocol (MCP):** - Relationship clarified: MCP handles tool/resource integration, A2A handles agent-to-agent coordination - Protocols are complementary, not competing - Agents may support both protocols for different use cases --- ## Impact on Developers ### Breaking Changes Requiring Code Updates #### 1. Part Type Unification (CRITICAL IMPACT) The most significant breaking change: TextPart, FilePart, and DataPart types have been removed and replaced with a single unified Part structure. **Before (v0.3.0):** ```typescript // Separate types with kind discriminator if (part.kind === "text") { return part.text; } else if (part.kind === "file") { if (part.file.fileWithUri) { return fetchFile(part.file.fileWithUri); } else { return part.file.fileWithBytes; } } else if (part.kind === "data") { return part.data; } ``` **After (v1.0):** ```typescript // Unified Part with oneof content if ("text" in part) { return part.text; } else if ("url" in part) { return fetchFile(part.url); } else if ("raw" in part) { return decodeBase64(part.raw); } else if ("data" in part) { return part.data; } ``` #### 2. Stream Event Discriminator Pattern (HIGH IMPACT) Stream events changed from kind-based to wrapper-based discrimination: **Before (v0.3.0):** ```typescript if (event.kind === "taskStatusUpdate") { handleStatusUpdate(event); } else if (event.kind === "taskArtifactUpdate") { handleArtifactUpdate(event); } ``` **After (v1.0):** ```typescript if ("taskStatusUpdate" in event) { handleStatusUpdate(event.taskStatusUpdate); } else if ("taskArtifactUpdate" in event) { handleArtifactUpdate(event.taskArtifactUpdate); } ``` #### 3. Agent Card Structure (HIGH IMPACT) Agent discovery and capability checking requires updates: **Before (v0.3.0):** ```typescript const endpoint = agentCard.url; const transport = agentCard.preferredTransport; const supportsExtended = agentCard.supportsAuthenticatedExtendedCard; ``` **After (v1.0):** ```typescript const primaryInterface = agentCard.supportedInterfaces[0]; const endpoint = primaryInterface.url; const transport = primaryInterface.protocolBinding; const supportsExtended = agentCard.capabilities.extendedAgentCard; ``` #### 4. Pagination (MEDIUM IMPACT) List Tasks implementation must switch from page-based to cursor-based: **Before (v0.3.0):** ```typescript const response = await listTasks({ page: 1, perPage: 50 }); ``` **After (v1.0):** ```typescript let cursor = undefined; do { const response = await listTasks({ cursor, limit: 50 }); // process response.tasks cursor = response.nextCursor; } while (cursor); ``` #### 5. Enum Value Changes (HIGH IMPACT) All enum values now use SCREAMING_SNAKE_CASE with type prefixes: **TaskState:** ```typescript // v0.3.0 if (task.status.state === "completed") { ... } if (task.status.state === "input-required") { ... } // v1.0 if (task.status.state === "TASK_STATE_COMPLETED") { ... } if (task.status.state === "TASK_STATE_INPUT_REQUIRED") { ... } ``` **MessageRole:** ```typescript // v0.3.0 const message = { role: "user", parts: [...] }; // v1.0 const message = { role: "ROLE_USER", parts: [...] }; ``` **Complete Mapping:** - `"submitted"` → `"TASK_STATE_SUBMITTED"` - `"working"` → `"TASK_STATE_WORKING"` - `"completed"` → `"TASK_STATE_COMPLETED"` - `"failed"` → `"TASK_STATE_FAILED"` - `"canceled"` → `"TASK_STATE_CANCELED"` - `"rejected"` → `"TASK_STATE_REJECTED"` - `"input-required"` → `"TASK_STATE_INPUT_REQUIRED"` - `"auth-required"` → `"TASK_STATE_AUTH_REQUIRED"` - `"user"` → `"ROLE_USER"` - `"agent"` → `"ROLE_AGENT"` #### 6. Field Name Changes (LOW IMPACT) - `file.mimeType` → `mediaType` - Operation names (aliases provided during transition) #### 7. Standardized Error Handling via google.rpc.Status (HIGH IMPACT) HTTP+JSON error responses have been updated to use the ProtoJSON representation of `google.rpc.Status` instead of RFC 9457 (Problem Details). JSON-RPC and HTTP+JSON bindings now use `google.rpc.ErrorInfo` within the `data` / `details` array to provide A2A-specific error context. **Changes:** - **HTTP+JSON Content-Type:** Changed from `application/problem+json` to `application/json`. - **Error Model:** Uses `google.rpc.Status` fields (`code`, `message`, `details`). - **A2A Error Info:** MUST include a `google.rpc.ErrorInfo` object in `details` with `reason` (UPPER_SNAKE_CASE from A2A error types) and `domain: "a2a-protocol.org"`. **JSON-RPC Example Migration:** ```json // v0.3.0 "error": { "code": -32001, "message": "Task not found", "data": { "taskId": "123" } } // v1.0 "error": { "code": -32001, "message": "Task not found", "data": [ { "@type": "type.googleapis.com/google.rpc.ErrorInfo", "reason": "TASK_NOT_FOUND", "domain": "a2a-protocol.org", "metadata": { "taskId": "123" } } ] } ``` **HTTP+JSON Example Migration:** ```http // v0.3.0 (Draft using RFC 9457) HTTP/1.1 404 Not Found Content-Type: application/problem+json { "type": "https://a2a-protocol.org/errors/task-not-found", "title": "Task Not Found", "status": 404, "detail": "The specified task ID does not exist" } // v1.0 HTTP/1.1 404 Not Found Content-Type: application/json { "error": { "code": 404, "status": "NOT_FOUND", "message": "The specified task ID does not exist", "details": [ { "@type": "type.googleapis.com/google.rpc.ErrorInfo", "reason": "TASK_NOT_FOUND", "domain": "a2a-protocol.org" } ] } } ``` ### New Capabilities to Leverage #### 1. Execution Mode Control ```typescript // Wait for task completion (Default) const result = await sendMessage(message, { returnImmediately: false }); // Return immediately, poll later const task = await sendMessage(message, { returnImmediately: true }); ``` #### 2. Agent Card Signature Verification ```typescript if (agentCard.signatures && agentCard.signatures.length > 0) { const verified = await verifyAgentCardSignature(agentCard); if (!verified) { throw new Error("Agent Card signature verification failed"); } } ``` #### 3. Extension Requirements ```typescript const requiredExtensions = agentCard.extensions .filter(ext => ext.required) .map(ext => ext.uri); // Check if client supports required extensions if (!clientSupportsAll(requiredExtensions)) { throw new Error("Missing required extension support"); } ``` #### 4. Enhanced Timestamp Tracking ```typescript const taskAge = Date.now() - new Date(task.createdAt).getTime(); const timeSinceUpdate = Date.now() - new Date(task.lastModified).getTime(); ``` #### 5. Versioning Negotiation ```typescript // Client sends A2A-Version header headers["A2A-Version"] = "1.0"; // Server validates and rejects if unsupported if (!supportedVersions.includes(requestedVersion)) { throw new VersionNotSupportedError(); } ``` ### Migration Strategy Recommendations #### Phase 1: Compatibility Layer 1. Add support for parsing both old and new discriminator patterns 2. Implement version detection based on protocol version 3. Support both Agent Card structures during transition #### Phase 2: Dual Support 1. Update all APIs to emit v1.0 format 2. Maintain backward compatibility readers for v0.3.0 3. Add A2A-Version header handling 4. Implement cursor-based pagination alongside legacy page-based #### Phase 3: v1.0 Only 1. Deprecate v0.3.0 compatibility code 2. Remove legacy discriminator parsing 3. Remove page-based pagination 4. Clean up dual-format support code #### Backward Compatibility Strategy (#1401) v1.0 introduces a formal approach to protocol versioning that enables SDK backward compatibility. **Protocol Version Per Interface:** - Each `AgentInterface` now specifies its own `protocolVersion` field - Agents can support multiple protocol versions simultaneously by exposing multiple interfaces - Clients negotiate version by selecting appropriate interface from Agent Card **SDK Implementation Pattern:** ```typescript // SDK can support multiple protocol versions class A2AClient { async connect(agentCardUrl: string) { const card = await this.getAgentCard(agentCardUrl); // Find best matching interface const interface = card.supportedInterfaces.find(i => this.supportedVersions.includes(i.protocolVersion) ); if (!interface) { throw new Error("No compatible protocol version"); } // Use version-specific adapter return this.createAdapter(interface.protocolVersion, interface); } } ``` **Benefits:** - SDKs can maintain support for multiple protocol versions - Agents can gradually migrate by supporting both old and new versions - Clients automatically select best compatible version - Enables graceful deprecation of old protocol versions ### Testing Considerations - Test with both v0.3.0 and v1.0 formatted data - Validate Agent Card signature verification - Test cursor-based pagination edge cases (empty results, single page, etc.) - Verify proper handling of new error types - Test extension requirement validation ### Recommended Priority #### Critical (Do Immediately) - Update Part and streaming event parsing (discriminator pattern) - Update Agent Card parsing (structure changes) - Add A2A-Version header to all requests #### High (Within 1 Month) - Implement cursor-based pagination - Update enum value handling (state field) - Add return_immediately parameter support #### Medium (Within 3 Months) - Implement Agent Card signature verification - Add extension requirement checking - Update timestamp handling to ISO 8601 format - Implement new error types #### Low (Nice to Have) - Add createdAt/lastModified timestamp tracking - Leverage enhanced metadata capabilities - Implement mutual TLS authentication support --- ## Conclusion A2A Protocol v1.0 represents a significant step forward in protocol maturity while maintaining the core architectural principles of v0.3.0. The changes focus on standardization, type safety, and enterprise readiness, requiring developers to update their implementations but providing clearer specifications and better developer experience in return. The breaking changes, while requiring code updates, are straightforward to implement and improve code clarity. The new capabilities around versioning, signatures, and enhanced extensions provide a solid foundation for future protocol evolution within the v1.x line. Developers should plan for a phased migration approach, prioritizing the critical breaking changes while gradually adopting new capabilities over time. a2a.a2a_db_cli module ********************* a2a.a2a_db_cli.create_parser() -> ArgumentParser Create the argument parser for the migration tool. a2a.a2a_db_cli.run_migrations() -> None CLI tool to manage database migrations. a2a.auth package **************** Submodules ========== * a2a.auth.user module * "UnauthenticatedUser" * "UnauthenticatedUser.is_authenticated" * "UnauthenticatedUser.user_name" * "User" * "User.is_authenticated" * "User.user_name" Module contents =============== a2a.auth.user module ******************** Authenticated user information. class a2a.auth.user.UnauthenticatedUser Bases: "User" A representation that no user has been authenticated in the request. property is_authenticated: bool Returns whether the current user is authenticated. property user_name: str Returns the user name of the current user. class a2a.auth.user.User Bases: "ABC" A representation of an authenticated user. abstract property is_authenticated: bool Returns whether the current user is authenticated. abstract property user_name: str Returns the user name of the current user. a2a.client.auth.credentials module ********************************** class a2a.client.auth.credentials.CredentialService Bases: "ABC" An abstract service for retrieving credentials. abstractmethod async get_credentials(security_scheme_name: str, context: ClientCallContext | None) -> str | None Retrieves a credential (e.g., token) for a security scheme. class a2a.client.auth.credentials.InMemoryContextCredentialStore Bases: "CredentialService" A simple in-memory store for session-keyed credentials. This class uses the 'sessionId' from the ClientCallContext state to store and retrieve credentials... async get_credentials(security_scheme_name: str, context: ClientCallContext | None) -> str | None Retrieves credentials from the in-memory store. Parameters: * **security_scheme_name** -- The name of the security scheme. * **context** -- The client call context. Returns: The credential string, or None if not found. async set_credentials(session_id: str, security_scheme_name: str, credential: str) -> None Method to populate the store. a2a.client.auth.interceptor module ********************************** class a2a.client.auth.interceptor.AuthInterceptor(credential_service: CredentialService) Bases: "ClientCallInterceptor" An interceptor that automatically adds authentication details to requests. Based on the agent's security schemes. async after(args: AfterArgs) -> None Invoked after the method is executed. async before(args: BeforeArgs) -> None Applies authentication headers to the request if credentials are available. a2a.client.auth package *********************** Submodules ========== * a2a.client.auth.credentials module * "CredentialService" * "CredentialService.get_credentials()" * "InMemoryContextCredentialStore" * "InMemoryContextCredentialStore.get_credentials()" * "InMemoryContextCredentialStore.set_credentials()" * a2a.client.auth.interceptor module * "AuthInterceptor" * "AuthInterceptor.after()" * "AuthInterceptor.before()" Module contents =============== Client-side authentication components for the A2A Python SDK. class a2a.client.auth.AuthInterceptor(credential_service: CredentialService) Bases: "ClientCallInterceptor" An interceptor that automatically adds authentication details to requests. Based on the agent's security schemes. async after(args: AfterArgs) -> None Invoked after the method is executed. async before(args: BeforeArgs) -> None Applies authentication headers to the request if credentials are available. class a2a.client.auth.CredentialService Bases: "ABC" An abstract service for retrieving credentials. abstractmethod async get_credentials(security_scheme_name: str, context: ClientCallContext | None) -> str | None Retrieves a credential (e.g., token) for a security scheme. class a2a.client.auth.InMemoryContextCredentialStore Bases: "CredentialService" A simple in-memory store for session-keyed credentials. This class uses the 'sessionId' from the ClientCallContext state to store and retrieve credentials... async get_credentials(security_scheme_name: str, context: ClientCallContext | None) -> str | None Retrieves credentials from the in-memory store. Parameters: * **security_scheme_name** -- The name of the security scheme. * **context** -- The client call context. Returns: The credential string, or None if not found. async set_credentials(session_id: str, security_scheme_name: str, credential: str) -> None Method to populate the store. a2a.client.base_client module ***************************** class a2a.client.base_client.BaseClient(card: AgentCard, config: ClientConfig, transport: ClientTransport, interceptors: list[ClientCallInterceptor]) Bases: "Client" Base implementation of the A2A client, containing transport- independent logic. async cancel_task(request: CancelTaskRequest, *, context: ClientCallContext | None = None) -> Task Requests the agent to cancel a specific task. Parameters: * **request** -- The *CancelTaskRequest* object specifying the task ID. * **context** -- Optional client call context. Returns: A *Task* object containing the updated task status. async close() -> None Closes the underlying transport. async create_task_push_notification_config(request: TaskPushNotificationConfig, *, context: ClientCallContext | None = None) -> TaskPushNotificationConfig Sets or updates the push notification configuration for a specific task. Parameters: * **request** -- The *TaskPushNotificationConfig* object with the new configuration. * **context** -- Optional client call context. Returns: The created or updated *TaskPushNotificationConfig* object. async delete_task_push_notification_config(request: DeleteTaskPushNotificationConfigRequest, *, context: ClientCallContext | None = None) -> None Deletes the push notification configuration for a specific task. Parameters: * **request** -- The *DeleteTaskPushNotificationConfigRequest* object specifying the request. * **context** -- Optional client call context. async get_extended_agent_card(request: GetExtendedAgentCardRequest, *, context: ClientCallContext | None = None, signature_verifier: Callable[[AgentCard], None] | None = None) -> AgentCard Retrieves the agent's card. This will fetch the authenticated card if necessary and update the client's internal state with the new card. Parameters: * **request** -- The *GetExtendedAgentCardRequest* object specifying the request. * **context** -- Optional client call context. * **signature_verifier** -- A callable used to verify the agent card's signatures. Returns: The *AgentCard* for the agent. async get_task(request: GetTaskRequest, *, context: ClientCallContext | None = None) -> Task Retrieves the current state and history of a specific task. Parameters: * **request** -- The *GetTaskRequest* object specifying the task ID. * **context** -- Optional client call context. Returns: A *Task* object representing the current state of the task. async get_task_push_notification_config(request: GetTaskPushNotificationConfigRequest, *, context: ClientCallContext | None = None) -> TaskPushNotificationConfig Retrieves the push notification configuration for a specific task. Parameters: * **request** -- The *GetTaskPushNotificationConfigParams* object specifying the task. * **context** -- Optional client call context. Returns: A *TaskPushNotificationConfig* object containing the configuration. async list_task_push_notification_configs(request: ListTaskPushNotificationConfigsRequest, *, context: ClientCallContext | None = None) -> ListTaskPushNotificationConfigsResponse Lists push notification configurations for a specific task. Parameters: * **request** -- The *ListTaskPushNotificationConfigsRequest* object specifying the request. * **context** -- Optional client call context. Returns: A *ListTaskPushNotificationConfigsResponse* object. async list_tasks(request: ListTasksRequest, *, context: ClientCallContext | None = None) -> ListTasksResponse Retrieves tasks for an agent. async send_message(request: SendMessageRequest, *, context: ClientCallContext | None = None) -> AsyncIterator[StreamResponse] Sends a message to the agent. This method handles both streaming and non-streaming (polling) interactions based on the client configuration and agent capabilities. It will yield events as they are received from the agent. Parameters: * **request** -- The message to send to the agent. * **context** -- Optional client call context. Yields: An async iterator of *StreamResponse* async subscribe(request: SubscribeToTaskRequest, *, context: ClientCallContext | None = None) -> AsyncIterator[StreamResponse] Resubscribes to a task's event stream. This is only available if both the client and server support streaming. Parameters: * **request** -- Parameters to identify the task to resubscribe to. * **context** -- Optional client call context. Yields: An async iterator of *StreamResponse* objects. Raises: **NotImplementedError** -- If streaming is not supported by the client or server. a2a.client.card_resolver module ******************************* class a2a.client.card_resolver.A2ACardResolver(httpx_client: AsyncClient, base_url: str, agent_card_path: str = '/.well-known/agent-card.json') Bases: "object" Agent Card resolver. async get_agent_card(relative_card_path: str | None = None, http_kwargs: dict[str, Any] | None = None, signature_verifier: Callable[[AgentCard], None] | None = None) -> AgentCard Fetches an agent card from a specified path relative to the base_url. If relative_card_path is None, it defaults to the resolver's configured agent_card_path (for the public agent card). Parameters: * **relative_card_path** -- Optional path to the agent card endpoint, relative to the base URL. If None, uses the default public agent card path. Use *'/'* for an empty path. * **http_kwargs** -- Optional dictionary of keyword arguments to pass to the underlying httpx.get request. * **signature_verifier** -- A callable used to verify the agent card's signatures. Returns: An *AgentCard* object representing the agent's capabilities. Raises: **AgentCardResolutionError** -- If an HTTP error occurs during the request, if the response body cannot be decoded as JSON, or if it cannot be validated against the AgentCard schema. a2a.client.card_resolver.parse_agent_card(agent_card_data: dict[str, Any]) -> AgentCard Parse AgentCard JSON dictionary and handle backward compatibility. a2a.client.client module ************************ class a2a.client.client.Client(interceptors: list[ClientCallInterceptor] | None = None) Bases: "ABC" Abstract base class defining the interface for an A2A client. This class provides a standard set of methods for interacting with an A2A agent, regardless of the underlying transport protocol (e.g., gRPC, JSON-RPC). It supports sending messages, managing tasks, and handling event streams. async add_interceptor(interceptor: ClientCallInterceptor) -> None Attaches additional interceptors to the *Client*. abstractmethod async cancel_task(request: CancelTaskRequest, *, context: ClientCallContext | None = None) -> Task Requests the agent to cancel a specific task. abstractmethod async close() -> None Closes the client and releases any underlying resources. abstractmethod async create_task_push_notification_config(request: TaskPushNotificationConfig, *, context: ClientCallContext | None = None) -> TaskPushNotificationConfig Sets or updates the push notification configuration for a specific task. abstractmethod async delete_task_push_notification_config(request: DeleteTaskPushNotificationConfigRequest, *, context: ClientCallContext | None = None) -> None Deletes the push notification configuration for a specific task. abstractmethod async get_extended_agent_card(request: GetExtendedAgentCardRequest, *, context: ClientCallContext | None = None, signature_verifier: Callable[[AgentCard], None] | None = None) -> AgentCard Retrieves the agent's card. abstractmethod async get_task(request: GetTaskRequest, *, context: ClientCallContext | None = None) -> Task Retrieves the current state and history of a specific task. abstractmethod async get_task_push_notification_config(request: GetTaskPushNotificationConfigRequest, *, context: ClientCallContext | None = None) -> TaskPushNotificationConfig Retrieves the push notification configuration for a specific task. abstractmethod async list_task_push_notification_configs(request: ListTaskPushNotificationConfigsRequest, *, context: ClientCallContext | None = None) -> ListTaskPushNotificationConfigsResponse Lists push notification configurations for a specific task. abstractmethod async list_tasks(request: ListTasksRequest, *, context: ClientCallContext | None = None) -> ListTasksResponse Retrieves tasks for an agent. abstractmethod async send_message(request: SendMessageRequest, *, context: ClientCallContext | None = None) -> AsyncIterator[StreamResponse] Sends a message to the server. This will automatically use the streaming or non-streaming approach as supported by the server and the client config. Client will aggregate update events and return an iterator of *StreamResponse*. abstractmethod async subscribe(request: SubscribeToTaskRequest, *, context: ClientCallContext | None = None) -> AsyncIterator[StreamResponse] Resubscribes to a task's event stream. class a2a.client.client.ClientCallContext(*, state: MutableMapping[str, ~typing.Any]=, timeout: float | None = None, service_parameters: dict[str, str] | None=None) Bases: "BaseModel" A context passed with each client call, allowing for call-specific. configuration and data passing. Such as authentication details or request deadlines. model_config = {} Configuration for the model, should be a dictionary conforming to [*ConfigDict*][pydantic.config.ConfigDict]. service_parameters: dict[str, str] | None state: MutableMapping[str, Any] timeout: float | None class a2a.client.client.ClientConfig(streaming: bool = True, polling: bool = False, httpx_client: ~httpx.AsyncClient | None = None, grpc_channel_factory: ~collections.abc.Callable[[str], ~grpc.aio._base_channel.Channel] | None = None, supported_protocol_bindings: list[str] = , use_client_preference: bool = False, accepted_output_modes: list[str] = , push_notification_config: ~a2a_pb2.TaskPushNotificationConfig | None = None) Bases: "object" Configuration class for the A2AClient Factory. accepted_output_modes: list[str] The set of accepted output modes for the client. grpc_channel_factory: Callable[[str], Channel] | None = None Generates a grpc connection channel for a given url. httpx_client: AsyncClient | None = None Http client to use to connect to agent. polling: bool = False send. It is the callers job to check if the response is completed and if not run a polling loop. Type: Whether client prefers to poll for updates from message push_notification_config: TaskPushNotificationConfig | None = None Push notification configuration to use for every request. streaming: bool = True Whether client supports streaming supported_protocol_bindings: list[str] Ordered list of transports for connecting to agent (in order of preference). Empty implies JSONRPC only. This is a string type to allow custom transports to exist in closed ecosystems. use_client_preference: bool = False Whether to use client transport preferences over server preferences. Recommended to use server preferences in most situations. a2a.client.client_factory module ******************************** class a2a.client.client_factory.ClientFactory(config: ClientConfig | None = None) Bases: "object" Factory for creating clients that communicate with A2A agents. The factory is configured with a *ClientConfig* and optionally custom transport producers registered via *register*. Example usage: factory = ClientFactory(config) # Optionally register custom transport implementations factory.register('my_custom_transport', custom_transport_producer) # Create a client from an AgentCard client = factory.create(card, interceptors) # Or resolve an AgentCard from a URL and create a client client = await factory.create_from_url('https://example.com') The client can be used consistently regardless of the transport. This aligns the client configuration with the server's capabilities. create(card: AgentCard, interceptors: list[ClientCallInterceptor] | None = None) -> Client Create a new *Client* for the provided *AgentCard*. Parameters: * **card** -- An *AgentCard* defining the characteristics of the agent. * **interceptors** -- A list of interceptors to use for each request. These are used for things like attaching credentials or http headers to all outbound requests. Returns: A *Client* object. Raises: * **If there is no valid matching**** of ****the client configuration with the** -- * **server configuration****, ****a ValueError is raised.** -- async create_from_url(url: str, interceptors: list[ClientCallInterceptor] | None = None, relative_card_path: str | None = None, resolver_http_kwargs: dict[str, Any] | None = None, signature_verifier: Callable[[AgentCard], None] | None = None) -> Client Create a *Client* by resolving an *AgentCard* from a URL. Resolves the agent card from the given URL using the factory's configured httpx client, then creates a client via *create*. If the agent card is already available, use *create* directly instead. Parameters: * **url** -- The base URL of the agent. The agent card will be fetched from */.well-known/agent-card.json* by default. * **interceptors** -- A list of interceptors to use for each request. These are used for things like attaching credentials or http headers to all outbound requests. * **relative_card_path** -- The relative path when resolving the agent card. See *A2ACardResolver.get_agent_card* for details. * **resolver_http_kwargs** -- Dictionary of arguments to provide to the httpx client when resolving the agent card. * **signature_verifier** -- A callable used to verify the agent card's signatures. Returns: A *Client* object. register(label: str, generator: Callable[[AgentCard, str, ClientConfig], ClientTransport]) -> None Register a new transport producer for a given transport label. async a2a.client.client_factory.create_client(agent: str | AgentCard, client_config: ClientConfig | None = None, interceptors: list[ClientCallInterceptor] | None = None, relative_card_path: str | None = None, resolver_http_kwargs: dict[str, Any] | None = None, signature_verifier: Callable[[AgentCard], None] | None = None) -> Client Create a *Client* for an agent from a URL or *AgentCard*. Convenience function that constructs a *ClientFactory* internally. For reusing a factory across multiple agents or registering custom transports, use *ClientFactory* directly instead. Parameters: * **agent** -- The base URL of the agent, or an *AgentCard* to use directly. * **client_config** -- Optional *ClientConfig*. A default config is created if not provided. * **interceptors** -- A list of interceptors to use for each request. * **relative_card_path** -- The relative path when resolving the agent card. Only used when *agent* is a URL. * **resolver_http_kwargs** -- Dictionary of arguments to provide to the httpx client when resolving the agent card. * **signature_verifier** -- A callable used to verify the agent card's signatures. Returns: A *Client* object. a2a.client.client_factory.minimal_agent_card(url: str, transports: list[str] | None = None) -> AgentCard Generates a minimal card to simplify bootstrapping client creation. This minimal card is not viable itself to interact with the remote agent. Instead this is a shorthand way to take a known url and transport option and interact with the get card endpoint of the agent server to get the correct agent card. This pattern is necessary for gRPC based card access as typically these servers won't expose a well known path card. a2a.client.errors module ************************ Custom exceptions for the A2A client. exception a2a.client.errors.A2AClientError(message: str | None = None, data: dict | None = None) Bases: "A2AError" Base exception for A2A Client errors. exception a2a.client.errors.A2AClientTimeoutError(message: str | None = None, data: dict | None = None) Bases: "A2AClientError" Exception for timeout errors during a request. exception a2a.client.errors.AgentCardResolutionError(message: str, status_code: int | None = None) Bases: "A2AClientError" Exception raised when an agent card cannot be resolved. a2a.client.interceptors module ****************************** class a2a.client.interceptors.AfterArgs(result: Any, method: str, agent_card: AgentCard, context: ClientCallContext | None = None, early_return: bool = False) Bases: "object" Arguments passed to the interceptor after a method call completes. agent_card: AgentCard context: ClientCallContext | None = None early_return: bool = False method: str result: Any class a2a.client.interceptors.BeforeArgs(input: Any, method: str, agent_card: AgentCard, context: ClientCallContext | None = None, early_return: Any | None = None) Bases: "object" Arguments passed to the interceptor before a method call. agent_card: AgentCard context: ClientCallContext | None = None early_return: Any | None = None input: Any method: str class a2a.client.interceptors.ClientCallInterceptor Bases: "ABC" An abstract base class for client-side call interceptors. Interceptors can inspect and modify requests before they are sent, which is ideal for concerns like authentication, logging, or tracing. abstractmethod async after(args: AfterArgs) -> None Invoked after transport method. abstractmethod async before(args: BeforeArgs) -> None Invoked before transport method. a2a.client.optionals module *************************** a2a.client.service_parameters module ************************************ class a2a.client.service_parameters.ServiceParametersFactory Bases: "object" Factory for creating ServiceParameters. static create(updates: list[Callable[[dict[str, str]], None]]) -> dict[str, str] Create ServiceParameters from a list of updates. Parameters: **updates** -- List of update functions to apply. Returns: The created ServiceParameters dictionary. static create_from(service_parameters: dict[str, str] | None, updates: list[Callable[[dict[str, str]], None]]) -> dict[str, str] Create new ServiceParameters from existing ones and apply updates. Parameters: * **service_parameters** -- Optional existing ServiceParameters to start from. * **updates** -- List of update functions to apply. Returns: New ServiceParameters dictionary. a2a.client.service_parameters.with_a2a_extensions(extensions: list[str]) -> Callable[[dict[str, str]], None] Create a ServiceParametersUpdate that merges A2A extension URIs. Unions the supplied URIs with any already present in the A2A- Extensions parameter, deduplicating and emitting them in sorted order. Repeated calls accumulate rather than overwrite. a2a.client.transports.base module ********************************* class a2a.client.transports.base.ClientTransport Bases: "ABC" Abstract base class for a client transport. abstractmethod async cancel_task(request: CancelTaskRequest, *, context: ClientCallContext | None = None) -> Task Requests the agent to cancel a specific task. abstractmethod async close() -> None Closes the transport. abstractmethod async create_task_push_notification_config(request: TaskPushNotificationConfig, *, context: ClientCallContext | None = None) -> TaskPushNotificationConfig Sets or updates the push notification configuration for a specific task. abstractmethod async delete_task_push_notification_config(request: DeleteTaskPushNotificationConfigRequest, *, context: ClientCallContext | None = None) -> None Deletes the push notification configuration for a specific task. abstractmethod async get_extended_agent_card(request: GetExtendedAgentCardRequest, *, context: ClientCallContext | None = None) -> AgentCard Retrieves the Extended AgentCard. abstractmethod async get_task(request: GetTaskRequest, *, context: ClientCallContext | None = None) -> Task Retrieves the current state and history of a specific task. abstractmethod async get_task_push_notification_config(request: GetTaskPushNotificationConfigRequest, *, context: ClientCallContext | None = None) -> TaskPushNotificationConfig Retrieves the push notification configuration for a specific task. abstractmethod async list_task_push_notification_configs(request: ListTaskPushNotificationConfigsRequest, *, context: ClientCallContext | None = None) -> ListTaskPushNotificationConfigsResponse Lists push notification configurations for a specific task. abstractmethod async list_tasks(request: ListTasksRequest, *, context: ClientCallContext | None = None) -> ListTasksResponse Retrieves tasks for an agent. abstractmethod async send_message(request: SendMessageRequest, *, context: ClientCallContext | None = None) -> SendMessageResponse Sends a non-streaming message request to the agent. abstractmethod async send_message_streaming(request: SendMessageRequest, *, context: ClientCallContext | None = None) -> AsyncGenerator[StreamResponse] Sends a streaming message request to the agent and yields responses as they arrive. abstractmethod async subscribe(request: SubscribeToTaskRequest, *, context: ClientCallContext | None = None) -> AsyncGenerator[StreamResponse] Reconnects to get task updates. a2a.client.transports.grpc module ********************************* class a2a.client.transports.grpc.GrpcTransport(channel: Channel, agent_card: AgentCard | None) Bases: "ClientTransport" A gRPC transport for the A2A client. async cancel_task(request: CancelTaskRequest, *, context: ClientCallContext | None = None) -> Task Requests the agent to cancel a specific task. async close() -> None Closes the gRPC channel. classmethod create(card: AgentCard, url: str, config: ClientConfig) -> GrpcTransport Creates a gRPC transport for the A2A client. async create_task_push_notification_config(request: TaskPushNotificationConfig, *, context: ClientCallContext | None = None) -> TaskPushNotificationConfig Sets or updates the push notification configuration for a specific task. async delete_task_push_notification_config(request: DeleteTaskPushNotificationConfigRequest, *, context: ClientCallContext | None = None) -> None Deletes the push notification configuration for a specific task. async get_extended_agent_card(request: GetExtendedAgentCardRequest, *, context: ClientCallContext | None = None) -> AgentCard Retrieves the agent's card. async get_task(request: GetTaskRequest, *, context: ClientCallContext | None = None) -> Task Retrieves the current state and history of a specific task. async get_task_push_notification_config(request: GetTaskPushNotificationConfigRequest, *, context: ClientCallContext | None = None) -> TaskPushNotificationConfig Retrieves the push notification configuration for a specific task. async list_task_push_notification_configs(request: ListTaskPushNotificationConfigsRequest, *, context: ClientCallContext | None = None) -> ListTaskPushNotificationConfigsResponse Lists push notification configurations for a specific task. async list_tasks(request: ListTasksRequest, *, context: ClientCallContext | None = None) -> ListTasksResponse Retrieves tasks for an agent. async send_message(request: SendMessageRequest, *, context: ClientCallContext | None = None) -> SendMessageResponse Sends a non-streaming message request to the agent. send_message_streaming(request: SendMessageRequest, *, context: ClientCallContext | None = None) -> AsyncGenerator[StreamResponse] Sends a streaming message request to the agent and yields responses as they arrive. subscribe(request: SubscribeToTaskRequest, *, context: ClientCallContext | None = None) -> AsyncGenerator[StreamResponse] Reconnects to get task updates. a2a.client.transports.http_helpers module ***************************************** a2a.client.transports.http_helpers.get_http_args(context: ClientCallContext | None) -> dict[str, Any] Extracts HTTP arguments from the client call context. a2a.client.transports.http_helpers.handle_http_exceptions(status_error_handler: Callable[[HTTPStatusError], NoReturn] | None = None) -> Iterator[None] Handles common HTTP exceptions for REST and JSON-RPC transports. Parameters: **status_error_handler** -- Optional handler for *httpx.HTTPStatusError*. If provided, this handler should raise an appropriate domain-specific exception. If not provided, a default *A2AClientError* will be raised. async a2a.client.transports.http_helpers.send_http_request(httpx_client: AsyncClient, request: Request, status_error_handler: Callable[[HTTPStatusError], NoReturn] | None = None) -> dict[str, Any] Sends an HTTP request and parses the JSON response, handling common exceptions. async a2a.client.transports.http_helpers.send_http_stream_request(httpx_client: ~httpx.AsyncClient, method: str, url: str, status_error_handler: ~collections.abc.Callable[[~httpx.HTTPStatusError], ~typing.NoReturn] | None = None, sse_error_handler: ~collections.abc.Callable[[str], ~typing.NoReturn] = , **kwargs: ~typing.Any) -> AsyncGenerator[str] Sends a streaming HTTP request, yielding SSE data strings and handling exceptions. Parameters: * **httpx_client** -- The async HTTP client. * **method** -- The HTTP method (e.g. 'POST', 'GET'). * **url** -- The URL to send the request to. * **status_error_handler** -- Handler for HTTP status errors. Should raise an appropriate domain-specific exception. * **sse_error_handler** -- Handler for SSE error events. Called with the raw SSE data string when an "event: error" SSE event is received. Should raise an appropriate domain-specific exception. * ****kwargs** -- Additional keyword arguments forwarded to "aconnect_sse". a2a.client.transports.jsonrpc module ************************************ class a2a.client.transports.jsonrpc.JsonRpcTransport(httpx_client: AsyncClient, agent_card: AgentCard, url: str) Bases: "ClientTransport" A JSON-RPC transport for the A2A client. async cancel_task(request: CancelTaskRequest, *, context: ClientCallContext | None = None) -> Task Requests the agent to cancel a specific task. async close() -> None Closes the httpx client. async create_task_push_notification_config(request: TaskPushNotificationConfig, *, context: ClientCallContext | None = None) -> TaskPushNotificationConfig Sets or updates the push notification configuration for a specific task. async delete_task_push_notification_config(request: DeleteTaskPushNotificationConfigRequest, *, context: ClientCallContext | None = None) -> None Deletes the push notification configuration for a specific task. async get_extended_agent_card(request: GetExtendedAgentCardRequest, *, context: ClientCallContext | None = None) -> AgentCard Retrieves the agent's card. async get_task(request: GetTaskRequest, *, context: ClientCallContext | None = None) -> Task Retrieves the current state and history of a specific task. async get_task_push_notification_config(request: GetTaskPushNotificationConfigRequest, *, context: ClientCallContext | None = None) -> TaskPushNotificationConfig Retrieves the push notification configuration for a specific task. async list_task_push_notification_configs(request: ListTaskPushNotificationConfigsRequest, *, context: ClientCallContext | None = None) -> ListTaskPushNotificationConfigsResponse Lists push notification configurations for a specific task. async list_tasks(request: ListTasksRequest, *, context: ClientCallContext | None = None) -> ListTasksResponse Retrieves tasks for an agent. async send_message(request: SendMessageRequest, *, context: ClientCallContext | None = None) -> SendMessageResponse Sends a non-streaming message request to the agent. send_message_streaming(request: SendMessageRequest, *, context: ClientCallContext | None = None) -> AsyncGenerator[StreamResponse] Sends a streaming message request to the agent and yields responses as they arrive. subscribe(request: SubscribeToTaskRequest, *, context: ClientCallContext | None = None) -> AsyncGenerator[StreamResponse] Reconnects to get task updates. a2a.client.transports.rest module ********************************* class a2a.client.transports.rest.RestTransport(httpx_client: AsyncClient, agent_card: AgentCard, url: str) Bases: "ClientTransport" A REST transport for the A2A client. async cancel_task(request: CancelTaskRequest, *, context: ClientCallContext | None = None) -> Task Requests the agent to cancel a specific task. async close() -> None Closes the httpx client. async create_task_push_notification_config(request: TaskPushNotificationConfig, *, context: ClientCallContext | None = None) -> TaskPushNotificationConfig Sets or updates the push notification configuration for a specific task. async delete_task_push_notification_config(request: DeleteTaskPushNotificationConfigRequest, *, context: ClientCallContext | None = None) -> None Deletes the push notification configuration for a specific task. async get_extended_agent_card(request: GetExtendedAgentCardRequest, *, context: ClientCallContext | None = None) -> AgentCard Retrieves the Extended AgentCard. async get_task(request: GetTaskRequest, *, context: ClientCallContext | None = None) -> Task Retrieves the current state and history of a specific task. async get_task_push_notification_config(request: GetTaskPushNotificationConfigRequest, *, context: ClientCallContext | None = None) -> TaskPushNotificationConfig Retrieves the push notification configuration for a specific task. async list_task_push_notification_configs(request: ListTaskPushNotificationConfigsRequest, *, context: ClientCallContext | None = None) -> ListTaskPushNotificationConfigsResponse Lists push notification configurations for a specific task. async list_tasks(request: ListTasksRequest, *, context: ClientCallContext | None = None) -> ListTasksResponse Retrieves tasks for an agent. async send_message(request: SendMessageRequest, *, context: ClientCallContext | None = None) -> SendMessageResponse Sends a non-streaming message request to the agent. send_message_streaming(request: SendMessageRequest, *, context: ClientCallContext | None = None) -> AsyncGenerator[StreamResponse] Sends a streaming message request to the agent and yields responses as they arrive. subscribe(request: SubscribeToTaskRequest, *, context: ClientCallContext | None = None) -> AsyncGenerator[StreamResponse] Reconnects to get task updates. a2a.client.transports.tenant_decorator module ********************************************* class a2a.client.transports.tenant_decorator.TenantTransportDecorator(base: ClientTransport, tenant: str) Bases: "ClientTransport" A transport decorator that attaches a tenant to all requests. async cancel_task(request: CancelTaskRequest, *, context: ClientCallContext | None = None) -> Task Requests the agent to cancel a specific task. async close() -> None Closes the transport. async create_task_push_notification_config(request: TaskPushNotificationConfig, *, context: ClientCallContext | None = None) -> TaskPushNotificationConfig Sets or updates the push notification configuration for a specific task. async delete_task_push_notification_config(request: DeleteTaskPushNotificationConfigRequest, *, context: ClientCallContext | None = None) -> None Deletes the push notification configuration for a specific task. async get_extended_agent_card(request: GetExtendedAgentCardRequest, *, context: ClientCallContext | None = None) -> AgentCard Retrieves the Extended AgentCard. async get_task(request: GetTaskRequest, *, context: ClientCallContext | None = None) -> Task Retrieves the current state and history of a specific task. async get_task_push_notification_config(request: GetTaskPushNotificationConfigRequest, *, context: ClientCallContext | None = None) -> TaskPushNotificationConfig Retrieves the push notification configuration for a specific task. async list_task_push_notification_configs(request: ListTaskPushNotificationConfigsRequest, *, context: ClientCallContext | None = None) -> ListTaskPushNotificationConfigsResponse Lists push notification configurations for a specific task. async list_tasks(request: ListTasksRequest, *, context: ClientCallContext | None = None) -> ListTasksResponse Retrieves tasks for an agent. async send_message(request: SendMessageRequest, *, context: ClientCallContext | None = None) -> SendMessageResponse Sends a streaming message request to the agent and yields responses as they arrive. async send_message_streaming(request: SendMessageRequest, *, context: ClientCallContext | None = None) -> AsyncGenerator[StreamResponse] Sends a streaming message request to the agent and yields responses. async subscribe(request: SubscribeToTaskRequest, *, context: ClientCallContext | None = None) -> AsyncGenerator[StreamResponse] Reconnects to get task updates. a2a.client.transports package ***************************** Submodules ========== * a2a.client.transports.base module * "ClientTransport" * "ClientTransport.cancel_task()" * "ClientTransport.close()" * "ClientTransport.create_task_push_notification_config()" * "ClientTransport.delete_task_push_notification_config()" * "ClientTransport.get_extended_agent_card()" * "ClientTransport.get_task()" * "ClientTransport.get_task_push_notification_config()" * "ClientTransport.list_task_push_notification_configs()" * "ClientTransport.list_tasks()" * "ClientTransport.send_message()" * "ClientTransport.send_message_streaming()" * "ClientTransport.subscribe()" * a2a.client.transports.grpc module * "GrpcTransport" * "GrpcTransport.cancel_task()" * "GrpcTransport.close()" * "GrpcTransport.create()" * "GrpcTransport.create_task_push_notification_config()" * "GrpcTransport.delete_task_push_notification_config()" * "GrpcTransport.get_extended_agent_card()" * "GrpcTransport.get_task()" * "GrpcTransport.get_task_push_notification_config()" * "GrpcTransport.list_task_push_notification_configs()" * "GrpcTransport.list_tasks()" * "GrpcTransport.send_message()" * "GrpcTransport.send_message_streaming()" * "GrpcTransport.subscribe()" * a2a.client.transports.http_helpers module * "get_http_args()" * "handle_http_exceptions()" * "send_http_request()" * "send_http_stream_request()" * a2a.client.transports.jsonrpc module * "JsonRpcTransport" * "JsonRpcTransport.cancel_task()" * "JsonRpcTransport.close()" * "JsonRpcTransport.create_task_push_notification_config()" * "JsonRpcTransport.delete_task_push_notification_config()" * "JsonRpcTransport.get_extended_agent_card()" * "JsonRpcTransport.get_task()" * "JsonRpcTransport.get_task_push_notification_config()" * "JsonRpcTransport.list_task_push_notification_configs()" * "JsonRpcTransport.list_tasks()" * "JsonRpcTransport.send_message()" * "JsonRpcTransport.send_message_streaming()" * "JsonRpcTransport.subscribe()" * a2a.client.transports.rest module * "RestTransport" * "RestTransport.cancel_task()" * "RestTransport.close()" * "RestTransport.create_task_push_notification_config()" * "RestTransport.delete_task_push_notification_config()" * "RestTransport.get_extended_agent_card()" * "RestTransport.get_task()" * "RestTransport.get_task_push_notification_config()" * "RestTransport.list_task_push_notification_configs()" * "RestTransport.list_tasks()" * "RestTransport.send_message()" * "RestTransport.send_message_streaming()" * "RestTransport.subscribe()" * a2a.client.transports.tenant_decorator module * "TenantTransportDecorator" * "TenantTransportDecorator.cancel_task()" * "TenantTransportDecorator.close()" * "TenantTransportDecorator.create_task_push_notification_config() " * "TenantTransportDecorator.delete_task_push_notification_config() " * "TenantTransportDecorator.get_extended_agent_card()" * "TenantTransportDecorator.get_task()" * "TenantTransportDecorator.get_task_push_notification_config()" * "TenantTransportDecorator.list_task_push_notification_configs()" * "TenantTransportDecorator.list_tasks()" * "TenantTransportDecorator.send_message()" * "TenantTransportDecorator.send_message_streaming()" * "TenantTransportDecorator.subscribe()" Module contents =============== A2A Client Transports. class a2a.client.transports.ClientTransport Bases: "ABC" Abstract base class for a client transport. abstractmethod async cancel_task(request: CancelTaskRequest, *, context: ClientCallContext | None = None) -> Task Requests the agent to cancel a specific task. abstractmethod async close() -> None Closes the transport. abstractmethod async create_task_push_notification_config(request: TaskPushNotificationConfig, *, context: ClientCallContext | None = None) -> TaskPushNotificationConfig Sets or updates the push notification configuration for a specific task. abstractmethod async delete_task_push_notification_config(request: DeleteTaskPushNotificationConfigRequest, *, context: ClientCallContext | None = None) -> None Deletes the push notification configuration for a specific task. abstractmethod async get_extended_agent_card(request: GetExtendedAgentCardRequest, *, context: ClientCallContext | None = None) -> AgentCard Retrieves the Extended AgentCard. abstractmethod async get_task(request: GetTaskRequest, *, context: ClientCallContext | None = None) -> Task Retrieves the current state and history of a specific task. abstractmethod async get_task_push_notification_config(request: GetTaskPushNotificationConfigRequest, *, context: ClientCallContext | None = None) -> TaskPushNotificationConfig Retrieves the push notification configuration for a specific task. abstractmethod async list_task_push_notification_configs(request: ListTaskPushNotificationConfigsRequest, *, context: ClientCallContext | None = None) -> ListTaskPushNotificationConfigsResponse Lists push notification configurations for a specific task. abstractmethod async list_tasks(request: ListTasksRequest, *, context: ClientCallContext | None = None) -> ListTasksResponse Retrieves tasks for an agent. abstractmethod async send_message(request: SendMessageRequest, *, context: ClientCallContext | None = None) -> SendMessageResponse Sends a non-streaming message request to the agent. abstractmethod async send_message_streaming(request: SendMessageRequest, *, context: ClientCallContext | None = None) -> AsyncGenerator[StreamResponse] Sends a streaming message request to the agent and yields responses as they arrive. abstractmethod async subscribe(request: SubscribeToTaskRequest, *, context: ClientCallContext | None = None) -> AsyncGenerator[StreamResponse] Reconnects to get task updates. class a2a.client.transports.GrpcTransport(channel: Channel, agent_card: AgentCard | None) Bases: "ClientTransport" A gRPC transport for the A2A client. async cancel_task(request: CancelTaskRequest, *, context: ClientCallContext | None = None) -> Task Requests the agent to cancel a specific task. async close() -> None Closes the gRPC channel. classmethod create(card: AgentCard, url: str, config: ClientConfig) -> GrpcTransport Creates a gRPC transport for the A2A client. async create_task_push_notification_config(request: TaskPushNotificationConfig, *, context: ClientCallContext | None = None) -> TaskPushNotificationConfig Sets or updates the push notification configuration for a specific task. async delete_task_push_notification_config(request: DeleteTaskPushNotificationConfigRequest, *, context: ClientCallContext | None = None) -> None Deletes the push notification configuration for a specific task. async get_extended_agent_card(request: GetExtendedAgentCardRequest, *, context: ClientCallContext | None = None) -> AgentCard Retrieves the agent's card. async get_task(request: GetTaskRequest, *, context: ClientCallContext | None = None) -> Task Retrieves the current state and history of a specific task. async get_task_push_notification_config(request: GetTaskPushNotificationConfigRequest, *, context: ClientCallContext | None = None) -> TaskPushNotificationConfig Retrieves the push notification configuration for a specific task. async list_task_push_notification_configs(request: ListTaskPushNotificationConfigsRequest, *, context: ClientCallContext | None = None) -> ListTaskPushNotificationConfigsResponse Lists push notification configurations for a specific task. async list_tasks(request: ListTasksRequest, *, context: ClientCallContext | None = None) -> ListTasksResponse Retrieves tasks for an agent. async send_message(request: SendMessageRequest, *, context: ClientCallContext | None = None) -> SendMessageResponse Sends a non-streaming message request to the agent. send_message_streaming(request: SendMessageRequest, *, context: ClientCallContext | None = None) -> AsyncGenerator[StreamResponse] Sends a streaming message request to the agent and yields responses as they arrive. subscribe(request: SubscribeToTaskRequest, *, context: ClientCallContext | None = None) -> AsyncGenerator[StreamResponse] Reconnects to get task updates. class a2a.client.transports.JsonRpcTransport(httpx_client: AsyncClient, agent_card: AgentCard, url: str) Bases: "ClientTransport" A JSON-RPC transport for the A2A client. async cancel_task(request: CancelTaskRequest, *, context: ClientCallContext | None = None) -> Task Requests the agent to cancel a specific task. async close() -> None Closes the httpx client. async create_task_push_notification_config(request: TaskPushNotificationConfig, *, context: ClientCallContext | None = None) -> TaskPushNotificationConfig Sets or updates the push notification configuration for a specific task. async delete_task_push_notification_config(request: DeleteTaskPushNotificationConfigRequest, *, context: ClientCallContext | None = None) -> None Deletes the push notification configuration for a specific task. async get_extended_agent_card(request: GetExtendedAgentCardRequest, *, context: ClientCallContext | None = None) -> AgentCard Retrieves the agent's card. async get_task(request: GetTaskRequest, *, context: ClientCallContext | None = None) -> Task Retrieves the current state and history of a specific task. async get_task_push_notification_config(request: GetTaskPushNotificationConfigRequest, *, context: ClientCallContext | None = None) -> TaskPushNotificationConfig Retrieves the push notification configuration for a specific task. async list_task_push_notification_configs(request: ListTaskPushNotificationConfigsRequest, *, context: ClientCallContext | None = None) -> ListTaskPushNotificationConfigsResponse Lists push notification configurations for a specific task. async list_tasks(request: ListTasksRequest, *, context: ClientCallContext | None = None) -> ListTasksResponse Retrieves tasks for an agent. async send_message(request: SendMessageRequest, *, context: ClientCallContext | None = None) -> SendMessageResponse Sends a non-streaming message request to the agent. send_message_streaming(request: SendMessageRequest, *, context: ClientCallContext | None = None) -> AsyncGenerator[StreamResponse] Sends a streaming message request to the agent and yields responses as they arrive. subscribe(request: SubscribeToTaskRequest, *, context: ClientCallContext | None = None) -> AsyncGenerator[StreamResponse] Reconnects to get task updates. class a2a.client.transports.RestTransport(httpx_client: AsyncClient, agent_card: AgentCard, url: str) Bases: "ClientTransport" A REST transport for the A2A client. async cancel_task(request: CancelTaskRequest, *, context: ClientCallContext | None = None) -> Task Requests the agent to cancel a specific task. async close() -> None Closes the httpx client. async create_task_push_notification_config(request: TaskPushNotificationConfig, *, context: ClientCallContext | None = None) -> TaskPushNotificationConfig Sets or updates the push notification configuration for a specific task. async delete_task_push_notification_config(request: DeleteTaskPushNotificationConfigRequest, *, context: ClientCallContext | None = None) -> None Deletes the push notification configuration for a specific task. async get_extended_agent_card(request: GetExtendedAgentCardRequest, *, context: ClientCallContext | None = None) -> AgentCard Retrieves the Extended AgentCard. async get_task(request: GetTaskRequest, *, context: ClientCallContext | None = None) -> Task Retrieves the current state and history of a specific task. async get_task_push_notification_config(request: GetTaskPushNotificationConfigRequest, *, context: ClientCallContext | None = None) -> TaskPushNotificationConfig Retrieves the push notification configuration for a specific task. async list_task_push_notification_configs(request: ListTaskPushNotificationConfigsRequest, *, context: ClientCallContext | None = None) -> ListTaskPushNotificationConfigsResponse Lists push notification configurations for a specific task. async list_tasks(request: ListTasksRequest, *, context: ClientCallContext | None = None) -> ListTasksResponse Retrieves tasks for an agent. async send_message(request: SendMessageRequest, *, context: ClientCallContext | None = None) -> SendMessageResponse Sends a non-streaming message request to the agent. send_message_streaming(request: SendMessageRequest, *, context: ClientCallContext | None = None) -> AsyncGenerator[StreamResponse] Sends a streaming message request to the agent and yields responses as they arrive. subscribe(request: SubscribeToTaskRequest, *, context: ClientCallContext | None = None) -> AsyncGenerator[StreamResponse] Reconnects to get task updates. a2a.client package ****************** Subpackages =========== * a2a.client.auth package * Submodules * a2a.client.auth.credentials module * "CredentialService" * "InMemoryContextCredentialStore" * a2a.client.auth.interceptor module * "AuthInterceptor" * Module contents * "AuthInterceptor" * "AuthInterceptor.after()" * "AuthInterceptor.before()" * "CredentialService" * "CredentialService.get_credentials()" * "InMemoryContextCredentialStore" * "InMemoryContextCredentialStore.get_credentials()" * "InMemoryContextCredentialStore.set_credentials()" * a2a.client.transports package * Submodules * a2a.client.transports.base module * "ClientTransport" * a2a.client.transports.grpc module * "GrpcTransport" * a2a.client.transports.http_helpers module * "get_http_args()" * "handle_http_exceptions()" * "send_http_request()" * "send_http_stream_request()" * a2a.client.transports.jsonrpc module * "JsonRpcTransport" * a2a.client.transports.rest module * "RestTransport" * a2a.client.transports.tenant_decorator module * "TenantTransportDecorator" * Module contents * "ClientTransport" * "ClientTransport.cancel_task()" * "ClientTransport.close()" * "ClientTransport.create_task_push_notification_config()" * "ClientTransport.delete_task_push_notification_config()" * "ClientTransport.get_extended_agent_card()" * "ClientTransport.get_task()" * "ClientTransport.get_task_push_notification_config()" * "ClientTransport.list_task_push_notification_configs()" * "ClientTransport.list_tasks()" * "ClientTransport.send_message()" * "ClientTransport.send_message_streaming()" * "ClientTransport.subscribe()" * "GrpcTransport" * "GrpcTransport.cancel_task()" * "GrpcTransport.close()" * "GrpcTransport.create()" * "GrpcTransport.create_task_push_notification_config()" * "GrpcTransport.delete_task_push_notification_config()" * "GrpcTransport.get_extended_agent_card()" * "GrpcTransport.get_task()" * "GrpcTransport.get_task_push_notification_config()" * "GrpcTransport.list_task_push_notification_configs()" * "GrpcTransport.list_tasks()" * "GrpcTransport.send_message()" * "GrpcTransport.send_message_streaming()" * "GrpcTransport.subscribe()" * "JsonRpcTransport" * "JsonRpcTransport.cancel_task()" * "JsonRpcTransport.close()" * "JsonRpcTransport.create_task_push_notification_config()" * "JsonRpcTransport.delete_task_push_notification_config()" * "JsonRpcTransport.get_extended_agent_card()" * "JsonRpcTransport.get_task()" * "JsonRpcTransport.get_task_push_notification_config()" * "JsonRpcTransport.list_task_push_notification_configs()" * "JsonRpcTransport.list_tasks()" * "JsonRpcTransport.send_message()" * "JsonRpcTransport.send_message_streaming()" * "JsonRpcTransport.subscribe()" * "RestTransport" * "RestTransport.cancel_task()" * "RestTransport.close()" * "RestTransport.create_task_push_notification_config()" * "RestTransport.delete_task_push_notification_config()" * "RestTransport.get_extended_agent_card()" * "RestTransport.get_task()" * "RestTransport.get_task_push_notification_config()" * "RestTransport.list_task_push_notification_configs()" * "RestTransport.list_tasks()" * "RestTransport.send_message()" * "RestTransport.send_message_streaming()" * "RestTransport.subscribe()" Submodules ========== * a2a.client.base_client module * "BaseClient" * "BaseClient.cancel_task()" * "BaseClient.close()" * "BaseClient.create_task_push_notification_config()" * "BaseClient.delete_task_push_notification_config()" * "BaseClient.get_extended_agent_card()" * "BaseClient.get_task()" * "BaseClient.get_task_push_notification_config()" * "BaseClient.list_task_push_notification_configs()" * "BaseClient.list_tasks()" * "BaseClient.send_message()" * "BaseClient.subscribe()" * a2a.client.card_resolver module * "A2ACardResolver" * "A2ACardResolver.get_agent_card()" * "parse_agent_card()" * a2a.client.client module * "Client" * "Client.add_interceptor()" * "Client.cancel_task()" * "Client.close()" * "Client.create_task_push_notification_config()" * "Client.delete_task_push_notification_config()" * "Client.get_extended_agent_card()" * "Client.get_task()" * "Client.get_task_push_notification_config()" * "Client.list_task_push_notification_configs()" * "Client.list_tasks()" * "Client.send_message()" * "Client.subscribe()" * "ClientCallContext" * "ClientCallContext.model_config" * "ClientCallContext.service_parameters" * "ClientCallContext.state" * "ClientCallContext.timeout" * "ClientConfig" * "ClientConfig.accepted_output_modes" * "ClientConfig.grpc_channel_factory" * "ClientConfig.httpx_client" * "ClientConfig.polling" * "ClientConfig.push_notification_config" * "ClientConfig.streaming" * "ClientConfig.supported_protocol_bindings" * "ClientConfig.use_client_preference" * a2a.client.client_factory module * "ClientFactory" * "ClientFactory.create()" * "ClientFactory.create_from_url()" * "ClientFactory.register()" * "create_client()" * "minimal_agent_card()" * a2a.client.errors module * "A2AClientError" * "A2AClientTimeoutError" * "AgentCardResolutionError" * a2a.client.interceptors module * "AfterArgs" * "AfterArgs.agent_card" * "AfterArgs.context" * "AfterArgs.early_return" * "AfterArgs.method" * "AfterArgs.result" * "BeforeArgs" * "BeforeArgs.agent_card" * "BeforeArgs.context" * "BeforeArgs.early_return" * "BeforeArgs.input" * "BeforeArgs.method" * "ClientCallInterceptor" * "ClientCallInterceptor.after()" * "ClientCallInterceptor.before()" * a2a.client.optionals module * a2a.client.service_parameters module * "ServiceParametersFactory" * "ServiceParametersFactory.create()" * "ServiceParametersFactory.create_from()" * "with_a2a_extensions()" Module contents =============== Client-side components for interacting with an A2A agent. class a2a.client.A2ACardResolver(httpx_client: AsyncClient, base_url: str, agent_card_path: str = '/.well-known/agent-card.json') Bases: "object" Agent Card resolver. async get_agent_card(relative_card_path: str | None = None, http_kwargs: dict[str, Any] | None = None, signature_verifier: Callable[[AgentCard], None] | None = None) -> AgentCard Fetches an agent card from a specified path relative to the base_url. If relative_card_path is None, it defaults to the resolver's configured agent_card_path (for the public agent card). Parameters: * **relative_card_path** -- Optional path to the agent card endpoint, relative to the base URL. If None, uses the default public agent card path. Use *'/'* for an empty path. * **http_kwargs** -- Optional dictionary of keyword arguments to pass to the underlying httpx.get request. * **signature_verifier** -- A callable used to verify the agent card's signatures. Returns: An *AgentCard* object representing the agent's capabilities. Raises: **AgentCardResolutionError** -- If an HTTP error occurs during the request, if the response body cannot be decoded as JSON, or if it cannot be validated against the AgentCard schema. exception a2a.client.A2AClientError(message: str | None = None, data: dict | None = None) Bases: "A2AError" Base exception for A2A Client errors. exception a2a.client.A2AClientTimeoutError(message: str | None = None, data: dict | None = None) Bases: "A2AClientError" Exception for timeout errors during a request. exception a2a.client.AgentCardResolutionError(message: str, status_code: int | None = None) Bases: "A2AClientError" Exception raised when an agent card cannot be resolved. class a2a.client.AuthInterceptor(credential_service: CredentialService) Bases: "ClientCallInterceptor" An interceptor that automatically adds authentication details to requests. Based on the agent's security schemes. async after(args: AfterArgs) -> None Invoked after the method is executed. async before(args: BeforeArgs) -> None Applies authentication headers to the request if credentials are available. class a2a.client.BaseClient(card: AgentCard, config: ClientConfig, transport: ClientTransport, interceptors: list[ClientCallInterceptor]) Bases: "Client" Base implementation of the A2A client, containing transport- independent logic. async cancel_task(request: CancelTaskRequest, *, context: ClientCallContext | None = None) -> Task Requests the agent to cancel a specific task. Parameters: * **request** -- The *CancelTaskRequest* object specifying the task ID. * **context** -- Optional client call context. Returns: A *Task* object containing the updated task status. async close() -> None Closes the underlying transport. async create_task_push_notification_config(request: TaskPushNotificationConfig, *, context: ClientCallContext | None = None) -> TaskPushNotificationConfig Sets or updates the push notification configuration for a specific task. Parameters: * **request** -- The *TaskPushNotificationConfig* object with the new configuration. * **context** -- Optional client call context. Returns: The created or updated *TaskPushNotificationConfig* object. async delete_task_push_notification_config(request: DeleteTaskPushNotificationConfigRequest, *, context: ClientCallContext | None = None) -> None Deletes the push notification configuration for a specific task. Parameters: * **request** -- The *DeleteTaskPushNotificationConfigRequest* object specifying the request. * **context** -- Optional client call context. async get_extended_agent_card(request: GetExtendedAgentCardRequest, *, context: ClientCallContext | None = None, signature_verifier: Callable[[AgentCard], None] | None = None) -> AgentCard Retrieves the agent's card. This will fetch the authenticated card if necessary and update the client's internal state with the new card. Parameters: * **request** -- The *GetExtendedAgentCardRequest* object specifying the request. * **context** -- Optional client call context. * **signature_verifier** -- A callable used to verify the agent card's signatures. Returns: The *AgentCard* for the agent. async get_task(request: GetTaskRequest, *, context: ClientCallContext | None = None) -> Task Retrieves the current state and history of a specific task. Parameters: * **request** -- The *GetTaskRequest* object specifying the task ID. * **context** -- Optional client call context. Returns: A *Task* object representing the current state of the task. async get_task_push_notification_config(request: GetTaskPushNotificationConfigRequest, *, context: ClientCallContext | None = None) -> TaskPushNotificationConfig Retrieves the push notification configuration for a specific task. Parameters: * **request** -- The *GetTaskPushNotificationConfigParams* object specifying the task. * **context** -- Optional client call context. Returns: A *TaskPushNotificationConfig* object containing the configuration. async list_task_push_notification_configs(request: ListTaskPushNotificationConfigsRequest, *, context: ClientCallContext | None = None) -> ListTaskPushNotificationConfigsResponse Lists push notification configurations for a specific task. Parameters: * **request** -- The *ListTaskPushNotificationConfigsRequest* object specifying the request. * **context** -- Optional client call context. Returns: A *ListTaskPushNotificationConfigsResponse* object. async list_tasks(request: ListTasksRequest, *, context: ClientCallContext | None = None) -> ListTasksResponse Retrieves tasks for an agent. async send_message(request: SendMessageRequest, *, context: ClientCallContext | None = None) -> AsyncIterator[StreamResponse] Sends a message to the agent. This method handles both streaming and non-streaming (polling) interactions based on the client configuration and agent capabilities. It will yield events as they are received from the agent. Parameters: * **request** -- The message to send to the agent. * **context** -- Optional client call context. Yields: An async iterator of *StreamResponse* async subscribe(request: SubscribeToTaskRequest, *, context: ClientCallContext | None = None) -> AsyncIterator[StreamResponse] Resubscribes to a task's event stream. This is only available if both the client and server support streaming. Parameters: * **request** -- Parameters to identify the task to resubscribe to. * **context** -- Optional client call context. Yields: An async iterator of *StreamResponse* objects. Raises: **NotImplementedError** -- If streaming is not supported by the client or server. class a2a.client.Client(interceptors: list[ClientCallInterceptor] | None = None) Bases: "ABC" Abstract base class defining the interface for an A2A client. This class provides a standard set of methods for interacting with an A2A agent, regardless of the underlying transport protocol (e.g., gRPC, JSON-RPC). It supports sending messages, managing tasks, and handling event streams. async add_interceptor(interceptor: ClientCallInterceptor) -> None Attaches additional interceptors to the *Client*. abstractmethod async cancel_task(request: CancelTaskRequest, *, context: ClientCallContext | None = None) -> Task Requests the agent to cancel a specific task. abstractmethod async close() -> None Closes the client and releases any underlying resources. abstractmethod async create_task_push_notification_config(request: TaskPushNotificationConfig, *, context: ClientCallContext | None = None) -> TaskPushNotificationConfig Sets or updates the push notification configuration for a specific task. abstractmethod async delete_task_push_notification_config(request: DeleteTaskPushNotificationConfigRequest, *, context: ClientCallContext | None = None) -> None Deletes the push notification configuration for a specific task. abstractmethod async get_extended_agent_card(request: GetExtendedAgentCardRequest, *, context: ClientCallContext | None = None, signature_verifier: Callable[[AgentCard], None] | None = None) -> AgentCard Retrieves the agent's card. abstractmethod async get_task(request: GetTaskRequest, *, context: ClientCallContext | None = None) -> Task Retrieves the current state and history of a specific task. abstractmethod async get_task_push_notification_config(request: GetTaskPushNotificationConfigRequest, *, context: ClientCallContext | None = None) -> TaskPushNotificationConfig Retrieves the push notification configuration for a specific task. abstractmethod async list_task_push_notification_configs(request: ListTaskPushNotificationConfigsRequest, *, context: ClientCallContext | None = None) -> ListTaskPushNotificationConfigsResponse Lists push notification configurations for a specific task. abstractmethod async list_tasks(request: ListTasksRequest, *, context: ClientCallContext | None = None) -> ListTasksResponse Retrieves tasks for an agent. abstractmethod async send_message(request: SendMessageRequest, *, context: ClientCallContext | None = None) -> AsyncIterator[StreamResponse] Sends a message to the server. This will automatically use the streaming or non-streaming approach as supported by the server and the client config. Client will aggregate update events and return an iterator of *StreamResponse*. abstractmethod async subscribe(request: SubscribeToTaskRequest, *, context: ClientCallContext | None = None) -> AsyncIterator[StreamResponse] Resubscribes to a task's event stream. class a2a.client.ClientCallContext(*, state: MutableMapping[str, ~typing.Any]=, timeout: float | None = None, service_parameters: dict[str, str] | None=None) Bases: "BaseModel" A context passed with each client call, allowing for call-specific. configuration and data passing. Such as authentication details or request deadlines. model_config = {} Configuration for the model, should be a dictionary conforming to [*ConfigDict*][pydantic.config.ConfigDict]. service_parameters: dict[str, str] | None state: MutableMapping[str, Any] timeout: float | None class a2a.client.ClientCallInterceptor Bases: "ABC" An abstract base class for client-side call interceptors. Interceptors can inspect and modify requests before they are sent, which is ideal for concerns like authentication, logging, or tracing. abstractmethod async after(args: AfterArgs) -> None Invoked after transport method. abstractmethod async before(args: BeforeArgs) -> None Invoked before transport method. class a2a.client.ClientConfig(streaming: bool = True, polling: bool = False, httpx_client: ~httpx.AsyncClient | None = None, grpc_channel_factory: ~collections.abc.Callable[[str], ~grpc.aio._base_channel.Channel] | None = None, supported_protocol_bindings: list[str] = , use_client_preference: bool = False, accepted_output_modes: list[str] = , push_notification_config: ~a2a_pb2.TaskPushNotificationConfig | None = None) Bases: "object" Configuration class for the A2AClient Factory. accepted_output_modes: list[str] The set of accepted output modes for the client. grpc_channel_factory: Callable[[str], Channel] | None = None Generates a grpc connection channel for a given url. httpx_client: AsyncClient | None = None Http client to use to connect to agent. polling: bool = False send. It is the callers job to check if the response is completed and if not run a polling loop. Type: Whether client prefers to poll for updates from message push_notification_config: TaskPushNotificationConfig | None = None Push notification configuration to use for every request. streaming: bool = True Whether client supports streaming supported_protocol_bindings: list[str] Ordered list of transports for connecting to agent (in order of preference). Empty implies JSONRPC only. This is a string type to allow custom transports to exist in closed ecosystems. use_client_preference: bool = False Whether to use client transport preferences over server preferences. Recommended to use server preferences in most situations. class a2a.client.ClientFactory(config: ClientConfig | None = None) Bases: "object" Factory for creating clients that communicate with A2A agents. The factory is configured with a *ClientConfig* and optionally custom transport producers registered via *register*. Example usage: factory = ClientFactory(config) # Optionally register custom transport implementations factory.register('my_custom_transport', custom_transport_producer) # Create a client from an AgentCard client = factory.create(card, interceptors) # Or resolve an AgentCard from a URL and create a client client = await factory.create_from_url('https://example.com') The client can be used consistently regardless of the transport. This aligns the client configuration with the server's capabilities. create(card: AgentCard, interceptors: list[ClientCallInterceptor] | None = None) -> Client Create a new *Client* for the provided *AgentCard*. Parameters: * **card** -- An *AgentCard* defining the characteristics of the agent. * **interceptors** -- A list of interceptors to use for each request. These are used for things like attaching credentials or http headers to all outbound requests. Returns: A *Client* object. Raises: * **If there is no valid matching**** of ****the client configuration with the** -- * **server configuration****, ****a ValueError is raised.** -- async create_from_url(url: str, interceptors: list[ClientCallInterceptor] | None = None, relative_card_path: str | None = None, resolver_http_kwargs: dict[str, Any] | None = None, signature_verifier: Callable[[AgentCard], None] | None = None) -> Client Create a *Client* by resolving an *AgentCard* from a URL. Resolves the agent card from the given URL using the factory's configured httpx client, then creates a client via *create*. If the agent card is already available, use *create* directly instead. Parameters: * **url** -- The base URL of the agent. The agent card will be fetched from */.well-known/agent-card.json* by default. * **interceptors** -- A list of interceptors to use for each request. These are used for things like attaching credentials or http headers to all outbound requests. * **relative_card_path** -- The relative path when resolving the agent card. See *A2ACardResolver.get_agent_card* for details. * **resolver_http_kwargs** -- Dictionary of arguments to provide to the httpx client when resolving the agent card. * **signature_verifier** -- A callable used to verify the agent card's signatures. Returns: A *Client* object. register(label: str, generator: Callable[[AgentCard, str, ClientConfig], ClientTransport]) -> None Register a new transport producer for a given transport label. class a2a.client.CredentialService Bases: "ABC" An abstract service for retrieving credentials. abstractmethod async get_credentials(security_scheme_name: str, context: ClientCallContext | None) -> str | None Retrieves a credential (e.g., token) for a security scheme. class a2a.client.InMemoryContextCredentialStore Bases: "CredentialService" A simple in-memory store for session-keyed credentials. This class uses the 'sessionId' from the ClientCallContext state to store and retrieve credentials... async get_credentials(security_scheme_name: str, context: ClientCallContext | None) -> str | None Retrieves credentials from the in-memory store. Parameters: * **security_scheme_name** -- The name of the security scheme. * **context** -- The client call context. Returns: The credential string, or None if not found. async set_credentials(session_id: str, security_scheme_name: str, credential: str) -> None Method to populate the store. async a2a.client.create_client(agent: str | AgentCard, client_config: ClientConfig | None = None, interceptors: list[ClientCallInterceptor] | None = None, relative_card_path: str | None = None, resolver_http_kwargs: dict[str, Any] | None = None, signature_verifier: Callable[[AgentCard], None] | None = None) -> Client Create a *Client* for an agent from a URL or *AgentCard*. Convenience function that constructs a *ClientFactory* internally. For reusing a factory across multiple agents or registering custom transports, use *ClientFactory* directly instead. Parameters: * **agent** -- The base URL of the agent, or an *AgentCard* to use directly. * **client_config** -- Optional *ClientConfig*. A default config is created if not provided. * **interceptors** -- A list of interceptors to use for each request. * **relative_card_path** -- The relative path when resolving the agent card. Only used when *agent* is a URL. * **resolver_http_kwargs** -- Dictionary of arguments to provide to the httpx client when resolving the agent card. * **signature_verifier** -- A callable used to verify the agent card's signatures. Returns: A *Client* object. a2a.client.minimal_agent_card(url: str, transports: list[str] | None = None) -> AgentCard Generates a minimal card to simplify bootstrapping client creation. This minimal card is not viable itself to interact with the remote agent. Instead this is a shorthand way to take a known url and transport option and interact with the get card endpoint of the agent server to get the correct agent card. This pattern is necessary for gRPC based card access as typically these servers won't expose a well known path card. a2a.compat package ****************** Subpackages =========== * a2a.compat.v0_3 package * Submodules * a2a.compat.v0_3.a2a_v0_3_pb2 module * a2a.compat.v0_3.a2a_v0_3_pb2_grpc module * "A2AService" * "A2AServiceServicer" * "A2AServiceStub" * "add_A2AServiceServicer_to_server()" * a2a.compat.v0_3.context_builders module * "V03GrpcServerCallContextBuilder" * "V03ServerCallContextBuilder" * a2a.compat.v0_3.conversions module * "to_compat_agent_capabilities()" * "to_compat_agent_card()" * "to_compat_agent_card_signature()" * "to_compat_agent_extension()" * "to_compat_agent_interface()" * "to_compat_agent_provider()" * "to_compat_agent_skill()" * "to_compat_artifact()" * "to_compat_authentication_info()" * "to_compat_cancel_task_request()" * "to_compat_create_task_push_notification_config_request()" * "to_compat_delete_task_push_notification_config_request()" * "to_compat_get_extended_agent_card_request()" * "to_compat_get_task_push_notification_config_request()" * "to_compat_get_task_request()" * "to_compat_list_task_push_notification_config_request()" * "to_compat_list_task_push_notification_config_response()" * "to_compat_message()" * "to_compat_oauth_flows()" * "to_compat_part()" * "to_compat_push_notification_config()" * "to_compat_security_requirement()" * "to_compat_security_scheme()" * "to_compat_send_message_configuration()" * "to_compat_send_message_request()" * "to_compat_send_message_response()" * "to_compat_stream_response()" * "to_compat_subscribe_to_task_request()" * "to_compat_task()" * "to_compat_task_artifact_update_event()" * "to_compat_task_push_notification_config()" * "to_compat_task_status()" * "to_compat_task_status_update_event()" * "to_core_agent_capabilities()" * "to_core_agent_card()" * "to_core_agent_card_signature()" * "to_core_agent_extension()" * "to_core_agent_interface()" * "to_core_agent_provider()" * "to_core_agent_skill()" * "to_core_artifact()" * "to_core_authentication_info()" * "to_core_cancel_task_request()" * "to_core_create_task_push_notification_config_request()" * "to_core_delete_task_push_notification_config_request()" * "to_core_get_extended_agent_card_request()" * "to_core_get_task_push_notification_config_request()" * "to_core_get_task_request()" * "to_core_list_task_push_notification_config_request()" * "to_core_list_task_push_notification_config_response()" * "to_core_message()" * "to_core_oauth_flows()" * "to_core_part()" * "to_core_push_notification_config()" * "to_core_security_requirement()" * "to_core_security_scheme()" * "to_core_send_message_configuration()" * "to_core_send_message_request()" * "to_core_send_message_response()" * "to_core_stream_response()" * "to_core_subscribe_to_task_request()" * "to_core_task()" * "to_core_task_artifact_update_event()" * "to_core_task_push_notification_config()" * "to_core_task_status()" * "to_core_task_status_update_event()" * a2a.compat.v0_3.extension_headers module * "add_legacy_extension_header()" * a2a.compat.v0_3.grpc_handler module * "CompatGrpcHandler" * a2a.compat.v0_3.grpc_transport module * "CompatGrpcTransport" * a2a.compat.v0_3.jsonrpc_adapter module * "JSONRPC03Adapter" * a2a.compat.v0_3.jsonrpc_transport module * "CompatJsonRpcTransport" * a2a.compat.v0_3.model_conversions module * "compat_push_notification_config_model_to_core()" * "compat_task_model_to_core()" * "core_to_compat_push_notification_config_model()" * "core_to_compat_task_model()" * a2a.compat.v0_3.proto_utils module * "FromProto" * "ToProto" * "dict_to_struct()" * "make_dict_serializable()" * "normalize_large_integers_to_strings()" * "parse_string_integers_in_dict()" * a2a.compat.v0_3.request_handler module * "RequestHandler03" * a2a.compat.v0_3.rest_adapter module * "REST03Adapter" * a2a.compat.v0_3.rest_handler module * "REST03Handler" * a2a.compat.v0_3.rest_transport module * "CompatRestTransport" * a2a.compat.v0_3.types module * "A2A" * "A2AError" * "A2ARequest" * "APIKeySecurityScheme" * "AgentCapabilities" * "AgentCard" * "AgentCardSignature" * "AgentExtension" * "AgentInterface" * "AgentProvider" * "AgentSkill" * "Artifact" * "AuthenticatedExtendedCardNotConfiguredError" * "AuthorizationCodeOAuthFlow" * "CancelTaskRequest" * "CancelTaskResponse" * "CancelTaskSuccessResponse" * "ClientCredentialsOAuthFlow" * "ContentTypeNotSupportedError" * "DataPart" * "DeleteTaskPushNotificationConfigParams" * "DeleteTaskPushNotificationConfigRequest" * "DeleteTaskPushNotificationConfigResponse" * "DeleteTaskPushNotificationConfigSuccessResponse" * "FileBase" * "FilePart" * "FileWithBytes" * "FileWithUri" * "GetAuthenticatedExtendedCardRequest" * "GetAuthenticatedExtendedCardResponse" * "GetAuthenticatedExtendedCardSuccessResponse" * "GetTaskPushNotificationConfigParams" * "GetTaskPushNotificationConfigRequest" * "GetTaskPushNotificationConfigResponse" * "GetTaskPushNotificationConfigSuccessResponse" * "GetTaskRequest" * "GetTaskResponse" * "GetTaskSuccessResponse" * "HTTPAuthSecurityScheme" * "ImplicitOAuthFlow" * "In" * "InternalError" * "InvalidAgentResponseError" * "InvalidParamsError" * "InvalidRequestError" * "JSONParseError" * "JSONRPCError" * "JSONRPCErrorResponse" * "JSONRPCMessage" * "JSONRPCRequest" * "JSONRPCResponse" * "JSONRPCSuccessResponse" * "ListTaskPushNotificationConfigParams" * "ListTaskPushNotificationConfigRequest" * "ListTaskPushNotificationConfigResponse" * "ListTaskPushNotificationConfigSuccessResponse" * "Message" * "MessageSendConfiguration" * "MessageSendParams" * "MethodNotFoundError" * "MutualTLSSecurityScheme" * "OAuth2SecurityScheme" * "OAuthFlows" * "OpenIdConnectSecurityScheme" * "Part" * "PartBase" * "PasswordOAuthFlow" * "PushNotificationAuthenticationInfo" * "PushNotificationConfig" * "PushNotificationNotSupportedError" * "Role" * "SecurityScheme" * "SecuritySchemeBase" * "SendMessageRequest" * "SendMessageResponse" * "SendMessageSuccessResponse" * "SendStreamingMessageRequest" * "SendStreamingMessageResponse" * "SendStreamingMessageSuccessResponse" * "SetTaskPushNotificationConfigRequest" * "SetTaskPushNotificationConfigResponse" * "SetTaskPushNotificationConfigSuccessResponse" * "Task" * "TaskArtifactUpdateEvent" * "TaskIdParams" * "TaskNotCancelableError" * "TaskNotFoundError" * "TaskPushNotificationConfig" * "TaskQueryParams" * "TaskResubscriptionRequest" * "TaskState" * "TaskStatus" * "TaskStatusUpdateEvent" * "TextPart" * "TransportProtocol" * "UnsupportedOperationError" * a2a.compat.v0_3.versions module * "is_legacy_version()" * Module contents Module contents =============== a2a.compat.v0_3.a2a_v0_3_pb2 module *********************************** Generated protocol buffer code. a2a.compat.v0_3.a2a_v0_3_pb2_grpc module **************************************** Client and server classes corresponding to protobuf-defined services. class a2a.compat.v0_3.a2a_v0_3_pb2_grpc.A2AService Bases: "object" A2AService defines the gRPC version of the A2A protocol. This has a slightly different shape than the JSONRPC version to better conform to AIP-127, where appropriate. The nouns are AgentCard, Message, Task and TaskPushNotificationConfig. - Messages are not a standard resource so there is no get/delete/update/list interface, only a send and stream custom methods. - Tasks have a get interface and custom cancel and subscribe methods. - TaskPushNotificationConfig are a resource whose parent is a task. They have get, list and create methods. - AgentCard is a static resource with only a get method. static CancelTask(request, target, options=(), channel_credentials=None, call_credentials=None, insecure=False, compression=None, wait_for_ready=None, timeout=None, metadata=None) static CreateTaskPushNotificationConfig(request, target, options=(), channel_credentials=None, call_credentials=None, insecure=False, compression=None, wait_for_ready=None, timeout=None, metadata=None) static DeleteTaskPushNotificationConfig(request, target, options=(), channel_credentials=None, call_credentials=None, insecure=False, compression=None, wait_for_ready=None, timeout=None, metadata=None) static GetAgentCard(request, target, options=(), channel_credentials=None, call_credentials=None, insecure=False, compression=None, wait_for_ready=None, timeout=None, metadata=None) static GetTask(request, target, options=(), channel_credentials=None, call_credentials=None, insecure=False, compression=None, wait_for_ready=None, timeout=None, metadata=None) static GetTaskPushNotificationConfig(request, target, options=(), channel_credentials=None, call_credentials=None, insecure=False, compression=None, wait_for_ready=None, timeout=None, metadata=None) static ListTaskPushNotificationConfig(request, target, options=(), channel_credentials=None, call_credentials=None, insecure=False, compression=None, wait_for_ready=None, timeout=None, metadata=None) static SendMessage(request, target, options=(), channel_credentials=None, call_credentials=None, insecure=False, compression=None, wait_for_ready=None, timeout=None, metadata=None) static SendStreamingMessage(request, target, options=(), channel_credentials=None, call_credentials=None, insecure=False, compression=None, wait_for_ready=None, timeout=None, metadata=None) static TaskSubscription(request, target, options=(), channel_credentials=None, call_credentials=None, insecure=False, compression=None, wait_for_ready=None, timeout=None, metadata=None) class a2a.compat.v0_3.a2a_v0_3_pb2_grpc.A2AServiceServicer Bases: "object" A2AService defines the gRPC version of the A2A protocol. This has a slightly different shape than the JSONRPC version to better conform to AIP-127, where appropriate. The nouns are AgentCard, Message, Task and TaskPushNotificationConfig. - Messages are not a standard resource so there is no get/delete/update/list interface, only a send and stream custom methods. - Tasks have a get interface and custom cancel and subscribe methods. - TaskPushNotificationConfig are a resource whose parent is a task. They have get, list and create methods. - AgentCard is a static resource with only a get method. CancelTask(request, context) Cancel a task from the agent. If supported one should expect no more task updates for the task. CreateTaskPushNotificationConfig(request, context) Set a push notification config for a task. DeleteTaskPushNotificationConfig(request, context) Delete a push notification config for a task. GetAgentCard(request, context) GetAgentCard returns the agent card for the agent. GetTask(request, context) Get the current state of a task from the agent. GetTaskPushNotificationConfig(request, context) Get a push notification config for a task. ListTaskPushNotificationConfig(request, context) Get a list of push notifications configured for a task. SendMessage(request, context) Send a message to the agent. This is a blocking call that will return the task once it is completed, or a LRO if requested. SendStreamingMessage(request, context) SendStreamingMessage is a streaming call that will return a stream of task update events until the Task is in an interrupted or terminal state. TaskSubscription(request, context) TaskSubscription is a streaming call that will return a stream of task update events. This attaches the stream to an existing in process task. If the task is complete the stream will return the completed task (like GetTask) and close the stream. class a2a.compat.v0_3.a2a_v0_3_pb2_grpc.A2AServiceStub(channel) Bases: "object" A2AService defines the gRPC version of the A2A protocol. This has a slightly different shape than the JSONRPC version to better conform to AIP-127, where appropriate. The nouns are AgentCard, Message, Task and TaskPushNotificationConfig. - Messages are not a standard resource so there is no get/delete/update/list interface, only a send and stream custom methods. - Tasks have a get interface and custom cancel and subscribe methods. - TaskPushNotificationConfig are a resource whose parent is a task. They have get, list and create methods. - AgentCard is a static resource with only a get method. a2a.compat.v0_3.a2a_v0_3_pb2_grpc.add_A2AServiceServicer_to_server(servicer, server) a2a.compat.v0_3.context_builders module *************************************** Context builders that add v0.3 backwards-compatibility for extensions. The current spec uses "A2A-Extensions" (RFC 6648, no "X-" prefix). v0.3 clients still send the old "X-A2A-Extensions" name, so the v0.3 compat adapters wrap the default builders with these classes to recognize both names. class a2a.compat.v0_3.context_builders.V03GrpcServerCallContextBuilder(inner: GrpcServerCallContextBuilder) Bases: "object" Wraps a GrpcServerCallContextBuilder to also accept the legacy metadata. Recognizes the v0.3 "X-A2A-Extensions" gRPC metadata key in addition to the spec "A2A-Extensions". build(context: grpc.aio.ServicerContext) -> ServerCallContext Builds a ServerCallContext, merging legacy extension metadata. class a2a.compat.v0_3.context_builders.V03ServerCallContextBuilder(inner: ServerCallContextBuilder) Bases: "object" Wraps a ServerCallContextBuilder to also accept the legacy header. Recognizes the v0.3 "X-A2A-Extensions" HTTP header in addition to the spec "A2A-Extensions". build(request: Request) -> ServerCallContext Builds a ServerCallContext, merging legacy extension headers. a2a.compat.v0_3.conversions module ********************************** a2a.compat.v0_3.conversions.to_compat_agent_capabilities(core_cap: AgentCapabilities) -> AgentCapabilities Convert agent capabilities to v0.3 compat type. a2a.compat.v0_3.conversions.to_compat_agent_card(core_card: AgentCard) -> AgentCard Convert agent card to v0.3 compat type. a2a.compat.v0_3.conversions.to_compat_agent_card_signature(core_sig: AgentCardSignature) -> AgentCardSignature Convert agent card signature to v0.3 compat type. a2a.compat.v0_3.conversions.to_compat_agent_extension(core_ext: AgentExtension) -> AgentExtension Convert agent extension to v0.3 compat type. a2a.compat.v0_3.conversions.to_compat_agent_interface(core_interface: AgentInterface) -> AgentInterface Convert agent interface to v0.3 compat type. a2a.compat.v0_3.conversions.to_compat_agent_provider(core_provider: AgentProvider) -> AgentProvider Convert agent provider to v0.3 compat type. a2a.compat.v0_3.conversions.to_compat_agent_skill(core_skill: AgentSkill) -> AgentSkill Convert agent skill to v0.3 compat type. a2a.compat.v0_3.conversions.to_compat_artifact(core_artifact: Artifact) -> Artifact Convert artifact to v0.3 compat type. a2a.compat.v0_3.conversions.to_compat_authentication_info(core_auth: AuthenticationInfo) -> PushNotificationAuthenticationInfo Convert authentication info to v0.3 compat type. a2a.compat.v0_3.conversions.to_compat_cancel_task_request(core_req: CancelTaskRequest, request_id: str | int) -> CancelTaskRequest Convert cancel task request to v0.3 compat type. a2a.compat.v0_3.conversions.to_compat_create_task_push_notification_config_request(core_req: TaskPushNotificationConfig, request_id: str | int) -> SetTaskPushNotificationConfigRequest Convert create task push notification config request to v0.3 compat type. a2a.compat.v0_3.conversions.to_compat_delete_task_push_notification_config_request(core_req: DeleteTaskPushNotificationConfigRequest, request_id: str | int) -> DeleteTaskPushNotificationConfigRequest Convert delete task push notification config request to v0.3 compat type. a2a.compat.v0_3.conversions.to_compat_get_extended_agent_card_request(core_req: GetExtendedAgentCardRequest, request_id: str | int) -> GetAuthenticatedExtendedCardRequest Convert get extended agent card request to v0.3 compat type. a2a.compat.v0_3.conversions.to_compat_get_task_push_notification_config_request(core_req: GetTaskPushNotificationConfigRequest, request_id: str | int) -> GetTaskPushNotificationConfigRequest Convert get task push notification config request to v0.3 compat type. a2a.compat.v0_3.conversions.to_compat_get_task_request(core_req: GetTaskRequest, request_id: str | int) -> GetTaskRequest Convert get task request to v0.3 compat type. a2a.compat.v0_3.conversions.to_compat_list_task_push_notification_config_request(core_req: ListTaskPushNotificationConfigsRequest, request_id: str | int) -> ListTaskPushNotificationConfigRequest Convert list task push notification config request to v0.3 compat type. a2a.compat.v0_3.conversions.to_compat_list_task_push_notification_config_response(core_res: ListTaskPushNotificationConfigsResponse, request_id: str | int | None = None) -> ListTaskPushNotificationConfigResponse Convert list task push notification config response to v0.3 compat type. a2a.compat.v0_3.conversions.to_compat_message(core_msg: Message) -> Message Convert message to v0.3 compat type. a2a.compat.v0_3.conversions.to_compat_oauth_flows(core_flows: OAuthFlows) -> OAuthFlows Convert oauth flows to v0.3 compat type. a2a.compat.v0_3.conversions.to_compat_part(core_part: Part) -> Part Converts a v1.0 core Part (Protobuf object) to a v0.3 Part (Pydantic model). a2a.compat.v0_3.conversions.to_compat_push_notification_config(core_config: TaskPushNotificationConfig) -> PushNotificationConfig Convert push notification config to v0.3 compat type. a2a.compat.v0_3.conversions.to_compat_security_requirement(core_req: SecurityRequirement) -> dict[str, list[str]] Convert security requirement to v0.3 compat type. a2a.compat.v0_3.conversions.to_compat_security_scheme(core_scheme: SecurityScheme) -> SecurityScheme Convert security scheme to v0.3 compat type. a2a.compat.v0_3.conversions.to_compat_send_message_configuration(core_config: SendMessageConfiguration) -> MessageSendConfiguration Convert send message configuration to v0.3 compat type. a2a.compat.v0_3.conversions.to_compat_send_message_request(core_req: SendMessageRequest, request_id: str | int) -> SendMessageRequest Convert send message request to v0.3 compat type. a2a.compat.v0_3.conversions.to_compat_send_message_response(core_res: SendMessageResponse, request_id: str | int | None = None) -> SendMessageResponse Convert send message response to v0.3 compat type. a2a.compat.v0_3.conversions.to_compat_stream_response(core_res: StreamResponse, request_id: str | int | None = None) -> SendStreamingMessageSuccessResponse Convert stream response to v0.3 compat type. a2a.compat.v0_3.conversions.to_compat_subscribe_to_task_request(core_req: SubscribeToTaskRequest, request_id: str | int) -> TaskResubscriptionRequest Convert subscribe to task request to v0.3 compat type. a2a.compat.v0_3.conversions.to_compat_task(core_task: Task) -> Task Convert task to v0.3 compat type. a2a.compat.v0_3.conversions.to_compat_task_artifact_update_event(core_event: TaskArtifactUpdateEvent) -> TaskArtifactUpdateEvent Convert task artifact update event to v0.3 compat type. a2a.compat.v0_3.conversions.to_compat_task_push_notification_config(core_config: TaskPushNotificationConfig) -> TaskPushNotificationConfig Convert task push notification config to v0.3 compat type. a2a.compat.v0_3.conversions.to_compat_task_status(core_status: TaskStatus) -> TaskStatus Convert task status to v0.3 compat type. a2a.compat.v0_3.conversions.to_compat_task_status_update_event(core_event: TaskStatusUpdateEvent) -> TaskStatusUpdateEvent Convert task status update event to v0.3 compat type. a2a.compat.v0_3.conversions.to_core_agent_capabilities(compat_cap: AgentCapabilities) -> AgentCapabilities Convert agent capabilities to v1.0 core type. a2a.compat.v0_3.conversions.to_core_agent_card(compat_card: AgentCard) -> AgentCard Convert agent card to v1.0 core type. a2a.compat.v0_3.conversions.to_core_agent_card_signature(compat_sig: AgentCardSignature) -> AgentCardSignature Convert agent card signature to v1.0 core type. a2a.compat.v0_3.conversions.to_core_agent_extension(compat_ext: AgentExtension) -> AgentExtension Convert agent extension to v1.0 core type. a2a.compat.v0_3.conversions.to_core_agent_interface(compat_interface: AgentInterface) -> AgentInterface Convert agent interface to v1.0 core type. a2a.compat.v0_3.conversions.to_core_agent_provider(compat_provider: AgentProvider) -> AgentProvider Convert agent provider to v1.0 core type. a2a.compat.v0_3.conversions.to_core_agent_skill(compat_skill: AgentSkill) -> AgentSkill Convert agent skill to v1.0 core type. a2a.compat.v0_3.conversions.to_core_artifact(compat_artifact: Artifact) -> Artifact Convert artifact to v1.0 core type. a2a.compat.v0_3.conversions.to_core_authentication_info(compat_auth: PushNotificationAuthenticationInfo) -> AuthenticationInfo Convert authentication info to v1.0 core type. a2a.compat.v0_3.conversions.to_core_cancel_task_request(compat_req: CancelTaskRequest) -> CancelTaskRequest Convert cancel task request to v1.0 core type. a2a.compat.v0_3.conversions.to_core_create_task_push_notification_config_request(compat_req: SetTaskPushNotificationConfigRequest) -> TaskPushNotificationConfig Convert create task push notification config request to v1.0 core type. a2a.compat.v0_3.conversions.to_core_delete_task_push_notification_config_request(compat_req: DeleteTaskPushNotificationConfigRequest) -> DeleteTaskPushNotificationConfigRequest Convert delete task push notification config request to v1.0 core type. a2a.compat.v0_3.conversions.to_core_get_extended_agent_card_request(compat_req: GetAuthenticatedExtendedCardRequest) -> GetExtendedAgentCardRequest Convert get extended agent card request to v1.0 core type. a2a.compat.v0_3.conversions.to_core_get_task_push_notification_config_request(compat_req: GetTaskPushNotificationConfigRequest) -> GetTaskPushNotificationConfigRequest Convert get task push notification config request to v1.0 core type. a2a.compat.v0_3.conversions.to_core_get_task_request(compat_req: GetTaskRequest) -> GetTaskRequest Convert get task request to v1.0 core type. a2a.compat.v0_3.conversions.to_core_list_task_push_notification_config_request(compat_req: ListTaskPushNotificationConfigRequest) -> ListTaskPushNotificationConfigsRequest Convert list task push notification config request to v1.0 core type. a2a.compat.v0_3.conversions.to_core_list_task_push_notification_config_response(compat_res: ListTaskPushNotificationConfigResponse) -> ListTaskPushNotificationConfigsResponse Convert list task push notification config response to v1.0 core type. a2a.compat.v0_3.conversions.to_core_message(compat_msg: Message) -> Message Convert message to v1.0 core type. a2a.compat.v0_3.conversions.to_core_oauth_flows(compat_flows: OAuthFlows) -> OAuthFlows Convert oauth flows to v1.0 core type. a2a.compat.v0_3.conversions.to_core_part(compat_part: Part) -> Part Converts a v0.3 Part (Pydantic model) to a v1.0 core Part (Protobuf object). a2a.compat.v0_3.conversions.to_core_push_notification_config(compat_config: PushNotificationConfig) -> TaskPushNotificationConfig Convert push notification config to v1.0 core type. a2a.compat.v0_3.conversions.to_core_security_requirement(compat_req: dict[str, list[str]]) -> SecurityRequirement Convert security requirement to v1.0 core type. a2a.compat.v0_3.conversions.to_core_security_scheme(compat_scheme: SecurityScheme) -> SecurityScheme Convert security scheme to v1.0 core type. a2a.compat.v0_3.conversions.to_core_send_message_configuration(compat_config: MessageSendConfiguration) -> SendMessageConfiguration Convert send message configuration to v1.0 core type. a2a.compat.v0_3.conversions.to_core_send_message_request(compat_req: SendMessageRequest) -> SendMessageRequest Convert send message request to v1.0 core type. a2a.compat.v0_3.conversions.to_core_send_message_response(compat_res: SendMessageResponse) -> SendMessageResponse Convert send message response to v1.0 core type. a2a.compat.v0_3.conversions.to_core_stream_response(compat_res: SendStreamingMessageSuccessResponse) -> StreamResponse Convert stream response to v1.0 core type. a2a.compat.v0_3.conversions.to_core_subscribe_to_task_request(compat_req: TaskResubscriptionRequest) -> SubscribeToTaskRequest Convert subscribe to task request to v1.0 core type. a2a.compat.v0_3.conversions.to_core_task(compat_task: Task) -> Task Convert task to v1.0 core type. a2a.compat.v0_3.conversions.to_core_task_artifact_update_event(compat_event: TaskArtifactUpdateEvent) -> TaskArtifactUpdateEvent Convert task artifact update event to v1.0 core type. a2a.compat.v0_3.conversions.to_core_task_push_notification_config(compat_config: TaskPushNotificationConfig) -> TaskPushNotificationConfig Convert task push notification config to v1.0 core type. a2a.compat.v0_3.conversions.to_core_task_status(compat_status: TaskStatus) -> TaskStatus Convert task status to v1.0 core type. a2a.compat.v0_3.conversions.to_core_task_status_update_event(compat_event: TaskStatusUpdateEvent) -> TaskStatusUpdateEvent Convert task status update event to v1.0 core type. a2a.compat.v0_3.extension_headers module **************************************** Shared header name constants for v0.3 extension compatibility. The current spec uses "A2A-Extensions". v0.3 used the "X-" prefixed "X -A2A-Extensions" form. v0.3 compat servers and clients accept/emit both names so they can interoperate with peers that only know the legacy one. a2a.compat.v0_3.extension_headers.add_legacy_extension_header(parameters: dict[str, str]) -> None Mirrors the "A2A-Extensions" parameter under its legacy name in- place. Used by v0.3 compat client transports so that requests can be understood by older v0.3 servers that only recognize "X-A2A- Extensions". a2a.compat.v0_3.grpc_handler module *********************************** class a2a.compat.v0_3.grpc_handler.CompatGrpcHandler(request_handler: RequestHandler, context_builder: GrpcServerCallContextBuilder | None = None) Bases: "A2AServiceServicer" Backward compatible gRPC handler for A2A v0.3. async CancelTask(request: CancelTaskRequest, context: ServicerContext) -> Task Handles the 'CancelTask' gRPC method (v0.3). async CreateTaskPushNotificationConfig(request: CreateTaskPushNotificationConfigRequest, context: ServicerContext) -> TaskPushNotificationConfig Handles the 'CreateTaskPushNotificationConfig' gRPC method (v0.3). async DeleteTaskPushNotificationConfig(request: DeleteTaskPushNotificationConfigRequest, context: ServicerContext) -> Empty Handles the 'DeleteTaskPushNotificationConfig' gRPC method (v0.3). async GetAgentCard(request: GetAgentCardRequest, context: ServicerContext) -> AgentCard Get the extended agent card for the agent served (v0.3). async GetTask(request: GetTaskRequest, context: ServicerContext) -> Task Handles the 'GetTask' gRPC method (v0.3). async GetTaskPushNotificationConfig(request: GetTaskPushNotificationConfigRequest, context: ServicerContext) -> TaskPushNotificationConfig Handles the 'GetTaskPushNotificationConfig' gRPC method (v0.3). async ListTaskPushNotificationConfig(request: ListTaskPushNotificationConfigRequest, context: ServicerContext) -> ListTaskPushNotificationConfigResponse Handles the 'ListTaskPushNotificationConfig' gRPC method (v0.3). async SendMessage(request: SendMessageRequest, context: ServicerContext) -> SendMessageResponse Handles the 'SendMessage' gRPC method (v0.3). async SendStreamingMessage(request: SendMessageRequest, context: ServicerContext) -> AsyncIterable[StreamResponse] Handles the 'SendStreamingMessage' gRPC method (v0.3). async TaskSubscription(request: TaskSubscriptionRequest, context: ServicerContext) -> AsyncIterable[StreamResponse] Handles the 'TaskSubscription' gRPC method (v0.3). async abort_context(error: A2AError, context: ServicerContext) -> None Sets the grpc errors appropriately in the context. a2a.compat.v0_3.grpc_transport module ************************************* class a2a.compat.v0_3.grpc_transport.CompatGrpcTransport(channel: Channel, agent_card: AgentCard | None) Bases: "ClientTransport" A backward compatible gRPC transport for A2A v0.3. async cancel_task(request: CancelTaskRequest, *, context: ClientCallContext | None = None) -> Task Requests the agent to cancel a specific task (v0.3). async close() -> None Closes the gRPC channel. classmethod create(card: AgentCard, url: str, config: ClientConfig) -> CompatGrpcTransport Creates a gRPC transport for the A2A client. async create_task_push_notification_config(request: TaskPushNotificationConfig, *, context: ClientCallContext | None = None) -> TaskPushNotificationConfig Sets or updates the push notification configuration (v0.3). async delete_task_push_notification_config(request: DeleteTaskPushNotificationConfigRequest, *, context: ClientCallContext | None = None) -> None Deletes the push notification configuration (v0.3). async get_extended_agent_card(request: GetExtendedAgentCardRequest, *, context: ClientCallContext | None = None) -> AgentCard Retrieves the agent's card (v0.3). async get_task(request: GetTaskRequest, *, context: ClientCallContext | None = None) -> Task Retrieves the current state and history of a specific task (v0.3). async get_task_push_notification_config(request: GetTaskPushNotificationConfigRequest, *, context: ClientCallContext | None = None) -> TaskPushNotificationConfig Retrieves the push notification configuration (v0.3). async list_task_push_notification_configs(request: ListTaskPushNotificationConfigsRequest, *, context: ClientCallContext | None = None) -> ListTaskPushNotificationConfigsResponse Lists push notification configurations for a specific task (v0.3). async list_tasks(request: ListTasksRequest, *, context: ClientCallContext | None = None) -> ListTasksResponse Retrieves tasks for an agent (v0.3 - NOT SUPPORTED in v0.3). async send_message(request: SendMessageRequest, *, context: ClientCallContext | None = None) -> SendMessageResponse Sends a non-streaming message request to the agent (v0.3). send_message_streaming(request: SendMessageRequest, *, context: ClientCallContext | None = None) -> AsyncGenerator[StreamResponse] Sends a streaming message request to the agent (v0.3). subscribe(request: SubscribeToTaskRequest, *, context: ClientCallContext | None = None) -> AsyncGenerator[StreamResponse] Reconnects to get task updates (v0.3). a2a.compat.v0_3.jsonrpc_adapter module ************************************** class a2a.compat.v0_3.jsonrpc_adapter.JSONRPC03Adapter(http_handler: RequestHandler, context_builder: ServerCallContextBuilder | None = None) Bases: "object" Adapter to make RequestHandler work with v0.3 JSONRPC API. METHOD_TO_MODEL = {'agent/getAuthenticatedExtendedCard': , 'message/send': , 'message/stream': , 'tasks/cancel': , 'tasks/get': , 'tasks/pushNotificationConfig/delete': , 'tasks/pushNotificationConfig/get': , 'tasks/pushNotificationConfig/list': , 'tasks/pushNotificationConfig/set': , 'tasks/resubscribe': } async handle_request(request_id: str | int | None, method: str, body: dict, request: Request) -> JSONResponse | EventSourceResponse Handles v0.3 specific JSON-RPC requests. supports_method(method: str) -> bool Returns True if the v0.3 adapter supports the given method name. a2a.compat.v0_3.jsonrpc_transport module **************************************** class a2a.compat.v0_3.jsonrpc_transport.CompatJsonRpcTransport(httpx_client: AsyncClient, agent_card: AgentCard | None, url: str) Bases: "ClientTransport" A backward compatible JSON-RPC transport for A2A v0.3. async cancel_task(request: CancelTaskRequest, *, context: ClientCallContext | None = None) -> Task Requests the agent to cancel a specific task. async close() -> None Closes the httpx client. async create_task_push_notification_config(request: TaskPushNotificationConfig, *, context: ClientCallContext | None = None) -> TaskPushNotificationConfig Sets or updates the push notification configuration for a specific task. async delete_task_push_notification_config(request: DeleteTaskPushNotificationConfigRequest, *, context: ClientCallContext | None = None) -> None Deletes the push notification configuration for a specific task. async get_extended_agent_card(request: GetExtendedAgentCardRequest, *, context: ClientCallContext | None = None) -> AgentCard Retrieves the Extended AgentCard. async get_task(request: GetTaskRequest, *, context: ClientCallContext | None = None) -> Task Retrieves the current state and history of a specific task. async get_task_push_notification_config(request: GetTaskPushNotificationConfigRequest, *, context: ClientCallContext | None = None) -> TaskPushNotificationConfig Retrieves the push notification configuration for a specific task. async list_task_push_notification_configs(request: ListTaskPushNotificationConfigsRequest, *, context: ClientCallContext | None = None) -> ListTaskPushNotificationConfigsResponse Lists push notification configurations for a specific task. async list_tasks(request: ListTasksRequest, *, context: ClientCallContext | None = None) -> ListTasksResponse Retrieves tasks for an agent. async send_message(request: SendMessageRequest, *, context: ClientCallContext | None = None) -> SendMessageResponse Sends a non-streaming message request to the agent. send_message_streaming(request: SendMessageRequest, *, context: ClientCallContext | None = None) -> AsyncGenerator[StreamResponse] Sends a streaming message request to the agent and yields responses as they arrive. subscribe(request: SubscribeToTaskRequest, *, context: ClientCallContext | None = None) -> AsyncGenerator[StreamResponse] Reconnects to get task updates. a2a.compat.v0_3.model_conversions module **************************************** Database model conversions for v0.3 compatibility. a2a.compat.v0_3.model_conversions.compat_push_notification_config_model_to_core(model_instance: str, task_id: str) -> TaskPushNotificationConfig Converts a PushNotificationConfigModel with v0.3 structure back to a 1.0 core TaskPushNotificationConfig. a2a.compat.v0_3.model_conversions.compat_task_model_to_core(task_model: TaskModel) -> Task Converts a TaskModel with v0.3 structure to a 1.0 core Task. a2a.compat.v0_3.model_conversions.core_to_compat_push_notification_config_model(task_id: str, config: TaskPushNotificationConfig, owner: str, fernet: Fernet | None = None) -> PushNotificationConfigModel Converts a 1.0 core TaskPushNotificationConfig to a PushNotificationConfigModel using v0.3 JSON structure. a2a.compat.v0_3.model_conversions.core_to_compat_task_model(task: Task, owner: str) -> TaskModel Converts a 1.0 core Task to a TaskModel using v0.3 JSON structure. a2a.compat.v0_3.proto_utils module ********************************** This file was migrated from the a2a-python SDK version 0.3. It provides utilities for converting between legacy v0.3 Pydantic models and legacy v0.3 Protobuf definitions. class a2a.compat.v0_3.proto_utils.FromProto Bases: "object" Converts proto types to Python types. classmethod agent_card(card: AgentCard) -> AgentCard classmethod agent_card_signature(signature: AgentCardSignature) -> AgentCardSignature classmethod agent_extension(extension: AgentExtension) -> AgentExtension classmethod agent_interface(interface: AgentInterface) -> AgentInterface classmethod artifact(artifact: Artifact) -> Artifact classmethod authentication_info(info: AuthenticationInfo) -> PushNotificationAuthenticationInfo classmethod capabilities(capabilities: AgentCapabilities) -> AgentCapabilities classmethod data(data: DataPart) -> dict[str, Any] classmethod file(file: FilePart) -> FileWithUri | FileWithBytes classmethod list_task_push_notification_config_response(response: ListTaskPushNotificationConfigResponse) -> ListTaskPushNotificationConfigResponse classmethod message(message: Message) -> Message classmethod message_send_configuration(config: SendMessageConfiguration) -> MessageSendConfiguration classmethod message_send_params(request: SendMessageRequest) -> MessageSendParams classmethod metadata(metadata: Struct) -> dict[str, Any] classmethod oauth2_flows(flows: OAuthFlows) -> OAuthFlows classmethod part(part: Part) -> Part classmethod provider(provider: AgentProvider | None) -> AgentProvider | None classmethod push_notification_config(config: PushNotificationConfig) -> PushNotificationConfig classmethod role(role: ) -> Role classmethod security(security: list[Security] | None) -> list[dict[str, list[str]]] | None classmethod security_scheme(scheme: SecurityScheme) -> SecurityScheme classmethod security_schemes(schemes: dict[str, SecurityScheme]) -> dict[str, SecurityScheme] classmethod skill(skill: AgentSkill) -> AgentSkill classmethod stream_response(response: StreamResponse) -> Message | Task | TaskStatusUpdateEvent | TaskArtifactUpdateEvent classmethod task(task: Task) -> Task classmethod task_artifact_update_event(event: TaskArtifactUpdateEvent) -> TaskArtifactUpdateEvent classmethod task_id_params(request: CancelTaskRequest | TaskSubscriptionRequest | GetTaskPushNotificationConfigRequest) -> TaskIdParams classmethod task_or_message(event: SendMessageResponse) -> Task | Message classmethod task_push_notification_config(config: TaskPushNotificationConfig) -> TaskPushNotificationConfig classmethod task_push_notification_config_request(request: CreateTaskPushNotificationConfigRequest) -> TaskPushNotificationConfig classmethod task_query_params(request: GetTaskRequest) -> TaskQueryParams classmethod task_state(state: ) -> TaskState classmethod task_status(status: TaskStatus) -> TaskStatus classmethod task_status_update_event(event: TaskStatusUpdateEvent) -> TaskStatusUpdateEvent class a2a.compat.v0_3.proto_utils.ToProto Bases: "object" Converts Python types to proto types. classmethod agent_card(card: AgentCard) -> AgentCard classmethod agent_card_signature(signature: AgentCardSignature) -> AgentCardSignature classmethod agent_interface(interface: AgentInterface) -> AgentInterface classmethod artifact(artifact: Artifact) -> Artifact classmethod authentication_info(info: PushNotificationAuthenticationInfo) -> AuthenticationInfo classmethod capabilities(capabilities: AgentCapabilities) -> AgentCapabilities classmethod data(data: dict[str, Any]) -> DataPart classmethod extension(extension: AgentExtension) -> AgentExtension classmethod file(file: FileWithUri | FileWithBytes) -> FilePart classmethod message(message: Message | None) -> Message | None classmethod message_send_configuration(config: MessageSendConfiguration | None) -> SendMessageConfiguration classmethod metadata(metadata: dict[str, Any] | None) -> Struct | None classmethod oauth2_flows(flows: OAuthFlows) -> OAuthFlows classmethod part(part: Part) -> Part classmethod provider(provider: AgentProvider | None) -> AgentProvider | None classmethod push_notification_config(config: PushNotificationConfig) -> PushNotificationConfig classmethod role(role: Role) -> classmethod security(security: list[dict[str, list[str]]] | None) -> list[Security] | None classmethod security_scheme(scheme: SecurityScheme) -> SecurityScheme classmethod security_schemes(schemes: dict[str, SecurityScheme] | None) -> dict[str, SecurityScheme] | None classmethod skill(skill: AgentSkill) -> AgentSkill classmethod stream_response(event: Message | Task | TaskStatusUpdateEvent | TaskArtifactUpdateEvent) -> StreamResponse classmethod task(task: Task) -> Task classmethod task_artifact_update_event(event: TaskArtifactUpdateEvent) -> TaskArtifactUpdateEvent classmethod task_or_message(event: Task | Message) -> SendMessageResponse classmethod task_push_notification_config(config: TaskPushNotificationConfig) -> TaskPushNotificationConfig classmethod task_state(state: TaskState) -> classmethod task_status(status: TaskStatus) -> TaskStatus classmethod task_status_update_event(event: TaskStatusUpdateEvent) -> TaskStatusUpdateEvent classmethod update_event(event: Task | Message | TaskStatusUpdateEvent | TaskArtifactUpdateEvent) -> StreamResponse Converts a task, message, or task update event to a StreamResponse. a2a.compat.v0_3.proto_utils.dict_to_struct(dictionary: dict[str, Any]) -> Struct Converts a Python dict to a Struct proto. Unfortunately, using *json_format.ParseDict* does not work because this wants the dictionary to be an exact match of the Struct proto with fields and keys and values, not the traditional Python dict structure. Parameters: **dictionary** -- The Python dict to convert. Returns: The Struct proto. a2a.compat.v0_3.proto_utils.make_dict_serializable(value: Any) -> Any Dict pre-processing utility: converts non-serializable values to serializable form. Use this when you want to normalize a dictionary before dict->Struct conversion. Parameters: **value** -- The value to convert. Returns: A serializable value. a2a.compat.v0_3.proto_utils.normalize_large_integers_to_strings(value: Any, max_safe_digits: int = 15) -> Any Integer preprocessing utility: converts large integers to strings. Use this when you want to convert large integers to strings considering JavaScript's MAX_SAFE_INTEGER (2^53 - 1) limitation. Parameters: * **value** -- The value to convert. * **max_safe_digits** -- Maximum safe integer digits (default: 15). Returns: A normalized value. a2a.compat.v0_3.proto_utils.parse_string_integers_in_dict(value: Any, max_safe_digits: int = 15) -> Any String post-processing utility: converts large integer strings back to integers. Use this when you want to restore large integer strings to integers after Struct->dict conversion. Parameters: * **value** -- The value to convert. * **max_safe_digits** -- Maximum safe integer digits (default: 15). Returns: A parsed value. a2a.compat.v0_3.request_handler module ************************************** class a2a.compat.v0_3.request_handler.RequestHandler03(request_handler: RequestHandler) Bases: "object" A protocol-agnostic v0.3 RequestHandler that delegates to the v1.0 RequestHandler. async on_cancel_task(request: CancelTaskRequest, context: ServerCallContext) -> Task Cancels a task using v0.3 protocol types. async on_create_task_push_notification_config(request: SetTaskPushNotificationConfigRequest, context: ServerCallContext) -> TaskPushNotificationConfig Creates a push notification config using v0.3 protocol types. async on_delete_task_push_notification_config(request: DeleteTaskPushNotificationConfigRequest, context: ServerCallContext) -> None Deletes a push notification config using v0.3 protocol types. async on_get_extended_agent_card(request: GetAuthenticatedExtendedCardRequest, context: ServerCallContext) -> AgentCard Gets the authenticated extended agent card using v0.3 protocol types. async on_get_task(request: GetTaskRequest, context: ServerCallContext) -> Task Gets a task using v0.3 protocol types. async on_get_task_push_notification_config(request: GetTaskPushNotificationConfigRequest, context: ServerCallContext) -> TaskPushNotificationConfig Gets a push notification config using v0.3 protocol types. async on_list_task_push_notification_configs(request: ListTaskPushNotificationConfigRequest, context: ServerCallContext) -> list[TaskPushNotificationConfig] Lists push notification configs using v0.3 protocol types. async on_message_send(request: SendMessageRequest, context: ServerCallContext) -> Task | Message Sends a message using v0.3 protocol types. async on_message_send_stream(request: SendMessageRequest, context: ServerCallContext) -> AsyncIterable[SendStreamingMessageSuccessResponse] Sends a message stream using v0.3 protocol types. async on_subscribe_to_task(request: TaskResubscriptionRequest, context: ServerCallContext) -> AsyncIterable[SendStreamingMessageSuccessResponse] Subscribes to a task using v0.3 protocol types. a2a.compat.v0_3.rest_adapter module *********************************** class a2a.compat.v0_3.rest_adapter.REST03Adapter(http_handler: RequestHandler, context_builder: ServerCallContextBuilder | None = None) Bases: "object" Adapter to make RequestHandler work with v0.3 RESTful API. Defines v0.3 REST request processors and their routes, as well as managing response generation including Server-Sent Events (SSE). routes() -> dict[tuple[str, str], Callable[[Request], Any]] Constructs a dictionary of API routes and their corresponding handlers. a2a.compat.v0_3.rest_handler module *********************************** class a2a.compat.v0_3.rest_handler.REST03Handler(request_handler: RequestHandler) Bases: "object" Maps incoming REST-like (JSON+HTTP) requests to the appropriate request handler method and formats responses for v0.3 compatibility. async get_push_notification(request: Request, context: ServerCallContext) -> dict[str, Any] Handles the 'tasks/pushNotificationConfig/get' REST method. Parameters: * **request** -- The incoming *Request* object. * **context** -- Context provided by the server. Returns: A *dict* containing the config in v0.3 format. async list_push_notifications(request: Request, context: ServerCallContext) -> dict[str, Any] Handles the 'tasks/pushNotificationConfig/list' REST method. async on_cancel_task(request: Request, context: ServerCallContext) -> dict[str, Any] Handles the 'tasks/cancel' REST method. Parameters: * **request** -- The incoming *Request* object. * **context** -- Context provided by the server. Returns: A *dict* containing the updated Task in v0.3 format. async on_get_extended_agent_card(request: Request, context: ServerCallContext) -> dict[str, Any] Handles the 'v1/agent/authenticatedExtendedAgentCard' REST method. async on_get_task(request: Request, context: ServerCallContext) -> dict[str, Any] Handles the 'v1/tasks/{id}' REST method. Parameters: * **request** -- The incoming *Request* object. * **context** -- Context provided by the server. Returns: A *Task* object containing the Task in v0.3 format. async on_message_send(request: Request, context: ServerCallContext) -> dict[str, Any] Handles the 'message/send' REST method. Parameters: * **request** -- The incoming *Request* object. * **context** -- Context provided by the server. Returns: A *dict* containing the result (Task or Message) in v0.3 format. on_message_send_stream(request: Request, context: ServerCallContext) -> AsyncIterator[dict[str, Any]] Handles the 'message/stream' REST method. Parameters: * **request** -- The incoming *Request* object. * **context** -- Context provided by the server. Yields: JSON serialized objects containing streaming events in v0.3 format. on_subscribe_to_task(request: Request, context: ServerCallContext) -> AsyncIterator[dict[str, Any]] Handles the 'tasks/{id}:subscribe' REST method. Parameters: * **request** -- The incoming *Request* object. * **context** -- Context provided by the server. Yields: JSON serialized objects containing streaming events in v0.3 format. async set_push_notification(request: Request, context: ServerCallContext) -> dict[str, Any] Handles the 'tasks/pushNotificationConfig/set' REST method. Parameters: * **request** -- The incoming *Request* object. * **context** -- Context provided by the server. Returns: A *dict* containing the config object in v0.3 format. a2a.compat.v0_3.rest_transport module ************************************* class a2a.compat.v0_3.rest_transport.CompatRestTransport(httpx_client: AsyncClient, agent_card: AgentCard | None, url: str, subscribe_method_override: str | None = None) Bases: "ClientTransport" A backward compatible REST transport for A2A v0.3. async cancel_task(request: CancelTaskRequest, *, context: ClientCallContext | None = None) -> Task Requests the agent to cancel a specific task. async close() -> None Closes the httpx client. async create_task_push_notification_config(request: TaskPushNotificationConfig, *, context: ClientCallContext | None = None) -> TaskPushNotificationConfig Sets or updates the push notification configuration for a specific task. async delete_task_push_notification_config(request: DeleteTaskPushNotificationConfigRequest, *, context: ClientCallContext | None = None) -> None Deletes the push notification configuration for a specific task. async get_extended_agent_card(request: GetExtendedAgentCardRequest, *, context: ClientCallContext | None = None) -> AgentCard Retrieves the Extended AgentCard. async get_task(request: GetTaskRequest, *, context: ClientCallContext | None = None) -> Task Retrieves the current state and history of a specific task. async get_task_push_notification_config(request: GetTaskPushNotificationConfigRequest, *, context: ClientCallContext | None = None) -> TaskPushNotificationConfig Retrieves the push notification configuration for a specific task. async list_task_push_notification_configs(request: ListTaskPushNotificationConfigsRequest, *, context: ClientCallContext | None = None) -> ListTaskPushNotificationConfigsResponse Lists push notification configurations for a specific task. async list_tasks(request: ListTasksRequest, *, context: ClientCallContext | None = None) -> ListTasksResponse Retrieves tasks for an agent. async send_message(request: SendMessageRequest, *, context: ClientCallContext | None = None) -> SendMessageResponse Sends a non-streaming message request to the agent. send_message_streaming(request: SendMessageRequest, *, context: ClientCallContext | None = None) -> AsyncGenerator[StreamResponse] Sends a streaming message request to the agent and yields responses as they arrive. subscribe(request: SubscribeToTaskRequest, *, context: ClientCallContext | None = None) -> AsyncGenerator[StreamResponse] Reconnects to get task updates. This method implements backward compatibility logic for the subscribe endpoint. It first attempts to use POST, which is the official method for A2A subscribe endpoint. If the server returns 405 Method Not Allowed, it falls back to GET and remembers this preference for future calls on this transport instance. If both fail with 405, it will default back to POST for next calls but will not retry again. a2a.compat.v0_3 package *********************** Submodules ========== * a2a.compat.v0_3.a2a_v0_3_pb2 module * a2a.compat.v0_3.a2a_v0_3_pb2_grpc module * "A2AService" * "A2AService.CancelTask()" * "A2AService.CreateTaskPushNotificationConfig()" * "A2AService.DeleteTaskPushNotificationConfig()" * "A2AService.GetAgentCard()" * "A2AService.GetTask()" * "A2AService.GetTaskPushNotificationConfig()" * "A2AService.ListTaskPushNotificationConfig()" * "A2AService.SendMessage()" * "A2AService.SendStreamingMessage()" * "A2AService.TaskSubscription()" * "A2AServiceServicer" * "A2AServiceServicer.CancelTask()" * "A2AServiceServicer.CreateTaskPushNotificationConfig()" * "A2AServiceServicer.DeleteTaskPushNotificationConfig()" * "A2AServiceServicer.GetAgentCard()" * "A2AServiceServicer.GetTask()" * "A2AServiceServicer.GetTaskPushNotificationConfig()" * "A2AServiceServicer.ListTaskPushNotificationConfig()" * "A2AServiceServicer.SendMessage()" * "A2AServiceServicer.SendStreamingMessage()" * "A2AServiceServicer.TaskSubscription()" * "A2AServiceStub" * "add_A2AServiceServicer_to_server()" * a2a.compat.v0_3.context_builders module * "V03GrpcServerCallContextBuilder" * "V03GrpcServerCallContextBuilder.build()" * "V03ServerCallContextBuilder" * "V03ServerCallContextBuilder.build()" * a2a.compat.v0_3.conversions module * "to_compat_agent_capabilities()" * "to_compat_agent_card()" * "to_compat_agent_card_signature()" * "to_compat_agent_extension()" * "to_compat_agent_interface()" * "to_compat_agent_provider()" * "to_compat_agent_skill()" * "to_compat_artifact()" * "to_compat_authentication_info()" * "to_compat_cancel_task_request()" * "to_compat_create_task_push_notification_config_request()" * "to_compat_delete_task_push_notification_config_request()" * "to_compat_get_extended_agent_card_request()" * "to_compat_get_task_push_notification_config_request()" * "to_compat_get_task_request()" * "to_compat_list_task_push_notification_config_request()" * "to_compat_list_task_push_notification_config_response()" * "to_compat_message()" * "to_compat_oauth_flows()" * "to_compat_part()" * "to_compat_push_notification_config()" * "to_compat_security_requirement()" * "to_compat_security_scheme()" * "to_compat_send_message_configuration()" * "to_compat_send_message_request()" * "to_compat_send_message_response()" * "to_compat_stream_response()" * "to_compat_subscribe_to_task_request()" * "to_compat_task()" * "to_compat_task_artifact_update_event()" * "to_compat_task_push_notification_config()" * "to_compat_task_status()" * "to_compat_task_status_update_event()" * "to_core_agent_capabilities()" * "to_core_agent_card()" * "to_core_agent_card_signature()" * "to_core_agent_extension()" * "to_core_agent_interface()" * "to_core_agent_provider()" * "to_core_agent_skill()" * "to_core_artifact()" * "to_core_authentication_info()" * "to_core_cancel_task_request()" * "to_core_create_task_push_notification_config_request()" * "to_core_delete_task_push_notification_config_request()" * "to_core_get_extended_agent_card_request()" * "to_core_get_task_push_notification_config_request()" * "to_core_get_task_request()" * "to_core_list_task_push_notification_config_request()" * "to_core_list_task_push_notification_config_response()" * "to_core_message()" * "to_core_oauth_flows()" * "to_core_part()" * "to_core_push_notification_config()" * "to_core_security_requirement()" * "to_core_security_scheme()" * "to_core_send_message_configuration()" * "to_core_send_message_request()" * "to_core_send_message_response()" * "to_core_stream_response()" * "to_core_subscribe_to_task_request()" * "to_core_task()" * "to_core_task_artifact_update_event()" * "to_core_task_push_notification_config()" * "to_core_task_status()" * "to_core_task_status_update_event()" * a2a.compat.v0_3.extension_headers module * "add_legacy_extension_header()" * a2a.compat.v0_3.grpc_handler module * "CompatGrpcHandler" * "CompatGrpcHandler.CancelTask()" * "CompatGrpcHandler.CreateTaskPushNotificationConfig()" * "CompatGrpcHandler.DeleteTaskPushNotificationConfig()" * "CompatGrpcHandler.GetAgentCard()" * "CompatGrpcHandler.GetTask()" * "CompatGrpcHandler.GetTaskPushNotificationConfig()" * "CompatGrpcHandler.ListTaskPushNotificationConfig()" * "CompatGrpcHandler.SendMessage()" * "CompatGrpcHandler.SendStreamingMessage()" * "CompatGrpcHandler.TaskSubscription()" * "CompatGrpcHandler.abort_context()" * a2a.compat.v0_3.grpc_transport module * "CompatGrpcTransport" * "CompatGrpcTransport.cancel_task()" * "CompatGrpcTransport.close()" * "CompatGrpcTransport.create()" * "CompatGrpcTransport.create_task_push_notification_config()" * "CompatGrpcTransport.delete_task_push_notification_config()" * "CompatGrpcTransport.get_extended_agent_card()" * "CompatGrpcTransport.get_task()" * "CompatGrpcTransport.get_task_push_notification_config()" * "CompatGrpcTransport.list_task_push_notification_configs()" * "CompatGrpcTransport.list_tasks()" * "CompatGrpcTransport.send_message()" * "CompatGrpcTransport.send_message_streaming()" * "CompatGrpcTransport.subscribe()" * a2a.compat.v0_3.jsonrpc_adapter module * "JSONRPC03Adapter" * "JSONRPC03Adapter.METHOD_TO_MODEL" * "JSONRPC03Adapter.handle_request()" * "JSONRPC03Adapter.supports_method()" * a2a.compat.v0_3.jsonrpc_transport module * "CompatJsonRpcTransport" * "CompatJsonRpcTransport.cancel_task()" * "CompatJsonRpcTransport.close()" * "CompatJsonRpcTransport.create_task_push_notification_config()" * "CompatJsonRpcTransport.delete_task_push_notification_config()" * "CompatJsonRpcTransport.get_extended_agent_card()" * "CompatJsonRpcTransport.get_task()" * "CompatJsonRpcTransport.get_task_push_notification_config()" * "CompatJsonRpcTransport.list_task_push_notification_configs()" * "CompatJsonRpcTransport.list_tasks()" * "CompatJsonRpcTransport.send_message()" * "CompatJsonRpcTransport.send_message_streaming()" * "CompatJsonRpcTransport.subscribe()" * a2a.compat.v0_3.model_conversions module * "compat_push_notification_config_model_to_core()" * "compat_task_model_to_core()" * "core_to_compat_push_notification_config_model()" * "core_to_compat_task_model()" * a2a.compat.v0_3.proto_utils module * "FromProto" * "FromProto.agent_card()" * "FromProto.agent_card_signature()" * "FromProto.agent_extension()" * "FromProto.agent_interface()" * "FromProto.artifact()" * "FromProto.authentication_info()" * "FromProto.capabilities()" * "FromProto.data()" * "FromProto.file()" * "FromProto.list_task_push_notification_config_response()" * "FromProto.message()" * "FromProto.message_send_configuration()" * "FromProto.message_send_params()" * "FromProto.metadata()" * "FromProto.oauth2_flows()" * "FromProto.part()" * "FromProto.provider()" * "FromProto.push_notification_config()" * "FromProto.role()" * "FromProto.security()" * "FromProto.security_scheme()" * "FromProto.security_schemes()" * "FromProto.skill()" * "FromProto.stream_response()" * "FromProto.task()" * "FromProto.task_artifact_update_event()" * "FromProto.task_id_params()" * "FromProto.task_or_message()" * "FromProto.task_push_notification_config()" * "FromProto.task_push_notification_config_request()" * "FromProto.task_query_params()" * "FromProto.task_state()" * "FromProto.task_status()" * "FromProto.task_status_update_event()" * "ToProto" * "ToProto.agent_card()" * "ToProto.agent_card_signature()" * "ToProto.agent_interface()" * "ToProto.artifact()" * "ToProto.authentication_info()" * "ToProto.capabilities()" * "ToProto.data()" * "ToProto.extension()" * "ToProto.file()" * "ToProto.message()" * "ToProto.message_send_configuration()" * "ToProto.metadata()" * "ToProto.oauth2_flows()" * "ToProto.part()" * "ToProto.provider()" * "ToProto.push_notification_config()" * "ToProto.role()" * "ToProto.security()" * "ToProto.security_scheme()" * "ToProto.security_schemes()" * "ToProto.skill()" * "ToProto.stream_response()" * "ToProto.task()" * "ToProto.task_artifact_update_event()" * "ToProto.task_or_message()" * "ToProto.task_push_notification_config()" * "ToProto.task_state()" * "ToProto.task_status()" * "ToProto.task_status_update_event()" * "ToProto.update_event()" * "dict_to_struct()" * "make_dict_serializable()" * "normalize_large_integers_to_strings()" * "parse_string_integers_in_dict()" * a2a.compat.v0_3.request_handler module * "RequestHandler03" * "RequestHandler03.on_cancel_task()" * "RequestHandler03.on_create_task_push_notification_config()" * "RequestHandler03.on_delete_task_push_notification_config()" * "RequestHandler03.on_get_extended_agent_card()" * "RequestHandler03.on_get_task()" * "RequestHandler03.on_get_task_push_notification_config()" * "RequestHandler03.on_list_task_push_notification_configs()" * "RequestHandler03.on_message_send()" * "RequestHandler03.on_message_send_stream()" * "RequestHandler03.on_subscribe_to_task()" * a2a.compat.v0_3.rest_adapter module * "REST03Adapter" * "REST03Adapter.routes()" * a2a.compat.v0_3.rest_handler module * "REST03Handler" * "REST03Handler.get_push_notification()" * "REST03Handler.list_push_notifications()" * "REST03Handler.on_cancel_task()" * "REST03Handler.on_get_extended_agent_card()" * "REST03Handler.on_get_task()" * "REST03Handler.on_message_send()" * "REST03Handler.on_message_send_stream()" * "REST03Handler.on_subscribe_to_task()" * "REST03Handler.set_push_notification()" * a2a.compat.v0_3.rest_transport module * "CompatRestTransport" * "CompatRestTransport.cancel_task()" * "CompatRestTransport.close()" * "CompatRestTransport.create_task_push_notification_config()" * "CompatRestTransport.delete_task_push_notification_config()" * "CompatRestTransport.get_extended_agent_card()" * "CompatRestTransport.get_task()" * "CompatRestTransport.get_task_push_notification_config()" * "CompatRestTransport.list_task_push_notification_configs()" * "CompatRestTransport.list_tasks()" * "CompatRestTransport.send_message()" * "CompatRestTransport.send_message_streaming()" * "CompatRestTransport.subscribe()" * a2a.compat.v0_3.types module * "A2A" * "A2A.model_config" * "A2A.root" * "A2AError" * "A2AError.model_config" * "A2AError.root" * "A2ARequest" * "A2ARequest.model_config" * "A2ARequest.root" * "APIKeySecurityScheme" * "APIKeySecurityScheme.description" * "APIKeySecurityScheme.in_" * "APIKeySecurityScheme.model_config" * "APIKeySecurityScheme.name" * "APIKeySecurityScheme.type" * "AgentCapabilities" * "AgentCapabilities.extensions" * "AgentCapabilities.model_config" * "AgentCapabilities.push_notifications" * "AgentCapabilities.state_transition_history" * "AgentCapabilities.streaming" * "AgentCard" * "AgentCard.additional_interfaces" * "AgentCard.capabilities" * "AgentCard.default_input_modes" * "AgentCard.default_output_modes" * "AgentCard.description" * "AgentCard.documentation_url" * "AgentCard.icon_url" * "AgentCard.model_config" * "AgentCard.name" * "AgentCard.preferred_transport" * "AgentCard.protocol_version" * "AgentCard.provider" * "AgentCard.security" * "AgentCard.security_schemes" * "AgentCard.signatures" * "AgentCard.skills" * "AgentCard.supports_authenticated_extended_card" * "AgentCard.url" * "AgentCard.version" * "AgentCardSignature" * "AgentCardSignature.header" * "AgentCardSignature.model_config" * "AgentCardSignature.protected" * "AgentCardSignature.signature" * "AgentExtension" * "AgentExtension.description" * "AgentExtension.model_config" * "AgentExtension.params" * "AgentExtension.required" * "AgentExtension.uri" * "AgentInterface" * "AgentInterface.model_config" * "AgentInterface.transport" * "AgentInterface.url" * "AgentProvider" * "AgentProvider.model_config" * "AgentProvider.organization" * "AgentProvider.url" * "AgentSkill" * "AgentSkill.description" * "AgentSkill.examples" * "AgentSkill.id" * "AgentSkill.input_modes" * "AgentSkill.model_config" * "AgentSkill.name" * "AgentSkill.output_modes" * "AgentSkill.security" * "AgentSkill.tags" * "Artifact" * "Artifact.artifact_id" * "Artifact.description" * "Artifact.extensions" * "Artifact.metadata" * "Artifact.model_config" * "Artifact.name" * "Artifact.parts" * "AuthenticatedExtendedCardNotConfiguredError" * "AuthenticatedExtendedCardNotConfiguredError.code" * "AuthenticatedExtendedCardNotConfiguredError.data" * "AuthenticatedExtendedCardNotConfiguredError.message" * "AuthenticatedExtendedCardNotConfiguredError.model_config" * "AuthorizationCodeOAuthFlow" * "AuthorizationCodeOAuthFlow.authorization_url" * "AuthorizationCodeOAuthFlow.model_config" * "AuthorizationCodeOAuthFlow.refresh_url" * "AuthorizationCodeOAuthFlow.scopes" * "AuthorizationCodeOAuthFlow.token_url" * "CancelTaskRequest" * "CancelTaskRequest.id" * "CancelTaskRequest.jsonrpc" * "CancelTaskRequest.method" * "CancelTaskRequest.model_config" * "CancelTaskRequest.params" * "CancelTaskResponse" * "CancelTaskResponse.model_config" * "CancelTaskResponse.root" * "CancelTaskSuccessResponse" * "CancelTaskSuccessResponse.id" * "CancelTaskSuccessResponse.jsonrpc" * "CancelTaskSuccessResponse.model_config" * "CancelTaskSuccessResponse.result" * "ClientCredentialsOAuthFlow" * "ClientCredentialsOAuthFlow.model_config" * "ClientCredentialsOAuthFlow.refresh_url" * "ClientCredentialsOAuthFlow.scopes" * "ClientCredentialsOAuthFlow.token_url" * "ContentTypeNotSupportedError" * "ContentTypeNotSupportedError.code" * "ContentTypeNotSupportedError.data" * "ContentTypeNotSupportedError.message" * "ContentTypeNotSupportedError.model_config" * "DataPart" * "DataPart.data" * "DataPart.kind" * "DataPart.metadata" * "DataPart.model_config" * "DeleteTaskPushNotificationConfigParams" * "DeleteTaskPushNotificationConfigParams.id" * "DeleteTaskPushNotificationConfigParams.metadata" * "DeleteTaskPushNotificationConfigParams.model_config" * "DeleteTaskPushNotificationConfigParams.push_notification_config _id" * "DeleteTaskPushNotificationConfigRequest" * "DeleteTaskPushNotificationConfigRequest.id" * "DeleteTaskPushNotificationConfigRequest.jsonrpc" * "DeleteTaskPushNotificationConfigRequest.method" * "DeleteTaskPushNotificationConfigRequest.model_config" * "DeleteTaskPushNotificationConfigRequest.params" * "DeleteTaskPushNotificationConfigResponse" * "DeleteTaskPushNotificationConfigResponse.model_config" * "DeleteTaskPushNotificationConfigResponse.root" * "DeleteTaskPushNotificationConfigSuccessResponse" * "DeleteTaskPushNotificationConfigSuccessResponse.id" * "DeleteTaskPushNotificationConfigSuccessResponse.jsonrpc" * "DeleteTaskPushNotificationConfigSuccessResponse.model_config" * "DeleteTaskPushNotificationConfigSuccessResponse.result" * "FileBase" * "FileBase.mime_type" * "FileBase.model_config" * "FileBase.name" * "FilePart" * "FilePart.file" * "FilePart.kind" * "FilePart.metadata" * "FilePart.model_config" * "FileWithBytes" * "FileWithBytes.bytes" * "FileWithBytes.mime_type" * "FileWithBytes.model_config" * "FileWithBytes.name" * "FileWithUri" * "FileWithUri.mime_type" * "FileWithUri.model_config" * "FileWithUri.name" * "FileWithUri.uri" * "GetAuthenticatedExtendedCardRequest" * "GetAuthenticatedExtendedCardRequest.id" * "GetAuthenticatedExtendedCardRequest.jsonrpc" * "GetAuthenticatedExtendedCardRequest.method" * "GetAuthenticatedExtendedCardRequest.model_config" * "GetAuthenticatedExtendedCardResponse" * "GetAuthenticatedExtendedCardResponse.model_config" * "GetAuthenticatedExtendedCardResponse.root" * "GetAuthenticatedExtendedCardSuccessResponse" * "GetAuthenticatedExtendedCardSuccessResponse.id" * "GetAuthenticatedExtendedCardSuccessResponse.jsonrpc" * "GetAuthenticatedExtendedCardSuccessResponse.model_config" * "GetAuthenticatedExtendedCardSuccessResponse.result" * "GetTaskPushNotificationConfigParams" * "GetTaskPushNotificationConfigParams.id" * "GetTaskPushNotificationConfigParams.metadata" * "GetTaskPushNotificationConfigParams.model_config" * "GetTaskPushNotificationConfigParams.push_notification_config_id " * "GetTaskPushNotificationConfigRequest" * "GetTaskPushNotificationConfigRequest.id" * "GetTaskPushNotificationConfigRequest.jsonrpc" * "GetTaskPushNotificationConfigRequest.method" * "GetTaskPushNotificationConfigRequest.model_config" * "GetTaskPushNotificationConfigRequest.params" * "GetTaskPushNotificationConfigResponse" * "GetTaskPushNotificationConfigResponse.model_config" * "GetTaskPushNotificationConfigResponse.root" * "GetTaskPushNotificationConfigSuccessResponse" * "GetTaskPushNotificationConfigSuccessResponse.id" * "GetTaskPushNotificationConfigSuccessResponse.jsonrpc" * "GetTaskPushNotificationConfigSuccessResponse.model_config" * "GetTaskPushNotificationConfigSuccessResponse.result" * "GetTaskRequest" * "GetTaskRequest.id" * "GetTaskRequest.jsonrpc" * "GetTaskRequest.method" * "GetTaskRequest.model_config" * "GetTaskRequest.params" * "GetTaskResponse" * "GetTaskResponse.model_config" * "GetTaskResponse.root" * "GetTaskSuccessResponse" * "GetTaskSuccessResponse.id" * "GetTaskSuccessResponse.jsonrpc" * "GetTaskSuccessResponse.model_config" * "GetTaskSuccessResponse.result" * "HTTPAuthSecurityScheme" * "HTTPAuthSecurityScheme.bearer_format" * "HTTPAuthSecurityScheme.description" * "HTTPAuthSecurityScheme.model_config" * "HTTPAuthSecurityScheme.scheme" * "HTTPAuthSecurityScheme.type" * "ImplicitOAuthFlow" * "ImplicitOAuthFlow.authorization_url" * "ImplicitOAuthFlow.model_config" * "ImplicitOAuthFlow.refresh_url" * "ImplicitOAuthFlow.scopes" * "In" * "In.cookie" * "In.header" * "In.query" * "InternalError" * "InternalError.code" * "InternalError.data" * "InternalError.message" * "InternalError.model_config" * "InvalidAgentResponseError" * "InvalidAgentResponseError.code" * "InvalidAgentResponseError.data" * "InvalidAgentResponseError.message" * "InvalidAgentResponseError.model_config" * "InvalidParamsError" * "InvalidParamsError.code" * "InvalidParamsError.data" * "InvalidParamsError.message" * "InvalidParamsError.model_config" * "InvalidRequestError" * "InvalidRequestError.code" * "InvalidRequestError.data" * "InvalidRequestError.message" * "InvalidRequestError.model_config" * "JSONParseError" * "JSONParseError.code" * "JSONParseError.data" * "JSONParseError.message" * "JSONParseError.model_config" * "JSONRPCError" * "JSONRPCError.code" * "JSONRPCError.data" * "JSONRPCError.message" * "JSONRPCError.model_config" * "JSONRPCErrorResponse" * "JSONRPCErrorResponse.error" * "JSONRPCErrorResponse.id" * "JSONRPCErrorResponse.jsonrpc" * "JSONRPCErrorResponse.model_config" * "JSONRPCMessage" * "JSONRPCMessage.id" * "JSONRPCMessage.jsonrpc" * "JSONRPCMessage.model_config" * "JSONRPCRequest" * "JSONRPCRequest.id" * "JSONRPCRequest.jsonrpc" * "JSONRPCRequest.method" * "JSONRPCRequest.model_config" * "JSONRPCRequest.params" * "JSONRPCResponse" * "JSONRPCResponse.model_config" * "JSONRPCResponse.root" * "JSONRPCSuccessResponse" * "JSONRPCSuccessResponse.id" * "JSONRPCSuccessResponse.jsonrpc" * "JSONRPCSuccessResponse.model_config" * "JSONRPCSuccessResponse.result" * "ListTaskPushNotificationConfigParams" * "ListTaskPushNotificationConfigParams.id" * "ListTaskPushNotificationConfigParams.metadata" * "ListTaskPushNotificationConfigParams.model_config" * "ListTaskPushNotificationConfigRequest" * "ListTaskPushNotificationConfigRequest.id" * "ListTaskPushNotificationConfigRequest.jsonrpc" * "ListTaskPushNotificationConfigRequest.method" * "ListTaskPushNotificationConfigRequest.model_config" * "ListTaskPushNotificationConfigRequest.params" * "ListTaskPushNotificationConfigResponse" * "ListTaskPushNotificationConfigResponse.model_config" * "ListTaskPushNotificationConfigResponse.root" * "ListTaskPushNotificationConfigSuccessResponse" * "ListTaskPushNotificationConfigSuccessResponse.id" * "ListTaskPushNotificationConfigSuccessResponse.jsonrpc" * "ListTaskPushNotificationConfigSuccessResponse.model_config" * "ListTaskPushNotificationConfigSuccessResponse.result" * "Message" * "Message.context_id" * "Message.extensions" * "Message.kind" * "Message.message_id" * "Message.metadata" * "Message.model_config" * "Message.parts" * "Message.reference_task_ids" * "Message.role" * "Message.task_id" * "MessageSendConfiguration" * "MessageSendConfiguration.accepted_output_modes" * "MessageSendConfiguration.blocking" * "MessageSendConfiguration.history_length" * "MessageSendConfiguration.model_config" * "MessageSendConfiguration.push_notification_config" * "MessageSendParams" * "MessageSendParams.configuration" * "MessageSendParams.message" * "MessageSendParams.metadata" * "MessageSendParams.model_config" * "MethodNotFoundError" * "MethodNotFoundError.code" * "MethodNotFoundError.data" * "MethodNotFoundError.message" * "MethodNotFoundError.model_config" * "MutualTLSSecurityScheme" * "MutualTLSSecurityScheme.description" * "MutualTLSSecurityScheme.model_config" * "MutualTLSSecurityScheme.type" * "OAuth2SecurityScheme" * "OAuth2SecurityScheme.description" * "OAuth2SecurityScheme.flows" * "OAuth2SecurityScheme.model_config" * "OAuth2SecurityScheme.oauth2_metadata_url" * "OAuth2SecurityScheme.type" * "OAuthFlows" * "OAuthFlows.authorization_code" * "OAuthFlows.client_credentials" * "OAuthFlows.implicit" * "OAuthFlows.model_config" * "OAuthFlows.password" * "OpenIdConnectSecurityScheme" * "OpenIdConnectSecurityScheme.description" * "OpenIdConnectSecurityScheme.model_config" * "OpenIdConnectSecurityScheme.open_id_connect_url" * "OpenIdConnectSecurityScheme.type" * "Part" * "Part.model_config" * "Part.root" * "PartBase" * "PartBase.metadata" * "PartBase.model_config" * "PasswordOAuthFlow" * "PasswordOAuthFlow.model_config" * "PasswordOAuthFlow.refresh_url" * "PasswordOAuthFlow.scopes" * "PasswordOAuthFlow.token_url" * "PushNotificationAuthenticationInfo" * "PushNotificationAuthenticationInfo.credentials" * "PushNotificationAuthenticationInfo.model_config" * "PushNotificationAuthenticationInfo.schemes" * "PushNotificationConfig" * "PushNotificationConfig.authentication" * "PushNotificationConfig.id" * "PushNotificationConfig.model_config" * "PushNotificationConfig.token" * "PushNotificationConfig.url" * "PushNotificationNotSupportedError" * "PushNotificationNotSupportedError.code" * "PushNotificationNotSupportedError.data" * "PushNotificationNotSupportedError.message" * "PushNotificationNotSupportedError.model_config" * "Role" * "Role.agent" * "Role.user" * "SecurityScheme" * "SecurityScheme.model_config" * "SecurityScheme.root" * "SecuritySchemeBase" * "SecuritySchemeBase.description" * "SecuritySchemeBase.model_config" * "SendMessageRequest" * "SendMessageRequest.id" * "SendMessageRequest.jsonrpc" * "SendMessageRequest.method" * "SendMessageRequest.model_config" * "SendMessageRequest.params" * "SendMessageResponse" * "SendMessageResponse.model_config" * "SendMessageResponse.root" * "SendMessageSuccessResponse" * "SendMessageSuccessResponse.id" * "SendMessageSuccessResponse.jsonrpc" * "SendMessageSuccessResponse.model_config" * "SendMessageSuccessResponse.result" * "SendStreamingMessageRequest" * "SendStreamingMessageRequest.id" * "SendStreamingMessageRequest.jsonrpc" * "SendStreamingMessageRequest.method" * "SendStreamingMessageRequest.model_config" * "SendStreamingMessageRequest.params" * "SendStreamingMessageResponse" * "SendStreamingMessageResponse.model_config" * "SendStreamingMessageResponse.root" * "SendStreamingMessageSuccessResponse" * "SendStreamingMessageSuccessResponse.id" * "SendStreamingMessageSuccessResponse.jsonrpc" * "SendStreamingMessageSuccessResponse.model_config" * "SendStreamingMessageSuccessResponse.result" * "SetTaskPushNotificationConfigRequest" * "SetTaskPushNotificationConfigRequest.id" * "SetTaskPushNotificationConfigRequest.jsonrpc" * "SetTaskPushNotificationConfigRequest.method" * "SetTaskPushNotificationConfigRequest.model_config" * "SetTaskPushNotificationConfigRequest.params" * "SetTaskPushNotificationConfigResponse" * "SetTaskPushNotificationConfigResponse.model_config" * "SetTaskPushNotificationConfigResponse.root" * "SetTaskPushNotificationConfigSuccessResponse" * "SetTaskPushNotificationConfigSuccessResponse.id" * "SetTaskPushNotificationConfigSuccessResponse.jsonrpc" * "SetTaskPushNotificationConfigSuccessResponse.model_config" * "SetTaskPushNotificationConfigSuccessResponse.result" * "Task" * "Task.artifacts" * "Task.context_id" * "Task.history" * "Task.id" * "Task.kind" * "Task.metadata" * "Task.model_config" * "Task.status" * "TaskArtifactUpdateEvent" * "TaskArtifactUpdateEvent.append" * "TaskArtifactUpdateEvent.artifact" * "TaskArtifactUpdateEvent.context_id" * "TaskArtifactUpdateEvent.kind" * "TaskArtifactUpdateEvent.last_chunk" * "TaskArtifactUpdateEvent.metadata" * "TaskArtifactUpdateEvent.model_config" * "TaskArtifactUpdateEvent.task_id" * "TaskIdParams" * "TaskIdParams.id" * "TaskIdParams.metadata" * "TaskIdParams.model_config" * "TaskNotCancelableError" * "TaskNotCancelableError.code" * "TaskNotCancelableError.data" * "TaskNotCancelableError.message" * "TaskNotCancelableError.model_config" * "TaskNotFoundError" * "TaskNotFoundError.code" * "TaskNotFoundError.data" * "TaskNotFoundError.message" * "TaskNotFoundError.model_config" * "TaskPushNotificationConfig" * "TaskPushNotificationConfig.model_config" * "TaskPushNotificationConfig.push_notification_config" * "TaskPushNotificationConfig.task_id" * "TaskQueryParams" * "TaskQueryParams.history_length" * "TaskQueryParams.id" * "TaskQueryParams.metadata" * "TaskQueryParams.model_config" * "TaskResubscriptionRequest" * "TaskResubscriptionRequest.id" * "TaskResubscriptionRequest.jsonrpc" * "TaskResubscriptionRequest.method" * "TaskResubscriptionRequest.model_config" * "TaskResubscriptionRequest.params" * "TaskState" * "TaskState.auth_required" * "TaskState.canceled" * "TaskState.completed" * "TaskState.failed" * "TaskState.input_required" * "TaskState.rejected" * "TaskState.submitted" * "TaskState.unknown" * "TaskState.working" * "TaskStatus" * "TaskStatus.message" * "TaskStatus.model_config" * "TaskStatus.state" * "TaskStatus.timestamp" * "TaskStatusUpdateEvent" * "TaskStatusUpdateEvent.context_id" * "TaskStatusUpdateEvent.final" * "TaskStatusUpdateEvent.kind" * "TaskStatusUpdateEvent.metadata" * "TaskStatusUpdateEvent.model_config" * "TaskStatusUpdateEvent.status" * "TaskStatusUpdateEvent.task_id" * "TextPart" * "TextPart.kind" * "TextPart.metadata" * "TextPart.model_config" * "TextPart.text" * "TransportProtocol" * "TransportProtocol.grpc" * "TransportProtocol.http_json" * "TransportProtocol.jsonrpc" * "UnsupportedOperationError" * "UnsupportedOperationError.code" * "UnsupportedOperationError.data" * "UnsupportedOperationError.message" * "UnsupportedOperationError.model_config" * a2a.compat.v0_3.versions module * "is_legacy_version()" Module contents =============== a2a.compat.v0_3.types module **************************** class a2a.compat.v0_3.types.A2A(root: RootModelRootType = PydanticUndefined) Bases: "RootModel[Any]" model_config = {} Configuration for the model, should be a dictionary conforming to [*ConfigDict*][pydantic.config.ConfigDict]. root: Any class a2a.compat.v0_3.types.A2AError(root: RootModelRootType = PydanticUndefined) Bases: "RootModel[Union[JSONParseError, InvalidRequestError, MethodNotFoundError, InvalidParamsError, InternalError, TaskNotFoundError, TaskNotCancelableError, PushNotificationNotSupportedError, UnsupportedOperationError, ContentTypeNotSupportedError, InvalidAgentResponseError, AuthenticatedExtendedCardNotConfiguredError]]" model_config = {} Configuration for the model, should be a dictionary conforming to [*ConfigDict*][pydantic.config.ConfigDict]. root: JSONParseError | InvalidRequestError | MethodNotFoundError | InvalidParamsError | InternalError | TaskNotFoundError | TaskNotCancelableError | PushNotificationNotSupportedError | UnsupportedOperationError | ContentTypeNotSupportedError | InvalidAgentResponseError | AuthenticatedExtendedCardNotConfiguredError A discriminated union of all standard JSON-RPC and A2A-specific error types. class a2a.compat.v0_3.types.A2ARequest(root: RootModelRootType = PydanticUndefined) Bases: "RootModel[Union[SendMessageRequest, SendStreamingMessageRequest, GetTaskRequest, CancelTaskRequest, SetTaskPushNotificationConfigRequest, GetTaskPushNotificationConfigRequest, TaskResubscriptionRequest, ListTaskPushNotificationConfigRequest, DeleteTaskPushNotificationConfigRequest, GetAuthenticatedExtendedCardRequest]]" model_config = {} Configuration for the model, should be a dictionary conforming to [*ConfigDict*][pydantic.config.ConfigDict]. root: SendMessageRequest | SendStreamingMessageRequest | GetTaskRequest | CancelTaskRequest | SetTaskPushNotificationConfigRequest | GetTaskPushNotificationConfigRequest | TaskResubscriptionRequest | ListTaskPushNotificationConfigRequest | DeleteTaskPushNotificationConfigRequest | GetAuthenticatedExtendedCardRequest A discriminated union representing all possible JSON-RPC 2.0 requests supported by the A2A specification. class a2a.compat.v0_3.types.APIKeySecurityScheme(*, description: str | None = None, in_: In, name: str, type: Literal['apiKey'] = 'apiKey') Bases: "A2ABaseModel" Defines a security scheme using an API key. description: str | None An optional description for the security scheme. in_: In The location of the API key. model_config = {'alias_generator': , 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True} Configuration for the model, should be a dictionary conforming to [*ConfigDict*][pydantic.config.ConfigDict]. name: str The name of the header, query, or cookie parameter to be used. type: Literal['apiKey'] The type of the security scheme. Must be 'apiKey'. class a2a.compat.v0_3.types.AgentCapabilities(*, extensions: list[AgentExtension] | None = None, pushNotifications: bool | None = None, stateTransitionHistory: bool | None = None, streaming: bool | None = None) Bases: "A2ABaseModel" Defines optional capabilities supported by an agent. extensions: list[AgentExtension] | None A list of protocol extensions supported by the agent. model_config = {'alias_generator': , 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True} Configuration for the model, should be a dictionary conforming to [*ConfigDict*][pydantic.config.ConfigDict]. push_notifications: bool | None Indicates if the agent supports sending push notifications for asynchronous task updates. state_transition_history: bool | None Indicates if the agent provides a history of state transitions for a task. streaming: bool | None Indicates if the agent supports Server-Sent Events (SSE) for streaming responses. class a2a.compat.v0_3.types.AgentCard(*, additionalInterfaces: list[AgentInterface] | None = None, capabilities: AgentCapabilities, defaultInputModes: list[str], defaultOutputModes: list[str], description: str, documentationUrl: str | None = None, iconUrl: str | None = None, name: str, preferredTransport: str | None = 'JSONRPC', protocolVersion: str | None = '0.3.0', provider: AgentProvider | None = None, security: list[dict[str, list[str]]] | None = None, securitySchemes: dict[str, SecurityScheme] | None = None, signatures: list[AgentCardSignature] | None = None, skills: list[AgentSkill], supportsAuthenticatedExtendedCard: bool | None = None, url: str, version: str) Bases: "A2ABaseModel" The AgentCard is a self-describing manifest for an agent. It provides essential metadata including the agent's identity, capabilities, skills, supported communication methods, and security requirements. additional_interfaces: list[AgentInterface] | None A list of additional supported interfaces (transport and URL combinations). This allows agents to expose multiple transports, potentially at different URLs. Best practices: - SHOULD include all supported transports for completeness - SHOULD include an entry matching the main 'url' and 'preferredTransport' - MAY reuse URLs if multiple transports are available at the same endpoint - MUST accurately declare the transport available at each URL Clients can select any interface from this list based on their transport capabilities and preferences. This enables transport negotiation and fallback scenarios. capabilities: AgentCapabilities A declaration of optional capabilities supported by the agent. default_input_modes: list[str] Default set of supported input MIME types for all skills, which can be overridden on a per-skill basis. default_output_modes: list[str] Default set of supported output MIME types for all skills, which can be overridden on a per-skill basis. description: str A human-readable description of the agent, assisting users and other agents in understanding its purpose. documentation_url: str | None An optional URL to the agent's documentation. icon_url: str | None An optional URL to an icon for the agent. model_config = {'alias_generator': , 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True} Configuration for the model, should be a dictionary conforming to [*ConfigDict*][pydantic.config.ConfigDict]. name: str A human-readable name for the agent. preferred_transport: str | None The transport protocol for the preferred endpoint (the main 'url' field). If not specified, defaults to 'JSONRPC'. IMPORTANT: The transport specified here MUST be available at the main 'url'. This creates a binding between the main URL and its supported transport protocol. Clients should prefer this transport and URL combination when both are supported. protocol_version: str | None The version of the A2A protocol this agent supports. provider: AgentProvider | None Information about the agent's service provider. security: list[dict[str, list[str]]] | None A list of security requirement objects that apply to all agent interactions. Each object lists security schemes that can be used. Follows the OpenAPI 3.0 Security Requirement Object. This list can be seen as an OR of ANDs. Each object in the list describes one possible set of security requirements that must be present on a request. This allows specifying, for example, "callers must either use OAuth OR an API Key AND mTLS." security_schemes: dict[str, SecurityScheme] | None A declaration of the security schemes available to authorize requests. The key is the scheme name. Follows the OpenAPI 3.0 Security Scheme Object. signatures: list[AgentCardSignature] | None JSON Web Signatures computed for this AgentCard. skills: list[AgentSkill] The set of skills, or distinct capabilities, that the agent can perform. supports_authenticated_extended_card: bool | None If true, the agent can provide an extended agent card with additional details to authenticated users. Defaults to false. url: str The preferred endpoint URL for interacting with the agent. This URL MUST support the transport specified by 'preferredTransport'. version: str The agent's own version number. The format is defined by the provider. class a2a.compat.v0_3.types.AgentCardSignature(*, header: dict[str, Any] | None = None, protected: str, signature: str) Bases: "A2ABaseModel" AgentCardSignature represents a JWS signature of an AgentCard. This follows the JSON format of an RFC 7515 JSON Web Signature (JWS). header: dict[str, Any] | None The unprotected JWS header values. model_config = {'alias_generator': , 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True} Configuration for the model, should be a dictionary conforming to [*ConfigDict*][pydantic.config.ConfigDict]. protected: str The protected JWS header for the signature. This is a Base64url- encoded JSON object, as per RFC 7515. signature: str The computed signature, Base64url-encoded. class a2a.compat.v0_3.types.AgentExtension(*, description: str | None = None, params: dict[str, Any] | None = None, required: bool | None = None, uri: str) Bases: "A2ABaseModel" A declaration of a protocol extension supported by an Agent. description: str | None A human-readable description of how this agent uses the extension. model_config = {'alias_generator': , 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True} Configuration for the model, should be a dictionary conforming to [*ConfigDict*][pydantic.config.ConfigDict]. params: dict[str, Any] | None Optional, extension-specific configuration parameters. required: bool | None If true, the client must understand and comply with the extension's requirements to interact with the agent. uri: str The unique URI identifying the extension. class a2a.compat.v0_3.types.AgentInterface(*, transport: str, url: str) Bases: "A2ABaseModel" Declares a combination of a target URL and a transport protocol for interacting with the agent. This allows agents to expose the same functionality over multiple transport mechanisms. model_config = {'alias_generator': , 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True} Configuration for the model, should be a dictionary conforming to [*ConfigDict*][pydantic.config.ConfigDict]. transport: str The transport protocol supported at this URL. url: str The URL where this interface is available. Must be a valid absolute HTTPS URL in production. class a2a.compat.v0_3.types.AgentProvider(*, organization: str, url: str) Bases: "A2ABaseModel" Represents the service provider of an agent. model_config = {'alias_generator': , 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True} Configuration for the model, should be a dictionary conforming to [*ConfigDict*][pydantic.config.ConfigDict]. organization: str The name of the agent provider's organization. url: str A URL for the agent provider's website or relevant documentation. class a2a.compat.v0_3.types.AgentSkill(*, description: str, examples: list[str] | None = None, id: str, inputModes: list[str] | None = None, name: str, outputModes: list[str] | None = None, security: list[dict[str, list[str]]] | None = None, tags: list[str]) Bases: "A2ABaseModel" Represents a distinct capability or function that an agent can perform. description: str A detailed description of the skill, intended to help clients or users understand its purpose and functionality. examples: list[str] | None Example prompts or scenarios that this skill can handle. Provides a hint to the client on how to use the skill. id: str A unique identifier for the agent's skill. input_modes: list[str] | None The set of supported input MIME types for this skill, overriding the agent's defaults. model_config = {'alias_generator': , 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True} Configuration for the model, should be a dictionary conforming to [*ConfigDict*][pydantic.config.ConfigDict]. name: str A human-readable name for the skill. output_modes: list[str] | None The set of supported output MIME types for this skill, overriding the agent's defaults. security: list[dict[str, list[str]]] | None Security schemes necessary for the agent to leverage this skill. As in the overall AgentCard.security, this list represents a logical OR of security requirement objects. Each object is a set of security schemes that must be used together (a logical AND). tags: list[str] A set of keywords describing the skill's capabilities. class a2a.compat.v0_3.types.Artifact(*, artifactId: str, description: str | None = None, extensions: list[str] | None = None, metadata: dict[str, Any] | None = None, name: str | None = None, parts: list[Part]) Bases: "A2ABaseModel" Represents a file, data structure, or other resource generated by an agent during a task. artifact_id: str A unique identifier (e.g. UUID) for the artifact within the scope of the task. description: str | None An optional, human-readable description of the artifact. extensions: list[str] | None The URIs of extensions that are relevant to this artifact. metadata: dict[str, Any] | None Optional metadata for extensions. The key is an extension- specific identifier. model_config = {'alias_generator': , 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True} Configuration for the model, should be a dictionary conforming to [*ConfigDict*][pydantic.config.ConfigDict]. name: str | None An optional, human-readable name for the artifact. parts: list[Part] An array of content parts that make up the artifact. class a2a.compat.v0_3.types.AuthenticatedExtendedCardNotConfiguredError(*, code: Literal[-32007] = -32007, data: Any | None = None, message: str | None = 'Authenticated Extended Card is not configured') Bases: "A2ABaseModel" An A2A-specific error indicating that the agent does not have an Authenticated Extended Card configured code: Literal[-32007] The error code for when an authenticated extended card is not configured. data: Any | None A primitive or structured value containing additional information about the error. This may be omitted. message: str | None The error message. model_config = {'alias_generator': , 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True} Configuration for the model, should be a dictionary conforming to [*ConfigDict*][pydantic.config.ConfigDict]. class a2a.compat.v0_3.types.AuthorizationCodeOAuthFlow(*, authorizationUrl: str, refreshUrl: str | None = None, scopes: dict[str, str], tokenUrl: str) Bases: "A2ABaseModel" Defines configuration details for the OAuth 2.0 Authorization Code flow. authorization_url: str The authorization URL to be used for this flow. This MUST be a URL and use TLS. model_config = {'alias_generator': , 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True} Configuration for the model, should be a dictionary conforming to [*ConfigDict*][pydantic.config.ConfigDict]. refresh_url: str | None The URL to be used for obtaining refresh tokens. This MUST be a URL and use TLS. scopes: dict[str, str] The available scopes for the OAuth2 security scheme. A map between the scope name and a short description for it. token_url: str The token URL to be used for this flow. This MUST be a URL and use TLS. class a2a.compat.v0_3.types.CancelTaskRequest(*, id: str | int, jsonrpc: Literal['2.0'] = '2.0', method: Literal['tasks/cancel'] = 'tasks/cancel', params: TaskIdParams) Bases: "A2ABaseModel" Represents a JSON-RPC request for the *tasks/cancel* method. id: str | int The identifier for this request. jsonrpc: Literal['2.0'] The version of the JSON-RPC protocol. MUST be exactly "2.0". method: Literal['tasks/cancel'] The method name. Must be 'tasks/cancel'. model_config = {'alias_generator': , 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True} Configuration for the model, should be a dictionary conforming to [*ConfigDict*][pydantic.config.ConfigDict]. params: TaskIdParams The parameters identifying the task to cancel. class a2a.compat.v0_3.types.CancelTaskResponse(root: RootModelRootType = PydanticUndefined) Bases: "RootModel[Union[JSONRPCErrorResponse, CancelTaskSuccessResponse]]" model_config = {} Configuration for the model, should be a dictionary conforming to [*ConfigDict*][pydantic.config.ConfigDict]. root: JSONRPCErrorResponse | CancelTaskSuccessResponse Represents a JSON-RPC response for the *tasks/cancel* method. class a2a.compat.v0_3.types.CancelTaskSuccessResponse(*, id: str | int | None = None, jsonrpc: Literal['2.0'] = '2.0', result: Task) Bases: "A2ABaseModel" Represents a successful JSON-RPC response for the *tasks/cancel* method. id: str | int | None The identifier established by the client. jsonrpc: Literal['2.0'] The version of the JSON-RPC protocol. MUST be exactly "2.0". model_config = {'alias_generator': , 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True} Configuration for the model, should be a dictionary conforming to [*ConfigDict*][pydantic.config.ConfigDict]. result: Task The result, containing the final state of the canceled Task object. class a2a.compat.v0_3.types.ClientCredentialsOAuthFlow(*, refreshUrl: str | None = None, scopes: dict[str, str], tokenUrl: str) Bases: "A2ABaseModel" Defines configuration details for the OAuth 2.0 Client Credentials flow. model_config = {'alias_generator': , 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True} Configuration for the model, should be a dictionary conforming to [*ConfigDict*][pydantic.config.ConfigDict]. refresh_url: str | None The URL to be used for obtaining refresh tokens. This MUST be a URL. scopes: dict[str, str] The available scopes for the OAuth2 security scheme. A map between the scope name and a short description for it. token_url: str The token URL to be used for this flow. This MUST be a URL. class a2a.compat.v0_3.types.ContentTypeNotSupportedError(*, code: Literal[-32005] = -32005, data: Any | None = None, message: str | None = 'Incompatible content types') Bases: "A2ABaseModel" An A2A-specific error indicating an incompatibility between the requested content types and the agent's capabilities. code: Literal[-32005] The error code for an unsupported content type. data: Any | None A primitive or structured value containing additional information about the error. This may be omitted. message: str | None The error message. model_config = {'alias_generator': , 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True} Configuration for the model, should be a dictionary conforming to [*ConfigDict*][pydantic.config.ConfigDict]. class a2a.compat.v0_3.types.DataPart(*, data: dict[str, Any], kind: Literal['data'] = 'data', metadata: dict[str, Any] | None = None) Bases: "A2ABaseModel" Represents a structured data segment (e.g., JSON) within a message or artifact. data: dict[str, Any] The structured data content. kind: Literal['data'] The type of this part, used as a discriminator. Always 'data'. metadata: dict[str, Any] | None Optional metadata associated with this part. model_config = {'alias_generator': , 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True} Configuration for the model, should be a dictionary conforming to [*ConfigDict*][pydantic.config.ConfigDict]. class a2a.compat.v0_3.types.DeleteTaskPushNotificationConfigParams(*, id: str, metadata: dict[str, Any] | None = None, pushNotificationConfigId: str) Bases: "A2ABaseModel" Defines parameters for deleting a specific push notification configuration for a task. id: str The unique identifier (e.g. UUID) of the task. metadata: dict[str, Any] | None Optional metadata associated with the request. model_config = {'alias_generator': , 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True} Configuration for the model, should be a dictionary conforming to [*ConfigDict*][pydantic.config.ConfigDict]. push_notification_config_id: str The ID of the push notification configuration to delete. class a2a.compat.v0_3.types.DeleteTaskPushNotificationConfigRequest(*, id: str | int, jsonrpc: Literal['2.0'] = '2.0', method: Literal['tasks/pushNotificationConfig/delete'] = 'tasks/pushNotificationConfig/delete', params: DeleteTaskPushNotificationConfigParams) Bases: "A2ABaseModel" Represents a JSON-RPC request for the *tasks/pushNotificationConfig/delete* method. id: str | int The identifier for this request. jsonrpc: Literal['2.0'] The version of the JSON-RPC protocol. MUST be exactly "2.0". method: Literal['tasks/pushNotificationConfig/delete'] The method name. Must be 'tasks/pushNotificationConfig/delete'. model_config = {'alias_generator': , 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True} Configuration for the model, should be a dictionary conforming to [*ConfigDict*][pydantic.config.ConfigDict]. params: DeleteTaskPushNotificationConfigParams The parameters identifying the push notification configuration to delete. class a2a.compat.v0_3.types.DeleteTaskPushNotificationConfigResponse(root: RootModelRootType = PydanticUndefined) Bases: "RootModel[Union[JSONRPCErrorResponse, DeleteTaskPushNotificationConfigSuccessResponse]]" model_config = {} Configuration for the model, should be a dictionary conforming to [*ConfigDict*][pydantic.config.ConfigDict]. root: JSONRPCErrorResponse | DeleteTaskPushNotificationConfigSuccessResponse Represents a JSON-RPC response for the *tasks/pushNotificationConfig/delete* method. class a2a.compat.v0_3.types.DeleteTaskPushNotificationConfigSuccessResponse(*, id: str | int | None = None, jsonrpc: Literal['2.0'] = '2.0', result: None) Bases: "A2ABaseModel" Represents a successful JSON-RPC response for the *tasks/pushNotificationConfig/delete* method. id: str | int | None The identifier established by the client. jsonrpc: Literal['2.0'] The version of the JSON-RPC protocol. MUST be exactly "2.0". model_config = {'alias_generator': , 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True} Configuration for the model, should be a dictionary conforming to [*ConfigDict*][pydantic.config.ConfigDict]. result: None The result is null on successful deletion. class a2a.compat.v0_3.types.FileBase(*, mimeType: str | None = None, name: str | None = None) Bases: "A2ABaseModel" Defines base properties for a file. mime_type: str | None The MIME type of the file (e.g., "application/pdf"). model_config = {'alias_generator': , 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True} Configuration for the model, should be a dictionary conforming to [*ConfigDict*][pydantic.config.ConfigDict]. name: str | None An optional name for the file (e.g., "document.pdf"). class a2a.compat.v0_3.types.FilePart(*, file: FileWithBytes | FileWithUri, kind: Literal['file'] = 'file', metadata: dict[str, Any] | None = None) Bases: "A2ABaseModel" Represents a file segment within a message or artifact. The file content can be provided either directly as bytes or as a URI. file: FileWithBytes | FileWithUri The file content, represented as either a URI or as base64-encoded bytes. kind: Literal['file'] The type of this part, used as a discriminator. Always 'file'. metadata: dict[str, Any] | None Optional metadata associated with this part. model_config = {'alias_generator': , 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True} Configuration for the model, should be a dictionary conforming to [*ConfigDict*][pydantic.config.ConfigDict]. class a2a.compat.v0_3.types.FileWithBytes(*, bytes: str, mimeType: str | None = None, name: str | None = None) Bases: "A2ABaseModel" Represents a file with its content provided directly as a base64-encoded string. bytes: str The base64-encoded content of the file. mime_type: str | None The MIME type of the file (e.g., "application/pdf"). model_config = {'alias_generator': , 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True} Configuration for the model, should be a dictionary conforming to [*ConfigDict*][pydantic.config.ConfigDict]. name: str | None An optional name for the file (e.g., "document.pdf"). class a2a.compat.v0_3.types.FileWithUri(*, mimeType: str | None = None, name: str | None = None, uri: str) Bases: "A2ABaseModel" Represents a file with its content located at a specific URI. mime_type: str | None The MIME type of the file (e.g., "application/pdf"). model_config = {'alias_generator': , 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True} Configuration for the model, should be a dictionary conforming to [*ConfigDict*][pydantic.config.ConfigDict]. name: str | None An optional name for the file (e.g., "document.pdf"). uri: str A URL pointing to the file's content. class a2a.compat.v0_3.types.GetAuthenticatedExtendedCardRequest(*, id: str | int, jsonrpc: Literal['2.0'] = '2.0', method: Literal['agent/getAuthenticatedExtendedCard'] = 'agent/getAuthenticatedExtendedCard') Bases: "A2ABaseModel" Represents a JSON-RPC request for the *agent/getAuthenticatedExtendedCard* method. id: str | int The identifier for this request. jsonrpc: Literal['2.0'] The version of the JSON-RPC protocol. MUST be exactly "2.0". method: Literal['agent/getAuthenticatedExtendedCard'] The method name. Must be 'agent/getAuthenticatedExtendedCard'. model_config = {'alias_generator': , 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True} Configuration for the model, should be a dictionary conforming to [*ConfigDict*][pydantic.config.ConfigDict]. class a2a.compat.v0_3.types.GetAuthenticatedExtendedCardResponse(root: RootModelRootType = PydanticUndefined) Bases: "RootModel[Union[JSONRPCErrorResponse, GetAuthenticatedExtendedCardSuccessResponse]]" model_config = {} Configuration for the model, should be a dictionary conforming to [*ConfigDict*][pydantic.config.ConfigDict]. root: JSONRPCErrorResponse | GetAuthenticatedExtendedCardSuccessResponse Represents a JSON-RPC response for the *agent/getAuthenticatedExtendedCard* method. class a2a.compat.v0_3.types.GetAuthenticatedExtendedCardSuccessResponse(*, id: str | int | None = None, jsonrpc: Literal['2.0'] = '2.0', result: AgentCard) Bases: "A2ABaseModel" Represents a successful JSON-RPC response for the *agent/getAuthenticatedExtendedCard* method. id: str | int | None The identifier established by the client. jsonrpc: Literal['2.0'] The version of the JSON-RPC protocol. MUST be exactly "2.0". model_config = {'alias_generator': , 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True} Configuration for the model, should be a dictionary conforming to [*ConfigDict*][pydantic.config.ConfigDict]. result: AgentCard The result is an Agent Card object. class a2a.compat.v0_3.types.GetTaskPushNotificationConfigParams(*, id: str, metadata: dict[str, Any] | None = None, pushNotificationConfigId: str | None = None) Bases: "A2ABaseModel" Defines parameters for fetching a specific push notification configuration for a task. id: str The unique identifier (e.g. UUID) of the task. metadata: dict[str, Any] | None Optional metadata associated with the request. model_config = {'alias_generator': , 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True} Configuration for the model, should be a dictionary conforming to [*ConfigDict*][pydantic.config.ConfigDict]. push_notification_config_id: str | None The ID of the push notification configuration to retrieve. class a2a.compat.v0_3.types.GetTaskPushNotificationConfigRequest(*, id: str | int, jsonrpc: Literal['2.0'] = '2.0', method: Literal['tasks/pushNotificationConfig/get'] = 'tasks/pushNotificationConfig/get', params: TaskIdParams | GetTaskPushNotificationConfigParams) Bases: "A2ABaseModel" Represents a JSON-RPC request for the *tasks/pushNotificationConfig/get* method. id: str | int The identifier for this request. jsonrpc: Literal['2.0'] The version of the JSON-RPC protocol. MUST be exactly "2.0". method: Literal['tasks/pushNotificationConfig/get'] The method name. Must be 'tasks/pushNotificationConfig/get'. model_config = {'alias_generator': , 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True} Configuration for the model, should be a dictionary conforming to [*ConfigDict*][pydantic.config.ConfigDict]. params: TaskIdParams | GetTaskPushNotificationConfigParams The parameters for getting a push notification configuration. class a2a.compat.v0_3.types.GetTaskPushNotificationConfigResponse(root: RootModelRootType = PydanticUndefined) Bases: "RootModel[Union[JSONRPCErrorResponse, GetTaskPushNotificationConfigSuccessResponse]]" model_config = {} Configuration for the model, should be a dictionary conforming to [*ConfigDict*][pydantic.config.ConfigDict]. root: JSONRPCErrorResponse | GetTaskPushNotificationConfigSuccessResponse Represents a JSON-RPC response for the *tasks/pushNotificationConfig/get* method. class a2a.compat.v0_3.types.GetTaskPushNotificationConfigSuccessResponse(*, id: str | int | None = None, jsonrpc: Literal['2.0'] = '2.0', result: TaskPushNotificationConfig) Bases: "A2ABaseModel" Represents a successful JSON-RPC response for the *tasks/pushNotificationConfig/get* method. id: str | int | None The identifier established by the client. jsonrpc: Literal['2.0'] The version of the JSON-RPC protocol. MUST be exactly "2.0". model_config = {'alias_generator': , 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True} Configuration for the model, should be a dictionary conforming to [*ConfigDict*][pydantic.config.ConfigDict]. result: TaskPushNotificationConfig The result, containing the requested push notification configuration. class a2a.compat.v0_3.types.GetTaskRequest(*, id: str | int, jsonrpc: Literal['2.0'] = '2.0', method: Literal['tasks/get'] = 'tasks/get', params: TaskQueryParams) Bases: "A2ABaseModel" Represents a JSON-RPC request for the *tasks/get* method. id: str | int The identifier for this request. jsonrpc: Literal['2.0'] The version of the JSON-RPC protocol. MUST be exactly "2.0". method: Literal['tasks/get'] The method name. Must be 'tasks/get'. model_config = {'alias_generator': , 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True} Configuration for the model, should be a dictionary conforming to [*ConfigDict*][pydantic.config.ConfigDict]. params: TaskQueryParams The parameters for querying a task. class a2a.compat.v0_3.types.GetTaskResponse(root: RootModelRootType = PydanticUndefined) Bases: "RootModel[Union[JSONRPCErrorResponse, GetTaskSuccessResponse]]" model_config = {} Configuration for the model, should be a dictionary conforming to [*ConfigDict*][pydantic.config.ConfigDict]. root: JSONRPCErrorResponse | GetTaskSuccessResponse Represents a JSON-RPC response for the *tasks/get* method. class a2a.compat.v0_3.types.GetTaskSuccessResponse(*, id: str | int | None = None, jsonrpc: Literal['2.0'] = '2.0', result: Task) Bases: "A2ABaseModel" Represents a successful JSON-RPC response for the *tasks/get* method. id: str | int | None The identifier established by the client. jsonrpc: Literal['2.0'] The version of the JSON-RPC protocol. MUST be exactly "2.0". model_config = {'alias_generator': , 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True} Configuration for the model, should be a dictionary conforming to [*ConfigDict*][pydantic.config.ConfigDict]. result: Task The result, containing the requested Task object. class a2a.compat.v0_3.types.HTTPAuthSecurityScheme(*, bearerFormat: str | None = None, description: str | None = None, scheme: str, type: Literal['http'] = 'http') Bases: "A2ABaseModel" Defines a security scheme using HTTP authentication. bearer_format: str | None A hint to the client to identify how the bearer token is formatted (e.g., "JWT"). This is primarily for documentation purposes. description: str | None An optional description for the security scheme. model_config = {'alias_generator': , 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True} Configuration for the model, should be a dictionary conforming to [*ConfigDict*][pydantic.config.ConfigDict]. scheme: str The name of the HTTP Authentication scheme to be used in the Authorization header, as defined in RFC7235 (e.g., "Bearer"). This value should be registered in the IANA Authentication Scheme registry. type: Literal['http'] The type of the security scheme. Must be 'http'. class a2a.compat.v0_3.types.ImplicitOAuthFlow(*, authorizationUrl: str, refreshUrl: str | None = None, scopes: dict[str, str]) Bases: "A2ABaseModel" Defines configuration details for the OAuth 2.0 Implicit flow. authorization_url: str The authorization URL to be used for this flow. This MUST be a URL. model_config = {'alias_generator': , 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True} Configuration for the model, should be a dictionary conforming to [*ConfigDict*][pydantic.config.ConfigDict]. refresh_url: str | None The URL to be used for obtaining refresh tokens. This MUST be a URL. scopes: dict[str, str] The available scopes for the OAuth2 security scheme. A map between the scope name and a short description for it. class a2a.compat.v0_3.types.In(*values) Bases: "str", "Enum" The location of the API key. cookie = 'cookie' header = 'header' query = 'query' class a2a.compat.v0_3.types.InternalError(*, code: Literal[-32603] = -32603, data: Any | None = None, message: str | None = 'Internal error') Bases: "A2ABaseModel" An error indicating an internal error on the server. code: Literal[-32603] The error code for an internal server error. data: Any | None A primitive or structured value containing additional information about the error. This may be omitted. message: str | None The error message. model_config = {'alias_generator': , 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True} Configuration for the model, should be a dictionary conforming to [*ConfigDict*][pydantic.config.ConfigDict]. class a2a.compat.v0_3.types.InvalidAgentResponseError(*, code: Literal[-32006] = -32006, data: Any | None = None, message: str | None = 'Invalid agent response') Bases: "A2ABaseModel" An A2A-specific error indicating that the agent returned a response that does not conform to the specification for the current method. code: Literal[-32006] The error code for an invalid agent response. data: Any | None A primitive or structured value containing additional information about the error. This may be omitted. message: str | None The error message. model_config = {'alias_generator': , 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True} Configuration for the model, should be a dictionary conforming to [*ConfigDict*][pydantic.config.ConfigDict]. class a2a.compat.v0_3.types.InvalidParamsError(*, code: Literal[-32602] = -32602, data: Any | None = None, message: str | None = 'Invalid parameters') Bases: "A2ABaseModel" An error indicating that the method parameters are invalid. code: Literal[-32602] The error code for an invalid parameters error. data: Any | None A primitive or structured value containing additional information about the error. This may be omitted. message: str | None The error message. model_config = {'alias_generator': , 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True} Configuration for the model, should be a dictionary conforming to [*ConfigDict*][pydantic.config.ConfigDict]. class a2a.compat.v0_3.types.InvalidRequestError(*, code: Literal[-32600] = -32600, data: Any | None = None, message: str | None = 'Request payload validation error') Bases: "A2ABaseModel" An error indicating that the JSON sent is not a valid Request object. code: Literal[-32600] The error code for an invalid request. data: Any | None A primitive or structured value containing additional information about the error. This may be omitted. message: str | None The error message. model_config = {'alias_generator': , 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True} Configuration for the model, should be a dictionary conforming to [*ConfigDict*][pydantic.config.ConfigDict]. class a2a.compat.v0_3.types.JSONParseError(*, code: Literal[-32700] = -32700, data: Any | None = None, message: str | None = 'Invalid JSON payload') Bases: "A2ABaseModel" An error indicating that the server received invalid JSON. code: Literal[-32700] The error code for a JSON parse error. data: Any | None A primitive or structured value containing additional information about the error. This may be omitted. message: str | None The error message. model_config = {'alias_generator': , 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True} Configuration for the model, should be a dictionary conforming to [*ConfigDict*][pydantic.config.ConfigDict]. class a2a.compat.v0_3.types.JSONRPCError(*, code: int, data: Any | None = None, message: str) Bases: "A2ABaseModel" Represents a JSON-RPC 2.0 Error object, included in an error response. code: int A number that indicates the error type that occurred. data: Any | None A primitive or structured value containing additional information about the error. This may be omitted. message: str A string providing a short description of the error. model_config = {'alias_generator': , 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True} Configuration for the model, should be a dictionary conforming to [*ConfigDict*][pydantic.config.ConfigDict]. class a2a.compat.v0_3.types.JSONRPCErrorResponse(*, error: JSONRPCError | JSONParseError | InvalidRequestError | MethodNotFoundError | InvalidParamsError | InternalError | TaskNotFoundError | TaskNotCancelableError | PushNotificationNotSupportedError | UnsupportedOperationError | ContentTypeNotSupportedError | InvalidAgentResponseError | AuthenticatedExtendedCardNotConfiguredError, id: str | int | None = None, jsonrpc: Literal['2.0'] = '2.0') Bases: "A2ABaseModel" Represents a JSON-RPC 2.0 Error Response object. error: JSONRPCError | JSONParseError | InvalidRequestError | MethodNotFoundError | InvalidParamsError | InternalError | TaskNotFoundError | TaskNotCancelableError | PushNotificationNotSupportedError | UnsupportedOperationError | ContentTypeNotSupportedError | InvalidAgentResponseError | AuthenticatedExtendedCardNotConfiguredError An object describing the error that occurred. id: str | int | None The identifier established by the client. jsonrpc: Literal['2.0'] The version of the JSON-RPC protocol. MUST be exactly "2.0". model_config = {'alias_generator': , 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True} Configuration for the model, should be a dictionary conforming to [*ConfigDict*][pydantic.config.ConfigDict]. class a2a.compat.v0_3.types.JSONRPCMessage(*, id: str | int | None = None, jsonrpc: Literal['2.0'] = '2.0') Bases: "A2ABaseModel" Defines the base structure for any JSON-RPC 2.0 request, response, or notification. id: str | int | None A unique identifier established by the client. It must be a String, a Number, or null. The server must reply with the same value in the response. This property is omitted for notifications. jsonrpc: Literal['2.0'] The version of the JSON-RPC protocol. MUST be exactly "2.0". model_config = {'alias_generator': , 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True} Configuration for the model, should be a dictionary conforming to [*ConfigDict*][pydantic.config.ConfigDict]. class a2a.compat.v0_3.types.JSONRPCRequest(*, id: str | int | None = None, jsonrpc: Literal['2.0'] = '2.0', method: str, params: dict[str, Any] | None = None) Bases: "A2ABaseModel" Represents a JSON-RPC 2.0 Request object. id: str | int | None A unique identifier established by the client. It must be a String, a Number, or null. The server must reply with the same value in the response. This property is omitted for notifications. jsonrpc: Literal['2.0'] The version of the JSON-RPC protocol. MUST be exactly "2.0". method: str A string containing the name of the method to be invoked. model_config = {'alias_generator': , 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True} Configuration for the model, should be a dictionary conforming to [*ConfigDict*][pydantic.config.ConfigDict]. params: dict[str, Any] | None A structured value holding the parameter values to be used during the method invocation. class a2a.compat.v0_3.types.JSONRPCResponse(root: RootModelRootType = PydanticUndefined) Bases: "RootModel[Union[JSONRPCErrorResponse, SendMessageSuccessResponse, SendStreamingMessageSuccessResponse, GetTaskSuccessResponse, CancelTaskSuccessResponse, SetTaskPushNotificationConfigSuccessResponse, GetTaskPushNotificationConfigSuccessResponse, ListTaskPushNotificationConfigSuccessResponse, DeleteTaskPushNotificationConfigSuccessResponse, GetAuthenticatedExtendedCardSuccessResponse]]" model_config = {} Configuration for the model, should be a dictionary conforming to [*ConfigDict*][pydantic.config.ConfigDict]. root: JSONRPCErrorResponse | SendMessageSuccessResponse | SendStreamingMessageSuccessResponse | GetTaskSuccessResponse | CancelTaskSuccessResponse | SetTaskPushNotificationConfigSuccessResponse | GetTaskPushNotificationConfigSuccessResponse | ListTaskPushNotificationConfigSuccessResponse | DeleteTaskPushNotificationConfigSuccessResponse | GetAuthenticatedExtendedCardSuccessResponse A discriminated union representing all possible JSON-RPC 2.0 responses for the A2A specification methods. class a2a.compat.v0_3.types.JSONRPCSuccessResponse(*, id: str | int | None = None, jsonrpc: Literal['2.0'] = '2.0', result: Any) Bases: "A2ABaseModel" Represents a successful JSON-RPC 2.0 Response object. id: str | int | None The identifier established by the client. jsonrpc: Literal['2.0'] The version of the JSON-RPC protocol. MUST be exactly "2.0". model_config = {'alias_generator': , 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True} Configuration for the model, should be a dictionary conforming to [*ConfigDict*][pydantic.config.ConfigDict]. result: Any The value of this member is determined by the method invoked on the Server. class a2a.compat.v0_3.types.ListTaskPushNotificationConfigParams(*, id: str, metadata: dict[str, Any] | None = None) Bases: "A2ABaseModel" Defines parameters for listing all push notification configurations associated with a task. id: str The unique identifier (e.g. UUID) of the task. metadata: dict[str, Any] | None Optional metadata associated with the request. model_config = {'alias_generator': , 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True} Configuration for the model, should be a dictionary conforming to [*ConfigDict*][pydantic.config.ConfigDict]. class a2a.compat.v0_3.types.ListTaskPushNotificationConfigRequest(*, id: str | int, jsonrpc: Literal['2.0'] = '2.0', method: Literal['tasks/pushNotificationConfig/list'] = 'tasks/pushNotificationConfig/list', params: ListTaskPushNotificationConfigParams) Bases: "A2ABaseModel" Represents a JSON-RPC request for the *tasks/pushNotificationConfig/list* method. id: str | int The identifier for this request. jsonrpc: Literal['2.0'] The version of the JSON-RPC protocol. MUST be exactly "2.0". method: Literal['tasks/pushNotificationConfig/list'] The method name. Must be 'tasks/pushNotificationConfig/list'. model_config = {'alias_generator': , 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True} Configuration for the model, should be a dictionary conforming to [*ConfigDict*][pydantic.config.ConfigDict]. params: ListTaskPushNotificationConfigParams The parameters identifying the task whose configurations are to be listed. class a2a.compat.v0_3.types.ListTaskPushNotificationConfigResponse(root: RootModelRootType = PydanticUndefined) Bases: "RootModel[Union[JSONRPCErrorResponse, ListTaskPushNotificationConfigSuccessResponse]]" model_config = {} Configuration for the model, should be a dictionary conforming to [*ConfigDict*][pydantic.config.ConfigDict]. root: JSONRPCErrorResponse | ListTaskPushNotificationConfigSuccessResponse Represents a JSON-RPC response for the *tasks/pushNotificationConfig/list* method. class a2a.compat.v0_3.types.ListTaskPushNotificationConfigSuccessResponse(*, id: str | int | None = None, jsonrpc: Literal['2.0'] = '2.0', result: list[TaskPushNotificationConfig]) Bases: "A2ABaseModel" Represents a successful JSON-RPC response for the *tasks/pushNotificationConfig/list* method. id: str | int | None The identifier established by the client. jsonrpc: Literal['2.0'] The version of the JSON-RPC protocol. MUST be exactly "2.0". model_config = {'alias_generator': , 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True} Configuration for the model, should be a dictionary conforming to [*ConfigDict*][pydantic.config.ConfigDict]. result: list[TaskPushNotificationConfig] The result, containing an array of all push notification configurations for the task. class a2a.compat.v0_3.types.Message(*, contextId: str | None = None, extensions: list[str] | None = None, kind: Literal['message'] = 'message', messageId: str, metadata: dict[str, Any] | None = None, parts: list[Part], referenceTaskIds: list[str] | None = None, role: Role, taskId: str | None = None) Bases: "A2ABaseModel" Represents a single message in the conversation between a user and an agent. context_id: str | None The context ID for this message, used to group related interactions. extensions: list[str] | None The URIs of extensions that are relevant to this message. kind: Literal['message'] The type of this object, used as a discriminator. Always 'message' for a Message. message_id: str A unique identifier for the message, typically a UUID, generated by the sender. metadata: dict[str, Any] | None Optional metadata for extensions. The key is an extension- specific identifier. model_config = {'alias_generator': , 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True} Configuration for the model, should be a dictionary conforming to [*ConfigDict*][pydantic.config.ConfigDict]. parts: list[Part] An array of content parts that form the message body. A message can be composed of multiple parts of different types (e.g., text and files). reference_task_ids: list[str] | None A list of other task IDs that this message references for additional context. role: Role Identifies the sender of the message. *user* for the client, *agent* for the service. task_id: str | None The ID of the task this message is part of. Can be omitted for the first message of a new task. class a2a.compat.v0_3.types.MessageSendConfiguration(*, acceptedOutputModes: list[str] | None = None, blocking: bool | None = None, historyLength: int | None = None, pushNotificationConfig: PushNotificationConfig | None = None) Bases: "A2ABaseModel" Defines configuration options for a *message/send* or *message/stream* request. accepted_output_modes: list[str] | None A list of output MIME types the client is prepared to accept in the response. blocking: bool | None If true, the client will wait for the task to complete. The server may reject this if the task is long-running. history_length: int | None The number of most recent messages from the task's history to retrieve in the response. model_config = {'alias_generator': , 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True} Configuration for the model, should be a dictionary conforming to [*ConfigDict*][pydantic.config.ConfigDict]. push_notification_config: PushNotificationConfig | None Configuration for the agent to send push notifications for updates after the initial response. class a2a.compat.v0_3.types.MessageSendParams(*, configuration: MessageSendConfiguration | None = None, message: Message, metadata: dict[str, Any] | None = None) Bases: "A2ABaseModel" Defines the parameters for a request to send a message to an agent. This can be used to create a new task, continue an existing one, or restart a task. configuration: MessageSendConfiguration | None Optional configuration for the send request. message: Message The message object being sent to the agent. metadata: dict[str, Any] | None Optional metadata for extensions. model_config = {'alias_generator': , 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True} Configuration for the model, should be a dictionary conforming to [*ConfigDict*][pydantic.config.ConfigDict]. class a2a.compat.v0_3.types.MethodNotFoundError(*, code: Literal[-32601] = -32601, data: Any | None = None, message: str | None = 'Method not found') Bases: "A2ABaseModel" An error indicating that the requested method does not exist or is not available. code: Literal[-32601] The error code for a method not found error. data: Any | None A primitive or structured value containing additional information about the error. This may be omitted. message: str | None The error message. model_config = {'alias_generator': , 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True} Configuration for the model, should be a dictionary conforming to [*ConfigDict*][pydantic.config.ConfigDict]. class a2a.compat.v0_3.types.MutualTLSSecurityScheme(*, description: str | None = None, type: Literal['mutualTLS'] = 'mutualTLS') Bases: "A2ABaseModel" Defines a security scheme using mTLS authentication. description: str | None An optional description for the security scheme. model_config = {'alias_generator': , 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True} Configuration for the model, should be a dictionary conforming to [*ConfigDict*][pydantic.config.ConfigDict]. type: Literal['mutualTLS'] The type of the security scheme. Must be 'mutualTLS'. class a2a.compat.v0_3.types.OAuth2SecurityScheme(*, description: str | None = None, flows: OAuthFlows, oauth2MetadataUrl: str | None = None, type: Literal['oauth2'] = 'oauth2') Bases: "A2ABaseModel" Defines a security scheme using OAuth 2.0. description: str | None An optional description for the security scheme. flows: OAuthFlows An object containing configuration information for the supported OAuth 2.0 flows. model_config = {'alias_generator': , 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True} Configuration for the model, should be a dictionary conforming to [*ConfigDict*][pydantic.config.ConfigDict]. oauth2_metadata_url: str | None URL to the oauth2 authorization server metadata [RFC8414](https://datatracker.ietf.org/doc/html/rfc8414). TLS is required. type: Literal['oauth2'] The type of the security scheme. Must be 'oauth2'. class a2a.compat.v0_3.types.OAuthFlows(*, authorizationCode: AuthorizationCodeOAuthFlow | None = None, clientCredentials: ClientCredentialsOAuthFlow | None = None, implicit: ImplicitOAuthFlow | None = None, password: PasswordOAuthFlow | None = None) Bases: "A2ABaseModel" Defines the configuration for the supported OAuth 2.0 flows. authorization_code: AuthorizationCodeOAuthFlow | None Configuration for the OAuth Authorization Code flow. Previously called accessCode in OpenAPI 2.0. client_credentials: ClientCredentialsOAuthFlow | None Configuration for the OAuth Client Credentials flow. Previously called application in OpenAPI 2.0. implicit: ImplicitOAuthFlow | None Configuration for the OAuth Implicit flow. model_config = {'alias_generator': , 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True} Configuration for the model, should be a dictionary conforming to [*ConfigDict*][pydantic.config.ConfigDict]. password: PasswordOAuthFlow | None Configuration for the OAuth Resource Owner Password flow. class a2a.compat.v0_3.types.OpenIdConnectSecurityScheme(*, description: str | None = None, openIdConnectUrl: str, type: Literal['openIdConnect'] = 'openIdConnect') Bases: "A2ABaseModel" Defines a security scheme using OpenID Connect. description: str | None An optional description for the security scheme. model_config = {'alias_generator': , 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True} Configuration for the model, should be a dictionary conforming to [*ConfigDict*][pydantic.config.ConfigDict]. open_id_connect_url: str The OpenID Connect Discovery URL for the OIDC provider's metadata. type: Literal['openIdConnect'] The type of the security scheme. Must be 'openIdConnect'. class a2a.compat.v0_3.types.Part(root: RootModelRootType = PydanticUndefined) Bases: "RootModel[Union[TextPart, FilePart, DataPart]]" model_config = {} Configuration for the model, should be a dictionary conforming to [*ConfigDict*][pydantic.config.ConfigDict]. root: TextPart | FilePart | DataPart A discriminated union representing a part of a message or artifact, which can be text, a file, or structured data. class a2a.compat.v0_3.types.PartBase(*, metadata: dict[str, Any] | None = None) Bases: "A2ABaseModel" Defines base properties common to all message or artifact parts. metadata: dict[str, Any] | None Optional metadata associated with this part. model_config = {'alias_generator': , 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True} Configuration for the model, should be a dictionary conforming to [*ConfigDict*][pydantic.config.ConfigDict]. class a2a.compat.v0_3.types.PasswordOAuthFlow(*, refreshUrl: str | None = None, scopes: dict[str, str], tokenUrl: str) Bases: "A2ABaseModel" Defines configuration details for the OAuth 2.0 Resource Owner Password flow. model_config = {'alias_generator': , 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True} Configuration for the model, should be a dictionary conforming to [*ConfigDict*][pydantic.config.ConfigDict]. refresh_url: str | None The URL to be used for obtaining refresh tokens. This MUST be a URL. scopes: dict[str, str] The available scopes for the OAuth2 security scheme. A map between the scope name and a short description for it. token_url: str The token URL to be used for this flow. This MUST be a URL. class a2a.compat.v0_3.types.PushNotificationAuthenticationInfo(*, credentials: str | None = None, schemes: list[str]) Bases: "A2ABaseModel" Defines authentication details for a push notification endpoint. credentials: str | None Optional credentials required by the push notification endpoint. model_config = {'alias_generator': , 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True} Configuration for the model, should be a dictionary conforming to [*ConfigDict*][pydantic.config.ConfigDict]. schemes: list[str] A list of supported authentication schemes (e.g., 'Basic', 'Bearer'). class a2a.compat.v0_3.types.PushNotificationConfig(*, authentication: PushNotificationAuthenticationInfo | None = None, id: str | None = None, token: str | None = None, url: str) Bases: "A2ABaseModel" Defines the configuration for setting up push notifications for task updates. authentication: PushNotificationAuthenticationInfo | None Optional authentication details for the agent to use when calling the notification URL. id: str | None A unique identifier (e.g. UUID) for the push notification configuration, set by the client to support multiple notification callbacks. model_config = {'alias_generator': , 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True} Configuration for the model, should be a dictionary conforming to [*ConfigDict*][pydantic.config.ConfigDict]. token: str | None A unique token for this task or session to validate incoming push notifications. url: str The callback URL where the agent should send push notifications. class a2a.compat.v0_3.types.PushNotificationNotSupportedError(*, code: Literal[-32003] = -32003, data: Any | None = None, message: str | None = 'Push Notification is not supported') Bases: "A2ABaseModel" An A2A-specific error indicating that the agent does not support push notifications. code: Literal[-32003] The error code for when push notifications are not supported. data: Any | None A primitive or structured value containing additional information about the error. This may be omitted. message: str | None The error message. model_config = {'alias_generator': , 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True} Configuration for the model, should be a dictionary conforming to [*ConfigDict*][pydantic.config.ConfigDict]. class a2a.compat.v0_3.types.Role(*values) Bases: "str", "Enum" Identifies the sender of the message. *user* for the client, *agent* for the service. agent = 'agent' user = 'user' class a2a.compat.v0_3.types.SecurityScheme(root: RootModelRootType = PydanticUndefined) Bases: "RootModel[Union[APIKeySecurityScheme, HTTPAuthSecurityScheme, OAuth2SecurityScheme, OpenIdConnectSecurityScheme, MutualTLSSecurityScheme]]" model_config = {} Configuration for the model, should be a dictionary conforming to [*ConfigDict*][pydantic.config.ConfigDict]. root: APIKeySecurityScheme | HTTPAuthSecurityScheme | OAuth2SecurityScheme | OpenIdConnectSecurityScheme | MutualTLSSecurityScheme Defines a security scheme that can be used to secure an agent's endpoints. This is a discriminated union type based on the OpenAPI 3.0 Security Scheme Object. class a2a.compat.v0_3.types.SecuritySchemeBase(*, description: str | None = None) Bases: "A2ABaseModel" Defines base properties shared by all security scheme objects. description: str | None An optional description for the security scheme. model_config = {'alias_generator': , 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True} Configuration for the model, should be a dictionary conforming to [*ConfigDict*][pydantic.config.ConfigDict]. class a2a.compat.v0_3.types.SendMessageRequest(*, id: str | int, jsonrpc: Literal['2.0'] = '2.0', method: Literal['message/send'] = 'message/send', params: MessageSendParams) Bases: "A2ABaseModel" Represents a JSON-RPC request for the *message/send* method. id: str | int The identifier for this request. jsonrpc: Literal['2.0'] The version of the JSON-RPC protocol. MUST be exactly "2.0". method: Literal['message/send'] The method name. Must be 'message/send'. model_config = {'alias_generator': , 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True} Configuration for the model, should be a dictionary conforming to [*ConfigDict*][pydantic.config.ConfigDict]. params: MessageSendParams The parameters for sending a message. class a2a.compat.v0_3.types.SendMessageResponse(root: RootModelRootType = PydanticUndefined) Bases: "RootModel[Union[JSONRPCErrorResponse, SendMessageSuccessResponse]]" model_config = {} Configuration for the model, should be a dictionary conforming to [*ConfigDict*][pydantic.config.ConfigDict]. root: JSONRPCErrorResponse | SendMessageSuccessResponse Represents a JSON-RPC response for the *message/send* method. class a2a.compat.v0_3.types.SendMessageSuccessResponse(*, id: str | int | None = None, jsonrpc: Literal['2.0'] = '2.0', result: Task | Message) Bases: "A2ABaseModel" Represents a successful JSON-RPC response for the *message/send* method. id: str | int | None The identifier established by the client. jsonrpc: Literal['2.0'] The version of the JSON-RPC protocol. MUST be exactly "2.0". model_config = {'alias_generator': , 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True} Configuration for the model, should be a dictionary conforming to [*ConfigDict*][pydantic.config.ConfigDict]. result: Task | Message The result, which can be a direct reply Message or the initial Task object. class a2a.compat.v0_3.types.SendStreamingMessageRequest(*, id: str | int, jsonrpc: Literal['2.0'] = '2.0', method: Literal['message/stream'] = 'message/stream', params: MessageSendParams) Bases: "A2ABaseModel" Represents a JSON-RPC request for the *message/stream* method. id: str | int The identifier for this request. jsonrpc: Literal['2.0'] The version of the JSON-RPC protocol. MUST be exactly "2.0". method: Literal['message/stream'] The method name. Must be 'message/stream'. model_config = {'alias_generator': , 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True} Configuration for the model, should be a dictionary conforming to [*ConfigDict*][pydantic.config.ConfigDict]. params: MessageSendParams The parameters for sending a message. class a2a.compat.v0_3.types.SendStreamingMessageResponse(root: RootModelRootType = PydanticUndefined) Bases: "RootModel[Union[JSONRPCErrorResponse, SendStreamingMessageSuccessResponse]]" model_config = {} Configuration for the model, should be a dictionary conforming to [*ConfigDict*][pydantic.config.ConfigDict]. root: JSONRPCErrorResponse | SendStreamingMessageSuccessResponse Represents a JSON-RPC response for the *message/stream* method. class a2a.compat.v0_3.types.SendStreamingMessageSuccessResponse(*, id: str | int | None = None, jsonrpc: Literal['2.0'] = '2.0', result: Task | Message | TaskStatusUpdateEvent | TaskArtifactUpdateEvent) Bases: "A2ABaseModel" Represents a successful JSON-RPC response for the *message/stream* method. The server may send multiple response objects for a single request. id: str | int | None The identifier established by the client. jsonrpc: Literal['2.0'] The version of the JSON-RPC protocol. MUST be exactly "2.0". model_config = {'alias_generator': , 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True} Configuration for the model, should be a dictionary conforming to [*ConfigDict*][pydantic.config.ConfigDict]. result: Task | Message | TaskStatusUpdateEvent | TaskArtifactUpdateEvent The result, which can be a Message, Task, or a streaming update event. class a2a.compat.v0_3.types.SetTaskPushNotificationConfigRequest(*, id: str | int, jsonrpc: Literal['2.0'] = '2.0', method: Literal['tasks/pushNotificationConfig/set'] = 'tasks/pushNotificationConfig/set', params: TaskPushNotificationConfig) Bases: "A2ABaseModel" Represents a JSON-RPC request for the *tasks/pushNotificationConfig/set* method. id: str | int The identifier for this request. jsonrpc: Literal['2.0'] The version of the JSON-RPC protocol. MUST be exactly "2.0". method: Literal['tasks/pushNotificationConfig/set'] The method name. Must be 'tasks/pushNotificationConfig/set'. model_config = {'alias_generator': , 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True} Configuration for the model, should be a dictionary conforming to [*ConfigDict*][pydantic.config.ConfigDict]. params: TaskPushNotificationConfig The parameters for setting the push notification configuration. class a2a.compat.v0_3.types.SetTaskPushNotificationConfigResponse(root: RootModelRootType = PydanticUndefined) Bases: "RootModel[Union[JSONRPCErrorResponse, SetTaskPushNotificationConfigSuccessResponse]]" model_config = {} Configuration for the model, should be a dictionary conforming to [*ConfigDict*][pydantic.config.ConfigDict]. root: JSONRPCErrorResponse | SetTaskPushNotificationConfigSuccessResponse Represents a JSON-RPC response for the *tasks/pushNotificationConfig/set* method. class a2a.compat.v0_3.types.SetTaskPushNotificationConfigSuccessResponse(*, id: str | int | None = None, jsonrpc: Literal['2.0'] = '2.0', result: TaskPushNotificationConfig) Bases: "A2ABaseModel" Represents a successful JSON-RPC response for the *tasks/pushNotificationConfig/set* method. id: str | int | None The identifier established by the client. jsonrpc: Literal['2.0'] The version of the JSON-RPC protocol. MUST be exactly "2.0". model_config = {'alias_generator': , 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True} Configuration for the model, should be a dictionary conforming to [*ConfigDict*][pydantic.config.ConfigDict]. result: TaskPushNotificationConfig The result, containing the configured push notification settings. class a2a.compat.v0_3.types.Task(*, artifacts: list[Artifact] | None = None, contextId: str, history: list[Message] | None = None, id: str, kind: Literal['task'] = 'task', metadata: dict[str, Any] | None = None, status: TaskStatus) Bases: "A2ABaseModel" Represents a single, stateful operation or conversation between a client and an agent. artifacts: list[Artifact] | None A collection of artifacts generated by the agent during the execution of the task. context_id: str A server-generated unique identifier (e.g. UUID) for maintaining context across multiple related tasks or interactions. history: list[Message] | None An array of messages exchanged during the task, representing the conversation history. id: str A unique identifier (e.g. UUID) for the task, generated by the server for a new task. kind: Literal['task'] The type of this object, used as a discriminator. Always 'task' for a Task. metadata: dict[str, Any] | None Optional metadata for extensions. The key is an extension- specific identifier. model_config = {'alias_generator': , 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True} Configuration for the model, should be a dictionary conforming to [*ConfigDict*][pydantic.config.ConfigDict]. status: TaskStatus The current status of the task, including its state and a descriptive message. class a2a.compat.v0_3.types.TaskArtifactUpdateEvent(*, append: bool | None = None, artifact: Artifact, contextId: str, kind: Literal['artifact-update'] = 'artifact-update', lastChunk: bool | None = None, metadata: dict[str, Any] | None = None, taskId: str) Bases: "A2ABaseModel" An event sent by the agent to notify the client that an artifact has been generated or updated. This is typically used in streaming models. append: bool | None If true, the content of this artifact should be appended to a previously sent artifact with the same ID. artifact: Artifact The artifact that was generated or updated. context_id: str The context ID associated with the task. kind: Literal['artifact-update'] The type of this event, used as a discriminator. Always 'artifact-update'. last_chunk: bool | None If true, this is the final chunk of the artifact. metadata: dict[str, Any] | None Optional metadata for extensions. model_config = {'alias_generator': , 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True} Configuration for the model, should be a dictionary conforming to [*ConfigDict*][pydantic.config.ConfigDict]. task_id: str The ID of the task this artifact belongs to. class a2a.compat.v0_3.types.TaskIdParams(*, id: str, metadata: dict[str, Any] | None = None) Bases: "A2ABaseModel" Defines parameters containing a task ID, used for simple task operations. id: str The unique identifier (e.g. UUID) of the task. metadata: dict[str, Any] | None Optional metadata associated with the request. model_config = {'alias_generator': , 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True} Configuration for the model, should be a dictionary conforming to [*ConfigDict*][pydantic.config.ConfigDict]. class a2a.compat.v0_3.types.TaskNotCancelableError(*, code: Literal[-32002] = -32002, data: Any | None = None, message: str | None = 'Task cannot be canceled') Bases: "A2ABaseModel" An A2A-specific error indicating that the task is in a state where it cannot be canceled. code: Literal[-32002] The error code for a task that cannot be canceled. data: Any | None A primitive or structured value containing additional information about the error. This may be omitted. message: str | None The error message. model_config = {'alias_generator': , 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True} Configuration for the model, should be a dictionary conforming to [*ConfigDict*][pydantic.config.ConfigDict]. class a2a.compat.v0_3.types.TaskNotFoundError(*, code: Literal[-32001] = -32001, data: Any | None = None, message: str | None = 'Task not found') Bases: "A2ABaseModel" An A2A-specific error indicating that the requested task ID was not found. code: Literal[-32001] The error code for a task not found error. data: Any | None A primitive or structured value containing additional information about the error. This may be omitted. message: str | None The error message. model_config = {'alias_generator': , 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True} Configuration for the model, should be a dictionary conforming to [*ConfigDict*][pydantic.config.ConfigDict]. class a2a.compat.v0_3.types.TaskPushNotificationConfig(*, pushNotificationConfig: PushNotificationConfig, taskId: str) Bases: "A2ABaseModel" A container associating a push notification configuration with a specific task. model_config = {'alias_generator': , 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True} Configuration for the model, should be a dictionary conforming to [*ConfigDict*][pydantic.config.ConfigDict]. push_notification_config: PushNotificationConfig The push notification configuration for this task. task_id: str The unique identifier (e.g. UUID) of the task. class a2a.compat.v0_3.types.TaskQueryParams(*, historyLength: int | None = None, id: str, metadata: dict[str, Any] | None = None) Bases: "A2ABaseModel" Defines parameters for querying a task, with an option to limit history length. history_length: int | None The number of most recent messages from the task's history to retrieve. id: str The unique identifier (e.g. UUID) of the task. metadata: dict[str, Any] | None Optional metadata associated with the request. model_config = {'alias_generator': , 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True} Configuration for the model, should be a dictionary conforming to [*ConfigDict*][pydantic.config.ConfigDict]. class a2a.compat.v0_3.types.TaskResubscriptionRequest(*, id: str | int, jsonrpc: Literal['2.0'] = '2.0', method: Literal['tasks/resubscribe'] = 'tasks/resubscribe', params: TaskIdParams) Bases: "A2ABaseModel" Represents a JSON-RPC request for the *tasks/resubscribe* method, used to resume a streaming connection. id: str | int The identifier for this request. jsonrpc: Literal['2.0'] The version of the JSON-RPC protocol. MUST be exactly "2.0". method: Literal['tasks/resubscribe'] The method name. Must be 'tasks/resubscribe'. model_config = {'alias_generator': , 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True} Configuration for the model, should be a dictionary conforming to [*ConfigDict*][pydantic.config.ConfigDict]. params: TaskIdParams The parameters identifying the task to resubscribe to. class a2a.compat.v0_3.types.TaskState(*values) Bases: "str", "Enum" Defines the lifecycle states of a Task. auth_required = 'auth-required' canceled = 'canceled' completed = 'completed' failed = 'failed' input_required = 'input-required' rejected = 'rejected' submitted = 'submitted' unknown = 'unknown' working = 'working' class a2a.compat.v0_3.types.TaskStatus(*, message: Message | None = None, state: TaskState, timestamp: str | None = None) Bases: "A2ABaseModel" Represents the status of a task at a specific point in time. message: Message | None An optional, human-readable message providing more details about the current status. model_config = {'alias_generator': , 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True} Configuration for the model, should be a dictionary conforming to [*ConfigDict*][pydantic.config.ConfigDict]. state: TaskState The current state of the task's lifecycle. timestamp: str | None An ISO 8601 datetime string indicating when this status was recorded. class a2a.compat.v0_3.types.TaskStatusUpdateEvent(*, contextId: str, final: bool, kind: Literal['status-update'] = 'status-update', metadata: dict[str, Any] | None = None, status: TaskStatus, taskId: str) Bases: "A2ABaseModel" An event sent by the agent to notify the client of a change in a task's status. This is typically used in streaming or subscription models. context_id: str The context ID associated with the task. final: bool If true, this is the final event in the stream for this interaction. kind: Literal['status-update'] The type of this event, used as a discriminator. Always 'status- update'. metadata: dict[str, Any] | None Optional metadata for extensions. model_config = {'alias_generator': , 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True} Configuration for the model, should be a dictionary conforming to [*ConfigDict*][pydantic.config.ConfigDict]. status: TaskStatus The new status of the task. task_id: str The ID of the task that was updated. class a2a.compat.v0_3.types.TextPart(*, kind: Literal['text'] = 'text', metadata: dict[str, Any] | None = None, text: str) Bases: "A2ABaseModel" Represents a text segment within a message or artifact. kind: Literal['text'] The type of this part, used as a discriminator. Always 'text'. metadata: dict[str, Any] | None Optional metadata associated with this part. model_config = {'alias_generator': , 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True} Configuration for the model, should be a dictionary conforming to [*ConfigDict*][pydantic.config.ConfigDict]. text: str The string content of the text part. class a2a.compat.v0_3.types.TransportProtocol(*values) Bases: "str", "Enum" Supported A2A transport protocols. grpc = 'GRPC' http_json = 'HTTP+JSON' jsonrpc = 'JSONRPC' class a2a.compat.v0_3.types.UnsupportedOperationError(*, code: Literal[-32004] = -32004, data: Any | None = None, message: str | None = 'This operation is not supported') Bases: "A2ABaseModel" An A2A-specific error indicating that the requested operation is not supported by the agent. code: Literal[-32004] The error code for an unsupported operation. data: Any | None A primitive or structured value containing additional information about the error. This may be omitted. message: str | None The error message. model_config = {'alias_generator': , 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True} Configuration for the model, should be a dictionary conforming to [*ConfigDict*][pydantic.config.ConfigDict]. a2a.compat.v0_3.versions module ******************************* Utility functions for protocol version comparison and validation. a2a.compat.v0_3.versions.is_legacy_version(version: str | None) -> bool Determines if the given version is a legacy protocol version (>=0.3 and <1.0). a2a.extensions.common module **************************** a2a.extensions.common.find_extension_by_uri(card: AgentCard, uri: str) -> AgentExtension | None Find an AgentExtension in an AgentCard given a uri. a2a.extensions.common.get_requested_extensions(values: list[str]) -> set[str] Get the set of requested extensions from an input list. This handles the list containing potentially comma-separated values, as occurs when using a list in an HTTP header. a2a.extensions package ********************** Submodules ========== * a2a.extensions.common module * "find_extension_by_uri()" * "get_requested_extensions()" Module contents =============== a2a.helpers.agent_card module ***************************** Utility functions for inspecting AgentCard instances. a2a.helpers.agent_card.display_agent_card(card: AgentCard) -> None Print a human-readable summary of an AgentCard to stdout. Parameters: **card** -- The AgentCard proto message to display. a2a.helpers.proto_helpers module ******************************** Unified helper functions for creating and handling A2A types. a2a.helpers.proto_helpers.get_artifact_text(artifact: Artifact, delimiter: str = '\n') -> str Extracts and joins all text content from an Artifact's parts. a2a.helpers.proto_helpers.get_data_parts(parts: Sequence[Part]) -> list[Any] Extracts structured data from all data Parts. Each returned element is the Python object obtained by converting the "google.protobuf.Value" back via "MessageToDict". Parameters: **parts** -- A sequence of "Part" objects. Returns: A list of deserialized Python objects from any data Parts found. a2a.helpers.proto_helpers.get_message_text(message: Message, delimiter: str = '\n') -> str Extracts and joins all text content from a Message's parts. a2a.helpers.proto_helpers.get_raw_parts(parts: Sequence[Part]) -> list[bytes] Extracts raw bytes content from all raw Parts. Parameters: **parts** -- A sequence of "Part" objects. Returns: A list of "bytes" from any raw Parts found. a2a.helpers.proto_helpers.get_stream_response_text(response: StreamResponse, delimiter: str = '\n') -> str Extracts text content from a StreamResponse. a2a.helpers.proto_helpers.get_text_parts(parts: Sequence[Part]) -> list[str] Extracts text content from all text Parts. a2a.helpers.proto_helpers.get_url_parts(parts: Sequence[Part]) -> list[str] Extracts URL strings from all URL Parts. Parameters: **parts** -- A sequence of "Part" objects. Returns: A list of URL strings from any URL Parts found. a2a.helpers.proto_helpers.new_artifact(parts: list[Part], name: str, description: str | None = None, artifact_id: str | None = None) -> Artifact Creates a new Artifact object. a2a.helpers.proto_helpers.new_data_artifact(name: str, data: Any, media_type: str | None = None, description: str | None = None, artifact_id: str | None = None) -> Artifact Creates a new Artifact object containing only a single data Part. Parameters: * **name** -- The name of the artifact. * **data** -- JSON-serializable data to embed (dict, list, str, etc.). * **media_type** -- Optional MIME type of the part content (e.g., "text/plain", "application/json", "image/png"). * **description** -- Optional description. * **artifact_id** -- Optional artifact ID (auto-generated if not provided). Returns: An Artifact with a single data Part. a2a.helpers.proto_helpers.new_data_artifact_update_event(task_id: str, context_id: str, name: str, data: Any, media_type: str | None = None, append: bool = False, last_chunk: bool = False, artifact_id: str | None = None) -> TaskArtifactUpdateEvent Creates a TaskArtifactUpdateEvent with a single data artifact. Parameters: * **task_id** -- The task ID. * **context_id** -- The context ID. * **name** -- The name of the artifact. * **data** -- JSON-serializable data to embed (dict, list, str, etc.). * **media_type** -- Optional MIME type of the part content. * **append** -- Whether to append to the existing artifact. * **last_chunk** -- Whether this is the last chunk. * **artifact_id** -- Optional artifact ID (auto-generated if not provided). Returns: A TaskArtifactUpdateEvent with a single data artifact. a2a.helpers.proto_helpers.new_data_message(data: Any, media_type: str | None = None, context_id: str | None = None, task_id: str | None = None, role: = 2) -> Message Creates a new message containing a single data Part. Parameters: * **data** -- JSON-serializable data to embed (dict, list, str, etc.). * **media_type** -- Optional MIME type of the part content (e.g., "text/plain", "application/json", "image/png"). * **context_id** -- Optional context ID. * **task_id** -- Optional task ID. * **role** -- The role of the message sender (default: ROLE_AGENT). Returns: A Message with a single data Part. a2a.helpers.proto_helpers.new_data_part(data: Any, media_type: str | None = None) -> Part Creates a Part with structured data (google.protobuf.Value). Parameters: * **data** -- JSON-serializable data to embed (dict, list, str, etc.). * **media_type** -- Optional MIME type of the part content (e.g., "text/plain", "application/json", "image/png"). Returns: A Part with the data field set. a2a.helpers.proto_helpers.new_message(parts: list[~a2a_pb2.Part], context_id: str | None = None, task_id: str | None = None, role: = 2) -> Message Creates a new message containing a list of Parts. a2a.helpers.proto_helpers.new_raw_artifact(name: str, raw: bytes, media_type: str | None = None, filename: str | None = None, description: str | None = None, artifact_id: str | None = None) -> Artifact Creates a new Artifact object containing only a single raw bytes Part. Parameters: * **name** -- The name of the artifact. * **raw** -- The raw bytes content. * **media_type** -- Optional MIME type (e.g. 'image/png'). * **filename** -- Optional filename. * **description** -- Optional description. * **artifact_id** -- Optional artifact ID (auto-generated if not provided). Returns: An Artifact with a single raw Part. a2a.helpers.proto_helpers.new_raw_artifact_update_event(task_id: str, context_id: str, name: str, raw: bytes, media_type: str | None = None, filename: str | None = None, append: bool = False, last_chunk: bool = False, artifact_id: str | None = None) -> TaskArtifactUpdateEvent Creates a TaskArtifactUpdateEvent with a single raw bytes artifact. Parameters: * **task_id** -- The task ID. * **context_id** -- The context ID. * **name** -- The name of the artifact. * **raw** -- The raw bytes content. * **media_type** -- Optional MIME type (e.g. 'image/png'). * **filename** -- Optional filename. * **append** -- Whether to append to the existing artifact. * **last_chunk** -- Whether this is the last chunk. * **artifact_id** -- Optional artifact ID (auto-generated if not provided). Returns: A TaskArtifactUpdateEvent with a single raw artifact. a2a.helpers.proto_helpers.new_raw_message(raw: bytes, media_type: str | None = None, filename: str | None = None, context_id: str | None = None, task_id: str | None = None, role: = 2) -> Message Creates a new message containing a single raw bytes Part. Parameters: * **raw** -- The raw bytes content. * **media_type** -- Optional MIME type (e.g. 'image/png'). * **filename** -- Optional filename. * **context_id** -- Optional context ID. * **task_id** -- Optional task ID. * **role** -- The role of the message sender (default: ROLE_AGENT). Returns: A Message with a single raw Part. a2a.helpers.proto_helpers.new_raw_part(raw: bytes, media_type: str | None = None, filename: str | None = None) -> Part Creates a Part with raw bytes content. Parameters: * **raw** -- The raw bytes content. * **media_type** -- Optional MIME type (e.g. 'image/png'). * **filename** -- Optional filename. Returns: A Part with the raw field set. a2a.helpers.proto_helpers.new_task(task_id: str, context_id: str, state: , artifacts: list[Artifact] | None = None, history: list[Message] | None = None) -> Task Creates a Task object with a specified status. a2a.helpers.proto_helpers.new_task_from_user_message(user_message: Message) -> Task Creates a new Task object from an initial user message. a2a.helpers.proto_helpers.new_text_artifact(name: str, text: str, media_type: str | None = None, description: str | None = None, artifact_id: str | None = None) -> Artifact Creates a new Artifact object containing only a single text Part. a2a.helpers.proto_helpers.new_text_artifact_update_event(task_id: str, context_id: str, name: str, text: str, append: bool = False, last_chunk: bool = False, artifact_id: str | None = None) -> TaskArtifactUpdateEvent Creates a TaskArtifactUpdateEvent with a single text artifact. a2a.helpers.proto_helpers.new_text_message(text: str, media_type: str | None = None, context_id: str | None = None, task_id: str | None = None, role: = 2) -> Message Creates a new message containing a single text Part. a2a.helpers.proto_helpers.new_text_part(text: str, media_type: str | None = None) -> Part Creates a Part with text content. Parameters: * **text** -- The text content. * **media_type** -- Optional MIME type (e.g. 'text/plain', 'text/markdown'). Returns: A Part with the text field set. a2a.helpers.proto_helpers.new_text_status_update_event(task_id: str, context_id: str, state: , text: str) -> TaskStatusUpdateEvent Creates a TaskStatusUpdateEvent with a single text message. a2a.helpers.proto_helpers.new_url_artifact(name: str, url: str, media_type: str | None = None, filename: str | None = None, description: str | None = None, artifact_id: str | None = None) -> Artifact Creates a new Artifact object containing only a single URL Part. Parameters: * **name** -- The name of the artifact. * **url** -- The URL pointing to the file content. * **media_type** -- Optional MIME type (e.g. 'image/png'). * **filename** -- Optional filename. * **description** -- Optional description. * **artifact_id** -- Optional artifact ID (auto-generated if not provided). Returns: An Artifact with a single URL Part. a2a.helpers.proto_helpers.new_url_artifact_update_event(task_id: str, context_id: str, name: str, url: str, media_type: str | None = None, filename: str | None = None, append: bool = False, last_chunk: bool = False, artifact_id: str | None = None) -> TaskArtifactUpdateEvent Creates a TaskArtifactUpdateEvent with a single URL artifact. Parameters: * **task_id** -- The task ID. * **context_id** -- The context ID. * **name** -- The name of the artifact. * **url** -- The URL pointing to the file content. * **media_type** -- Optional MIME type (e.g. 'image/png'). * **filename** -- Optional filename. * **append** -- Whether to append to the existing artifact. * **last_chunk** -- Whether this is the last chunk. * **artifact_id** -- Optional artifact ID (auto-generated if not provided). Returns: A TaskArtifactUpdateEvent with a single URL artifact. a2a.helpers.proto_helpers.new_url_message(url: str, media_type: str | None = None, filename: str | None = None, context_id: str | None = None, task_id: str | None = None, role: = 2) -> Message Creates a new message containing a single URL Part. Parameters: * **url** -- The URL pointing to the file content. * **media_type** -- Optional MIME type (e.g. 'image/png'). * **filename** -- Optional filename. * **context_id** -- Optional context ID. * **task_id** -- Optional task ID. * **role** -- The role of the message sender (default: ROLE_AGENT). Returns: A Message with a single URL Part. a2a.helpers.proto_helpers.new_url_part(url: str, media_type: str | None = None, filename: str | None = None) -> Part Creates a Part with a URL pointing to file content. Parameters: * **url** -- The URL to the file content. * **media_type** -- Optional MIME type (e.g. 'image/png'). * **filename** -- Optional filename. Returns: A Part with the url field set. a2a.helpers package ******************* Submodules ========== * a2a.helpers.agent_card module * "display_agent_card()" * a2a.helpers.proto_helpers module * "get_artifact_text()" * "get_data_parts()" * "get_message_text()" * "get_raw_parts()" * "get_stream_response_text()" * "get_text_parts()" * "get_url_parts()" * "new_artifact()" * "new_data_artifact()" * "new_data_artifact_update_event()" * "new_data_message()" * "new_data_part()" * "new_message()" * "new_raw_artifact()" * "new_raw_artifact_update_event()" * "new_raw_message()" * "new_raw_part()" * "new_task()" * "new_task_from_user_message()" * "new_text_artifact()" * "new_text_artifact_update_event()" * "new_text_message()" * "new_text_part()" * "new_text_status_update_event()" * "new_url_artifact()" * "new_url_artifact_update_event()" * "new_url_message()" * "new_url_part()" Module contents =============== Helper functions for the A2A Python SDK. a2a.helpers.display_agent_card(card: AgentCard) -> None Print a human-readable summary of an AgentCard to stdout. Parameters: **card** -- The AgentCard proto message to display. a2a.helpers.get_artifact_text(artifact: Artifact, delimiter: str = '\n') -> str Extracts and joins all text content from an Artifact's parts. a2a.helpers.get_data_parts(parts: Sequence[Part]) -> list[Any] Extracts structured data from all data Parts. Each returned element is the Python object obtained by converting the "google.protobuf.Value" back via "MessageToDict". Parameters: **parts** -- A sequence of "Part" objects. Returns: A list of deserialized Python objects from any data Parts found. a2a.helpers.get_message_text(message: Message, delimiter: str = '\n') -> str Extracts and joins all text content from a Message's parts. a2a.helpers.get_raw_parts(parts: Sequence[Part]) -> list[bytes] Extracts raw bytes content from all raw Parts. Parameters: **parts** -- A sequence of "Part" objects. Returns: A list of "bytes" from any raw Parts found. a2a.helpers.get_stream_response_text(response: StreamResponse, delimiter: str = '\n') -> str Extracts text content from a StreamResponse. a2a.helpers.get_text_parts(parts: Sequence[Part]) -> list[str] Extracts text content from all text Parts. a2a.helpers.get_url_parts(parts: Sequence[Part]) -> list[str] Extracts URL strings from all URL Parts. Parameters: **parts** -- A sequence of "Part" objects. Returns: A list of URL strings from any URL Parts found. a2a.helpers.new_artifact(parts: list[Part], name: str, description: str | None = None, artifact_id: str | None = None) -> Artifact Creates a new Artifact object. a2a.helpers.new_data_artifact(name: str, data: Any, media_type: str | None = None, description: str | None = None, artifact_id: str | None = None) -> Artifact Creates a new Artifact object containing only a single data Part. Parameters: * **name** -- The name of the artifact. * **data** -- JSON-serializable data to embed (dict, list, str, etc.). * **media_type** -- Optional MIME type of the part content (e.g., "text/plain", "application/json", "image/png"). * **description** -- Optional description. * **artifact_id** -- Optional artifact ID (auto-generated if not provided). Returns: An Artifact with a single data Part. a2a.helpers.new_data_artifact_update_event(task_id: str, context_id: str, name: str, data: Any, media_type: str | None = None, append: bool = False, last_chunk: bool = False, artifact_id: str | None = None) -> TaskArtifactUpdateEvent Creates a TaskArtifactUpdateEvent with a single data artifact. Parameters: * **task_id** -- The task ID. * **context_id** -- The context ID. * **name** -- The name of the artifact. * **data** -- JSON-serializable data to embed (dict, list, str, etc.). * **media_type** -- Optional MIME type of the part content. * **append** -- Whether to append to the existing artifact. * **last_chunk** -- Whether this is the last chunk. * **artifact_id** -- Optional artifact ID (auto-generated if not provided). Returns: A TaskArtifactUpdateEvent with a single data artifact. a2a.helpers.new_data_message(data: Any, media_type: str | None = None, context_id: str | None = None, task_id: str | None = None, role: = 2) -> Message Creates a new message containing a single data Part. Parameters: * **data** -- JSON-serializable data to embed (dict, list, str, etc.). * **media_type** -- Optional MIME type of the part content (e.g., "text/plain", "application/json", "image/png"). * **context_id** -- Optional context ID. * **task_id** -- Optional task ID. * **role** -- The role of the message sender (default: ROLE_AGENT). Returns: A Message with a single data Part. a2a.helpers.new_data_part(data: Any, media_type: str | None = None) -> Part Creates a Part with structured data (google.protobuf.Value). Parameters: * **data** -- JSON-serializable data to embed (dict, list, str, etc.). * **media_type** -- Optional MIME type of the part content (e.g., "text/plain", "application/json", "image/png"). Returns: A Part with the data field set. a2a.helpers.new_message(parts: list[~a2a_pb2.Part], context_id: str | None = None, task_id: str | None = None, role: = 2) -> Message Creates a new message containing a list of Parts. a2a.helpers.new_raw_artifact(name: str, raw: bytes, media_type: str | None = None, filename: str | None = None, description: str | None = None, artifact_id: str | None = None) -> Artifact Creates a new Artifact object containing only a single raw bytes Part. Parameters: * **name** -- The name of the artifact. * **raw** -- The raw bytes content. * **media_type** -- Optional MIME type (e.g. 'image/png'). * **filename** -- Optional filename. * **description** -- Optional description. * **artifact_id** -- Optional artifact ID (auto-generated if not provided). Returns: An Artifact with a single raw Part. a2a.helpers.new_raw_artifact_update_event(task_id: str, context_id: str, name: str, raw: bytes, media_type: str | None = None, filename: str | None = None, append: bool = False, last_chunk: bool = False, artifact_id: str | None = None) -> TaskArtifactUpdateEvent Creates a TaskArtifactUpdateEvent with a single raw bytes artifact. Parameters: * **task_id** -- The task ID. * **context_id** -- The context ID. * **name** -- The name of the artifact. * **raw** -- The raw bytes content. * **media_type** -- Optional MIME type (e.g. 'image/png'). * **filename** -- Optional filename. * **append** -- Whether to append to the existing artifact. * **last_chunk** -- Whether this is the last chunk. * **artifact_id** -- Optional artifact ID (auto-generated if not provided). Returns: A TaskArtifactUpdateEvent with a single raw artifact. a2a.helpers.new_raw_message(raw: bytes, media_type: str | None = None, filename: str | None = None, context_id: str | None = None, task_id: str | None = None, role: = 2) -> Message Creates a new message containing a single raw bytes Part. Parameters: * **raw** -- The raw bytes content. * **media_type** -- Optional MIME type (e.g. 'image/png'). * **filename** -- Optional filename. * **context_id** -- Optional context ID. * **task_id** -- Optional task ID. * **role** -- The role of the message sender (default: ROLE_AGENT). Returns: A Message with a single raw Part. a2a.helpers.new_raw_part(raw: bytes, media_type: str | None = None, filename: str | None = None) -> Part Creates a Part with raw bytes content. Parameters: * **raw** -- The raw bytes content. * **media_type** -- Optional MIME type (e.g. 'image/png'). * **filename** -- Optional filename. Returns: A Part with the raw field set. a2a.helpers.new_task(task_id: str, context_id: str, state: , artifacts: list[Artifact] | None = None, history: list[Message] | None = None) -> Task Creates a Task object with a specified status. a2a.helpers.new_task_from_user_message(user_message: Message) -> Task Creates a new Task object from an initial user message. a2a.helpers.new_text_artifact(name: str, text: str, media_type: str | None = None, description: str | None = None, artifact_id: str | None = None) -> Artifact Creates a new Artifact object containing only a single text Part. a2a.helpers.new_text_artifact_update_event(task_id: str, context_id: str, name: str, text: str, append: bool = False, last_chunk: bool = False, artifact_id: str | None = None) -> TaskArtifactUpdateEvent Creates a TaskArtifactUpdateEvent with a single text artifact. a2a.helpers.new_text_message(text: str, media_type: str | None = None, context_id: str | None = None, task_id: str | None = None, role: = 2) -> Message Creates a new message containing a single text Part. a2a.helpers.new_text_part(text: str, media_type: str | None = None) -> Part Creates a Part with text content. Parameters: * **text** -- The text content. * **media_type** -- Optional MIME type (e.g. 'text/plain', 'text/markdown'). Returns: A Part with the text field set. a2a.helpers.new_text_status_update_event(task_id: str, context_id: str, state: , text: str) -> TaskStatusUpdateEvent Creates a TaskStatusUpdateEvent with a single text message. a2a.helpers.new_url_artifact(name: str, url: str, media_type: str | None = None, filename: str | None = None, description: str | None = None, artifact_id: str | None = None) -> Artifact Creates a new Artifact object containing only a single URL Part. Parameters: * **name** -- The name of the artifact. * **url** -- The URL pointing to the file content. * **media_type** -- Optional MIME type (e.g. 'image/png'). * **filename** -- Optional filename. * **description** -- Optional description. * **artifact_id** -- Optional artifact ID (auto-generated if not provided). Returns: An Artifact with a single URL Part. a2a.helpers.new_url_artifact_update_event(task_id: str, context_id: str, name: str, url: str, media_type: str | None = None, filename: str | None = None, append: bool = False, last_chunk: bool = False, artifact_id: str | None = None) -> TaskArtifactUpdateEvent Creates a TaskArtifactUpdateEvent with a single URL artifact. Parameters: * **task_id** -- The task ID. * **context_id** -- The context ID. * **name** -- The name of the artifact. * **url** -- The URL pointing to the file content. * **media_type** -- Optional MIME type (e.g. 'image/png'). * **filename** -- Optional filename. * **append** -- Whether to append to the existing artifact. * **last_chunk** -- Whether this is the last chunk. * **artifact_id** -- Optional artifact ID (auto-generated if not provided). Returns: A TaskArtifactUpdateEvent with a single URL artifact. a2a.helpers.new_url_message(url: str, media_type: str | None = None, filename: str | None = None, context_id: str | None = None, task_id: str | None = None, role: = 2) -> Message Creates a new message containing a single URL Part. Parameters: * **url** -- The URL pointing to the file content. * **media_type** -- Optional MIME type (e.g. 'image/png'). * **filename** -- Optional filename. * **context_id** -- Optional context ID. * **task_id** -- Optional task ID. * **role** -- The role of the message sender (default: ROLE_AGENT). Returns: A Message with a single URL Part. a2a.helpers.new_url_part(url: str, media_type: str | None = None, filename: str | None = None) -> Part Creates a Part with a URL pointing to file content. Parameters: * **url** -- The URL to the file content. * **media_type** -- Optional MIME type (e.g. 'image/png'). * **filename** -- Optional filename. Returns: A Part with the url field set. a2a.migrations.env module ************************* a2a.migrations.migration_utils module ************************************* Utility functions for Alembic migrations. a2a.migrations.migration_utils.add_column(table: str, column_name: str, nullable: bool, type_: TypeEngine, default: Any | None = None) -> None Add a column to a table if it doesn't already exist. a2a.migrations.migration_utils.add_index(table: str, index_name: str, columns: list[str]) -> None Create an index on a table if it doesn't already exist. a2a.migrations.migration_utils.column_exists(table_name: str, column_name: str, downgrade_mode: bool = False) -> bool Check if a column exists in a table. a2a.migrations.migration_utils.drop_column(table: str, column_name: str) -> None Drop a column from a table if it exists. a2a.migrations.migration_utils.drop_index(table: str, index_name: str) -> None Drop an index from a table if it exists. a2a.migrations.migration_utils.index_exists(table_name: str, index_name: str, downgrade_mode: bool = False) -> bool Check if an index exists on a table. a2a.migrations.migration_utils.table_exists(table_name: str) -> bool Check if a table exists in the database. a2a.migrations package ********************** Subpackages =========== * a2a.migrations.versions package * Submodules * a2a.migrations.versions.38ce57e08137_add_column_protocol_version module * "downgrade()" * "upgrade()" * a2a.migrations.versions.6419d2d130f6_add_columns_owner_last_upda ted module * "downgrade()" * "upgrade()" * Module contents Submodules ========== * a2a.migrations.env module * a2a.migrations.migration_utils module * "add_column()" * "add_index()" * "column_exists()" * "drop_column()" * "drop_index()" * "index_exists()" * "table_exists()" Module contents =============== Alembic database migration package. a2a.migrations.versions.38ce57e08137_add_column_protocol_version module *********************************************************************** add column protocol version Revision ID: 38ce57e08137 Revises: 6419d2d130f6 Create Date: 2026-03-09 12:07:16.998955 a2a.migrations.versions.38ce57e08137_add_column_protocol_version.downgrade() -> None Downgrade schema. a2a.migrations.versions.38ce57e08137_add_column_protocol_version.upgrade() -> None Upgrade schema. a2a.migrations.versions.6419d2d130f6_add_columns_owner_last_updated module ************************************************************************** add_columns_owner_last_updated. Revision ID: 6419d2d130f6 Revises: Create Date: 2026-02-17 09:23:06.758085 a2a.migrations.versions.6419d2d130f6_add_columns_owner_last_updated.downgrade() -> None Downgrade schema. a2a.migrations.versions.6419d2d130f6_add_columns_owner_last_updated.upgrade() -> None Upgrade schema. a2a.migrations.versions package ******************************* Submodules ========== * a2a.migrations.versions.38ce57e08137_add_column_protocol_version module * "downgrade()" * "upgrade()" * a2a.migrations.versions.6419d2d130f6_add_columns_owner_last_updated module * "downgrade()" * "upgrade()" Module contents =============== Alembic migrations scripts for the A2A project. a2a.server.agent_execution.active_task module ********************************************* Active Task execution and data flow architecture. This module manages the lifecycle, execution, and data flow of an active A2A task. High-Level Architecture: - *AgentExecutor*: An interface with two main methods, *execute(...)* and *cancel(...)*, responsible for running the core agent logic. * *ActiveTask*: Coordinates the execution. It runs a main agent loop in *ActiveTask._run_producer()*. Data Flow and Event Handling: 1. Producer (*ActiveTask._run_producer*): * Listens for incoming requests from *ActiveTask._request_queue*. * Acquires *ActiveTask._request_lock* to ensure requests are processed sequentially. * Calls *AgentExecutor.execute()* passing *ActiveTask._event_queue_agent* as the primary communication channel. * Enqueues internal lifecycle events (e.g., *_RequestStarted*, *_RequestCompleted*) and exceptions to the same *ActiveTask._event_queue_agent*. 2. Consumer (*EventConsumer*): - Consumes events from *ActiveTask._event_queue_agent*. - Processes all events, updating task state and the database (*TaskManager*). - Upon receiving *_RequestCompleted*, it releases *ActiveTask._request_lock*, making the producer ready to process the next queued request. * Propagates relevant agent updates and state changes to *ActiveTask._event_queue_subscribers*. * Exception Handling: Re-raises exceptions dequeued from the agent queue, or raises its own validation errors (e.g., 'Received Message object in task mode.'). In case of failure, it updates the task state to failed and propagates the exception to *ActiveTask._event_queue_subscribers*. 3. Subscribers (*ActiveTask.subscribe*): - *ActiveTask._event_queue_subscribers* is not consumed directly. Instead, it is consumed by tapped queues created within the *ActiveTask.subscribe()* method. * The *ActiveTask.subscribe()* method is also used to actively run requests, creating a temporary subscription that yields events and automatically finishes once the request is completed. class a2a.server.agent_execution.active_task.ActiveTask(agent_executor: AgentExecutor, task_id: str, task_manager: TaskManager, push_sender: PushNotificationSender | None = None, on_cleanup: Callable[[ActiveTask], None] | None = None) Bases: "object" Manages the lifecycle and execution of an active A2A task. It coordinates between the agent's execution (the producer), the persistence and state management (the TaskManager), and the event distribution to subscribers (the consumer). Concurrency Guarantees: - This class is designed to be highly concurrent. It manages an internal producer-consumer model using >>`< Task Cancels the running active task. Concurrency Guarantee: Uses *_lock* to ensure we don't attempt to cancel a producer that is already winding down or hasn't started. It fires the cancellation signal and blocks until the consumer processes the cancellation events. async enqueue_request(request_context: RequestContext) -> UUID Enqueues a request for the active task to process. async get_task() -> Task Get task from db. async start(call_context: ServerCallContext, create_task_if_missing: bool = False) -> None Starts the active task background processes. Concurrency Guarantee: Uses *self._lock* to ensure the producer and consumer tasks are strictly singleton instances for the lifetime of this ActiveTask. async subscribe(*, request: RequestContext | None = None, include_initial_task: bool = False, replace_status_update_with_task: bool = False) -> AsyncGenerator[Event, None] Creates a queue tap and yields events as they are produced. Concurrency Guarantee: Uses *_lock* to safely increment and decrement *_reference_count*. Safely detaches its queue tap when the client disconnects or the task finishes, triggering *_maybe_cleanup()* to potentially garbage collect the ActiveTask. property task_id: str The ID of the task. class a2a.server.agent_execution.active_task.EventConsumer(active_task: ActiveTask) Bases: "object" Consumes events from the agent and updates system state. async run() -> None Consumes events from the agent and updates system state. a2a.server.agent_execution.active_task_registry module ****************************************************** class a2a.server.agent_execution.active_task_registry.ActiveTaskRegistry(agent_executor: AgentExecutor, task_store: TaskStore, push_sender: PushNotificationSender | None = None) Bases: "object" A registry for active ActiveTask instances. async get(task_id: str) -> ActiveTask | None Retrieves an existing task. async get_or_create(task_id: str, call_context: ServerCallContext, context_id: str | None = None, create_task_if_missing: bool = False) -> ActiveTask Retrieves an existing ActiveTask or creates a new one. a2a.server.agent_execution.agent_executor module ************************************************ class a2a.server.agent_execution.agent_executor.AgentExecutor Bases: "ABC" Agent Executor interface. Implementations of this interface contain the core logic of the agent, executing tasks based on requests and publishing updates to an event queue. abstractmethod async cancel(context: RequestContext, event_queue: EventQueue) -> None Request the agent to cancel an ongoing task. The agent should attempt to stop the task identified by the task_id in the context and publish a *TaskStatusUpdateEvent* with state *TaskState.TASK_STATE_CANCELED* to the *event_queue*. Parameters: * **context** -- The request context containing the task ID to cancel. * **event_queue** -- The queue to publish the cancellation status update to. abstractmethod async execute(context: RequestContext, event_queue: EventQueue) -> None Execute the agent's logic for a given request context. The agent should read necessary information from the *context* and publish *Task* or *Message* events, or *TaskStatusUpdateEvent* / *TaskArtifactUpdateEvent* to the *event_queue*. This method should return once the agent's execution for this request is complete or yields control (e.g., enters an input-required state). Request Lifecycle & AgentExecutor Responsibilities: - **Concurrency**: The framework guarantees single execution per request; *execute()* will not be called concurrently for the same request context. * **Exception Handling**: Unhandled exceptions raised by *execute()* will be caught by the framework and result in the task transitioning to *TaskState.TASK_STATE_ERROR*. * **Post-Completion**: Once *execute()* completes (returns or raises), the executor must not access the *context* or *event_queue* anymore. * **Terminal States**: Before completing the call normally, the executor SHOULD publish a *TaskStatusUpdateEvent* to transition the task to a terminal state (e.g., *TASK_STATE_COMPLETED*) or an interrupted state (*TASK_STATE_INPUT_REQUIRED* or *TASK_STATE_AUTH_REQUIRED*). * **Interrupted Workflows**: * *TASK_STATE_INPUT_REQUIRED*: The executor publishes a *TaskStatusUpdateEvent* with *TaskState.TASK_STATE_INPUT_REQUIRED* and returns to yield control. The request will resume once user input is provided. * *TASK_STATE_AUTH_REQUIRED*: There are in-bound and out- of-bound auth models. In both scenarios, the agent publishes a *TaskStatusUpdateEvent* with *TaskState.TASK_STATE_AUTH_REQUIRED*. * In-bound: The agent should return from *execute()*. The framework will call *execute()* again once the user response is received. * Out-of-bound: The agent should not return from *execute()*. It should wait for the out-of-band auth provider to complete the authentication and then continue execution. * **Cancellation Workflow**: When a cancellation request is received, the async task running *execute()* is cancelled (raising an *asyncio.CancelledError*), and *cancel()* is explicitly called by the framework. Allowed Workflows: - Immediate response: Enqueue a SINGLE *Message* object. - Asynchronous/Long-running: Enqueue a *Task* object, perform work, and emit multiple *TaskStatusUpdateEvent* / *TaskArtifactUpdateEvent* objects over time. Note that the framework waits with response to the send_message request with *return_immediately=True* parameter until the first event (Message or Task) is enqueued by AgentExecutor. Parameters: * **context** -- The request context containing the message, task ID, etc. * **event_queue** -- The queue to publish events to. a2a.server.agent_execution.context module ***************************************** class a2a.server.agent_execution.context.RequestContext(call_context: ServerCallContext, request: SendMessageRequest | None = None, task_id: str | None = None, context_id: str | None = None, task: Task | None = None, related_tasks: list[Task] | None = None, task_id_generator: IDGenerator | None = None, context_id_generator: IDGenerator | None = None) Bases: "object" Request Context. Holds information about the current request being processed by the server, including the incoming message, task and context identifiers, and related tasks. attach_related_task(task: Task) -> None Attaches a related task to the context. This is useful for scenarios like tool execution where a new task might be spawned. Parameters: **task** -- The *Task* object to attach. property call_context: ServerCallContext The server call context associated with this request. property configuration: SendMessageConfiguration | None The *SendMessageConfiguration* from the request, if available. property context_id: str | None The ID of the conversation context associated with this task. property current_task: Task | None The current *Task* object being processed. get_user_input(delimiter: str = '\n') -> str Extracts text content from the user's message parts. Parameters: **delimiter** -- The string to use when joining multiple text parts. Returns: A single string containing all text content from the user message, joined by the specified delimiter. Returns an empty string if no user message is present or if it contains no text parts. property message: Message | None The incoming *Message* object from the request, if available. property metadata: dict[str, Any] Metadata associated with the request, if available. property related_tasks: list[Task] A list of tasks related to the current request. property requested_extensions: set[str] Extensions that the client requested for this interaction. property task_id: str | None The ID of the task associated with this context. property tenant: str The tenant associated with this request. a2a.server.agent_execution.request_context_builder module ********************************************************* class a2a.server.agent_execution.request_context_builder.RequestContextBuilder Bases: "ABC" Builds request context to be supplied to agent executor. abstractmethod async build(context: ServerCallContext, params: SendMessageRequest | None = None, task_id: str | None = None, context_id: str | None = None, task: Task | None = None) -> RequestContext a2a.server.agent_execution.simple_request_context_builder module **************************************************************** class a2a.server.agent_execution.simple_request_context_builder.SimpleRequestContextBuilder(should_populate_referred_tasks: bool = False, task_store: TaskStore | None = None, task_id_generator: IDGenerator | None = None, context_id_generator: IDGenerator | None = None) Bases: "RequestContextBuilder" Builds request context and populates referred tasks. async build(context: ServerCallContext, params: SendMessageRequest | None = None, task_id: str | None = None, context_id: str | None = None, task: Task | None = None) -> RequestContext Builds the request context for an agent execution. This method assembles the RequestContext object. If the builder was initialized with *should_populate_referred_tasks=True*, it fetches all tasks referenced in *params.message.reference_task_ids* from the *task_store*. Parameters: * **context** -- The server call context, containing metadata about the call. * **params** -- The parameters of the incoming message send request. * **task_id** -- The ID of the task being executed. * **context_id** -- The ID of the current execution context. * **task** -- The primary task object associated with the request. Returns: An instance of RequestContext populated with the provided information and potentially a list of related tasks. a2a.server.agent_execution package ********************************** Submodules ========== * a2a.server.agent_execution.active_task module * "ActiveTask" * "ActiveTask.cancel()" * "ActiveTask.enqueue_request()" * "ActiveTask.get_task()" * "ActiveTask.start()" * "ActiveTask.subscribe()" * "ActiveTask.task_id" * "EventConsumer" * "EventConsumer.run()" * a2a.server.agent_execution.active_task_registry module * "ActiveTaskRegistry" * "ActiveTaskRegistry.get()" * "ActiveTaskRegistry.get_or_create()" * a2a.server.agent_execution.agent_executor module * "AgentExecutor" * "AgentExecutor.cancel()" * "AgentExecutor.execute()" * a2a.server.agent_execution.context module * "RequestContext" * "RequestContext.attach_related_task()" * "RequestContext.call_context" * "RequestContext.configuration" * "RequestContext.context_id" * "RequestContext.current_task" * "RequestContext.get_user_input()" * "RequestContext.message" * "RequestContext.metadata" * "RequestContext.related_tasks" * "RequestContext.requested_extensions" * "RequestContext.task_id" * "RequestContext.tenant" * a2a.server.agent_execution.request_context_builder module * "RequestContextBuilder" * "RequestContextBuilder.build()" * a2a.server.agent_execution.simple_request_context_builder module * "SimpleRequestContextBuilder" * "SimpleRequestContextBuilder.build()" Module contents =============== Components for executing agent logic within the A2A server. class a2a.server.agent_execution.AgentExecutor Bases: "ABC" Agent Executor interface. Implementations of this interface contain the core logic of the agent, executing tasks based on requests and publishing updates to an event queue. abstractmethod async cancel(context: RequestContext, event_queue: EventQueue) -> None Request the agent to cancel an ongoing task. The agent should attempt to stop the task identified by the task_id in the context and publish a *TaskStatusUpdateEvent* with state *TaskState.TASK_STATE_CANCELED* to the *event_queue*. Parameters: * **context** -- The request context containing the task ID to cancel. * **event_queue** -- The queue to publish the cancellation status update to. abstractmethod async execute(context: RequestContext, event_queue: EventQueue) -> None Execute the agent's logic for a given request context. The agent should read necessary information from the *context* and publish *Task* or *Message* events, or *TaskStatusUpdateEvent* / *TaskArtifactUpdateEvent* to the *event_queue*. This method should return once the agent's execution for this request is complete or yields control (e.g., enters an input-required state). Request Lifecycle & AgentExecutor Responsibilities: - **Concurrency**: The framework guarantees single execution per request; *execute()* will not be called concurrently for the same request context. * **Exception Handling**: Unhandled exceptions raised by *execute()* will be caught by the framework and result in the task transitioning to *TaskState.TASK_STATE_ERROR*. * **Post-Completion**: Once *execute()* completes (returns or raises), the executor must not access the *context* or *event_queue* anymore. * **Terminal States**: Before completing the call normally, the executor SHOULD publish a *TaskStatusUpdateEvent* to transition the task to a terminal state (e.g., *TASK_STATE_COMPLETED*) or an interrupted state (*TASK_STATE_INPUT_REQUIRED* or *TASK_STATE_AUTH_REQUIRED*). * **Interrupted Workflows**: * *TASK_STATE_INPUT_REQUIRED*: The executor publishes a *TaskStatusUpdateEvent* with *TaskState.TASK_STATE_INPUT_REQUIRED* and returns to yield control. The request will resume once user input is provided. * *TASK_STATE_AUTH_REQUIRED*: There are in-bound and out- of-bound auth models. In both scenarios, the agent publishes a *TaskStatusUpdateEvent* with *TaskState.TASK_STATE_AUTH_REQUIRED*. * In-bound: The agent should return from *execute()*. The framework will call *execute()* again once the user response is received. * Out-of-bound: The agent should not return from *execute()*. It should wait for the out-of-band auth provider to complete the authentication and then continue execution. * **Cancellation Workflow**: When a cancellation request is received, the async task running *execute()* is cancelled (raising an *asyncio.CancelledError*), and *cancel()* is explicitly called by the framework. Allowed Workflows: - Immediate response: Enqueue a SINGLE *Message* object. - Asynchronous/Long-running: Enqueue a *Task* object, perform work, and emit multiple *TaskStatusUpdateEvent* / *TaskArtifactUpdateEvent* objects over time. Note that the framework waits with response to the send_message request with *return_immediately=True* parameter until the first event (Message or Task) is enqueued by AgentExecutor. Parameters: * **context** -- The request context containing the message, task ID, etc. * **event_queue** -- The queue to publish events to. class a2a.server.agent_execution.RequestContext(call_context: ServerCallContext, request: SendMessageRequest | None = None, task_id: str | None = None, context_id: str | None = None, task: Task | None = None, related_tasks: list[Task] | None = None, task_id_generator: IDGenerator | None = None, context_id_generator: IDGenerator | None = None) Bases: "object" Request Context. Holds information about the current request being processed by the server, including the incoming message, task and context identifiers, and related tasks. attach_related_task(task: Task) -> None Attaches a related task to the context. This is useful for scenarios like tool execution where a new task might be spawned. Parameters: **task** -- The *Task* object to attach. property call_context: ServerCallContext The server call context associated with this request. property configuration: SendMessageConfiguration | None The *SendMessageConfiguration* from the request, if available. property context_id: str | None The ID of the conversation context associated with this task. property current_task: Task | None The current *Task* object being processed. get_user_input(delimiter: str = '\n') -> str Extracts text content from the user's message parts. Parameters: **delimiter** -- The string to use when joining multiple text parts. Returns: A single string containing all text content from the user message, joined by the specified delimiter. Returns an empty string if no user message is present or if it contains no text parts. property message: Message | None The incoming *Message* object from the request, if available. property metadata: dict[str, Any] Metadata associated with the request, if available. property related_tasks: list[Task] A list of tasks related to the current request. property requested_extensions: set[str] Extensions that the client requested for this interaction. property task_id: str | None The ID of the task associated with this context. property tenant: str The tenant associated with this request. class a2a.server.agent_execution.RequestContextBuilder Bases: "ABC" Builds request context to be supplied to agent executor. abstractmethod async build(context: ServerCallContext, params: SendMessageRequest | None = None, task_id: str | None = None, context_id: str | None = None, task: Task | None = None) -> RequestContext class a2a.server.agent_execution.SimpleRequestContextBuilder(should_populate_referred_tasks: bool = False, task_store: TaskStore | None = None, task_id_generator: IDGenerator | None = None, context_id_generator: IDGenerator | None = None) Bases: "RequestContextBuilder" Builds request context and populates referred tasks. async build(context: ServerCallContext, params: SendMessageRequest | None = None, task_id: str | None = None, context_id: str | None = None, task: Task | None = None) -> RequestContext Builds the request context for an agent execution. This method assembles the RequestContext object. If the builder was initialized with *should_populate_referred_tasks=True*, it fetches all tasks referenced in *params.message.reference_task_ids* from the *task_store*. Parameters: * **context** -- The server call context, containing metadata about the call. * **params** -- The parameters of the incoming message send request. * **task_id** -- The ID of the task being executed. * **context_id** -- The ID of the current execution context. * **task** -- The primary task object associated with the request. Returns: An instance of RequestContext populated with the provided information and potentially a list of related tasks. a2a.server.context module ************************* Defines the ServerCallContext class. class a2a.server.context.ServerCallContext(*, state: MutableMapping[str, ~typing.Any]=, user: User = , tenant: str = '', requested_extensions: set[str] = ) Bases: "BaseModel" A context passed when calling a server method. This class allows storing arbitrary user data in the state attribute. model_config = {'arbitrary_types_allowed': True} Configuration for the model, should be a dictionary conforming to [*ConfigDict*][pydantic.config.ConfigDict]. requested_extensions: set[str] state: MutableMapping[str, Any] tenant: str user: User a2a.server.events.event_consumer module *************************************** class a2a.server.events.event_consumer.EventConsumer(queue: EventQueueLegacy) Bases: "object" Consumer to read events from the agent event queue. agent_task_callback(agent_task: Task[None]) -> None Callback to handle exceptions from the agent's execution task. If the agent's asyncio task raises an exception, this callback is invoked, and the exception is stored to be re-raised by the consumer loop. Parameters: **agent_task** -- The asyncio.Task that completed. consume_all() -> AsyncGenerator[Message | Task | TaskStatusUpdateEvent | TaskArtifactUpdateEvent] Consume all the generated streaming events from the agent. This method yields events as they become available from the queue until a final event is received or the queue is closed. It also monitors for exceptions set by the *agent_task_callback*. Yields: Events dequeued from the queue. Raises: **BaseException** -- If an exception was set by the *agent_task_callback*. a2a.server.events.event_queue module ************************************ a2a.server.events.event_queue.Event = a2a_pb2.Message | a2a_pb2.Task | a2a_pb2.TaskStatusUpdateEvent | a2a_pb2.TaskArtifactUpdateEvent Type alias for events that can be enqueued. class a2a.server.events.event_queue.EventQueue(*args: Any, **kwargs: Any) Bases: "ABC" Producer-side interface passed to *AgentExecutor.execute*/*cancel*. Exposes only *enqueue_event*. The consumer is framework-managed and not part of the public surface. Default request handlers construct the queue and pass it in; executors should accept it and not construct one. To run an executor outside the framework, write a custom subclass or use *EventQueueLegacy* (deprecated, will be removed in a future release). abstractmethod async enqueue_event(event: Message | Task | TaskStatusUpdateEvent | TaskArtifactUpdateEvent) -> None Pushes an event into the queue. Only main queue can enqueue events. Child queues can only dequeue events. class a2a.server.events.event_queue.EventQueueLegacy(*args: Any, **kwargs: Any) Bases: "EventQueue" Event queue for A2A responses from agent. Acts as a buffer between the agent's asynchronous execution and the server's response handling (e.g., streaming via SSE). Supports tapping to create child queues that receive the same events. async close(immediate: bool = False) -> None Closes the queue for future push events and also closes all child queues. Parameters: **immediate** -- If True, immediately flushes the queue, discarding all pending events, and causes any currently blocked *dequeue_event* calls to raise *QueueShutDown*. If False (default), the queue is marked as closed to new events, but existing events can still be dequeued and processed until the queue is fully drained. async dequeue_event() -> Message | Task | TaskStatusUpdateEvent | TaskArtifactUpdateEvent Dequeues an event from the queue. This implementation expects that dequeue to raise an exception when the queue has been closed. In python 3.13+ this is naturally provided by the QueueShutDown exception generated when the queue has closed and the user is awaiting the queue.get method. Python<=3.12 this needs to manage this lifecycle itself. The current implementation can lead to blocking if the dequeue_event is called before the EventQueue has been closed but when there are no events on the queue. One way to avoid this is to use an async Task management solution to cancel the get task if the queue has closed or some other condition is met. The implementation of the EventConsumer uses an async.wait with a timeout to abort the dequeue_event call and retry, when it will return with a closed error. Returns: The next event from the queue. Raises: **asyncio.QueueShutDown** -- If the queue has been closed and is empty. async enqueue_event(event: Message | Task | TaskStatusUpdateEvent | TaskArtifactUpdateEvent) -> None Enqueues an event to this queue and all its children. Parameters: **event** -- The event object to enqueue. is_closed() -> bool Checks if the queue is closed. property queue: Queue[Message | Task | TaskStatusUpdateEvent | TaskArtifactUpdateEvent] [DEPRECATED] Returns the underlying asyncio.Queue. async tap(max_queue_size: int = 1024) -> EventQueueLegacy Taps the event queue to create a new child queue that receives future events. Returns: A new *EventQueue* instance that will receive all events enqueued to this parent queue from this point forward. task_done() -> None Signals that a formerly enqueued task is complete. Used in conjunction with *dequeue_event* to track processed items. a2a.server.events.event_queue_v2 module *************************************** class a2a.server.events.event_queue_v2.EventQueueSink(*args: Any, **kwargs: Any) Bases: "EventQueue" The Child EventQueue. Acts as a read-only consumer endpoint. Events are pushed here exclusively by the parent EventQueueSource's dispatcher task. async close(immediate: bool = False) -> None Closes the child sink queue. It is safe to call it multiple times. If immediate is True, the queue will be closed without waiting for all events to be processed. If immediate is False, the queue will be closed after all events are processed (and confirmed with task_done() calls). async dequeue_event() -> Message | Task | TaskStatusUpdateEvent | TaskArtifactUpdateEvent Pulls an event from the sink queue. async enqueue_event(event: Message | Task | TaskStatusUpdateEvent | TaskArtifactUpdateEvent) -> None Sinks are read-only and cannot have events directly enqueued to them. is_closed() -> bool [DEPRECATED] Checks if the queue is closed. NOTE: Relying on this for enqueue logic introduces race conditions. It is maintained primarily for backwards compatibility, workarounds for Python 3.10/3.12 async queues in consumers, and for the test suite. property queue: Queue[Message | Task | TaskStatusUpdateEvent | TaskArtifactUpdateEvent] Returns the underlying asyncio.Queue of this sink. async tap(max_queue_size: int = 1024) -> EventQueueSink Creates a child queue that receives future events. Note: The tapped queue may receive some old events if the incoming event queue is lagging behind and hasn't dispatched them yet. task_done() -> None Signals that a work on dequeued event is complete in this sink queue. class a2a.server.events.event_queue_v2.EventQueueSource(*args: Any, **kwargs: Any) Bases: "EventQueue" The Parent EventQueue. Acts as the single entry point for producers. Events pushed here are buffered in *_incoming_queue* and distributed to all child Sinks by a background dispatcher task. async close(immediate: bool = False) -> None Closes the queue and all its child sinks. It is safe to call it multiple times. If immediate is True, the queue will be closed without waiting for all events to be processed. If immediate is False, the queue will be closed after all events are processed (and confirmed with task_done() calls). WARNING: Closing the parent queue with immediate=False is a deadlock risk if there are unconsumed events in any of the child sinks and the consumer has crashed without draining its queue. It is highly recommended to wrap graceful shutdowns with a timeout, e.g., *asyncio.wait_for(queue.close(immediate=False), timeout=...)*. async dequeue_event() -> Message | Task | TaskStatusUpdateEvent | TaskArtifactUpdateEvent Pulls an event from the default internal sink queue. async enqueue_event(event: Message | Task | TaskStatusUpdateEvent | TaskArtifactUpdateEvent) -> None Enqueues an event to this queue and all its children. is_closed() -> bool [DEPRECATED] Checks if the queue is closed. NOTE: Relying on this for enqueue logic introduces race conditions. It is maintained primarily for backwards compatibility, workarounds for Python 3.10/3.12 async queues in consumers, and for the test suite. property queue: Queue[Message | Task | TaskStatusUpdateEvent | TaskArtifactUpdateEvent] Returns the underlying asyncio.Queue of the default sink. async remove_sink(sink: EventQueueSink) -> None Removes a sink from the source's internal list. async tap(max_queue_size: int = 1024) -> EventQueueSink Taps the event queue to create a new child queue that receives future events. Note: The tapped queue may receive some old events if the incoming event queue is lagging behind and hasn't dispatched them yet. task_done() -> None Signals that a work on dequeued event is complete via the default internal sink queue. async test_only_join_incoming_queue() -> None Wait for incoming queue to be fully processed. a2a.server.events.in_memory_queue_manager module ************************************************ class a2a.server.events.in_memory_queue_manager.InMemoryQueueManager Bases: "QueueManager" InMemoryQueueManager is used for a single binary management. This implements the *QueueManager* interface using in-memory storage for event queues. It requires all incoming interactions for a given task ID to hit the same binary instance. This implementation is suitable for single-instance deployments but needs a distributed approach for scalable deployments. async add(task_id: str, queue: EventQueueLegacy) -> None Adds a new event queue for a task ID. Raises: **TaskQueueExists** -- If a queue for the given *task_id* already exists. async close(task_id: str) -> None Closes and removes the event queue for a task ID. Raises: **NoTaskQueue** -- If no queue exists for the given *task_id*. async create_or_tap(task_id: str) -> EventQueueLegacy Creates a new event queue for a task ID if one doesn't exist, otherwise taps the existing one. Returns: A new or child *EventQueueLegacy* instance for the *task_id*. async get(task_id: str) -> EventQueueLegacy | None Retrieves the event queue for a task ID. Returns: The *EventQueueLegacy* instance for the *task_id*, or *None* if not found. async tap(task_id: str) -> EventQueueLegacy | None Taps the event queue for a task ID to create a child queue. Returns: A new child *EventQueueLegacy* instance, or *None* if the task ID is not found. a2a.server.events.queue_manager module ************************************** exception a2a.server.events.queue_manager.NoTaskQueue Bases: "Exception" Exception raised when attempting to access or close a queue for a task ID that does not exist. class a2a.server.events.queue_manager.QueueManager Bases: "ABC" Interface for managing the event queue lifecycles per task. abstractmethod async add(task_id: str, queue: EventQueueLegacy) -> None Adds a new event queue associated with a task ID. abstractmethod async close(task_id: str) -> None Closes and removes the event queue for a task ID. abstractmethod async create_or_tap(task_id: str) -> EventQueueLegacy Creates a queue if one doesn't exist, otherwise taps the existing one. abstractmethod async get(task_id: str) -> EventQueueLegacy | None Retrieves the event queue for a task ID. abstractmethod async tap(task_id: str) -> EventQueueLegacy | None Creates a child event queue (tap) for an existing task ID. exception a2a.server.events.queue_manager.TaskQueueExists Bases: "Exception" Exception raised when attempting to add a queue for a task ID that already exists. a2a.server.events package ************************* Submodules ========== * a2a.server.events.event_consumer module * "EventConsumer" * "EventConsumer.agent_task_callback()" * "EventConsumer.consume_all()" * a2a.server.events.event_queue module * "Event" * "EventQueue" * "EventQueue.enqueue_event()" * "EventQueueLegacy" * "EventQueueLegacy.close()" * "EventQueueLegacy.dequeue_event()" * "EventQueueLegacy.enqueue_event()" * "EventQueueLegacy.is_closed()" * "EventQueueLegacy.queue" * "EventQueueLegacy.tap()" * "EventQueueLegacy.task_done()" * a2a.server.events.event_queue_v2 module * "EventQueueSink" * "EventQueueSink.close()" * "EventQueueSink.dequeue_event()" * "EventQueueSink.enqueue_event()" * "EventQueueSink.is_closed()" * "EventQueueSink.queue" * "EventQueueSink.tap()" * "EventQueueSink.task_done()" * "EventQueueSource" * "EventQueueSource.close()" * "EventQueueSource.dequeue_event()" * "EventQueueSource.enqueue_event()" * "EventQueueSource.is_closed()" * "EventQueueSource.queue" * "EventQueueSource.remove_sink()" * "EventQueueSource.tap()" * "EventQueueSource.task_done()" * "EventQueueSource.test_only_join_incoming_queue()" * a2a.server.events.in_memory_queue_manager module * "InMemoryQueueManager" * "InMemoryQueueManager.add()" * "InMemoryQueueManager.close()" * "InMemoryQueueManager.create_or_tap()" * "InMemoryQueueManager.get()" * "InMemoryQueueManager.tap()" * a2a.server.events.queue_manager module * "NoTaskQueue" * "QueueManager" * "QueueManager.add()" * "QueueManager.close()" * "QueueManager.create_or_tap()" * "QueueManager.get()" * "QueueManager.tap()" * "TaskQueueExists" Module contents =============== Event handling components for the A2A server. class a2a.server.events.EventConsumer(queue: EventQueueLegacy) Bases: "object" Consumer to read events from the agent event queue. agent_task_callback(agent_task: Task[None]) -> None Callback to handle exceptions from the agent's execution task. If the agent's asyncio task raises an exception, this callback is invoked, and the exception is stored to be re-raised by the consumer loop. Parameters: **agent_task** -- The asyncio.Task that completed. consume_all() -> AsyncGenerator[Message | Task | TaskStatusUpdateEvent | TaskArtifactUpdateEvent] Consume all the generated streaming events from the agent. This method yields events as they become available from the queue until a final event is received or the queue is closed. It also monitors for exceptions set by the *agent_task_callback*. Yields: Events dequeued from the queue. Raises: **BaseException** -- If an exception was set by the *agent_task_callback*. class a2a.server.events.EventQueue(*args: Any, **kwargs: Any) Bases: "ABC" Producer-side interface passed to *AgentExecutor.execute*/*cancel*. Exposes only *enqueue_event*. The consumer is framework-managed and not part of the public surface. Default request handlers construct the queue and pass it in; executors should accept it and not construct one. To run an executor outside the framework, write a custom subclass or use *EventQueueLegacy* (deprecated, will be removed in a future release). abstractmethod async enqueue_event(event: Message | Task | TaskStatusUpdateEvent | TaskArtifactUpdateEvent) -> None Pushes an event into the queue. Only main queue can enqueue events. Child queues can only dequeue events. class a2a.server.events.EventQueueLegacy(*args: Any, **kwargs: Any) Bases: "EventQueue" Event queue for A2A responses from agent. Acts as a buffer between the agent's asynchronous execution and the server's response handling (e.g., streaming via SSE). Supports tapping to create child queues that receive the same events. async close(immediate: bool = False) -> None Closes the queue for future push events and also closes all child queues. Parameters: **immediate** -- If True, immediately flushes the queue, discarding all pending events, and causes any currently blocked *dequeue_event* calls to raise *QueueShutDown*. If False (default), the queue is marked as closed to new events, but existing events can still be dequeued and processed until the queue is fully drained. async dequeue_event() -> Message | Task | TaskStatusUpdateEvent | TaskArtifactUpdateEvent Dequeues an event from the queue. This implementation expects that dequeue to raise an exception when the queue has been closed. In python 3.13+ this is naturally provided by the QueueShutDown exception generated when the queue has closed and the user is awaiting the queue.get method. Python<=3.12 this needs to manage this lifecycle itself. The current implementation can lead to blocking if the dequeue_event is called before the EventQueue has been closed but when there are no events on the queue. One way to avoid this is to use an async Task management solution to cancel the get task if the queue has closed or some other condition is met. The implementation of the EventConsumer uses an async.wait with a timeout to abort the dequeue_event call and retry, when it will return with a closed error. Returns: The next event from the queue. Raises: **asyncio.QueueShutDown** -- If the queue has been closed and is empty. async enqueue_event(event: Message | Task | TaskStatusUpdateEvent | TaskArtifactUpdateEvent) -> None Enqueues an event to this queue and all its children. Parameters: **event** -- The event object to enqueue. is_closed() -> bool Checks if the queue is closed. property queue: Queue[Message | Task | TaskStatusUpdateEvent | TaskArtifactUpdateEvent] [DEPRECATED] Returns the underlying asyncio.Queue. async tap(max_queue_size: int = 1024) -> EventQueueLegacy Taps the event queue to create a new child queue that receives future events. Returns: A new *EventQueue* instance that will receive all events enqueued to this parent queue from this point forward. task_done() -> None Signals that a formerly enqueued task is complete. Used in conjunction with *dequeue_event* to track processed items. class a2a.server.events.InMemoryQueueManager Bases: "QueueManager" InMemoryQueueManager is used for a single binary management. This implements the *QueueManager* interface using in-memory storage for event queues. It requires all incoming interactions for a given task ID to hit the same binary instance. This implementation is suitable for single-instance deployments but needs a distributed approach for scalable deployments. async add(task_id: str, queue: EventQueueLegacy) -> None Adds a new event queue for a task ID. Raises: **TaskQueueExists** -- If a queue for the given *task_id* already exists. async close(task_id: str) -> None Closes and removes the event queue for a task ID. Raises: **NoTaskQueue** -- If no queue exists for the given *task_id*. async create_or_tap(task_id: str) -> EventQueueLegacy Creates a new event queue for a task ID if one doesn't exist, otherwise taps the existing one. Returns: A new or child *EventQueueLegacy* instance for the *task_id*. async get(task_id: str) -> EventQueueLegacy | None Retrieves the event queue for a task ID. Returns: The *EventQueueLegacy* instance for the *task_id*, or *None* if not found. async tap(task_id: str) -> EventQueueLegacy | None Taps the event queue for a task ID to create a child queue. Returns: A new child *EventQueueLegacy* instance, or *None* if the task ID is not found. exception a2a.server.events.NoTaskQueue Bases: "Exception" Exception raised when attempting to access or close a queue for a task ID that does not exist. class a2a.server.events.QueueManager Bases: "ABC" Interface for managing the event queue lifecycles per task. abstractmethod async add(task_id: str, queue: EventQueueLegacy) -> None Adds a new event queue associated with a task ID. abstractmethod async close(task_id: str) -> None Closes and removes the event queue for a task ID. abstractmethod async create_or_tap(task_id: str) -> EventQueueLegacy Creates a queue if one doesn't exist, otherwise taps the existing one. abstractmethod async get(task_id: str) -> EventQueueLegacy | None Retrieves the event queue for a task ID. abstractmethod async tap(task_id: str) -> EventQueueLegacy | None Creates a child event queue (tap) for an existing task ID. exception a2a.server.events.TaskQueueExists Bases: "Exception" Exception raised when attempting to add a queue for a task ID that already exists. a2a.server.id_generator module ****************************** class a2a.server.id_generator.IDGenerator Bases: "ABC" Interface for generating unique identifiers. abstractmethod generate(context: IDGeneratorContext) -> str class a2a.server.id_generator.IDGeneratorContext(*, task_id: str | None = None, context_id: str | None = None) Bases: "BaseModel" Context for providing additional information to ID generators. context_id: str | None model_config = {} Configuration for the model, should be a dictionary conforming to [*ConfigDict*][pydantic.config.ConfigDict]. task_id: str | None class a2a.server.id_generator.UUIDGenerator Bases: "IDGenerator" UUID implementation of the IDGenerator interface. generate(context: IDGeneratorContext) -> str Generates a random UUID, ignoring the context. a2a.server.jsonrpc_models module ******************************** class a2a.server.jsonrpc_models.InternalError(*, code: Literal[-32603] = -32603, message: str = 'Internal error', data: Any | None = None, **extra_data: Any) Bases: "JSONRPCError" Error raised when internal JSON-RPC error. code: Literal[-32603] message: str model_config = {'arbitrary_types_allowed': True, 'extra': 'allow', 'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True} Configuration for the model, should be a dictionary conforming to [*ConfigDict*][pydantic.config.ConfigDict]. class a2a.server.jsonrpc_models.InvalidParamsError(*, code: Literal[-32602] = -32602, message: str = 'Invalid params', data: Any | None = None, **extra_data: Any) Bases: "JSONRPCError" Error raised when invalid method parameter(s). code: Literal[-32602] message: str model_config = {'arbitrary_types_allowed': True, 'extra': 'allow', 'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True} Configuration for the model, should be a dictionary conforming to [*ConfigDict*][pydantic.config.ConfigDict]. class a2a.server.jsonrpc_models.InvalidRequestError(*, code: Literal[-32600] = -32600, message: str = 'Invalid Request', data: Any | None = None, **extra_data: Any) Bases: "JSONRPCError" Error raised when the JSON sent is not a valid Request object. code: Literal[-32600] message: str model_config = {'arbitrary_types_allowed': True, 'extra': 'allow', 'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True} Configuration for the model, should be a dictionary conforming to [*ConfigDict*][pydantic.config.ConfigDict]. class a2a.server.jsonrpc_models.JSONParseError(*, code: Literal[-32700] = -32700, message: str = 'Parse error', data: Any | None = None, **extra_data: Any) Bases: "JSONRPCError" Error raised when invalid JSON was received by the server. code: Literal[-32700] message: str model_config = {'arbitrary_types_allowed': True, 'extra': 'allow', 'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True} Configuration for the model, should be a dictionary conforming to [*ConfigDict*][pydantic.config.ConfigDict]. class a2a.server.jsonrpc_models.JSONRPCBaseModel(**extra_data: Any) Bases: "BaseModel" Base model for JSON-RPC objects. model_config = {'arbitrary_types_allowed': True, 'extra': 'allow', 'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True} Configuration for the model, should be a dictionary conforming to [*ConfigDict*][pydantic.config.ConfigDict]. class a2a.server.jsonrpc_models.JSONRPCError(*, code: int, message: str, data: Any | None = None, **extra_data: Any) Bases: "JSONRPCBaseModel" Base model for JSON-RPC error objects. code: int data: Any | None message: str model_config = {'arbitrary_types_allowed': True, 'extra': 'allow', 'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True} Configuration for the model, should be a dictionary conforming to [*ConfigDict*][pydantic.config.ConfigDict]. class a2a.server.jsonrpc_models.MethodNotFoundError(*, code: Literal[-32601] = -32601, message: str = 'Method not found', data: Any | None = None, **extra_data: Any) Bases: "JSONRPCError" Error raised when the method does not exist / is not available. code: Literal[-32601] message: str model_config = {'arbitrary_types_allowed': True, 'extra': 'allow', 'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True} Configuration for the model, should be a dictionary conforming to [*ConfigDict*][pydantic.config.ConfigDict]. a2a.server.models module ************************ class a2a.server.models.Base(**kwargs: Any) Bases: "DeclarativeBase" Base class for declarative models in A2A SDK. metadata: ClassVar[MetaData] = MetaData() Refers to the "_schema.MetaData" collection that will be used for new "_schema.Table" objects. See also: *orm_declarative_metadata* registry: ClassVar[registry] = Refers to the "_orm.registry" in use where new "_orm.Mapper" objects will be associated. class a2a.server.models.PushNotificationConfigMixin Bases: "object" Mixin providing standard push notification config columns. config_data: Mapped[bytes] = config_id: Mapped[str] = owner: Mapped[str] = protocol_version: Mapped[str | None] = task_id: Mapped[str] = class a2a.server.models.PushNotificationConfigModel(**kwargs) Bases: "PushNotificationConfigMixin", "Base" Default push notification config model with standard table name. config_data: Mapped[bytes] config_id: Mapped[str] owner: Mapped[str] protocol_version: Mapped[str | None] task_id: Mapped[str] class a2a.server.models.TaskMixin Bases: "object" Mixin providing standard task columns with proper type handling. artifacts: Mapped[list[Artifact] | None] = context_id: Mapped[str] = history: Mapped[list[Message] | None] = id: Mapped[str] = kind: Mapped[str] = last_updated: Mapped[datetime | None] = owner: Mapped[str] = protocol_version: Mapped[str | None] = status: Mapped[TaskStatus] = task_metadata = class a2a.server.models.TaskModel(**kwargs) Bases: "TaskMixin", "Base" Default task model with standard table name. artifacts: Mapped[list[Artifact] | None] context_id: Mapped[str] history: Mapped[list[Message] | None] id: Mapped[str] kind: Mapped[str] last_updated: Mapped[datetime | None] owner: Mapped[str] protocol_version: Mapped[str | None] status: Mapped[TaskStatus] task_metadata a2a.server.models.create_push_notification_config_model(table_name: str = 'push_notification_configs', base: type[DeclarativeBase] = ) -> type Create a PushNotificationConfigModel class with a configurable table name. a2a.server.models.create_task_model(table_name: str = 'tasks', base: type[DeclarativeBase] = ) -> type Create a TaskModel class with a configurable table name. Parameters: * **table_name** -- Name of the database table. Defaults to 'tasks'. * **base** -- Base declarative class to use. Defaults to the SDK's Base class. Returns: TaskModel class with the specified table name. -[ Example ]- # Create a task model with default table name TaskModel = create_task_model() # Create a task model with custom table name CustomTaskModel = create_task_model('my_tasks') # Use with a custom base from myapp.database import Base as MyBase TaskModel = create_task_model('tasks', MyBase) a2a.server.models.override(func) Override decorator. a2a.server.owner_resolver module ******************************** a2a.server.owner_resolver.resolve_user_scope(context: ServerCallContext) -> str Resolves the owner scope based on the user in the context. a2a.server.request_handlers.default_request_handler module ********************************************************** class a2a.server.request_handlers.default_request_handler.LegacyRequestHandler(agent_executor: AgentExecutor, task_store: TaskStore, agent_card: AgentCard, queue_manager: QueueManager | None = None, push_config_store: PushNotificationConfigStore | None = None, push_sender: PushNotificationSender | None = None, request_context_builder: RequestContextBuilder | None = None, extended_agent_card: AgentCard | None = None, extended_card_modifier: Callable[[AgentCard, ServerCallContext], Awaitable[AgentCard]] | None = None) Bases: "RequestHandler" Default request handler for all incoming requests. This handler provides default implementations for all A2A JSON-RPC methods, coordinating between the *AgentExecutor*, *TaskStore*, *QueueManager*, and optional *PushNotifier*. async on_cancel_task(params: CancelTaskRequest, context: ServerCallContext) -> Task | None Default handler for 'tasks/cancel'. Attempts to cancel the task managed by the *AgentExecutor*. async on_create_task_push_notification_config(params: TaskPushNotificationConfig, context: ServerCallContext) -> TaskPushNotificationConfig Default handler for 'tasks/pushNotificationConfig/create'. Requires a *PushNotifier* to be configured. async on_delete_task_push_notification_config(params: DeleteTaskPushNotificationConfigRequest, context: ServerCallContext) -> None Default handler for 'tasks/pushNotificationConfig/delete'. Requires a *PushConfigStore* to be configured. async on_get_extended_agent_card(params: GetExtendedAgentCardRequest, context: ServerCallContext) -> AgentCard Default handler for 'GetExtendedAgentCard'. Requires *capabilities.extended_agent_card* to be true. async on_get_task(params: GetTaskRequest, context: ServerCallContext) -> Task | None Default handler for 'tasks/get'. async on_get_task_push_notification_config(params: GetTaskPushNotificationConfigRequest, context: ServerCallContext) -> TaskPushNotificationConfig Default handler for 'tasks/pushNotificationConfig/get'. Requires a *PushConfigStore* to be configured. async on_list_task_push_notification_configs(params: ListTaskPushNotificationConfigsRequest, context: ServerCallContext) -> ListTaskPushNotificationConfigsResponse Default handler for 'ListTaskPushNotificationConfigs'. Requires a *PushConfigStore* to be configured. async on_list_tasks(params: ListTasksRequest, context: ServerCallContext) -> ListTasksResponse Default handler for 'tasks/list'. async on_message_send(params: SendMessageRequest, context: ServerCallContext) -> Message | Task Default handler for 'message/send' interface (non-streaming). Starts the agent execution for the message and waits for the final result (Task or Message). on_message_send_stream(params: SendMessageRequest, context: ServerCallContext) -> AsyncGenerator[Message | Task | TaskStatusUpdateEvent | TaskArtifactUpdateEvent] Default handler for 'message/stream' (streaming). Starts the agent execution and yields events as they are produced by the agent. on_subscribe_to_task(params: SubscribeToTaskRequest, context: ServerCallContext) -> AsyncGenerator[Message | Task | TaskStatusUpdateEvent | TaskArtifactUpdateEvent, None] Default handler for 'SubscribeToTask'. Allows a client to re-attach to a running streaming task's event stream. Requires the task and its queue to still be active. a2a.server.request_handlers.default_request_handler_v2 module ************************************************************* class a2a.server.request_handlers.default_request_handler_v2.DefaultRequestHandlerV2(agent_executor: AgentExecutor, task_store: TaskStore, agent_card: AgentCard, queue_manager: Any | None = None, push_config_store: PushNotificationConfigStore | None = None, push_sender: PushNotificationSender | None = None, request_context_builder: RequestContextBuilder | None = None, extended_agent_card: AgentCard | None = None, extended_card_modifier: Callable[[AgentCard, ServerCallContext], Awaitable[AgentCard]] | None = None) Bases: "RequestHandler" Default request handler for all incoming requests. async on_cancel_task(params: CancelTaskRequest, context: ServerCallContext) -> Task | None Handles the 'tasks/cancel' method. Requests the agent to cancel an ongoing task. Parameters: * **params** -- Parameters specifying the task ID. * **context** -- Context provided by the server. Returns: The *Task* object with its status updated to canceled, or *None* if the task was not found. async on_create_task_push_notification_config(params: TaskPushNotificationConfig, context: ServerCallContext) -> TaskPushNotificationConfig Handles the 'tasks/pushNotificationConfig/create' method. Sets or updates the push notification configuration for a task. Parameters: * **params** -- Parameters including the task ID and push notification configuration. * **context** -- Context provided by the server. Returns: The provided *TaskPushNotificationConfig* upon success. async on_delete_task_push_notification_config(params: DeleteTaskPushNotificationConfigRequest, context: ServerCallContext) -> None Handles the 'tasks/pushNotificationConfig/delete' method. Deletes a push notification configuration associated with a task. Parameters: * **params** -- Parameters including the task ID. * **context** -- Context provided by the server. Returns: None async on_get_extended_agent_card(params: GetExtendedAgentCardRequest, context: ServerCallContext) -> AgentCard Default handler for 'GetExtendedAgentCard'. Requires *capabilities.extended_agent_card* to be true. async on_get_task(params: GetTaskRequest, context: ServerCallContext) -> Task | None Handles the 'tasks/get' method. Retrieves the state and history of a specific task. Parameters: * **params** -- Parameters specifying the task ID and optionally history length. * **context** -- Context provided by the server. Returns: The *Task* object if found, otherwise *None*. async on_get_task_push_notification_config(params: GetTaskPushNotificationConfigRequest, context: ServerCallContext) -> TaskPushNotificationConfig Handles the 'tasks/pushNotificationConfig/get' method. Retrieves the current push notification configuration for a task. Parameters: * **params** -- Parameters including the task ID. * **context** -- Context provided by the server. Returns: The *TaskPushNotificationConfig* for the task. async on_list_task_push_notification_configs(params: ListTaskPushNotificationConfigsRequest, context: ServerCallContext) -> ListTaskPushNotificationConfigsResponse Handles the 'ListTaskPushNotificationConfigs' method. Retrieves the current push notification configurations for a task. Parameters: * **params** -- Parameters including the task ID. * **context** -- Context provided by the server. Returns: The *list[TaskPushNotificationConfig]* for the task. async on_list_tasks(params: ListTasksRequest, context: ServerCallContext) -> ListTasksResponse Handles the tasks/list method. Retrieves all tasks for an agent. Supports filtering, pagination, ordering, limiting the history length, excluding artifacts, etc. Parameters: * **params** -- Parameters with filtering criteria. * **context** -- Context provided by the server. Returns: The *ListTasksResponse* containing the tasks. async on_message_send(params: SendMessageRequest, context: ServerCallContext) -> Message | Task Handles the 'message/send' method (non-streaming). Sends a message to the agent to create, continue, or restart a task, and waits for the final result (Task or Message). Parameters: * **params** -- Parameters including the message and configuration. * **context** -- Context provided by the server. Returns: The final *Task* object or a final *Message* object. on_message_send_stream(params: SendMessageRequest, context: ServerCallContext) -> AsyncGenerator[Event, None] Handles the 'message/stream' method (streaming). Sends a message to the agent and yields stream events as they are produced (Task updates, Message chunks, Artifact updates). Parameters: * **params** -- Parameters including the message and configuration. * **context** -- Context provided by the server. Yields: *Event* objects from the agent's execution. on_subscribe_to_task(params: SubscribeToTaskRequest, context: ServerCallContext) -> AsyncGenerator[Event, None] Handles the 'SubscribeToTask' method. Allows a client to subscribe to a running streaming task's event stream. Parameters: * **params** -- Parameters including the task ID. * **context** -- Context provided by the server. Yields: *Event* objects from the agent's ongoing execution for the specified task. a2a.server.request_handlers.grpc_handler module *********************************************** class a2a.server.request_handlers.grpc_handler.DefaultGrpcServerCallContextBuilder Bases: "GrpcServerCallContextBuilder" Default implementation of GrpcServerCallContextBuilder. build(context: ServicerContext) -> ServerCallContext Builds a ServerCallContext from a gRPC ServicerContext. build_user(context: ServicerContext) -> User Builds a User from a gRPC ServicerContext. class a2a.server.request_handlers.grpc_handler.GrpcHandler(request_handler: RequestHandler, context_builder: GrpcServerCallContextBuilder | None = None) Bases: "A2AServiceServicer" Maps incoming gRPC requests to the appropriate request handler method. async CancelTask(request: CancelTaskRequest, context: ServicerContext) -> Task Handles the 'CancelTask' gRPC method. async CreateTaskPushNotificationConfig(request: TaskPushNotificationConfig, context: ServicerContext) -> TaskPushNotificationConfig Handles the 'CreateTaskPushNotificationConfig' gRPC method. async DeleteTaskPushNotificationConfig(request: DeleteTaskPushNotificationConfigRequest, context: ServicerContext) -> Empty Handles the 'DeleteTaskPushNotificationConfig' gRPC method. async GetExtendedAgentCard(request: GetExtendedAgentCardRequest, context: ServicerContext) -> AgentCard Get the extended agent card for the agent served. async GetTask(request: GetTaskRequest, context: ServicerContext) -> Task Handles the 'GetTask' gRPC method. async GetTaskPushNotificationConfig(request: GetTaskPushNotificationConfigRequest, context: ServicerContext) -> TaskPushNotificationConfig Handles the 'GetTaskPushNotificationConfig' gRPC method. async ListTaskPushNotificationConfigs(request: ListTaskPushNotificationConfigsRequest, context: ServicerContext) -> ListTaskPushNotificationConfigsResponse Handles the 'ListTaskPushNotificationConfig' gRPC method. async ListTasks(request: ListTasksRequest, context: ServicerContext) -> ListTasksResponse Handles the 'ListTasks' gRPC method. async SendMessage(request: SendMessageRequest, context: ServicerContext) -> SendMessageResponse Handles the 'SendMessage' gRPC method. async SendStreamingMessage(request: SendMessageRequest, context: ServicerContext) -> AsyncIterable[StreamResponse] Handles the 'StreamMessage' gRPC method. async SubscribeToTask(request: SubscribeToTaskRequest, context: ServicerContext) -> AsyncIterable[StreamResponse] Handles the 'SubscribeToTask' gRPC method. async abort_context(error: A2AError, context: ServicerContext) -> None Sets the grpc errors appropriately in the context. class a2a.server.request_handlers.grpc_handler.GrpcServerCallContextBuilder Bases: "ABC" Interface for building ServerCallContext from gRPC context. abstractmethod build(context: ServicerContext) -> ServerCallContext Builds a ServerCallContext from a gRPC ServicerContext. a2a.server.request_handlers.request_handler module ************************************************** class a2a.server.request_handlers.request_handler.RequestHandler Bases: "ABC" A2A request handler interface. This interface defines the methods that an A2A server implementation must provide to handle incoming A2A requests from any transport (gRPC, REST, JSON-RPC). abstractmethod async on_cancel_task(params: CancelTaskRequest, context: ServerCallContext) -> Task | None Handles the 'tasks/cancel' method. Requests the agent to cancel an ongoing task. Parameters: * **params** -- Parameters specifying the task ID. * **context** -- Context provided by the server. Returns: The *Task* object with its status updated to canceled, or *None* if the task was not found. abstractmethod async on_create_task_push_notification_config(params: TaskPushNotificationConfig, context: ServerCallContext) -> TaskPushNotificationConfig Handles the 'tasks/pushNotificationConfig/create' method. Sets or updates the push notification configuration for a task. Parameters: * **params** -- Parameters including the task ID and push notification configuration. * **context** -- Context provided by the server. Returns: The provided *TaskPushNotificationConfig* upon success. abstractmethod async on_delete_task_push_notification_config(params: DeleteTaskPushNotificationConfigRequest, context: ServerCallContext) -> None Handles the 'tasks/pushNotificationConfig/delete' method. Deletes a push notification configuration associated with a task. Parameters: * **params** -- Parameters including the task ID. * **context** -- Context provided by the server. Returns: None abstractmethod async on_get_extended_agent_card(params: GetExtendedAgentCardRequest, context: ServerCallContext) -> AgentCard Handles the 'GetExtendedAgentCard' method. Retrieves the extended agent card for the agent. Parameters: * **params** -- Parameters for the request. * **context** -- Context provided by the server. Returns: The *AgentCard* object representing the extended properties of the agent. abstractmethod async on_get_task(params: GetTaskRequest, context: ServerCallContext) -> Task | None Handles the 'tasks/get' method. Retrieves the state and history of a specific task. Parameters: * **params** -- Parameters specifying the task ID and optionally history length. * **context** -- Context provided by the server. Returns: The *Task* object if found, otherwise *None*. abstractmethod async on_get_task_push_notification_config(params: GetTaskPushNotificationConfigRequest, context: ServerCallContext) -> TaskPushNotificationConfig Handles the 'tasks/pushNotificationConfig/get' method. Retrieves the current push notification configuration for a task. Parameters: * **params** -- Parameters including the task ID. * **context** -- Context provided by the server. Returns: The *TaskPushNotificationConfig* for the task. abstractmethod async on_list_task_push_notification_configs(params: ListTaskPushNotificationConfigsRequest, context: ServerCallContext) -> ListTaskPushNotificationConfigsResponse Handles the 'ListTaskPushNotificationConfigs' method. Retrieves the current push notification configurations for a task. Parameters: * **params** -- Parameters including the task ID. * **context** -- Context provided by the server. Returns: The *list[TaskPushNotificationConfig]* for the task. abstractmethod async on_list_tasks(params: ListTasksRequest, context: ServerCallContext) -> ListTasksResponse Handles the tasks/list method. Retrieves all tasks for an agent. Supports filtering, pagination, ordering, limiting the history length, excluding artifacts, etc. Parameters: * **params** -- Parameters with filtering criteria. * **context** -- Context provided by the server. Returns: The *ListTasksResponse* containing the tasks. abstractmethod async on_message_send(params: SendMessageRequest, context: ServerCallContext) -> Task | Message Handles the 'message/send' method (non-streaming). Sends a message to the agent to create, continue, or restart a task, and waits for the final result (Task or Message). Parameters: * **params** -- Parameters including the message and configuration. * **context** -- Context provided by the server. Returns: The final *Task* object or a final *Message* object. abstractmethod async on_message_send_stream(params: SendMessageRequest, context: ServerCallContext) -> AsyncGenerator[Message | Task | TaskStatusUpdateEvent | TaskArtifactUpdateEvent] Handles the 'message/stream' method (streaming). Sends a message to the agent and yields stream events as they are produced (Task updates, Message chunks, Artifact updates). Parameters: * **params** -- Parameters including the message and configuration. * **context** -- Context provided by the server. Yields: *Event* objects from the agent's execution. abstractmethod async on_subscribe_to_task(params: SubscribeToTaskRequest, context: ServerCallContext) -> AsyncGenerator[Message | Task | TaskStatusUpdateEvent | TaskArtifactUpdateEvent] Handles the 'SubscribeToTask' method. Allows a client to subscribe to a running streaming task's event stream. Parameters: * **params** -- Parameters including the task ID. * **context** -- Context provided by the server. Yields: *Event* objects from the agent's ongoing execution for the specified task. a2a.server.request_handlers.request_handler.validate(expression: ~collections.abc.Callable[[~typing.Any], bool], error_message: str | None = None, error_type: type[Exception] = ) -> Callable Decorator that validates if a given expression evaluates to True. Typically used on class methods to check capabilities or configuration before executing the method's logic. If the expression is False, the specified *error_type* (defaults to *UnsupportedOperationError*) is raised. Parameters: * **expression** -- A callable that takes the instance (*self*) as its argument and returns a boolean. * **error_message** -- An optional custom error message for the error raised. If None, the string representation of the expression will be used. * **error_type** -- The exception class to raise on validation failure. Must take a *message* keyword argument (inherited from A2AError). -[ Examples ]- Demonstrating with an async method: >>> import asyncio >>> from a2a.utils.errors import UnsupportedOperationError >>> >>> class MyAgent: ... def __init__(self, streaming_enabled: bool): ... self.streaming_enabled = streaming_enabled ... ... @validate( ... lambda self: self.streaming_enabled, ... 'Streaming is not enabled for this agent', ... ) ... async def stream_response(self, message: str): ... return f'Streaming: {message}' >>> >>> async def run_async_test(): ... # Successful call ... agent_ok = MyAgent(streaming_enabled=True) ... result = await agent_ok.stream_response('hello') ... print(result) ... ... # Call that fails validation ... agent_fail = MyAgent(streaming_enabled=False) ... try: ... await agent_fail.stream_response('world') ... except UnsupportedOperationError as e: ... print(e.message) >>> >>> asyncio.run(run_async_test()) Streaming: hello Streaming is not enabled for this agent Demonstrating with a sync method: >>> class SecureAgent: ... def __init__(self): ... self.auth_enabled = False ... ... @validate( ... lambda self: self.auth_enabled, ... 'Authentication must be enabled for this operation', ... ) ... def secure_operation(self, data: str): ... return f'Processing secure data: {data}' >>> >>> # Error case example >>> agent = SecureAgent() >>> try: ... agent.secure_operation('secret') ... except UnsupportedOperationError as e: ... print(e.message) Authentication must be enabled for this operation Note: This decorator works with both sync and async methods automatically. a2a.server.request_handlers.request_handler.validate_request_params(method: Callable) -> Callable Decorator for RequestHandler methods to validate required fields on incoming requests. a2a.server.request_handlers.response_helpers module *************************************************** Helper functions for building A2A JSON-RPC responses. a2a.server.request_handlers.response_helpers.EventTypes = a2a_pb2.Task | a2a_pb2.Message | a2a_pb2.TaskArtifactUpdateEvent | a2a_pb2.TaskStatusUpdateEvent | a2a_pb2.TaskPushNotificationConfig | a2a_pb2.StreamResponse | a2a_pb2.SendMessageResponse | a2a.utils.errors.A2AError | a2a.server.jsonrpc_models.JSONRPCError | list[a2a_pb2.TaskPushNotificationConfig] | a2a_pb2.ListTasksResponse Type alias for possible event types produced by handlers. a2a.server.request_handlers.response_helpers.agent_card_to_dict(card: AgentCard) -> dict[str, Any] Convert AgentCard to dict and inject backward compatibility fields. a2a.server.request_handlers.response_helpers.build_error_response(request_id: str | int | None, error: A2AError | JSONRPCError) -> dict[str, Any] Build a JSON-RPC error response dict. Parameters: * **request_id** -- The ID of the request that caused the error. * **error** -- The A2AError or JSONRPCError object. Returns: A dict representing the JSON-RPC error response. a2a.server.request_handlers.response_helpers.prepare_response_object(request_id: str | int | None, response: Task | Message | TaskArtifactUpdateEvent | TaskStatusUpdateEvent | TaskPushNotificationConfig | StreamResponse | SendMessageResponse | A2AError | JSONRPCError | list[TaskPushNotificationConfig] | ListTasksResponse, success_response_types: tuple[type, ...]) -> dict[str, Any] Build a JSON-RPC response dict from handler output. Based on the type of the *response* object received from the handler, it constructs either a success response or an error response. Parameters: * **request_id** -- The ID of the request. * **response** -- The object received from the request handler. * **success_response_types** -- A tuple of expected types for a successful result. Returns: A dict representing the JSON-RPC response (success or error). a2a.server.request_handlers package *********************************** Submodules ========== * a2a.server.request_handlers.default_request_handler module * "LegacyRequestHandler" * "LegacyRequestHandler.on_cancel_task()" * "LegacyRequestHandler.on_create_task_push_notification_config()" * "LegacyRequestHandler.on_delete_task_push_notification_config()" * "LegacyRequestHandler.on_get_extended_agent_card()" * "LegacyRequestHandler.on_get_task()" * "LegacyRequestHandler.on_get_task_push_notification_config()" * "LegacyRequestHandler.on_list_task_push_notification_configs()" * "LegacyRequestHandler.on_list_tasks()" * "LegacyRequestHandler.on_message_send()" * "LegacyRequestHandler.on_message_send_stream()" * "LegacyRequestHandler.on_subscribe_to_task()" * a2a.server.request_handlers.default_request_handler_v2 module * "DefaultRequestHandlerV2" * "DefaultRequestHandlerV2.on_cancel_task()" * "DefaultRequestHandlerV2.on_create_task_push_notification_config ()" * "DefaultRequestHandlerV2.on_delete_task_push_notification_config ()" * "DefaultRequestHandlerV2.on_get_extended_agent_card()" * "DefaultRequestHandlerV2.on_get_task()" * "DefaultRequestHandlerV2.on_get_task_push_notification_config()" * "DefaultRequestHandlerV2.on_list_task_push_notification_configs( )" * "DefaultRequestHandlerV2.on_list_tasks()" * "DefaultRequestHandlerV2.on_message_send()" * "DefaultRequestHandlerV2.on_message_send_stream()" * "DefaultRequestHandlerV2.on_subscribe_to_task()" * a2a.server.request_handlers.grpc_handler module * "DefaultGrpcServerCallContextBuilder" * "DefaultGrpcServerCallContextBuilder.build()" * "DefaultGrpcServerCallContextBuilder.build_user()" * "GrpcHandler" * "GrpcHandler.CancelTask()" * "GrpcHandler.CreateTaskPushNotificationConfig()" * "GrpcHandler.DeleteTaskPushNotificationConfig()" * "GrpcHandler.GetExtendedAgentCard()" * "GrpcHandler.GetTask()" * "GrpcHandler.GetTaskPushNotificationConfig()" * "GrpcHandler.ListTaskPushNotificationConfigs()" * "GrpcHandler.ListTasks()" * "GrpcHandler.SendMessage()" * "GrpcHandler.SendStreamingMessage()" * "GrpcHandler.SubscribeToTask()" * "GrpcHandler.abort_context()" * "GrpcServerCallContextBuilder" * "GrpcServerCallContextBuilder.build()" * a2a.server.request_handlers.request_handler module * "RequestHandler" * "RequestHandler.on_cancel_task()" * "RequestHandler.on_create_task_push_notification_config()" * "RequestHandler.on_delete_task_push_notification_config()" * "RequestHandler.on_get_extended_agent_card()" * "RequestHandler.on_get_task()" * "RequestHandler.on_get_task_push_notification_config()" * "RequestHandler.on_list_task_push_notification_configs()" * "RequestHandler.on_list_tasks()" * "RequestHandler.on_message_send()" * "RequestHandler.on_message_send_stream()" * "RequestHandler.on_subscribe_to_task()" * "validate()" * "validate_request_params()" * a2a.server.request_handlers.response_helpers module * "EventTypes" * "agent_card_to_dict()" * "build_error_response()" * "prepare_response_object()" Module contents =============== Request handler components for the A2A server. class a2a.server.request_handlers.DefaultGrpcServerCallContextBuilder Bases: "GrpcServerCallContextBuilder" Default implementation of GrpcServerCallContextBuilder. build(context: ServicerContext) -> ServerCallContext Builds a ServerCallContext from a gRPC ServicerContext. build_user(context: ServicerContext) -> User Builds a User from a gRPC ServicerContext. a2a.server.request_handlers.DefaultRequestHandler alias of "DefaultRequestHandlerV2" class a2a.server.request_handlers.DefaultRequestHandlerV2(agent_executor: AgentExecutor, task_store: TaskStore, agent_card: AgentCard, queue_manager: Any | None = None, push_config_store: PushNotificationConfigStore | None = None, push_sender: PushNotificationSender | None = None, request_context_builder: RequestContextBuilder | None = None, extended_agent_card: AgentCard | None = None, extended_card_modifier: Callable[[AgentCard, ServerCallContext], Awaitable[AgentCard]] | None = None) Bases: "RequestHandler" Default request handler for all incoming requests. async on_cancel_task(params: CancelTaskRequest, context: ServerCallContext) -> Task | None Handles the 'tasks/cancel' method. Requests the agent to cancel an ongoing task. Parameters: * **params** -- Parameters specifying the task ID. * **context** -- Context provided by the server. Returns: The *Task* object with its status updated to canceled, or *None* if the task was not found. async on_create_task_push_notification_config(params: TaskPushNotificationConfig, context: ServerCallContext) -> TaskPushNotificationConfig Handles the 'tasks/pushNotificationConfig/create' method. Sets or updates the push notification configuration for a task. Parameters: * **params** -- Parameters including the task ID and push notification configuration. * **context** -- Context provided by the server. Returns: The provided *TaskPushNotificationConfig* upon success. async on_delete_task_push_notification_config(params: DeleteTaskPushNotificationConfigRequest, context: ServerCallContext) -> None Handles the 'tasks/pushNotificationConfig/delete' method. Deletes a push notification configuration associated with a task. Parameters: * **params** -- Parameters including the task ID. * **context** -- Context provided by the server. Returns: None async on_get_extended_agent_card(params: GetExtendedAgentCardRequest, context: ServerCallContext) -> AgentCard Default handler for 'GetExtendedAgentCard'. Requires *capabilities.extended_agent_card* to be true. async on_get_task(params: GetTaskRequest, context: ServerCallContext) -> Task | None Handles the 'tasks/get' method. Retrieves the state and history of a specific task. Parameters: * **params** -- Parameters specifying the task ID and optionally history length. * **context** -- Context provided by the server. Returns: The *Task* object if found, otherwise *None*. async on_get_task_push_notification_config(params: GetTaskPushNotificationConfigRequest, context: ServerCallContext) -> TaskPushNotificationConfig Handles the 'tasks/pushNotificationConfig/get' method. Retrieves the current push notification configuration for a task. Parameters: * **params** -- Parameters including the task ID. * **context** -- Context provided by the server. Returns: The *TaskPushNotificationConfig* for the task. async on_list_task_push_notification_configs(params: ListTaskPushNotificationConfigsRequest, context: ServerCallContext) -> ListTaskPushNotificationConfigsResponse Handles the 'ListTaskPushNotificationConfigs' method. Retrieves the current push notification configurations for a task. Parameters: * **params** -- Parameters including the task ID. * **context** -- Context provided by the server. Returns: The *list[TaskPushNotificationConfig]* for the task. async on_list_tasks(params: ListTasksRequest, context: ServerCallContext) -> ListTasksResponse Handles the tasks/list method. Retrieves all tasks for an agent. Supports filtering, pagination, ordering, limiting the history length, excluding artifacts, etc. Parameters: * **params** -- Parameters with filtering criteria. * **context** -- Context provided by the server. Returns: The *ListTasksResponse* containing the tasks. async on_message_send(params: SendMessageRequest, context: ServerCallContext) -> Message | Task Handles the 'message/send' method (non-streaming). Sends a message to the agent to create, continue, or restart a task, and waits for the final result (Task or Message). Parameters: * **params** -- Parameters including the message and configuration. * **context** -- Context provided by the server. Returns: The final *Task* object or a final *Message* object. on_message_send_stream(params: SendMessageRequest, context: ServerCallContext) -> AsyncGenerator[Event, None] Handles the 'message/stream' method (streaming). Sends a message to the agent and yields stream events as they are produced (Task updates, Message chunks, Artifact updates). Parameters: * **params** -- Parameters including the message and configuration. * **context** -- Context provided by the server. Yields: *Event* objects from the agent's execution. on_subscribe_to_task(params: SubscribeToTaskRequest, context: ServerCallContext) -> AsyncGenerator[Event, None] Handles the 'SubscribeToTask' method. Allows a client to subscribe to a running streaming task's event stream. Parameters: * **params** -- Parameters including the task ID. * **context** -- Context provided by the server. Yields: *Event* objects from the agent's ongoing execution for the specified task. class a2a.server.request_handlers.GrpcHandler(request_handler: RequestHandler, context_builder: GrpcServerCallContextBuilder | None = None) Bases: "A2AServiceServicer" Maps incoming gRPC requests to the appropriate request handler method. async CancelTask(request: CancelTaskRequest, context: ServicerContext) -> Task Handles the 'CancelTask' gRPC method. async CreateTaskPushNotificationConfig(request: TaskPushNotificationConfig, context: ServicerContext) -> TaskPushNotificationConfig Handles the 'CreateTaskPushNotificationConfig' gRPC method. async DeleteTaskPushNotificationConfig(request: DeleteTaskPushNotificationConfigRequest, context: ServicerContext) -> Empty Handles the 'DeleteTaskPushNotificationConfig' gRPC method. async GetExtendedAgentCard(request: GetExtendedAgentCardRequest, context: ServicerContext) -> AgentCard Get the extended agent card for the agent served. async GetTask(request: GetTaskRequest, context: ServicerContext) -> Task Handles the 'GetTask' gRPC method. async GetTaskPushNotificationConfig(request: GetTaskPushNotificationConfigRequest, context: ServicerContext) -> TaskPushNotificationConfig Handles the 'GetTaskPushNotificationConfig' gRPC method. async ListTaskPushNotificationConfigs(request: ListTaskPushNotificationConfigsRequest, context: ServicerContext) -> ListTaskPushNotificationConfigsResponse Handles the 'ListTaskPushNotificationConfig' gRPC method. async ListTasks(request: ListTasksRequest, context: ServicerContext) -> ListTasksResponse Handles the 'ListTasks' gRPC method. async SendMessage(request: SendMessageRequest, context: ServicerContext) -> SendMessageResponse Handles the 'SendMessage' gRPC method. async SendStreamingMessage(request: SendMessageRequest, context: ServicerContext) -> AsyncIterable[StreamResponse] Handles the 'StreamMessage' gRPC method. async SubscribeToTask(request: SubscribeToTaskRequest, context: ServicerContext) -> AsyncIterable[StreamResponse] Handles the 'SubscribeToTask' gRPC method. async abort_context(error: A2AError, context: ServicerContext) -> None Sets the grpc errors appropriately in the context. class a2a.server.request_handlers.GrpcServerCallContextBuilder Bases: "ABC" Interface for building ServerCallContext from gRPC context. abstractmethod build(context: ServicerContext) -> ServerCallContext Builds a ServerCallContext from a gRPC ServicerContext. class a2a.server.request_handlers.LegacyRequestHandler(agent_executor: AgentExecutor, task_store: TaskStore, agent_card: AgentCard, queue_manager: QueueManager | None = None, push_config_store: PushNotificationConfigStore | None = None, push_sender: PushNotificationSender | None = None, request_context_builder: RequestContextBuilder | None = None, extended_agent_card: AgentCard | None = None, extended_card_modifier: Callable[[AgentCard, ServerCallContext], Awaitable[AgentCard]] | None = None) Bases: "RequestHandler" Default request handler for all incoming requests. This handler provides default implementations for all A2A JSON-RPC methods, coordinating between the *AgentExecutor*, *TaskStore*, *QueueManager*, and optional *PushNotifier*. async on_cancel_task(params: CancelTaskRequest, context: ServerCallContext) -> Task | None Default handler for 'tasks/cancel'. Attempts to cancel the task managed by the *AgentExecutor*. async on_create_task_push_notification_config(params: TaskPushNotificationConfig, context: ServerCallContext) -> TaskPushNotificationConfig Default handler for 'tasks/pushNotificationConfig/create'. Requires a *PushNotifier* to be configured. async on_delete_task_push_notification_config(params: DeleteTaskPushNotificationConfigRequest, context: ServerCallContext) -> None Default handler for 'tasks/pushNotificationConfig/delete'. Requires a *PushConfigStore* to be configured. async on_get_extended_agent_card(params: GetExtendedAgentCardRequest, context: ServerCallContext) -> AgentCard Default handler for 'GetExtendedAgentCard'. Requires *capabilities.extended_agent_card* to be true. async on_get_task(params: GetTaskRequest, context: ServerCallContext) -> Task | None Default handler for 'tasks/get'. async on_get_task_push_notification_config(params: GetTaskPushNotificationConfigRequest, context: ServerCallContext) -> TaskPushNotificationConfig Default handler for 'tasks/pushNotificationConfig/get'. Requires a *PushConfigStore* to be configured. async on_list_task_push_notification_configs(params: ListTaskPushNotificationConfigsRequest, context: ServerCallContext) -> ListTaskPushNotificationConfigsResponse Default handler for 'ListTaskPushNotificationConfigs'. Requires a *PushConfigStore* to be configured. async on_list_tasks(params: ListTasksRequest, context: ServerCallContext) -> ListTasksResponse Default handler for 'tasks/list'. async on_message_send(params: SendMessageRequest, context: ServerCallContext) -> Message | Task Default handler for 'message/send' interface (non-streaming). Starts the agent execution for the message and waits for the final result (Task or Message). on_message_send_stream(params: SendMessageRequest, context: ServerCallContext) -> AsyncGenerator[Message | Task | TaskStatusUpdateEvent | TaskArtifactUpdateEvent] Default handler for 'message/stream' (streaming). Starts the agent execution and yields events as they are produced by the agent. on_subscribe_to_task(params: SubscribeToTaskRequest, context: ServerCallContext) -> AsyncGenerator[Message | Task | TaskStatusUpdateEvent | TaskArtifactUpdateEvent, None] Default handler for 'SubscribeToTask'. Allows a client to re-attach to a running streaming task's event stream. Requires the task and its queue to still be active. class a2a.server.request_handlers.RequestHandler Bases: "ABC" A2A request handler interface. This interface defines the methods that an A2A server implementation must provide to handle incoming A2A requests from any transport (gRPC, REST, JSON-RPC). abstractmethod async on_cancel_task(params: CancelTaskRequest, context: ServerCallContext) -> Task | None Handles the 'tasks/cancel' method. Requests the agent to cancel an ongoing task. Parameters: * **params** -- Parameters specifying the task ID. * **context** -- Context provided by the server. Returns: The *Task* object with its status updated to canceled, or *None* if the task was not found. abstractmethod async on_create_task_push_notification_config(params: TaskPushNotificationConfig, context: ServerCallContext) -> TaskPushNotificationConfig Handles the 'tasks/pushNotificationConfig/create' method. Sets or updates the push notification configuration for a task. Parameters: * **params** -- Parameters including the task ID and push notification configuration. * **context** -- Context provided by the server. Returns: The provided *TaskPushNotificationConfig* upon success. abstractmethod async on_delete_task_push_notification_config(params: DeleteTaskPushNotificationConfigRequest, context: ServerCallContext) -> None Handles the 'tasks/pushNotificationConfig/delete' method. Deletes a push notification configuration associated with a task. Parameters: * **params** -- Parameters including the task ID. * **context** -- Context provided by the server. Returns: None abstractmethod async on_get_extended_agent_card(params: GetExtendedAgentCardRequest, context: ServerCallContext) -> AgentCard Handles the 'GetExtendedAgentCard' method. Retrieves the extended agent card for the agent. Parameters: * **params** -- Parameters for the request. * **context** -- Context provided by the server. Returns: The *AgentCard* object representing the extended properties of the agent. abstractmethod async on_get_task(params: GetTaskRequest, context: ServerCallContext) -> Task | None Handles the 'tasks/get' method. Retrieves the state and history of a specific task. Parameters: * **params** -- Parameters specifying the task ID and optionally history length. * **context** -- Context provided by the server. Returns: The *Task* object if found, otherwise *None*. abstractmethod async on_get_task_push_notification_config(params: GetTaskPushNotificationConfigRequest, context: ServerCallContext) -> TaskPushNotificationConfig Handles the 'tasks/pushNotificationConfig/get' method. Retrieves the current push notification configuration for a task. Parameters: * **params** -- Parameters including the task ID. * **context** -- Context provided by the server. Returns: The *TaskPushNotificationConfig* for the task. abstractmethod async on_list_task_push_notification_configs(params: ListTaskPushNotificationConfigsRequest, context: ServerCallContext) -> ListTaskPushNotificationConfigsResponse Handles the 'ListTaskPushNotificationConfigs' method. Retrieves the current push notification configurations for a task. Parameters: * **params** -- Parameters including the task ID. * **context** -- Context provided by the server. Returns: The *list[TaskPushNotificationConfig]* for the task. abstractmethod async on_list_tasks(params: ListTasksRequest, context: ServerCallContext) -> ListTasksResponse Handles the tasks/list method. Retrieves all tasks for an agent. Supports filtering, pagination, ordering, limiting the history length, excluding artifacts, etc. Parameters: * **params** -- Parameters with filtering criteria. * **context** -- Context provided by the server. Returns: The *ListTasksResponse* containing the tasks. abstractmethod async on_message_send(params: SendMessageRequest, context: ServerCallContext) -> Task | Message Handles the 'message/send' method (non-streaming). Sends a message to the agent to create, continue, or restart a task, and waits for the final result (Task or Message). Parameters: * **params** -- Parameters including the message and configuration. * **context** -- Context provided by the server. Returns: The final *Task* object or a final *Message* object. abstractmethod async on_message_send_stream(params: SendMessageRequest, context: ServerCallContext) -> AsyncGenerator[Message | Task | TaskStatusUpdateEvent | TaskArtifactUpdateEvent] Handles the 'message/stream' method (streaming). Sends a message to the agent and yields stream events as they are produced (Task updates, Message chunks, Artifact updates). Parameters: * **params** -- Parameters including the message and configuration. * **context** -- Context provided by the server. Yields: *Event* objects from the agent's execution. abstractmethod async on_subscribe_to_task(params: SubscribeToTaskRequest, context: ServerCallContext) -> AsyncGenerator[Message | Task | TaskStatusUpdateEvent | TaskArtifactUpdateEvent] Handles the 'SubscribeToTask' method. Allows a client to subscribe to a running streaming task's event stream. Parameters: * **params** -- Parameters including the task ID. * **context** -- Context provided by the server. Yields: *Event* objects from the agent's ongoing execution for the specified task. a2a.server.request_handlers.build_error_response(request_id: str | int | None, error: A2AError | JSONRPCError) -> dict[str, Any] Build a JSON-RPC error response dict. Parameters: * **request_id** -- The ID of the request that caused the error. * **error** -- The A2AError or JSONRPCError object. Returns: A dict representing the JSON-RPC error response. a2a.server.request_handlers.prepare_response_object(request_id: str | int | None, response: Task | Message | TaskArtifactUpdateEvent | TaskStatusUpdateEvent | TaskPushNotificationConfig | StreamResponse | SendMessageResponse | A2AError | JSONRPCError | list[TaskPushNotificationConfig] | ListTasksResponse, success_response_types: tuple[type, ...]) -> dict[str, Any] Build a JSON-RPC response dict from handler output. Based on the type of the *response* object received from the handler, it constructs either a success response or an error response. Parameters: * **request_id** -- The ID of the request. * **response** -- The object received from the request handler. * **success_response_types** -- A tuple of expected types for a successful result. Returns: A dict representing the JSON-RPC response (success or error). a2a.server.request_handlers.validate_request_params(method: Callable) -> Callable Decorator for RequestHandler methods to validate required fields on incoming requests. a2a.server.routes.agent_card_routes module ****************************************** a2a.server.routes.agent_card_routes.create_agent_card_routes(agent_card: AgentCard, card_modifier: Callable[[AgentCard], Awaitable[AgentCard]] | None = None, card_url: str = '/.well-known/agent-card.json') -> list[Route] Creates the Starlette Route for the A2A protocol agent card endpoint. a2a.server.routes.common module ******************************* class a2a.server.routes.common.DefaultServerCallContextBuilder Bases: "ServerCallContextBuilder" A default implementation of ServerCallContextBuilder. build(request: Request) -> ServerCallContext Builds a ServerCallContext from a Starlette Request. Parameters: **request** -- The incoming Starlette Request object. Returns: A ServerCallContext instance populated with user and state information from the request. build_user(request: Request) -> User Builds a User from a Starlette Request. Parameters: **request** -- The incoming Starlette Request object. Returns: A User instance populated with user information from the request. class a2a.server.routes.common.ServerCallContextBuilder Bases: "ABC" A class for building ServerCallContexts using the Starlette Request. abstractmethod build(request: Request) -> ServerCallContext Builds a ServerCallContext from a Starlette Request. class a2a.server.routes.common.StarletteUser(user: BaseUser) Bases: "User" Adapts a Starlette BaseUser to the A2A User interface. property is_authenticated: bool Returns whether the current user is authenticated. property user_name: str Returns the user name of the current user. a2a.server.routes.fastapi_routes module *************************************** a2a.server.routes.fastapi_routes.add_a2a_routes_to_fastapi(app: FastAPI, *, agent_card_routes: Sequence[BaseRoute] | None = None, jsonrpc_routes: Sequence[BaseRoute] | None = None, rest_routes: Sequence[BaseRoute] | None = None) -> None Mounts A2A routes on a FastAPI app and enriches them for "/docs". Re-registers Starlette routes as "APIRoute" instances so they appear in the auto-generated OpenAPI schema, tagged and annotated with proto-derived request-body schemas. Usage: app = FastAPI() add_a2a_routes_to_fastapi( app, agent_card_routes=create_agent_card_routes(agent_card), jsonrpc_routes=create_jsonrpc_routes(request_handler, rpc_url='/'), rest_routes=create_rest_routes(request_handler), ) Parameters: * **app** -- The FastAPI application to mount the routes on. * **agent_card_routes** -- Routes returned by "create_agent_card_routes". * **jsonrpc_routes** -- Routes returned by "create_jsonrpc_routes". * **rest_routes** -- Routes returned by "create_rest_routes". a2a.server.routes.jsonrpc_dispatcher module ******************************************* JSON-RPC application for A2A server. class a2a.server.routes.jsonrpc_dispatcher.JsonRpcDispatcher(request_handler: RequestHandler, context_builder: ServerCallContextBuilder | None = None, enable_v0_3_compat: bool = False) Bases: "object" Base class for A2A JSONRPC applications. Handles incoming JSON-RPC requests, routes them to the appropriate handler methods, and manages response generation including Server- Sent Events (SSE). METHOD_TO_MODEL: dict[str, type] = {'CancelTask': , 'CreateTaskPushNotificationConfig': , 'DeleteTaskPushNotificationConfig': , 'GetExtendedAgentCard': , 'GetTask': , 'GetTaskPushNotificationConfig': , 'ListTaskPushNotificationConfigs': , 'ListTasks': , 'SendMessage': , 'SendStreamingMessage': , 'SubscribeToTask': } async handle_requests(request: Request) -> Response Handles incoming POST requests to the main A2A endpoint. Parses the request body as JSON, validates it against A2A request types, dispatches it to the appropriate handler method, and returns the response. Handles JSON parsing errors, validation errors, and other exceptions, returning appropriate JSON-RPC error responses. Parameters: **request** -- The incoming Starlette Request object. Returns: A Starlette Response object (JSONResponse or EventSourceResponse). Raises: * **(****Implicitly handled****)** -- Various exceptions are caught and converted * **into JSON-RPC error responses by this method.** -- a2a.server.routes.jsonrpc_routes module *************************************** a2a.server.routes.jsonrpc_routes.create_jsonrpc_routes(request_handler: RequestHandler, rpc_url: str, context_builder: ServerCallContextBuilder | None = None, enable_v0_3_compat: bool = False) -> list[Route] Creates the Starlette Route for the A2A protocol JSON-RPC endpoint. Handles incoming JSON-RPC requests, routes them to the appropriate handler methods, and manages response generation including Server- Sent Events (SSE). Parameters: * **request_handler** -- The handler instance responsible for processing A2A requests via http. * **rpc_url** -- The URL prefix for the RPC endpoints. Should start with a leading slash '/'. * **context_builder** -- The ServerCallContextBuilder used to construct the ServerCallContext passed to the request_handler. If None the DefaultServerCallContextBuilder is used. * **enable_v0_3_compat** -- Whether to enable v0.3 backward compatibility on the same endpoint. a2a.server.routes.rest_dispatcher module **************************************** class a2a.server.routes.rest_dispatcher.RestDispatcher(request_handler: RequestHandler, context_builder: ServerCallContextBuilder | None = None) Bases: "object" Dispatches incoming REST requests to the appropriate handler methods. Handles context building, routing to RequestHandler directly, and response formatting (JSON/SSE). async delete_push_notification(request: Request) -> Response Handles the 'tasks/pushNotificationConfig/delete' REST method. async get_push_notification(request: Request) -> Response Handles the 'tasks/pushNotificationConfig/get' REST method. async handle_authenticated_agent_card(request: Request) -> Response Handles the 'agentCard' REST method. async list_push_notifications(request: Request) -> Response Handles the 'tasks/pushNotificationConfig/list' REST method. async list_tasks(request: Request) -> Response Handles the 'tasks/list' REST method. async on_cancel_task(request: Request) -> Response Handles the 'tasks/cancel' REST method. async on_get_task(request: Request) -> Response Handles the 'tasks/{id}' REST method. async on_message_send(request: Request) -> Response Handles the 'message/send' REST method. async on_message_send_stream(request: Request) -> EventSourceResponse Handles the 'message/stream' REST method. async on_subscribe_to_task(request: Request) -> EventSourceResponse Handles the 'SubscribeToTask' REST method. async set_push_notification(request: Request) -> Response Handles the 'tasks/pushNotificationConfig/set' REST method. a2a.server.routes.rest_routes module ************************************ a2a.server.routes.rest_routes.create_rest_routes(request_handler: RequestHandler, context_builder: ServerCallContextBuilder | None = None, enable_v0_3_compat: bool = False, path_prefix: str = '') -> list[BaseRoute] Creates the Starlette Routes for the A2A protocol REST endpoint. Parameters: * **request_handler** -- The handler instance responsible for processing A2A requests via http. * **context_builder** -- The ServerCallContextBuilder used to construct the ServerCallContext passed to the request_handler. If None the DefaultServerCallContextBuilder is used. * **enable_v0_3_compat** -- If True, mounts backward-compatible v0.3 protocol endpoints using REST03Adapter. * **path_prefix** -- The URL prefix for the REST endpoints. a2a.server.routes package ************************* Submodules ========== * a2a.server.routes.agent_card_routes module * "create_agent_card_routes()" * a2a.server.routes.common module * "DefaultServerCallContextBuilder" * "DefaultServerCallContextBuilder.build()" * "DefaultServerCallContextBuilder.build_user()" * "ServerCallContextBuilder" * "ServerCallContextBuilder.build()" * "StarletteUser" * "StarletteUser.is_authenticated" * "StarletteUser.user_name" * a2a.server.routes.fastapi_routes module * "add_a2a_routes_to_fastapi()" * a2a.server.routes.jsonrpc_dispatcher module * "JsonRpcDispatcher" * "JsonRpcDispatcher.METHOD_TO_MODEL" * "JsonRpcDispatcher.handle_requests()" * a2a.server.routes.jsonrpc_routes module * "create_jsonrpc_routes()" * a2a.server.routes.rest_dispatcher module * "RestDispatcher" * "RestDispatcher.delete_push_notification()" * "RestDispatcher.get_push_notification()" * "RestDispatcher.handle_authenticated_agent_card()" * "RestDispatcher.list_push_notifications()" * "RestDispatcher.list_tasks()" * "RestDispatcher.on_cancel_task()" * "RestDispatcher.on_get_task()" * "RestDispatcher.on_message_send()" * "RestDispatcher.on_message_send_stream()" * "RestDispatcher.on_subscribe_to_task()" * "RestDispatcher.set_push_notification()" * a2a.server.routes.rest_routes module * "create_rest_routes()" Module contents =============== A2A Routes. class a2a.server.routes.DefaultServerCallContextBuilder Bases: "ServerCallContextBuilder" A default implementation of ServerCallContextBuilder. build(request: Request) -> ServerCallContext Builds a ServerCallContext from a Starlette Request. Parameters: **request** -- The incoming Starlette Request object. Returns: A ServerCallContext instance populated with user and state information from the request. build_user(request: Request) -> User Builds a User from a Starlette Request. Parameters: **request** -- The incoming Starlette Request object. Returns: A User instance populated with user information from the request. class a2a.server.routes.ServerCallContextBuilder Bases: "ABC" A class for building ServerCallContexts using the Starlette Request. abstractmethod build(request: Request) -> ServerCallContext Builds a ServerCallContext from a Starlette Request. a2a.server.routes.add_a2a_routes_to_fastapi(app: FastAPI, *, agent_card_routes: Sequence[BaseRoute] | None = None, jsonrpc_routes: Sequence[BaseRoute] | None = None, rest_routes: Sequence[BaseRoute] | None = None) -> None Mounts A2A routes on a FastAPI app and enriches them for "/docs". Re-registers Starlette routes as "APIRoute" instances so they appear in the auto-generated OpenAPI schema, tagged and annotated with proto-derived request-body schemas. Usage: app = FastAPI() add_a2a_routes_to_fastapi( app, agent_card_routes=create_agent_card_routes(agent_card), jsonrpc_routes=create_jsonrpc_routes(request_handler, rpc_url='/'), rest_routes=create_rest_routes(request_handler), ) Parameters: * **app** -- The FastAPI application to mount the routes on. * **agent_card_routes** -- Routes returned by "create_agent_card_routes". * **jsonrpc_routes** -- Routes returned by "create_jsonrpc_routes". * **rest_routes** -- Routes returned by "create_rest_routes". a2a.server.routes.create_agent_card_routes(agent_card: AgentCard, card_modifier: Callable[[AgentCard], Awaitable[AgentCard]] | None = None, card_url: str = '/.well-known/agent-card.json') -> list[Route] Creates the Starlette Route for the A2A protocol agent card endpoint. a2a.server.routes.create_jsonrpc_routes(request_handler: RequestHandler, rpc_url: str, context_builder: ServerCallContextBuilder | None = None, enable_v0_3_compat: bool = False) -> list[Route] Creates the Starlette Route for the A2A protocol JSON-RPC endpoint. Handles incoming JSON-RPC requests, routes them to the appropriate handler methods, and manages response generation including Server- Sent Events (SSE). Parameters: * **request_handler** -- The handler instance responsible for processing A2A requests via http. * **rpc_url** -- The URL prefix for the RPC endpoints. Should start with a leading slash '/'. * **context_builder** -- The ServerCallContextBuilder used to construct the ServerCallContext passed to the request_handler. If None the DefaultServerCallContextBuilder is used. * **enable_v0_3_compat** -- Whether to enable v0.3 backward compatibility on the same endpoint. a2a.server.routes.create_rest_routes(request_handler: RequestHandler, context_builder: ServerCallContextBuilder | None = None, enable_v0_3_compat: bool = False, path_prefix: str = '') -> list[BaseRoute] Creates the Starlette Routes for the A2A protocol REST endpoint. Parameters: * **request_handler** -- The handler instance responsible for processing A2A requests via http. * **context_builder** -- The ServerCallContextBuilder used to construct the ServerCallContext passed to the request_handler. If None the DefaultServerCallContextBuilder is used. * **enable_v0_3_compat** -- If True, mounts backward-compatible v0.3 protocol endpoints using REST03Adapter. * **path_prefix** -- The URL prefix for the REST endpoints. a2a.server.tasks.base_push_notification_sender module ***************************************************** class a2a.server.tasks.base_push_notification_sender.BasePushNotificationSender(httpx_client: AsyncClient, config_store: PushNotificationConfigStore, context: ServerCallContext | None = None) Bases: "PushNotificationSender" Base implementation of PushNotificationSender interface. async send_notification(task_id: str, event: Task | TaskStatusUpdateEvent | TaskArtifactUpdateEvent) -> None Sends a push notification for an event if configuration exists. a2a.server.tasks.copying_task_store module ****************************************** class a2a.server.tasks.copying_task_store.CopyingTaskStoreAdapter(underlying_store: TaskStore) Bases: "TaskStore" An adapter that ensures deep copies of tasks are passed to and returned from the underlying TaskStore. This prevents accidental shared mutable state bugs where code modifies a Task object retrieved from the store without explicitly saving it, which hides missing save calls. async delete(task_id: str, context: ServerCallContext) -> None Deletes a task from the underlying store. async get(task_id: str, context: ServerCallContext) -> Task | None Retrieves a task from the underlying store and returns a copy. async list(params: ListTasksRequest, context: ServerCallContext) -> ListTasksResponse Retrieves a list of tasks from the underlying store and returns a copy. async save(task: Task, context: ServerCallContext) -> None Saves a copy of the task to the underlying store. a2a.server.tasks.database_push_notification_config_store module *************************************************************** class a2a.server.tasks.database_push_notification_config_store.DatabasePushNotificationConfigStore(engine: ~sqlalchemy.ext.asyncio.engine.AsyncEngine, create_table: bool = True, table_name: str = 'push_notification_configs', encryption_key: str | bytes | None = None, owner_resolver: ~collections.abc.Callable[[~a2a.server.context.ServerCallContext], str] = , core_to_model_conversion: ~collections.abc.Callable[[str, ~a2a_pb2.TaskPushNotificationConfig, str, Fernet | None], ~a2a.server.models.PushNotificationConfigModel] | None = None, model_to_core_conversion: ~collections.abc.Callable[[~a2a.server.models.PushNotificationConfigModel], ~a2a_pb2.TaskPushNotificationConfig] | None = None) Bases: "PushNotificationConfigStore" SQLAlchemy-based implementation of PushNotificationConfigStore. Stores push notification configurations in a database supported by SQLAlchemy. async_session_maker: async_sessionmaker[AsyncSession] config_model: type[PushNotificationConfigModel] core_to_model_conversion: Callable[[str, TaskPushNotificationConfig, str, Fernet | None], PushNotificationConfigModel] | None create_table: bool async delete_info(task_id: str, context: ServerCallContext, config_id: str | None = None) -> None Deletes push notification configurations for a task. If config_id is provided, only that specific configuration is deleted. If config_id is None, all configurations for the task for the owner are deleted. engine: AsyncEngine async get_info(task_id: str, context: ServerCallContext) -> list[TaskPushNotificationConfig] Retrieves all push notification configurations for a task, for the given owner. Used by the user-callable read endpoints. async get_info_for_dispatch(task_id: str) -> list[TaskPushNotificationConfig] Retrieves all push notification configurations for a task, across all owners. Used by the push-notification dispatch path. async initialize() -> None Initialize the database and create the table if needed. model_to_core_conversion: Callable[[PushNotificationConfigModel], TaskPushNotificationConfig] | None owner_resolver: Callable[[ServerCallContext], str] async set_info(task_id: str, notification_config: TaskPushNotificationConfig, context: ServerCallContext) -> None Sets or updates the push notification configuration for a task. a2a.server.tasks.database_task_store module ******************************************* class a2a.server.tasks.database_task_store.DatabaseTaskStore(engine: ~sqlalchemy.ext.asyncio.engine.AsyncEngine, create_table: bool = True, table_name: str = 'tasks', owner_resolver: ~collections.abc.Callable[[~a2a.server.context.ServerCallContext], str] = , core_to_model_conversion: ~collections.abc.Callable[[~a2a_pb2.Task, str], ~a2a.server.models.TaskModel] | None = None, model_to_core_conversion: ~collections.abc.Callable[[~a2a.server.models.TaskModel], ~a2a_pb2.Task] | None = None) Bases: "TaskStore" SQLAlchemy-based implementation of TaskStore. Stores task objects in a database supported by SQLAlchemy. async_session_maker: async_sessionmaker[AsyncSession] core_to_model_conversion: Callable[[Task, str], TaskModel] | None = None create_table: bool async delete(task_id: str, context: ServerCallContext) -> None Deletes a task from the database by ID, for the given owner. engine: AsyncEngine async get(task_id: str, context: ServerCallContext) -> Task | None Retrieves a task from the database by ID, for the given owner. async initialize() -> None Initialize the database and create the table if needed. async list(params: ListTasksRequest, context: ServerCallContext) -> ListTasksResponse Retrieves tasks from the database based on provided parameters, for the given owner. model_to_core_conversion: Callable[[TaskModel], Task] | None = None owner_resolver: Callable[[ServerCallContext], str] async save(task: Task, context: ServerCallContext) -> None Saves or updates a task in the database for the resolved owner. task_model: type[TaskModel] a2a.server.tasks.inmemory_push_notification_config_store module *************************************************************** class a2a.server.tasks.inmemory_push_notification_config_store.InMemoryPushNotificationConfigStore(owner_resolver: ~collections.abc.Callable[[~a2a.server.context.ServerCallContext], str] = ) Bases: "PushNotificationConfigStore" In-memory implementation of PushNotificationConfigStore interface. Stores push notification configurations in a nested dictionary in memory, keyed by owner then task_id. async delete_info(task_id: str, context: ServerCallContext, config_id: str | None = None) -> None Deletes push notification configurations for a task from memory. If config_id is provided, only that specific configuration is deleted. If config_id is None, all configurations for the task for the owner are deleted. async get_info(task_id: str, context: ServerCallContext) -> list[TaskPushNotificationConfig] Retrieves all push notification configurations for a task from memory, for the given owner. Used by the user-callable read endpoints. async get_info_for_dispatch(task_id: str) -> list[TaskPushNotificationConfig] Retrieves all push notification configurations for a task across all owners. Used by the push-notification dispatch path. async set_info(task_id: str, notification_config: TaskPushNotificationConfig, context: ServerCallContext) -> None Sets or updates the push notification configuration for a task in memory. a2a.server.tasks.inmemory_task_store module ******************************************* class a2a.server.tasks.inmemory_task_store.InMemoryTaskStore(owner_resolver: ~collections.abc.Callable[[~a2a.server.context.ServerCallContext], str] = , use_copying: bool = True) Bases: "TaskStore" In-memory implementation of TaskStore. Can optionally use CopyingTaskStoreAdapter to wrap the internal dictionary-based implementation, preventing shared mutable state issues by always returning and storing deep copies. async delete(task_id: str, context: ServerCallContext) -> None Deletes a task from the store by ID. async get(task_id: str, context: ServerCallContext) -> Task | None Retrieves a task from the store by ID. async list(params: ListTasksRequest, context: ServerCallContext) -> ListTasksResponse Retrieves a list of tasks from the store. async save(task: Task, context: ServerCallContext) -> None Saves or updates a task in the store. a2a.server.tasks.push_notification_config_store module ****************************************************** class a2a.server.tasks.push_notification_config_store.PushNotificationConfigStore Bases: "ABC" Interface for storing and retrieving push notification configurations for tasks. abstractmethod async delete_info(task_id: str, context: ServerCallContext, config_id: str | None = None) -> None Deletes the push notification configuration for a task. abstractmethod async get_info(task_id: str, context: ServerCallContext) -> list[TaskPushNotificationConfig] Retrieves push notification configurations for a task, scoped to the caller. This is the user-callable read path. Implementations MUST return only configurations owned by the caller (as resolved from context). async get_info_for_dispatch(task_id: str) -> list[TaskPushNotificationConfig] Retrieves all push notification configurations for a task, across all owners. This is the internal read path used by the push-notification dispatch loop. Implementations SHOULD override this method to return every configuration registered for task_id regardless of which user registered it. Authorization already happened at registration time and the dispatch path fires every registered webhook for the task. The default implementation falls back to calling get_info with a synthetic empty ServerCallContext. This preserves 1.0 behavior for subclasses that have not implemented the override but is INCORRECT for any deployment with multiple owners: the empty context resolves to the empty-string owner partition and returns no configs (silently dropping every notification). A warning is logged on every call to flag the misconfiguration. Custom subclasses MUST override this method to deliver notifications correctly in multi-owner deployments. abstractmethod async set_info(task_id: str, notification_config: TaskPushNotificationConfig, context: ServerCallContext) -> None Sets or updates the push notification configuration for a task. a2a.server.tasks.push_notification_sender module ************************************************ class a2a.server.tasks.push_notification_sender.PushNotificationSender Bases: "ABC" Interface for sending push notifications for tasks. abstractmethod async send_notification(task_id: str, event: Task | TaskStatusUpdateEvent | TaskArtifactUpdateEvent) -> None Sends a push notification containing the latest task state. a2a.server.tasks.result_aggregator module ***************************************** class a2a.server.tasks.result_aggregator.ResultAggregator(task_manager: TaskManager) Bases: "object" ResultAggregator is used to process the event streams from an AgentExecutor. There are three main ways to use the ResultAggregator: 1) As part of a processing pipe. consume_and_emit will construct the updated task as the events arrive, and re-emit those events for another consumer 2. As part of a blocking call. consume_all will process the entire stream and return the final Task or Message object 3. As part of a push solution where the latest Task is emitted after processing an event. consume_and_emit_task will consume the Event stream, process the events to the current Task object and emit that Task object. async consume_all(consumer: EventConsumer) -> Task | Message | None Processes the entire event stream from the consumer and returns the final result. Blocks until the event stream ends (queue is closed after final event or exception). Parameters: **consumer** -- The *EventConsumer* to read events from. Returns: The final *Task* object or *Message* object after the stream is exhausted. Returns *None* if the stream ends without producing a final result. Raises: **BaseException** -- If the *EventConsumer* raises an exception during consumption. async consume_and_break_on_interrupt(consumer: EventConsumer, blocking: bool = True, event_callback: Callable[[Message | Task | TaskStatusUpdateEvent | TaskArtifactUpdateEvent], Awaitable[None]] | None = None) -> tuple[Task | Message | None, bool, Task | None] Processes the event stream until completion or an interruptible state is encountered. If *blocking* is False, it returns after the first event that creates a Task or Message. If *blocking* is True, it waits for completion unless an *auth_required* state is encountered, which is always an interruption. If interrupted, consumption continues in a background task. Parameters: * **consumer** -- The *EventConsumer* to read events from. * **blocking** -- If *False*, the method returns as soon as a task/message is available. If *True*, it waits for a terminal state. * **event_callback** -- Optional async callback function to be called after each event is processed in the background continuation. Mainly used for push notifications currently. Returns: * The current aggregated result (*Task* or *Message*) at the point of completion or interruption. * A boolean indicating whether the consumption was interrupted (*True*) or completed naturally (*False*). * The background "asyncio.Task" that continues consuming events after an interruption, or "None" when no background work was spawned. **Callers must hold a strong reference** to this task (e.g. in a "set") to prevent the garbage collector from collecting it before it finishes — the event loop only keeps weak references to tasks. Return type: A tuple containing Raises: **BaseException** -- If the *EventConsumer* raises an exception during consumption. async consume_and_emit(consumer: EventConsumer) -> AsyncGenerator[Message | Task | TaskStatusUpdateEvent | TaskArtifactUpdateEvent] Processes the event stream from the consumer, updates the task state, and re-emits the same events. Useful for streaming scenarios where the server needs to observe and process events (e.g., save task state, send push notifications) while forwarding them to the client. Parameters: **consumer** -- The *EventConsumer* to read events from. Yields: The *Event* objects consumed from the *EventConsumer*. property current_result: Task | Message | None Returns the current aggregated result (Task or Message). This is the latest state processed from the event stream. Returns: The current *Task* object managed by the *TaskManager*, or the final *Message* if one was received, or *None* if no result has been produced yet. a2a.server.tasks.task_manager module ************************************ class a2a.server.tasks.task_manager.TaskManager(task_store: TaskStore, context: ServerCallContext, task_id: str | None, context_id: str | None, initial_message: Message | None) Bases: "object" Helps manage a task's lifecycle during execution of a request. Responsible for retrieving, saving, and updating the *Task* object based on events received from the agent. async ensure_task(event: TaskStatusUpdateEvent | TaskArtifactUpdateEvent) -> Task Ensures a Task object exists in memory, loading from store or creating new if needed. Parameters: **event** -- The task-related event triggering the need for a Task object. Returns: An existing or newly created *Task* object. async ensure_task_id(task_id: str, context_id: str) -> Task Ensures a Task object exists in memory, loading from store or creating new if needed. Parameters: * **task_id** -- The ID for the new task. * **context_id** -- The context ID for the new task. Returns: An existing or newly created *Task* object. async get_task() -> Task | None Retrieves the current task object, either from memory or the store. If *task_id* is set, it first checks the in-memory *_current_task*, then attempts to load it from the *task_store*. Returns: The *Task* object if found, otherwise *None*. async process(event: Message | Task | TaskStatusUpdateEvent | TaskArtifactUpdateEvent) -> Message | Task | TaskStatusUpdateEvent | TaskArtifactUpdateEvent Processes an event, updates the task state if applicable, stores it, and returns the event. If the event is task-related (*Task*, *TaskStatusUpdateEvent*, *TaskArtifactUpdateEvent*), the internal task state is updated and persisted. Parameters: **event** -- The event object received from the agent. Returns: The same event object that was processed. async save_task_event(event: Task | TaskStatusUpdateEvent | TaskArtifactUpdateEvent) -> Task | None Processes a task-related event (Task, Status, Artifact) and saves the updated task state. Ensures task and context IDs match or are set from the event. Parameters: **event** -- The task-related event (*Task*, *TaskStatusUpdateEvent*, or *TaskArtifactUpdateEvent*). Returns: The updated *Task* object after processing the event. Raises: **InvalidParamsError** -- If the task ID in the event conflicts with the TaskManager's ID when the TaskManager's ID is already set. update_with_message(message: Message, task: Task) -> Task Updates a task object in memory by adding a new message to its history. If the task has a message in its current status, that message is moved to the history first. Parameters: * **message** -- The new *Message* to add to the history. * **task** -- The *Task* object to update. Returns: The updated *Task* object (updated in-place). a2a.server.tasks.task_manager.append_artifact_to_task(task: Task, event: TaskArtifactUpdateEvent) -> None Helper method for updating a Task object with new artifact data from an event. Handles creating the artifacts list if it doesn't exist, adding new artifacts, and appending parts to existing artifacts based on the *append* flag in the event. Parameters: * **task** -- The *Task* object to modify. * **event** -- The *TaskArtifactUpdateEvent* containing the artifact data. a2a.server.tasks.task_store module ********************************** class a2a.server.tasks.task_store.TaskStore Bases: "ABC" Agent Task Store interface. Defines the methods for persisting and retrieving *Task* objects. abstractmethod async delete(task_id: str, context: ServerCallContext) -> None Deletes a task from the store by ID. abstractmethod async get(task_id: str, context: ServerCallContext) -> Task | None Retrieves a task from the store by ID. abstractmethod async list(params: ListTasksRequest, context: ServerCallContext) -> ListTasksResponse Retrieves a list of tasks from the store. abstractmethod async save(task: Task, context: ServerCallContext) -> None Saves or updates a task in the store. a2a.server.tasks.task_updater module ************************************ class a2a.server.tasks.task_updater.TaskUpdater(event_queue: EventQueue, task_id: str, context_id: str, artifact_id_generator: IDGenerator | None = None, message_id_generator: IDGenerator | None = None) Bases: "object" Helper class for agents to publish updates to a task's event queue. Simplifies the process of creating and enqueueing standard task events. async add_artifact(parts: list[Part], artifact_id: str | None = None, name: str | None = None, metadata: dict[str, Any] | None = None, append: bool | None = None, last_chunk: bool | None = None, extensions: list[str] | None = None) -> None Adds an artifact chunk to the task and publishes a *TaskArtifactUpdateEvent*. Parameters: * **parts** -- A list of *Part* objects forming the artifact chunk. * **artifact_id** -- The ID of the artifact. A new UUID is generated if not provided. * **name** -- Optional name for the artifact. * **metadata** -- Optional metadata for the artifact. * **append** -- Optional boolean indicating if this chunk appends to a previous one. * **last_chunk** -- Optional boolean indicating if this is the last chunk. * **extensions** -- Optional list of extensions for the artifact. async cancel(message: Message | None = None) -> None Marks the task as cancelled and publishes a finalstatus update. async complete(message: Message | None = None) -> None Marks the task as completed and publishes a final status update. async failed(message: Message | None = None) -> None Marks the task as failed and publishes a final status update. new_agent_message(parts: list[Part], metadata: dict[str, Any] | None = None) -> Message Creates a new message object sent by the agent for this task/context. Note: This method only *creates* the message object. It does not automatically enqueue it. Parameters: * **parts** -- A list of *Part* objects for the message content. * **metadata** -- Optional metadata for the message. Returns: A new *Message* object. async reject(message: Message | None = None) -> None Marks the task as rejected and publishes a final status update. async requires_auth(message: Message | None = None) -> None Marks the task as auth required and publishes a status update. async requires_input(message: Message | None = None) -> None Marks the task as input required and publishes a status update. async start_work(message: Message | None = None) -> None Marks the task as working and publishes a status update. async submit(message: Message | None = None) -> None Marks the task as submitted and publishes a status update. async update_status(state: , message: Message | None = None, timestamp: str | None = None, metadata: dict[str, ~typing.Any] | None=None) -> None Updates the status of the task and publishes a *TaskStatusUpdateEvent*. Parameters: * **state** -- The new state of the task. * **message** -- An optional message associated with the status update. * **timestamp** -- Optional ISO 8601 datetime string. Defaults to current time. * **metadata** -- Optional metadata for extensions. a2a.server.tasks package ************************ Submodules ========== * a2a.server.tasks.base_push_notification_sender module * "BasePushNotificationSender" * "BasePushNotificationSender.send_notification()" * a2a.server.tasks.copying_task_store module * "CopyingTaskStoreAdapter" * "CopyingTaskStoreAdapter.delete()" * "CopyingTaskStoreAdapter.get()" * "CopyingTaskStoreAdapter.list()" * "CopyingTaskStoreAdapter.save()" * a2a.server.tasks.database_push_notification_config_store module * "DatabasePushNotificationConfigStore" * "DatabasePushNotificationConfigStore.async_session_maker" * "DatabasePushNotificationConfigStore.config_model" * "DatabasePushNotificationConfigStore.core_to_model_conversion" * "DatabasePushNotificationConfigStore.create_table" * "DatabasePushNotificationConfigStore.delete_info()" * "DatabasePushNotificationConfigStore.engine" * "DatabasePushNotificationConfigStore.get_info()" * "DatabasePushNotificationConfigStore.get_info_for_dispatch()" * "DatabasePushNotificationConfigStore.initialize()" * "DatabasePushNotificationConfigStore.model_to_core_conversion" * "DatabasePushNotificationConfigStore.owner_resolver" * "DatabasePushNotificationConfigStore.set_info()" * a2a.server.tasks.database_task_store module * "DatabaseTaskStore" * "DatabaseTaskStore.async_session_maker" * "DatabaseTaskStore.core_to_model_conversion" * "DatabaseTaskStore.create_table" * "DatabaseTaskStore.delete()" * "DatabaseTaskStore.engine" * "DatabaseTaskStore.get()" * "DatabaseTaskStore.initialize()" * "DatabaseTaskStore.list()" * "DatabaseTaskStore.model_to_core_conversion" * "DatabaseTaskStore.owner_resolver" * "DatabaseTaskStore.save()" * "DatabaseTaskStore.task_model" * a2a.server.tasks.inmemory_push_notification_config_store module * "InMemoryPushNotificationConfigStore" * "InMemoryPushNotificationConfigStore.delete_info()" * "InMemoryPushNotificationConfigStore.get_info()" * "InMemoryPushNotificationConfigStore.get_info_for_dispatch()" * "InMemoryPushNotificationConfigStore.set_info()" * a2a.server.tasks.inmemory_task_store module * "InMemoryTaskStore" * "InMemoryTaskStore.delete()" * "InMemoryTaskStore.get()" * "InMemoryTaskStore.list()" * "InMemoryTaskStore.save()" * a2a.server.tasks.push_notification_config_store module * "PushNotificationConfigStore" * "PushNotificationConfigStore.delete_info()" * "PushNotificationConfigStore.get_info()" * "PushNotificationConfigStore.get_info_for_dispatch()" * "PushNotificationConfigStore.set_info()" * a2a.server.tasks.push_notification_sender module * "PushNotificationSender" * "PushNotificationSender.send_notification()" * a2a.server.tasks.result_aggregator module * "ResultAggregator" * "ResultAggregator.consume_all()" * "ResultAggregator.consume_and_break_on_interrupt()" * "ResultAggregator.consume_and_emit()" * "ResultAggregator.current_result" * a2a.server.tasks.task_manager module * "TaskManager" * "TaskManager.ensure_task()" * "TaskManager.ensure_task_id()" * "TaskManager.get_task()" * "TaskManager.process()" * "TaskManager.save_task_event()" * "TaskManager.update_with_message()" * "append_artifact_to_task()" * a2a.server.tasks.task_store module * "TaskStore" * "TaskStore.delete()" * "TaskStore.get()" * "TaskStore.list()" * "TaskStore.save()" * a2a.server.tasks.task_updater module * "TaskUpdater" * "TaskUpdater.add_artifact()" * "TaskUpdater.cancel()" * "TaskUpdater.complete()" * "TaskUpdater.failed()" * "TaskUpdater.new_agent_message()" * "TaskUpdater.reject()" * "TaskUpdater.requires_auth()" * "TaskUpdater.requires_input()" * "TaskUpdater.start_work()" * "TaskUpdater.submit()" * "TaskUpdater.update_status()" Module contents =============== Components for managing tasks within the A2A server. class a2a.server.tasks.BasePushNotificationSender(httpx_client: AsyncClient, config_store: PushNotificationConfigStore, context: ServerCallContext | None = None) Bases: "PushNotificationSender" Base implementation of PushNotificationSender interface. async send_notification(task_id: str, event: Task | TaskStatusUpdateEvent | TaskArtifactUpdateEvent) -> None Sends a push notification for an event if configuration exists. class a2a.server.tasks.DatabasePushNotificationConfigStore(engine: ~sqlalchemy.ext.asyncio.engine.AsyncEngine, create_table: bool = True, table_name: str = 'push_notification_configs', encryption_key: str | bytes | None = None, owner_resolver: ~collections.abc.Callable[[~a2a.server.context.ServerCallContext], str] = , core_to_model_conversion: ~collections.abc.Callable[[str, ~a2a_pb2.TaskPushNotificationConfig, str, Fernet | None], ~a2a.server.models.PushNotificationConfigModel] | None = None, model_to_core_conversion: ~collections.abc.Callable[[~a2a.server.models.PushNotificationConfigModel], ~a2a_pb2.TaskPushNotificationConfig] | None = None) Bases: "PushNotificationConfigStore" SQLAlchemy-based implementation of PushNotificationConfigStore. Stores push notification configurations in a database supported by SQLAlchemy. async_session_maker: async_sessionmaker[AsyncSession] config_model: type[PushNotificationConfigModel] core_to_model_conversion: Callable[[str, TaskPushNotificationConfig, str, Fernet | None], PushNotificationConfigModel] | None create_table: bool async delete_info(task_id: str, context: ServerCallContext, config_id: str | None = None) -> None Deletes push notification configurations for a task. If config_id is provided, only that specific configuration is deleted. If config_id is None, all configurations for the task for the owner are deleted. engine: AsyncEngine async get_info(task_id: str, context: ServerCallContext) -> list[TaskPushNotificationConfig] Retrieves all push notification configurations for a task, for the given owner. Used by the user-callable read endpoints. async get_info_for_dispatch(task_id: str) -> list[TaskPushNotificationConfig] Retrieves all push notification configurations for a task, across all owners. Used by the push-notification dispatch path. async initialize() -> None Initialize the database and create the table if needed. model_to_core_conversion: Callable[[PushNotificationConfigModel], TaskPushNotificationConfig] | None owner_resolver: Callable[[ServerCallContext], str] async set_info(task_id: str, notification_config: TaskPushNotificationConfig, context: ServerCallContext) -> None Sets or updates the push notification configuration for a task. class a2a.server.tasks.DatabaseTaskStore(engine: ~sqlalchemy.ext.asyncio.engine.AsyncEngine, create_table: bool = True, table_name: str = 'tasks', owner_resolver: ~collections.abc.Callable[[~a2a.server.context.ServerCallContext], str] = , core_to_model_conversion: ~collections.abc.Callable[[~a2a_pb2.Task, str], ~a2a.server.models.TaskModel] | None = None, model_to_core_conversion: ~collections.abc.Callable[[~a2a.server.models.TaskModel], ~a2a_pb2.Task] | None = None) Bases: "TaskStore" SQLAlchemy-based implementation of TaskStore. Stores task objects in a database supported by SQLAlchemy. async_session_maker: async_sessionmaker[AsyncSession] core_to_model_conversion: Callable[[Task, str], TaskModel] | None = None create_table: bool async delete(task_id: str, context: ServerCallContext) -> None Deletes a task from the database by ID, for the given owner. engine: AsyncEngine async get(task_id: str, context: ServerCallContext) -> Task | None Retrieves a task from the database by ID, for the given owner. async initialize() -> None Initialize the database and create the table if needed. async list(params: ListTasksRequest, context: ServerCallContext) -> ListTasksResponse Retrieves tasks from the database based on provided parameters, for the given owner. model_to_core_conversion: Callable[[TaskModel], Task] | None = None owner_resolver: Callable[[ServerCallContext], str] async save(task: Task, context: ServerCallContext) -> None Saves or updates a task in the database for the resolved owner. task_model: type[TaskModel] class a2a.server.tasks.InMemoryPushNotificationConfigStore(owner_resolver: ~collections.abc.Callable[[~a2a.server.context.ServerCallContext], str] = ) Bases: "PushNotificationConfigStore" In-memory implementation of PushNotificationConfigStore interface. Stores push notification configurations in a nested dictionary in memory, keyed by owner then task_id. async delete_info(task_id: str, context: ServerCallContext, config_id: str | None = None) -> None Deletes push notification configurations for a task from memory. If config_id is provided, only that specific configuration is deleted. If config_id is None, all configurations for the task for the owner are deleted. async get_info(task_id: str, context: ServerCallContext) -> list[TaskPushNotificationConfig] Retrieves all push notification configurations for a task from memory, for the given owner. Used by the user-callable read endpoints. async get_info_for_dispatch(task_id: str) -> list[TaskPushNotificationConfig] Retrieves all push notification configurations for a task across all owners. Used by the push-notification dispatch path. async set_info(task_id: str, notification_config: TaskPushNotificationConfig, context: ServerCallContext) -> None Sets or updates the push notification configuration for a task in memory. class a2a.server.tasks.InMemoryTaskStore(owner_resolver: ~collections.abc.Callable[[~a2a.server.context.ServerCallContext], str] = , use_copying: bool = True) Bases: "TaskStore" In-memory implementation of TaskStore. Can optionally use CopyingTaskStoreAdapter to wrap the internal dictionary-based implementation, preventing shared mutable state issues by always returning and storing deep copies. async delete(task_id: str, context: ServerCallContext) -> None Deletes a task from the store by ID. async get(task_id: str, context: ServerCallContext) -> Task | None Retrieves a task from the store by ID. async list(params: ListTasksRequest, context: ServerCallContext) -> ListTasksResponse Retrieves a list of tasks from the store. async save(task: Task, context: ServerCallContext) -> None Saves or updates a task in the store. class a2a.server.tasks.PushNotificationConfigStore Bases: "ABC" Interface for storing and retrieving push notification configurations for tasks. abstractmethod async delete_info(task_id: str, context: ServerCallContext, config_id: str | None = None) -> None Deletes the push notification configuration for a task. abstractmethod async get_info(task_id: str, context: ServerCallContext) -> list[TaskPushNotificationConfig] Retrieves push notification configurations for a task, scoped to the caller. This is the user-callable read path. Implementations MUST return only configurations owned by the caller (as resolved from context). async get_info_for_dispatch(task_id: str) -> list[TaskPushNotificationConfig] Retrieves all push notification configurations for a task, across all owners. This is the internal read path used by the push-notification dispatch loop. Implementations SHOULD override this method to return every configuration registered for task_id regardless of which user registered it. Authorization already happened at registration time and the dispatch path fires every registered webhook for the task. The default implementation falls back to calling get_info with a synthetic empty ServerCallContext. This preserves 1.0 behavior for subclasses that have not implemented the override but is INCORRECT for any deployment with multiple owners: the empty context resolves to the empty-string owner partition and returns no configs (silently dropping every notification). A warning is logged on every call to flag the misconfiguration. Custom subclasses MUST override this method to deliver notifications correctly in multi-owner deployments. abstractmethod async set_info(task_id: str, notification_config: TaskPushNotificationConfig, context: ServerCallContext) -> None Sets or updates the push notification configuration for a task. class a2a.server.tasks.PushNotificationSender Bases: "ABC" Interface for sending push notifications for tasks. abstractmethod async send_notification(task_id: str, event: Task | TaskStatusUpdateEvent | TaskArtifactUpdateEvent) -> None Sends a push notification containing the latest task state. class a2a.server.tasks.ResultAggregator(task_manager: TaskManager) Bases: "object" ResultAggregator is used to process the event streams from an AgentExecutor. There are three main ways to use the ResultAggregator: 1) As part of a processing pipe. consume_and_emit will construct the updated task as the events arrive, and re-emit those events for another consumer 2. As part of a blocking call. consume_all will process the entire stream and return the final Task or Message object 3. As part of a push solution where the latest Task is emitted after processing an event. consume_and_emit_task will consume the Event stream, process the events to the current Task object and emit that Task object. async consume_all(consumer: EventConsumer) -> Task | Message | None Processes the entire event stream from the consumer and returns the final result. Blocks until the event stream ends (queue is closed after final event or exception). Parameters: **consumer** -- The *EventConsumer* to read events from. Returns: The final *Task* object or *Message* object after the stream is exhausted. Returns *None* if the stream ends without producing a final result. Raises: **BaseException** -- If the *EventConsumer* raises an exception during consumption. async consume_and_break_on_interrupt(consumer: EventConsumer, blocking: bool = True, event_callback: Callable[[Message | Task | TaskStatusUpdateEvent | TaskArtifactUpdateEvent], Awaitable[None]] | None = None) -> tuple[Task | Message | None, bool, Task | None] Processes the event stream until completion or an interruptible state is encountered. If *blocking* is False, it returns after the first event that creates a Task or Message. If *blocking* is True, it waits for completion unless an *auth_required* state is encountered, which is always an interruption. If interrupted, consumption continues in a background task. Parameters: * **consumer** -- The *EventConsumer* to read events from. * **blocking** -- If *False*, the method returns as soon as a task/message is available. If *True*, it waits for a terminal state. * **event_callback** -- Optional async callback function to be called after each event is processed in the background continuation. Mainly used for push notifications currently. Returns: * The current aggregated result (*Task* or *Message*) at the point of completion or interruption. * A boolean indicating whether the consumption was interrupted (*True*) or completed naturally (*False*). * The background "asyncio.Task" that continues consuming events after an interruption, or "None" when no background work was spawned. **Callers must hold a strong reference** to this task (e.g. in a "set") to prevent the garbage collector from collecting it before it finishes — the event loop only keeps weak references to tasks. Return type: A tuple containing Raises: **BaseException** -- If the *EventConsumer* raises an exception during consumption. async consume_and_emit(consumer: EventConsumer) -> AsyncGenerator[Message | Task | TaskStatusUpdateEvent | TaskArtifactUpdateEvent] Processes the event stream from the consumer, updates the task state, and re-emits the same events. Useful for streaming scenarios where the server needs to observe and process events (e.g., save task state, send push notifications) while forwarding them to the client. Parameters: **consumer** -- The *EventConsumer* to read events from. Yields: The *Event* objects consumed from the *EventConsumer*. property current_result: Task | Message | None Returns the current aggregated result (Task or Message). This is the latest state processed from the event stream. Returns: The current *Task* object managed by the *TaskManager*, or the final *Message* if one was received, or *None* if no result has been produced yet. class a2a.server.tasks.TaskManager(task_store: TaskStore, context: ServerCallContext, task_id: str | None, context_id: str | None, initial_message: Message | None) Bases: "object" Helps manage a task's lifecycle during execution of a request. Responsible for retrieving, saving, and updating the *Task* object based on events received from the agent. async ensure_task(event: TaskStatusUpdateEvent | TaskArtifactUpdateEvent) -> Task Ensures a Task object exists in memory, loading from store or creating new if needed. Parameters: **event** -- The task-related event triggering the need for a Task object. Returns: An existing or newly created *Task* object. async ensure_task_id(task_id: str, context_id: str) -> Task Ensures a Task object exists in memory, loading from store or creating new if needed. Parameters: * **task_id** -- The ID for the new task. * **context_id** -- The context ID for the new task. Returns: An existing or newly created *Task* object. async get_task() -> Task | None Retrieves the current task object, either from memory or the store. If *task_id* is set, it first checks the in-memory *_current_task*, then attempts to load it from the *task_store*. Returns: The *Task* object if found, otherwise *None*. async process(event: Message | Task | TaskStatusUpdateEvent | TaskArtifactUpdateEvent) -> Message | Task | TaskStatusUpdateEvent | TaskArtifactUpdateEvent Processes an event, updates the task state if applicable, stores it, and returns the event. If the event is task-related (*Task*, *TaskStatusUpdateEvent*, *TaskArtifactUpdateEvent*), the internal task state is updated and persisted. Parameters: **event** -- The event object received from the agent. Returns: The same event object that was processed. async save_task_event(event: Task | TaskStatusUpdateEvent | TaskArtifactUpdateEvent) -> Task | None Processes a task-related event (Task, Status, Artifact) and saves the updated task state. Ensures task and context IDs match or are set from the event. Parameters: **event** -- The task-related event (*Task*, *TaskStatusUpdateEvent*, or *TaskArtifactUpdateEvent*). Returns: The updated *Task* object after processing the event. Raises: **InvalidParamsError** -- If the task ID in the event conflicts with the TaskManager's ID when the TaskManager's ID is already set. update_with_message(message: Message, task: Task) -> Task Updates a task object in memory by adding a new message to its history. If the task has a message in its current status, that message is moved to the history first. Parameters: * **message** -- The new *Message* to add to the history. * **task** -- The *Task* object to update. Returns: The updated *Task* object (updated in-place). class a2a.server.tasks.TaskStore Bases: "ABC" Agent Task Store interface. Defines the methods for persisting and retrieving *Task* objects. abstractmethod async delete(task_id: str, context: ServerCallContext) -> None Deletes a task from the store by ID. abstractmethod async get(task_id: str, context: ServerCallContext) -> Task | None Retrieves a task from the store by ID. abstractmethod async list(params: ListTasksRequest, context: ServerCallContext) -> ListTasksResponse Retrieves a list of tasks from the store. abstractmethod async save(task: Task, context: ServerCallContext) -> None Saves or updates a task in the store. class a2a.server.tasks.TaskUpdater(event_queue: EventQueue, task_id: str, context_id: str, artifact_id_generator: IDGenerator | None = None, message_id_generator: IDGenerator | None = None) Bases: "object" Helper class for agents to publish updates to a task's event queue. Simplifies the process of creating and enqueueing standard task events. async add_artifact(parts: list[Part], artifact_id: str | None = None, name: str | None = None, metadata: dict[str, Any] | None = None, append: bool | None = None, last_chunk: bool | None = None, extensions: list[str] | None = None) -> None Adds an artifact chunk to the task and publishes a *TaskArtifactUpdateEvent*. Parameters: * **parts** -- A list of *Part* objects forming the artifact chunk. * **artifact_id** -- The ID of the artifact. A new UUID is generated if not provided. * **name** -- Optional name for the artifact. * **metadata** -- Optional metadata for the artifact. * **append** -- Optional boolean indicating if this chunk appends to a previous one. * **last_chunk** -- Optional boolean indicating if this is the last chunk. * **extensions** -- Optional list of extensions for the artifact. async cancel(message: Message | None = None) -> None Marks the task as cancelled and publishes a finalstatus update. async complete(message: Message | None = None) -> None Marks the task as completed and publishes a final status update. async failed(message: Message | None = None) -> None Marks the task as failed and publishes a final status update. new_agent_message(parts: list[Part], metadata: dict[str, Any] | None = None) -> Message Creates a new message object sent by the agent for this task/context. Note: This method only *creates* the message object. It does not automatically enqueue it. Parameters: * **parts** -- A list of *Part* objects for the message content. * **metadata** -- Optional metadata for the message. Returns: A new *Message* object. async reject(message: Message | None = None) -> None Marks the task as rejected and publishes a final status update. async requires_auth(message: Message | None = None) -> None Marks the task as auth required and publishes a status update. async requires_input(message: Message | None = None) -> None Marks the task as input required and publishes a status update. async start_work(message: Message | None = None) -> None Marks the task as working and publishes a status update. async submit(message: Message | None = None) -> None Marks the task as submitted and publishes a status update. async update_status(state: , message: Message | None = None, timestamp: str | None = None, metadata: dict[str, ~typing.Any] | None=None) -> None Updates the status of the task and publishes a *TaskStatusUpdateEvent*. Parameters: * **state** -- The new state of the task. * **message** -- An optional message associated with the status update. * **timestamp** -- Optional ISO 8601 datetime string. Defaults to current time. * **metadata** -- Optional metadata for extensions. a2a.server package ****************** Subpackages =========== * a2a.server.agent_execution package * Submodules * a2a.server.agent_execution.active_task module * "ActiveTask" * "EventConsumer" * a2a.server.agent_execution.active_task_registry module * "ActiveTaskRegistry" * a2a.server.agent_execution.agent_executor module * "AgentExecutor" * a2a.server.agent_execution.context module * "RequestContext" * a2a.server.agent_execution.request_context_builder module * "RequestContextBuilder" * a2a.server.agent_execution.simple_request_context_builder module * "SimpleRequestContextBuilder" * Module contents * "AgentExecutor" * "AgentExecutor.cancel()" * "AgentExecutor.execute()" * "RequestContext" * "RequestContext.attach_related_task()" * "RequestContext.call_context" * "RequestContext.configuration" * "RequestContext.context_id" * "RequestContext.current_task" * "RequestContext.get_user_input()" * "RequestContext.message" * "RequestContext.metadata" * "RequestContext.related_tasks" * "RequestContext.requested_extensions" * "RequestContext.task_id" * "RequestContext.tenant" * "RequestContextBuilder" * "RequestContextBuilder.build()" * "SimpleRequestContextBuilder" * "SimpleRequestContextBuilder.build()" * a2a.server.events package * Submodules * a2a.server.events.event_consumer module * "EventConsumer" * a2a.server.events.event_queue module * "Event" * "EventQueue" * "EventQueueLegacy" * a2a.server.events.event_queue_v2 module * "EventQueueSink" * "EventQueueSource" * a2a.server.events.in_memory_queue_manager module * "InMemoryQueueManager" * a2a.server.events.queue_manager module * "NoTaskQueue" * "QueueManager" * "TaskQueueExists" * Module contents * "EventConsumer" * "EventConsumer.agent_task_callback()" * "EventConsumer.consume_all()" * "EventQueue" * "EventQueue.enqueue_event()" * "EventQueueLegacy" * "EventQueueLegacy.close()" * "EventQueueLegacy.dequeue_event()" * "EventQueueLegacy.enqueue_event()" * "EventQueueLegacy.is_closed()" * "EventQueueLegacy.queue" * "EventQueueLegacy.tap()" * "EventQueueLegacy.task_done()" * "InMemoryQueueManager" * "InMemoryQueueManager.add()" * "InMemoryQueueManager.close()" * "InMemoryQueueManager.create_or_tap()" * "InMemoryQueueManager.get()" * "InMemoryQueueManager.tap()" * "NoTaskQueue" * "QueueManager" * "QueueManager.add()" * "QueueManager.close()" * "QueueManager.create_or_tap()" * "QueueManager.get()" * "QueueManager.tap()" * "TaskQueueExists" * a2a.server.request_handlers package * Submodules * a2a.server.request_handlers.default_request_handler module * "LegacyRequestHandler" * a2a.server.request_handlers.default_request_handler_v2 module * "DefaultRequestHandlerV2" * a2a.server.request_handlers.grpc_handler module * "DefaultGrpcServerCallContextBuilder" * "GrpcHandler" * "GrpcServerCallContextBuilder" * a2a.server.request_handlers.request_handler module * "RequestHandler" * "validate()" * "validate_request_params()" * a2a.server.request_handlers.response_helpers module * "EventTypes" * "agent_card_to_dict()" * "build_error_response()" * "prepare_response_object()" * Module contents * "DefaultGrpcServerCallContextBuilder" * "DefaultGrpcServerCallContextBuilder.build()" * "DefaultGrpcServerCallContextBuilder.build_user()" * "DefaultRequestHandler" * "DefaultRequestHandlerV2" * "DefaultRequestHandlerV2.on_cancel_task()" * "DefaultRequestHandlerV2.on_create_task_push_notification_conf ig()" * "DefaultRequestHandlerV2.on_delete_task_push_notification_conf ig()" * "DefaultRequestHandlerV2.on_get_extended_agent_card()" * "DefaultRequestHandlerV2.on_get_task()" * "DefaultRequestHandlerV2.on_get_task_push_notification_config( )" * "DefaultRequestHandlerV2.on_list_task_push_notification_config s()" * "DefaultRequestHandlerV2.on_list_tasks()" * "DefaultRequestHandlerV2.on_message_send()" * "DefaultRequestHandlerV2.on_message_send_stream()" * "DefaultRequestHandlerV2.on_subscribe_to_task()" * "GrpcHandler" * "GrpcHandler.CancelTask()" * "GrpcHandler.CreateTaskPushNotificationConfig()" * "GrpcHandler.DeleteTaskPushNotificationConfig()" * "GrpcHandler.GetExtendedAgentCard()" * "GrpcHandler.GetTask()" * "GrpcHandler.GetTaskPushNotificationConfig()" * "GrpcHandler.ListTaskPushNotificationConfigs()" * "GrpcHandler.ListTasks()" * "GrpcHandler.SendMessage()" * "GrpcHandler.SendStreamingMessage()" * "GrpcHandler.SubscribeToTask()" * "GrpcHandler.abort_context()" * "GrpcServerCallContextBuilder" * "GrpcServerCallContextBuilder.build()" * "LegacyRequestHandler" * "LegacyRequestHandler.on_cancel_task()" * "LegacyRequestHandler.on_create_task_push_notification_config( )" * "LegacyRequestHandler.on_delete_task_push_notification_config( )" * "LegacyRequestHandler.on_get_extended_agent_card()" * "LegacyRequestHandler.on_get_task()" * "LegacyRequestHandler.on_get_task_push_notification_config()" * "LegacyRequestHandler.on_list_task_push_notification_configs() " * "LegacyRequestHandler.on_list_tasks()" * "LegacyRequestHandler.on_message_send()" * "LegacyRequestHandler.on_message_send_stream()" * "LegacyRequestHandler.on_subscribe_to_task()" * "RequestHandler" * "RequestHandler.on_cancel_task()" * "RequestHandler.on_create_task_push_notification_config()" * "RequestHandler.on_delete_task_push_notification_config()" * "RequestHandler.on_get_extended_agent_card()" * "RequestHandler.on_get_task()" * "RequestHandler.on_get_task_push_notification_config()" * "RequestHandler.on_list_task_push_notification_configs()" * "RequestHandler.on_list_tasks()" * "RequestHandler.on_message_send()" * "RequestHandler.on_message_send_stream()" * "RequestHandler.on_subscribe_to_task()" * "build_error_response()" * "prepare_response_object()" * "validate_request_params()" * a2a.server.routes package * Submodules * a2a.server.routes.agent_card_routes module * "create_agent_card_routes()" * a2a.server.routes.common module * "DefaultServerCallContextBuilder" * "ServerCallContextBuilder" * "StarletteUser" * a2a.server.routes.fastapi_routes module * "add_a2a_routes_to_fastapi()" * a2a.server.routes.jsonrpc_dispatcher module * "JsonRpcDispatcher" * a2a.server.routes.jsonrpc_routes module * "create_jsonrpc_routes()" * a2a.server.routes.rest_dispatcher module * "RestDispatcher" * a2a.server.routes.rest_routes module * "create_rest_routes()" * Module contents * "DefaultServerCallContextBuilder" * "DefaultServerCallContextBuilder.build()" * "DefaultServerCallContextBuilder.build_user()" * "ServerCallContextBuilder" * "ServerCallContextBuilder.build()" * "add_a2a_routes_to_fastapi()" * "create_agent_card_routes()" * "create_jsonrpc_routes()" * "create_rest_routes()" * a2a.server.tasks package * Submodules * a2a.server.tasks.base_push_notification_sender module * "BasePushNotificationSender" * a2a.server.tasks.copying_task_store module * "CopyingTaskStoreAdapter" * a2a.server.tasks.database_push_notification_config_store module * "DatabasePushNotificationConfigStore" * a2a.server.tasks.database_task_store module * "DatabaseTaskStore" * a2a.server.tasks.inmemory_push_notification_config_store module * "InMemoryPushNotificationConfigStore" * a2a.server.tasks.inmemory_task_store module * "InMemoryTaskStore" * a2a.server.tasks.push_notification_config_store module * "PushNotificationConfigStore" * a2a.server.tasks.push_notification_sender module * "PushNotificationSender" * a2a.server.tasks.result_aggregator module * "ResultAggregator" * a2a.server.tasks.task_manager module * "TaskManager" * "append_artifact_to_task()" * a2a.server.tasks.task_store module * "TaskStore" * a2a.server.tasks.task_updater module * "TaskUpdater" * Module contents * "BasePushNotificationSender" * "BasePushNotificationSender.send_notification()" * "DatabasePushNotificationConfigStore" * "DatabasePushNotificationConfigStore.async_session_maker" * "DatabasePushNotificationConfigStore.config_model" * "DatabasePushNotificationConfigStore.core_to_model_conversion" * "DatabasePushNotificationConfigStore.create_table" * "DatabasePushNotificationConfigStore.delete_info()" * "DatabasePushNotificationConfigStore.engine" * "DatabasePushNotificationConfigStore.get_info()" * "DatabasePushNotificationConfigStore.get_info_for_dispatch()" * "DatabasePushNotificationConfigStore.initialize()" * "DatabasePushNotificationConfigStore.model_to_core_conversion" * "DatabasePushNotificationConfigStore.owner_resolver" * "DatabasePushNotificationConfigStore.set_info()" * "DatabaseTaskStore" * "DatabaseTaskStore.async_session_maker" * "DatabaseTaskStore.core_to_model_conversion" * "DatabaseTaskStore.create_table" * "DatabaseTaskStore.delete()" * "DatabaseTaskStore.engine" * "DatabaseTaskStore.get()" * "DatabaseTaskStore.initialize()" * "DatabaseTaskStore.list()" * "DatabaseTaskStore.model_to_core_conversion" * "DatabaseTaskStore.owner_resolver" * "DatabaseTaskStore.save()" * "DatabaseTaskStore.task_model" * "InMemoryPushNotificationConfigStore" * "InMemoryPushNotificationConfigStore.delete_info()" * "InMemoryPushNotificationConfigStore.get_info()" * "InMemoryPushNotificationConfigStore.get_info_for_dispatch()" * "InMemoryPushNotificationConfigStore.set_info()" * "InMemoryTaskStore" * "InMemoryTaskStore.delete()" * "InMemoryTaskStore.get()" * "InMemoryTaskStore.list()" * "InMemoryTaskStore.save()" * "PushNotificationConfigStore" * "PushNotificationConfigStore.delete_info()" * "PushNotificationConfigStore.get_info()" * "PushNotificationConfigStore.get_info_for_dispatch()" * "PushNotificationConfigStore.set_info()" * "PushNotificationSender" * "PushNotificationSender.send_notification()" * "ResultAggregator" * "ResultAggregator.consume_all()" * "ResultAggregator.consume_and_break_on_interrupt()" * "ResultAggregator.consume_and_emit()" * "ResultAggregator.current_result" * "TaskManager" * "TaskManager.ensure_task()" * "TaskManager.ensure_task_id()" * "TaskManager.get_task()" * "TaskManager.process()" * "TaskManager.save_task_event()" * "TaskManager.update_with_message()" * "TaskStore" * "TaskStore.delete()" * "TaskStore.get()" * "TaskStore.list()" * "TaskStore.save()" * "TaskUpdater" * "TaskUpdater.add_artifact()" * "TaskUpdater.cancel()" * "TaskUpdater.complete()" * "TaskUpdater.failed()" * "TaskUpdater.new_agent_message()" * "TaskUpdater.reject()" * "TaskUpdater.requires_auth()" * "TaskUpdater.requires_input()" * "TaskUpdater.start_work()" * "TaskUpdater.submit()" * "TaskUpdater.update_status()" Submodules ========== * a2a.server.context module * "ServerCallContext" * "ServerCallContext.model_config" * "ServerCallContext.requested_extensions" * "ServerCallContext.state" * "ServerCallContext.tenant" * "ServerCallContext.user" * a2a.server.id_generator module * "IDGenerator" * "IDGenerator.generate()" * "IDGeneratorContext" * "IDGeneratorContext.context_id" * "IDGeneratorContext.model_config" * "IDGeneratorContext.task_id" * "UUIDGenerator" * "UUIDGenerator.generate()" * a2a.server.jsonrpc_models module * "InternalError" * "InternalError.code" * "InternalError.message" * "InternalError.model_config" * "InvalidParamsError" * "InvalidParamsError.code" * "InvalidParamsError.message" * "InvalidParamsError.model_config" * "InvalidRequestError" * "InvalidRequestError.code" * "InvalidRequestError.message" * "InvalidRequestError.model_config" * "JSONParseError" * "JSONParseError.code" * "JSONParseError.message" * "JSONParseError.model_config" * "JSONRPCBaseModel" * "JSONRPCBaseModel.model_config" * "JSONRPCError" * "JSONRPCError.code" * "JSONRPCError.data" * "JSONRPCError.message" * "JSONRPCError.model_config" * "MethodNotFoundError" * "MethodNotFoundError.code" * "MethodNotFoundError.message" * "MethodNotFoundError.model_config" * a2a.server.models module * "Base" * "Base.metadata" * "Base.registry" * "PushNotificationConfigMixin" * "PushNotificationConfigMixin.config_data" * "PushNotificationConfigMixin.config_id" * "PushNotificationConfigMixin.owner" * "PushNotificationConfigMixin.protocol_version" * "PushNotificationConfigMixin.task_id" * "PushNotificationConfigModel" * "PushNotificationConfigModel.config_data" * "PushNotificationConfigModel.config_id" * "PushNotificationConfigModel.owner" * "PushNotificationConfigModel.protocol_version" * "PushNotificationConfigModel.task_id" * "TaskMixin" * "TaskMixin.artifacts" * "TaskMixin.context_id" * "TaskMixin.history" * "TaskMixin.id" * "TaskMixin.kind" * "TaskMixin.last_updated" * "TaskMixin.owner" * "TaskMixin.protocol_version" * "TaskMixin.status" * "TaskMixin.task_metadata" * "TaskModel" * "TaskModel.artifacts" * "TaskModel.context_id" * "TaskModel.history" * "TaskModel.id" * "TaskModel.kind" * "TaskModel.last_updated" * "TaskModel.owner" * "TaskModel.protocol_version" * "TaskModel.status" * "TaskModel.task_metadata" * "create_push_notification_config_model()" * "create_task_model()" * "override()" * a2a.server.owner_resolver module * "resolve_user_scope()" Module contents =============== Server-side components for implementing an A2A agent. a2a package *********** Subpackages =========== * a2a.auth package * Submodules * a2a.auth.user module * "UnauthenticatedUser" * "User" * Module contents * a2a.client package * Subpackages * a2a.client.auth package * Submodules * Module contents * a2a.client.transports package * Submodules * Module contents * Submodules * a2a.client.base_client module * "BaseClient" * a2a.client.card_resolver module * "A2ACardResolver" * "parse_agent_card()" * a2a.client.client module * "Client" * "ClientCallContext" * "ClientConfig" * a2a.client.client_factory module * "ClientFactory" * "create_client()" * "minimal_agent_card()" * a2a.client.errors module * "A2AClientError" * "A2AClientTimeoutError" * "AgentCardResolutionError" * a2a.client.interceptors module * "AfterArgs" * "BeforeArgs" * "ClientCallInterceptor" * a2a.client.optionals module * a2a.client.service_parameters module * "ServiceParametersFactory" * "with_a2a_extensions()" * Module contents * "A2ACardResolver" * "A2ACardResolver.get_agent_card()" * "A2AClientError" * "A2AClientTimeoutError" * "AgentCardResolutionError" * "AuthInterceptor" * "AuthInterceptor.after()" * "AuthInterceptor.before()" * "BaseClient" * "BaseClient.cancel_task()" * "BaseClient.close()" * "BaseClient.create_task_push_notification_config()" * "BaseClient.delete_task_push_notification_config()" * "BaseClient.get_extended_agent_card()" * "BaseClient.get_task()" * "BaseClient.get_task_push_notification_config()" * "BaseClient.list_task_push_notification_configs()" * "BaseClient.list_tasks()" * "BaseClient.send_message()" * "BaseClient.subscribe()" * "Client" * "Client.add_interceptor()" * "Client.cancel_task()" * "Client.close()" * "Client.create_task_push_notification_config()" * "Client.delete_task_push_notification_config()" * "Client.get_extended_agent_card()" * "Client.get_task()" * "Client.get_task_push_notification_config()" * "Client.list_task_push_notification_configs()" * "Client.list_tasks()" * "Client.send_message()" * "Client.subscribe()" * "ClientCallContext" * "ClientCallContext.model_config" * "ClientCallContext.service_parameters" * "ClientCallContext.state" * "ClientCallContext.timeout" * "ClientCallInterceptor" * "ClientCallInterceptor.after()" * "ClientCallInterceptor.before()" * "ClientConfig" * "ClientConfig.accepted_output_modes" * "ClientConfig.grpc_channel_factory" * "ClientConfig.httpx_client" * "ClientConfig.polling" * "ClientConfig.push_notification_config" * "ClientConfig.streaming" * "ClientConfig.supported_protocol_bindings" * "ClientConfig.use_client_preference" * "ClientFactory" * "ClientFactory.create()" * "ClientFactory.create_from_url()" * "ClientFactory.register()" * "CredentialService" * "CredentialService.get_credentials()" * "InMemoryContextCredentialStore" * "InMemoryContextCredentialStore.get_credentials()" * "InMemoryContextCredentialStore.set_credentials()" * "create_client()" * "minimal_agent_card()" * a2a.compat package * Subpackages * a2a.compat.v0_3 package * Submodules * Module contents * Module contents * a2a.extensions package * Submodules * a2a.extensions.common module * "find_extension_by_uri()" * "get_requested_extensions()" * Module contents * a2a.helpers package * Submodules * a2a.helpers.agent_card module * "display_agent_card()" * a2a.helpers.proto_helpers module * "get_artifact_text()" * "get_data_parts()" * "get_message_text()" * "get_raw_parts()" * "get_stream_response_text()" * "get_text_parts()" * "get_url_parts()" * "new_artifact()" * "new_data_artifact()" * "new_data_artifact_update_event()" * "new_data_message()" * "new_data_part()" * "new_message()" * "new_raw_artifact()" * "new_raw_artifact_update_event()" * "new_raw_message()" * "new_raw_part()" * "new_task()" * "new_task_from_user_message()" * "new_text_artifact()" * "new_text_artifact_update_event()" * "new_text_message()" * "new_text_part()" * "new_text_status_update_event()" * "new_url_artifact()" * "new_url_artifact_update_event()" * "new_url_message()" * "new_url_part()" * Module contents * "display_agent_card()" * "get_artifact_text()" * "get_data_parts()" * "get_message_text()" * "get_raw_parts()" * "get_stream_response_text()" * "get_text_parts()" * "get_url_parts()" * "new_artifact()" * "new_data_artifact()" * "new_data_artifact_update_event()" * "new_data_message()" * "new_data_part()" * "new_message()" * "new_raw_artifact()" * "new_raw_artifact_update_event()" * "new_raw_message()" * "new_raw_part()" * "new_task()" * "new_task_from_user_message()" * "new_text_artifact()" * "new_text_artifact_update_event()" * "new_text_message()" * "new_text_part()" * "new_text_status_update_event()" * "new_url_artifact()" * "new_url_artifact_update_event()" * "new_url_message()" * "new_url_part()" * a2a.migrations package * Subpackages * a2a.migrations.versions package * Submodules * Module contents * Submodules * a2a.migrations.env module * a2a.migrations.migration_utils module * "add_column()" * "add_index()" * "column_exists()" * "drop_column()" * "drop_index()" * "index_exists()" * "table_exists()" * Module contents * a2a.server package * Subpackages * a2a.server.agent_execution package * Submodules * Module contents * a2a.server.events package * Submodules * Module contents * a2a.server.request_handlers package * Submodules * Module contents * a2a.server.routes package * Submodules * Module contents * a2a.server.tasks package * Submodules * Module contents * Submodules * a2a.server.context module * "ServerCallContext" * a2a.server.id_generator module * "IDGenerator" * "IDGeneratorContext" * "UUIDGenerator" * a2a.server.jsonrpc_models module * "InternalError" * "InvalidParamsError" * "InvalidRequestError" * "JSONParseError" * "JSONRPCBaseModel" * "JSONRPCError" * "MethodNotFoundError" * a2a.server.models module * "Base" * "PushNotificationConfigMixin" * "PushNotificationConfigModel" * "TaskMixin" * "TaskModel" * "create_push_notification_config_model()" * "create_task_model()" * "override()" * a2a.server.owner_resolver module * "resolve_user_scope()" * Module contents * a2a.types package * Submodules * a2a.types.a2a_pb2 module * a2a.types.a2a_pb2_grpc module * "A2AService" * "A2AServiceServicer" * "A2AServiceStub" * "add_A2AServiceServicer_to_server()" * Module contents * "APIKeySecurityScheme" * "APIKeySecurityScheme.DESCRIPTOR" * "AgentCapabilities" * "AgentCapabilities.DESCRIPTOR" * "AgentCard" * "AgentCard.DESCRIPTOR" * "AgentCard.SecuritySchemesEntry" * "AgentCardSignature" * "AgentCardSignature.DESCRIPTOR" * "AgentExtension" * "AgentExtension.DESCRIPTOR" * "AgentInterface" * "AgentInterface.DESCRIPTOR" * "AgentProvider" * "AgentProvider.DESCRIPTOR" * "AgentSkill" * "AgentSkill.DESCRIPTOR" * "Artifact" * "Artifact.DESCRIPTOR" * "AuthenticationInfo" * "AuthenticationInfo.DESCRIPTOR" * "AuthorizationCodeOAuthFlow" * "AuthorizationCodeOAuthFlow.DESCRIPTOR" * "AuthorizationCodeOAuthFlow.ScopesEntry" * "CancelTaskRequest" * "CancelTaskRequest.DESCRIPTOR" * "ClientCredentialsOAuthFlow" * "ClientCredentialsOAuthFlow.DESCRIPTOR" * "ClientCredentialsOAuthFlow.ScopesEntry" * "ContentTypeNotSupportedError" * "ContentTypeNotSupportedError.message" * "DeleteTaskPushNotificationConfigRequest" * "DeleteTaskPushNotificationConfigRequest.DESCRIPTOR" * "DeviceCodeOAuthFlow" * "DeviceCodeOAuthFlow.DESCRIPTOR" * "DeviceCodeOAuthFlow.ScopesEntry" * "ExtendedAgentCardNotConfiguredError" * "ExtendedAgentCardNotConfiguredError.message" * "ExtensionSupportRequiredError" * "ExtensionSupportRequiredError.message" * "GetExtendedAgentCardRequest" * "GetExtendedAgentCardRequest.DESCRIPTOR" * "GetTaskPushNotificationConfigRequest" * "GetTaskPushNotificationConfigRequest.DESCRIPTOR" * "GetTaskRequest" * "GetTaskRequest.DESCRIPTOR" * "HTTPAuthSecurityScheme" * "HTTPAuthSecurityScheme.DESCRIPTOR" * "ImplicitOAuthFlow" * "ImplicitOAuthFlow.DESCRIPTOR" * "ImplicitOAuthFlow.ScopesEntry" * "InternalError" * "InternalError.message" * "InvalidAgentResponseError" * "InvalidAgentResponseError.message" * "InvalidParamsError" * "InvalidParamsError.message" * "InvalidRequestError" * "InvalidRequestError.message" * "ListTaskPushNotificationConfigsRequest" * "ListTaskPushNotificationConfigsRequest.DESCRIPTOR" * "ListTaskPushNotificationConfigsResponse" * "ListTaskPushNotificationConfigsResponse.DESCRIPTOR" * "ListTasksRequest" * "ListTasksRequest.DESCRIPTOR" * "ListTasksResponse" * "ListTasksResponse.DESCRIPTOR" * "Message" * "Message.DESCRIPTOR" * "MethodNotFoundError" * "MethodNotFoundError.message" * "MutualTlsSecurityScheme" * "MutualTlsSecurityScheme.DESCRIPTOR" * "OAuth2SecurityScheme" * "OAuth2SecurityScheme.DESCRIPTOR" * "OAuthFlows" * "OAuthFlows.DESCRIPTOR" * "OpenIdConnectSecurityScheme" * "OpenIdConnectSecurityScheme.DESCRIPTOR" * "Part" * "Part.DESCRIPTOR" * "PasswordOAuthFlow" * "PasswordOAuthFlow.DESCRIPTOR" * "PasswordOAuthFlow.ScopesEntry" * "PushNotificationNotSupportedError" * "PushNotificationNotSupportedError.message" * "SecurityRequirement" * "SecurityRequirement.DESCRIPTOR" * "SecurityRequirement.SchemesEntry" * "SecurityScheme" * "SecurityScheme.DESCRIPTOR" * "SendMessageConfiguration" * "SendMessageConfiguration.DESCRIPTOR" * "SendMessageRequest" * "SendMessageRequest.DESCRIPTOR" * "SendMessageResponse" * "SendMessageResponse.DESCRIPTOR" * "StreamResponse" * "StreamResponse.DESCRIPTOR" * "StringList" * "StringList.DESCRIPTOR" * "SubscribeToTaskRequest" * "SubscribeToTaskRequest.DESCRIPTOR" * "Task" * "Task.DESCRIPTOR" * "TaskArtifactUpdateEvent" * "TaskArtifactUpdateEvent.DESCRIPTOR" * "TaskNotCancelableError" * "TaskNotCancelableError.message" * "TaskNotFoundError" * "TaskNotFoundError.message" * "TaskPushNotificationConfig" * "TaskPushNotificationConfig.DESCRIPTOR" * "TaskStatus" * "TaskStatus.DESCRIPTOR" * "TaskStatusUpdateEvent" * "TaskStatusUpdateEvent.DESCRIPTOR" * "UnsupportedOperationError" * "UnsupportedOperationError.message" * "VersionNotSupportedError" * "VersionNotSupportedError.message" * a2a.utils package * Submodules * a2a.utils.constants module * "DEFAULT_LIST_TASKS_PAGE_SIZE" * "MAX_LIST_TASKS_PAGE_SIZE" * "TransportProtocol" * a2a.utils.error_handlers module * "build_error_details()" * "build_rest_error_payload()" * "rest_error_handler()" * "rest_stream_error_handler()" * a2a.utils.errors module * "ErrorMapping" * "ExtensionSupportRequiredError" * "InternalError" * "InvalidAgentResponseError" * "InvalidParamsError" * "InvalidRequestError" * "JSONParseError" * "MethodNotFoundError" * "PushNotificationNotSupportedError" * "TaskNotCancelableError" * "TaskNotFoundError" * "UnsupportedOperationError" * "VersionNotSupportedError" * a2a.utils.json_utils module * "dumps()" * a2a.utils.proto_utils module * "ValidationDetail" * "bad_request_to_validation_errors()" * "make_dict_serializable()" * "normalize_large_integers_to_strings()" * "parse_params()" * "parse_string_integers_in_dict()" * "to_stream_response()" * "validate_proto_required_fields()" * "validation_errors_to_bad_request()" * a2a.utils.signing module * "InvalidSignaturesError" * "NoSignatureError" * "ProtectedHeader" * "SignatureVerificationError" * "create_agent_card_signer()" * "create_signature_verifier()" * a2a.utils.task module * "HistoryLengthConfig" * "apply_history_length()" * "decode_page_token()" * "encode_page_token()" * "validate_history_length()" * "validate_page_size()" * a2a.utils.telemetry module * "SpanKind" * a2a.utils.version_validator module * "validate_version()" * Module contents * "TransportProtocol" * "TransportProtocol.GRPC" * "TransportProtocol.HTTP_JSON" * "TransportProtocol.JSONRPC" * "to_stream_response()" Submodules ========== * a2a.a2a_db_cli module * "create_parser()" * "run_migrations()" Module contents =============== The A2A Python SDK. a2a.types.a2a_pb2 module ************************ Generated protocol buffer code. a2a.types.a2a_pb2_grpc module ***************************** Client and server classes corresponding to protobuf-defined services. class a2a.types.a2a_pb2_grpc.A2AService Bases: "object" Provides operations for interacting with agents using the A2A protocol. static CancelTask(request, target, options=(), channel_credentials=None, call_credentials=None, insecure=False, compression=None, wait_for_ready=None, timeout=None, metadata=None) static CreateTaskPushNotificationConfig(request, target, options=(), channel_credentials=None, call_credentials=None, insecure=False, compression=None, wait_for_ready=None, timeout=None, metadata=None) static DeleteTaskPushNotificationConfig(request, target, options=(), channel_credentials=None, call_credentials=None, insecure=False, compression=None, wait_for_ready=None, timeout=None, metadata=None) static GetExtendedAgentCard(request, target, options=(), channel_credentials=None, call_credentials=None, insecure=False, compression=None, wait_for_ready=None, timeout=None, metadata=None) static GetTask(request, target, options=(), channel_credentials=None, call_credentials=None, insecure=False, compression=None, wait_for_ready=None, timeout=None, metadata=None) static GetTaskPushNotificationConfig(request, target, options=(), channel_credentials=None, call_credentials=None, insecure=False, compression=None, wait_for_ready=None, timeout=None, metadata=None) static ListTaskPushNotificationConfigs(request, target, options=(), channel_credentials=None, call_credentials=None, insecure=False, compression=None, wait_for_ready=None, timeout=None, metadata=None) static ListTasks(request, target, options=(), channel_credentials=None, call_credentials=None, insecure=False, compression=None, wait_for_ready=None, timeout=None, metadata=None) static SendMessage(request, target, options=(), channel_credentials=None, call_credentials=None, insecure=False, compression=None, wait_for_ready=None, timeout=None, metadata=None) static SendStreamingMessage(request, target, options=(), channel_credentials=None, call_credentials=None, insecure=False, compression=None, wait_for_ready=None, timeout=None, metadata=None) static SubscribeToTask(request, target, options=(), channel_credentials=None, call_credentials=None, insecure=False, compression=None, wait_for_ready=None, timeout=None, metadata=None) class a2a.types.a2a_pb2_grpc.A2AServiceServicer Bases: "object" Provides operations for interacting with agents using the A2A protocol. CancelTask(request, context) Cancels a task in progress. CreateTaskPushNotificationConfig(request, context) (-- api-linter: client-libraries::4232::required-fields=disabled api-linter: core::0133::method-signature=disabled api-linter: core::0133::request-message-name=disabled aip.dev/not-precedent: method_signature preserved for backwards compatibility --) Creates a push notification config for a task. DeleteTaskPushNotificationConfig(request, context) Deletes a push notification config for a task. GetExtendedAgentCard(request, context) Gets the extended agent card for the authenticated agent. GetTask(request, context) Gets the latest state of a task. GetTaskPushNotificationConfig(request, context) Gets a push notification config for a task. ListTaskPushNotificationConfigs(request, context) Get a list of push notifications configured for a task. ListTasks(request, context) Lists tasks that match the specified filter. SendMessage(request, context) Sends a message to an agent. SendStreamingMessage(request, context) Sends a streaming message to an agent, allowing for real-time interaction and status updates. Streaming version of *SendMessage* SubscribeToTask(request, context) Subscribes to task updates for tasks not in a terminal state. Returns *UnsupportedOperationError* if the task is already in a terminal state (completed, failed, canceled, rejected). class a2a.types.a2a_pb2_grpc.A2AServiceStub(channel) Bases: "object" Provides operations for interacting with agents using the A2A protocol. a2a.types.a2a_pb2_grpc.add_A2AServiceServicer_to_server(servicer, server) a2a.types package ***************** Submodules ========== * a2a.types.a2a_pb2 module * a2a.types.a2a_pb2_grpc module * "A2AService" * "A2AService.CancelTask()" * "A2AService.CreateTaskPushNotificationConfig()" * "A2AService.DeleteTaskPushNotificationConfig()" * "A2AService.GetExtendedAgentCard()" * "A2AService.GetTask()" * "A2AService.GetTaskPushNotificationConfig()" * "A2AService.ListTaskPushNotificationConfigs()" * "A2AService.ListTasks()" * "A2AService.SendMessage()" * "A2AService.SendStreamingMessage()" * "A2AService.SubscribeToTask()" * "A2AServiceServicer" * "A2AServiceServicer.CancelTask()" * "A2AServiceServicer.CreateTaskPushNotificationConfig()" * "A2AServiceServicer.DeleteTaskPushNotificationConfig()" * "A2AServiceServicer.GetExtendedAgentCard()" * "A2AServiceServicer.GetTask()" * "A2AServiceServicer.GetTaskPushNotificationConfig()" * "A2AServiceServicer.ListTaskPushNotificationConfigs()" * "A2AServiceServicer.ListTasks()" * "A2AServiceServicer.SendMessage()" * "A2AServiceServicer.SendStreamingMessage()" * "A2AServiceServicer.SubscribeToTask()" * "A2AServiceStub" * "add_A2AServiceServicer_to_server()" Module contents =============== A2A Types Package - Protocol Buffer and SDK-specific types. class a2a.types.APIKeySecurityScheme Bases: "Message", "Message" DESCRIPTOR = class a2a.types.AgentCapabilities Bases: "Message", "Message" DESCRIPTOR = class a2a.types.AgentCard Bases: "Message", "Message" DESCRIPTOR = class SecuritySchemesEntry Bases: "Message", "Message" DESCRIPTOR = class a2a.types.AgentCardSignature Bases: "Message", "Message" DESCRIPTOR = class a2a.types.AgentExtension Bases: "Message", "Message" DESCRIPTOR = class a2a.types.AgentInterface Bases: "Message", "Message" DESCRIPTOR = class a2a.types.AgentProvider Bases: "Message", "Message" DESCRIPTOR = class a2a.types.AgentSkill Bases: "Message", "Message" DESCRIPTOR = class a2a.types.Artifact Bases: "Message", "Message" DESCRIPTOR = class a2a.types.AuthenticationInfo Bases: "Message", "Message" DESCRIPTOR = class a2a.types.AuthorizationCodeOAuthFlow Bases: "Message", "Message" DESCRIPTOR = class ScopesEntry Bases: "Message", "Message" DESCRIPTOR = class a2a.types.CancelTaskRequest Bases: "Message", "Message" DESCRIPTOR = class a2a.types.ClientCredentialsOAuthFlow Bases: "Message", "Message" DESCRIPTOR = class ScopesEntry Bases: "Message", "Message" DESCRIPTOR = exception a2a.types.ContentTypeNotSupportedError(message: str | None = None, data: dict | None = None) Bases: "A2AError" Exception raised when the content type is incompatible. message: str = 'Incompatible content types' class a2a.types.DeleteTaskPushNotificationConfigRequest Bases: "Message", "Message" DESCRIPTOR = class a2a.types.DeviceCodeOAuthFlow Bases: "Message", "Message" DESCRIPTOR = class ScopesEntry Bases: "Message", "Message" DESCRIPTOR = exception a2a.types.ExtendedAgentCardNotConfiguredError(message: str | None = None, data: dict | None = None) Bases: "A2AError" Exception raised when the authenticated extended card is not configured. message: str = 'Authenticated Extended Card is not configured' exception a2a.types.ExtensionSupportRequiredError(message: str | None = None, data: dict | None = None) Bases: "A2AError" Exception raised when extension support is required but not present. message: str = 'Extension support required' class a2a.types.GetExtendedAgentCardRequest Bases: "Message", "Message" DESCRIPTOR = class a2a.types.GetTaskPushNotificationConfigRequest Bases: "Message", "Message" DESCRIPTOR = class a2a.types.GetTaskRequest Bases: "Message", "Message" DESCRIPTOR = class a2a.types.HTTPAuthSecurityScheme Bases: "Message", "Message" DESCRIPTOR = class a2a.types.ImplicitOAuthFlow Bases: "Message", "Message" DESCRIPTOR = class ScopesEntry Bases: "Message", "Message" DESCRIPTOR = exception a2a.types.InternalError(message: str | None = None, data: dict | None = None) Bases: "A2AError" Exception raised for internal server errors. message: str = 'Internal error' exception a2a.types.InvalidAgentResponseError(message: str | None = None, data: dict | None = None) Bases: "A2AError" Exception raised when the agent response is invalid. message: str = 'Invalid agent response' exception a2a.types.InvalidParamsError(message: str | None = None, data: dict | None = None) Bases: "A2AError" Exception raised when parameters are invalid. message: str = 'Invalid params' exception a2a.types.InvalidRequestError(message: str | None = None, data: dict | None = None) Bases: "A2AError" Exception raised when the request is invalid. message: str = 'Invalid Request' class a2a.types.ListTaskPushNotificationConfigsRequest Bases: "Message", "Message" DESCRIPTOR = class a2a.types.ListTaskPushNotificationConfigsResponse Bases: "Message", "Message" DESCRIPTOR = class a2a.types.ListTasksRequest Bases: "Message", "Message" DESCRIPTOR = class a2a.types.ListTasksResponse Bases: "Message", "Message" DESCRIPTOR = class a2a.types.Message Bases: "Message", "Message" DESCRIPTOR = exception a2a.types.MethodNotFoundError(message: str | None = None, data: dict | None = None) Bases: "A2AError" Exception raised when a method is not found. message: str = 'Method not found' class a2a.types.MutualTlsSecurityScheme Bases: "Message", "Message" DESCRIPTOR = class a2a.types.OAuth2SecurityScheme Bases: "Message", "Message" DESCRIPTOR = class a2a.types.OAuthFlows Bases: "Message", "Message" DESCRIPTOR = class a2a.types.OpenIdConnectSecurityScheme Bases: "Message", "Message" DESCRIPTOR = class a2a.types.Part Bases: "Message", "Message" DESCRIPTOR = class a2a.types.PasswordOAuthFlow Bases: "Message", "Message" DESCRIPTOR = class ScopesEntry Bases: "Message", "Message" DESCRIPTOR = exception a2a.types.PushNotificationNotSupportedError(message: str | None = None, data: dict | None = None) Bases: "A2AError" Exception raised when push notifications are not supported. message: str = 'Push Notification is not supported' class a2a.types.SecurityRequirement Bases: "Message", "Message" DESCRIPTOR = class SchemesEntry Bases: "Message", "Message" DESCRIPTOR = class a2a.types.SecurityScheme Bases: "Message", "Message" DESCRIPTOR = class a2a.types.SendMessageConfiguration Bases: "Message", "Message" DESCRIPTOR = class a2a.types.SendMessageRequest Bases: "Message", "Message" DESCRIPTOR = class a2a.types.SendMessageResponse Bases: "Message", "Message" DESCRIPTOR = class a2a.types.StreamResponse Bases: "Message", "Message" DESCRIPTOR = class a2a.types.StringList Bases: "Message", "Message" DESCRIPTOR = class a2a.types.SubscribeToTaskRequest Bases: "Message", "Message" DESCRIPTOR = class a2a.types.Task Bases: "Message", "Message" DESCRIPTOR = class a2a.types.TaskArtifactUpdateEvent Bases: "Message", "Message" DESCRIPTOR = exception a2a.types.TaskNotCancelableError(message: str | None = None, data: dict | None = None) Bases: "A2AError" Exception raised when a task cannot be canceled. message: str = 'Task cannot be canceled' exception a2a.types.TaskNotFoundError(message: str | None = None, data: dict | None = None) Bases: "A2AError" Exception raised when a task is not found. message: str = 'Task not found' class a2a.types.TaskPushNotificationConfig Bases: "Message", "Message" DESCRIPTOR = class a2a.types.TaskStatus Bases: "Message", "Message" DESCRIPTOR = class a2a.types.TaskStatusUpdateEvent Bases: "Message", "Message" DESCRIPTOR = exception a2a.types.UnsupportedOperationError(message: str | None = None, data: dict | None = None) Bases: "A2AError" Exception raised when an operation is not supported. message: str = 'This operation is not supported' exception a2a.types.VersionNotSupportedError(message: str | None = None, data: dict | None = None) Bases: "A2AError" Exception raised when the requested version is not supported. message: str = 'Version not supported' a2a.utils.constants module ************************** Constants for well-known URIs used throughout the A2A Python SDK. a2a.utils.constants.DEFAULT_LIST_TASKS_PAGE_SIZE = 50 Default page size for the *tasks/list* method. a2a.utils.constants.MAX_LIST_TASKS_PAGE_SIZE = 100 Maximum page size for the *tasks/list* method. class a2a.utils.constants.TransportProtocol(*values) Bases: "str", "Enum" Transport protocol string constants. GRPC = 'GRPC' HTTP_JSON = 'HTTP+JSON' JSONRPC = 'JSONRPC' a2a.utils.error_handlers module ******************************* a2a.utils.error_handlers.build_error_details(error: A2AError) -> list[dict[str, Any]] Build the typed-details array for an "A2AError". Always emits a leading "google.rpc.ErrorInfo" carrying the A2A reason and "error.data" as "metadata". For *InvalidParamsError* whose "data" contains an "errors" list of validation details, also appends a "google.rpc.BadRequest" so all transports surface field- level violations identically. a2a.utils.error_handlers.build_rest_error_payload(error: Exception) -> dict[str, Any] Build a REST error payload dict from an exception. Returns: A dict with the error payload in the standard REST error format. a2a.utils.error_handlers.rest_error_handler(func: Callable[[...], Awaitable[Response]]) -> Callable[[...], Awaitable[Response]] Decorator to catch A2AError and map it to an appropriate JSONResponse. a2a.utils.error_handlers.rest_stream_error_handler(func: Callable[[...], Coroutine[Any, Any, Any]]) -> Callable[[...], Coroutine[Any, Any, Any]] Decorator to catch A2AError for a streaming method. Maps synchronous errors to JSONResponse and logs streaming errors. a2a.utils.errors module *********************** Custom exceptions and error types for A2A server-side errors. This module contains A2A-specific error codes, as well as server exception classes. class a2a.utils.errors.ErrorMapping(http_code: int, grpc_status: str, reason: str) Bases: "NamedTuple" Named tuple mapping HTTP status, gRPC status, and reason strings. grpc_status: str Alias for field number 1 http_code: int Alias for field number 0 reason: str Alias for field number 2 exception a2a.utils.errors.ExtensionSupportRequiredError(message: str | None = None, data: dict | None = None) Bases: "A2AError" Exception raised when extension support is required but not present. message: str = 'Extension support required' exception a2a.utils.errors.InternalError(message: str | None = None, data: dict | None = None) Bases: "A2AError" Exception raised for internal server errors. message: str = 'Internal error' exception a2a.utils.errors.InvalidAgentResponseError(message: str | None = None, data: dict | None = None) Bases: "A2AError" Exception raised when the agent response is invalid. message: str = 'Invalid agent response' exception a2a.utils.errors.InvalidParamsError(message: str | None = None, data: dict | None = None) Bases: "A2AError" Exception raised when parameters are invalid. message: str = 'Invalid params' exception a2a.utils.errors.InvalidRequestError(message: str | None = None, data: dict | None = None) Bases: "A2AError" Exception raised when the request is invalid. message: str = 'Invalid Request' exception a2a.utils.errors.JSONParseError(message: str | None = None, data: dict | None = None) Bases: "A2AError" Exception raised when invalid JSON was received by the server. message: str = 'Invalid JSON payload' exception a2a.utils.errors.MethodNotFoundError(message: str | None = None, data: dict | None = None) Bases: "A2AError" Exception raised when a method is not found. message: str = 'Method not found' exception a2a.utils.errors.PushNotificationNotSupportedError(message: str | None = None, data: dict | None = None) Bases: "A2AError" Exception raised when push notifications are not supported. message: str = 'Push Notification is not supported' exception a2a.utils.errors.TaskNotCancelableError(message: str | None = None, data: dict | None = None) Bases: "A2AError" Exception raised when a task cannot be canceled. message: str = 'Task cannot be canceled' exception a2a.utils.errors.TaskNotFoundError(message: str | None = None, data: dict | None = None) Bases: "A2AError" Exception raised when a task is not found. message: str = 'Task not found' exception a2a.utils.errors.UnsupportedOperationError(message: str | None = None, data: dict | None = None) Bases: "A2AError" Exception raised when an operation is not supported. message: str = 'This operation is not supported' exception a2a.utils.errors.VersionNotSupportedError(message: str | None = None, data: dict | None = None) Bases: "A2AError" Exception raised when the requested version is not supported. message: str = 'Version not supported' a2a.utils.json_utils module *************************** JSON serialization helpers for the A2A Python SDK. a2a.utils.json_utils.dumps(obj: Any) -> str Serialize "obj" to a JSON-formatted "str" with UTF-8 defaults. Use this in SSE/streaming code paths where payloads are serialized manually before being written to the wire. Unary HTTP responses do not need it because Starlette's "JSONResponse.render" already calls "json.dumps(content, ensure_ascii=False, ...)" internally; this helper makes the streaming paths behave identically so non-ASCII characters (CJK, emoji, etc.) reach clients as raw UTF-8 rather than escape sequences. a2a.utils.proto_utils module **************************** Utilities for working with proto types. This module provides helper functions for common proto type operations. class a2a.utils.proto_utils.ValidationDetail Bases: "TypedDict" Structured validation error detail. field: str message: str a2a.utils.proto_utils.bad_request_to_validation_errors(bad_request: BadRequest) -> list[ValidationDetail] Convert a gRPC BadRequest proto to validation error details. a2a.utils.proto_utils.make_dict_serializable(value: Any) -> Any Dict pre-processing utility: converts non-serializable values to serializable form. Use this when you want to normalize a dictionary before dict->Struct conversion. Parameters: **value** -- The value to convert. Returns: A serializable value. a2a.utils.proto_utils.normalize_large_integers_to_strings(value: Any, max_safe_digits: int = 15) -> Any Integer preprocessing utility: converts large integers to strings. Use this when you want to convert large integers to strings considering JavaScript's MAX_SAFE_INTEGER (2^53 - 1) limitation. Parameters: * **value** -- The value to convert. * **max_safe_digits** -- Maximum safe integer digits (default: 15). Returns: A normalized value. a2a.utils.proto_utils.parse_params(params: QueryParams, message: Message) -> None Converts REST query parameters back into a Protobuf message. Handles A2A-specific pre-processing before calling ParseDict: - Booleans: 'true'/'false' -> True/False - Repeated: Supports BOTH repeated keys and comma-separated values. - Others: Handles string->enum/timestamp/number conversion via ParseDict. See also: https://a2a-protocol.org/latest/specification/#115-query- parameter-naming-for-request-parameters a2a.utils.proto_utils.parse_string_integers_in_dict(value: Any, max_safe_digits: int = 15) -> Any String post-processing utility: converts large integer strings back to integers. Use this when you want to restore large integer strings to integers after Struct->dict conversion. Parameters: * **value** -- The value to convert. * **max_safe_digits** -- Maximum safe integer digits (default: 15). Returns: A parsed value. a2a.utils.proto_utils.to_stream_response(event: Message | Task | TaskStatusUpdateEvent | TaskArtifactUpdateEvent) -> StreamResponse Convert internal Event to StreamResponse proto. Parameters: **event** -- The event (Task, Message, TaskStatusUpdateEvent, TaskArtifactUpdateEvent) Returns: A StreamResponse proto with the appropriate field set. a2a.utils.proto_utils.validate_proto_required_fields(msg: Message) -> None Validate that all fields marked as REQUIRED are present on the proto message. Parameters: **msg** -- The Protobuf message to validate. Raises: **InvalidParamsError** -- If a required field is missing or empty. a2a.utils.proto_utils.validation_errors_to_bad_request(errors: list[ValidationDetail]) -> BadRequest Convert validation error details to a gRPC BadRequest proto. a2a.utils.signing module ************************ exception a2a.utils.signing.InvalidSignaturesError Bases: "SignatureVerificationError" Exception raised when all signatures are invalid. exception a2a.utils.signing.NoSignatureError Bases: "SignatureVerificationError" Exception raised when no signature is found on an AgentCard. class a2a.utils.signing.ProtectedHeader Bases: "TypedDict" Protected header parameters for JWS (JSON Web Signature). alg: str | None Algorithm used for signing. jku: str | None JSON Web Key Set URL. kid: str Key identifier. typ: str | None Token type. Best practice: SHOULD be "JOSE" for JWS tokens. exception a2a.utils.signing.SignatureVerificationError Bases: "Exception" Base exception for signature verification errors. a2a.utils.signing.create_agent_card_signer(signing_key: PyJWK | str | bytes, protected_header: ProtectedHeader, header: dict[str, Any] | None = None) -> Callable[[AgentCard], AgentCard] Creates a function that signs an AgentCard and adds the signature. Parameters: * **signing_key** -- The private key for signing. * **protected_header** -- The protected header parameters. * **header** -- Unprotected header parameters. Returns: A callable that takes an AgentCard and returns the modified AgentCard with a signature. a2a.utils.signing.create_signature_verifier(key_provider: Callable[[str | None, str | None], PyJWK | str | bytes], algorithms: list[str]) -> Callable[[AgentCard], None] Creates a function that verifies the signatures on an AgentCard. The verifier succeeds if at least one signature is valid. Otherwise, it raises an error. Parameters: * **key_provider** -- A callable that accepts a key ID (kid) and a JWK Set URL (jku) and returns the verification key. This function is responsible for fetching the correct key for a given signature. * **algorithms** -- A list of acceptable algorithms (e.g., ['ES256', 'RS256']) for verification used to prevent algorithm confusion attacks. Returns: A function that takes an AgentCard as input, and raises an error if none of the signatures are valid. a2a.utils.task module ********************* Utility functions for creating A2A Task objects. class a2a.utils.task.HistoryLengthConfig(*args, **kwargs) Bases: "Protocol" Protocol for configuration arguments containing history_length field. HasField(field_name: Literal['history_length']) -> bool Checks if a field is set. This method name matches the generated Protobuf code. history_length: int a2a.utils.task.apply_history_length(task: Task, config: HistoryLengthConfig | None) -> Task Applies history_length parameter on task and returns a new task object. Parameters: * **task** -- The original task object with complete history * **config** -- Configuration object containing 'history_length' field and HasField method. Returns: A new task object with limited history See also: https://a2a-protocol.org/latest/specification/#324-history- length-semantics a2a.utils.task.decode_page_token(page_token: str) -> str Decodes page token for tasks pagination. Parameters: **page_token** -- The encoded page token. Returns: The decoded task ID. a2a.utils.task.encode_page_token(task_id: str) -> str Encodes page token for tasks pagination. Parameters: **task_id** -- The ID of the task. Returns: The encoded page token. a2a.utils.task.validate_history_length(config: HistoryLengthConfig | None) -> None Validates that history_length is non-negative. a2a.utils.task.validate_page_size(page_size: int) -> None Validates that page_size is in range [1, 100]. See also: https://a2a-protocol.org/latest/specification/#314-list-tasks a2a.utils.telemetry module ************************** OpenTelemetry Tracing Utilities for A2A Python SDK. This module provides decorators to simplify the integration of OpenTelemetry tracing into Python applications. It offers *trace_function* for instrumenting individual functions (both synchronous and asynchronous) and *trace_class* for instrumenting multiple methods within a class. The tracer is initialized with the module name and version defined by *INSTRUMENTING_MODULE_NAME* ('a2a-python-sdk') and *INSTRUMENTING_MODULE_VERSION* ('1.0.0'). Features: - Automatic span creation for decorated functions/methods. - Support for both synchronous and asynchronous functions. - Default span naming based on module and function/class/method name. - Customizable span names, kinds, and static attributes. - Dynamic attribute setting via an *attribute_extractor* callback. - Automatic recording of exceptions and setting of span status. - Selective method tracing in classes using include/exclude lists. Configuration: - Environment Variable Control: OpenTelemetry instrumentation can be disabled using the *OTEL_INSTRUMENTATION_A2A_SDK_ENABLED* environment variable. * Default: *true* (tracing enabled when OpenTelemetry is installed) * To disable: Set *OTEL_INSTRUMENTATION_A2A_SDK_ENABLED=false* * Case insensitive: 'true', 'True', 'TRUE' all enable tracing * Any other value disables tracing and logs a debug message Usage: For a single function: >>``<<>>`<>``<<>>`<< For a class: >>``<<>>`<>``<<>>`<< class a2a.utils.telemetry.SpanKind(*values) Bases: "Enum" Specifies additional details on how this span relates to its parent span. Note that this enumeration is experimental and likely to change. See https://github.com/open-telemetry/opentelemetry- specification/pull/226. CLIENT = 2 Indicates that the span describes a request to some remote service. CONSUMER = 4 Indicates that the span describes a consumer receiving a message from a broker. Unlike client and server, there is usually no direct critical path latency relationship between producer and consumer spans. INTERNAL = 0 PRODUCER = 3 Indicates that the span describes a producer sending a message to a broker. Unlike client and server, there is usually no direct critical path latency relationship between producer and consumer spans. SERVER = 1 a2a.utils package ***************** Submodules ========== * a2a.utils.constants module * "DEFAULT_LIST_TASKS_PAGE_SIZE" * "MAX_LIST_TASKS_PAGE_SIZE" * "TransportProtocol" * "TransportProtocol.GRPC" * "TransportProtocol.HTTP_JSON" * "TransportProtocol.JSONRPC" * a2a.utils.error_handlers module * "build_error_details()" * "build_rest_error_payload()" * "rest_error_handler()" * "rest_stream_error_handler()" * a2a.utils.errors module * "ErrorMapping" * "ErrorMapping.grpc_status" * "ErrorMapping.http_code" * "ErrorMapping.reason" * "ExtensionSupportRequiredError" * "ExtensionSupportRequiredError.message" * "InternalError" * "InternalError.message" * "InvalidAgentResponseError" * "InvalidAgentResponseError.message" * "InvalidParamsError" * "InvalidParamsError.message" * "InvalidRequestError" * "InvalidRequestError.message" * "JSONParseError" * "JSONParseError.message" * "MethodNotFoundError" * "MethodNotFoundError.message" * "PushNotificationNotSupportedError" * "PushNotificationNotSupportedError.message" * "TaskNotCancelableError" * "TaskNotCancelableError.message" * "TaskNotFoundError" * "TaskNotFoundError.message" * "UnsupportedOperationError" * "UnsupportedOperationError.message" * "VersionNotSupportedError" * "VersionNotSupportedError.message" * a2a.utils.json_utils module * "dumps()" * a2a.utils.proto_utils module * "ValidationDetail" * "ValidationDetail.field" * "ValidationDetail.message" * "bad_request_to_validation_errors()" * "make_dict_serializable()" * "normalize_large_integers_to_strings()" * "parse_params()" * "parse_string_integers_in_dict()" * "to_stream_response()" * "validate_proto_required_fields()" * "validation_errors_to_bad_request()" * a2a.utils.signing module * "InvalidSignaturesError" * "NoSignatureError" * "ProtectedHeader" * "ProtectedHeader.alg" * "ProtectedHeader.jku" * "ProtectedHeader.kid" * "ProtectedHeader.typ" * "SignatureVerificationError" * "create_agent_card_signer()" * "create_signature_verifier()" * a2a.utils.task module * "HistoryLengthConfig" * "HistoryLengthConfig.HasField()" * "HistoryLengthConfig.history_length" * "apply_history_length()" * "decode_page_token()" * "encode_page_token()" * "validate_history_length()" * "validate_page_size()" * a2a.utils.telemetry module * "SpanKind" * "SpanKind.CLIENT" * "SpanKind.CONSUMER" * "SpanKind.INTERNAL" * "SpanKind.PRODUCER" * "SpanKind.SERVER" * a2a.utils.version_validator module * "validate_version()" Module contents =============== Utility functions for the A2A Python SDK. class a2a.utils.TransportProtocol(*values) Bases: "str", "Enum" Transport protocol string constants. GRPC = 'GRPC' HTTP_JSON = 'HTTP+JSON' JSONRPC = 'JSONRPC' a2a.utils.to_stream_response(event: Message | Task | TaskStatusUpdateEvent | TaskArtifactUpdateEvent) -> StreamResponse Convert internal Event to StreamResponse proto. Parameters: **event** -- The event (Task, Message, TaskStatusUpdateEvent, TaskArtifactUpdateEvent) Returns: A StreamResponse proto with the appropriate field set. a2a.utils.version_validator module ********************************** General utility functions for the A2A Python SDK. a2a.utils.version_validator.validate_version(expected_version: str) -> Callable[[F], F] Decorator that validates the A2A-Version header in the request context. The header name is defined by *constants.VERSION_HEADER* ('A2A- Version'). If the header is missing or empty, it is interpreted as *constants.PROTOCOL_VERSION_0_3* ('0.3'). If the version in the header does not match the *expected_version* (major and minor parts), a *VersionNotSupportedError* is raised. Patch version is ignored. This decorator supports both async methods and async generator methods. It expects a *ServerCallContext* to be present either in the arguments or keyword arguments of the decorated method. Parameters: **expected_version** -- The A2A protocol version string expected by the method. Returns: The decorated function. Raises: **VersionNotSupportedError** -- If the version in the request does not match *expected_version*. A2A Python SDK Reference ************************ This page contains the SDK documentation for the "a2a-sdk" Python package. pip install a2a-sdk * a2a * a2a package * Subpackages * a2a.auth package * a2a.client package * a2a.compat package * a2a.extensions package * a2a.helpers package * a2a.migrations package * a2a.server package * a2a.types package * a2a.utils package * Submodules * a2a.a2a_db_cli module * Module contents a2a *** * a2a package * Subpackages * a2a.auth package * Submodules * Module contents * a2a.client package * Subpackages * Submodules * Module contents * a2a.compat package * Subpackages * Module contents * a2a.extensions package * Submodules * Module contents * a2a.helpers package * Submodules * Module contents * a2a.migrations package * Subpackages * Submodules * Module contents * a2a.server package * Subpackages * Submodules * Module contents * a2a.types package * Submodules * Module contents * a2a.utils package * Submodules * Module contents * Submodules * a2a.a2a_db_cli module * "create_parser()" * "run_migrations()" * Module contents // Older protoc compilers don't understand edition yet. syntax = "proto3"; package lf.a2a.v1; import "google/api/annotations.proto"; import "google/api/client.proto"; import "google/api/field_behavior.proto"; import "google/protobuf/empty.proto"; import "google/protobuf/struct.proto"; import "google/protobuf/timestamp.proto"; option csharp_namespace = "Lf.A2a.V1"; option go_package = "google.golang.org/lf/a2a/v1"; option java_multiple_files = true; option java_outer_classname = "A2A"; option java_package = "com.google.lf.a2a.v1"; // Provides operations for interacting with agents using the A2A protocol. service A2AService { // Sends a message to an agent. rpc SendMessage(SendMessageRequest) returns (SendMessageResponse) { option (google.api.http) = { post: "/message:send" body: "*" additional_bindings: { post: "/{tenant}/message:send" body: "*" } }; } // Sends a streaming message to an agent, allowing for real-time interaction and status updates. // Streaming version of `SendMessage` rpc SendStreamingMessage(SendMessageRequest) returns (stream StreamResponse) { option (google.api.http) = { post: "/message:stream" body: "*" additional_bindings: { post: "/{tenant}/message:stream" body: "*" } }; } // Gets the latest state of a task. rpc GetTask(GetTaskRequest) returns (Task) { option (google.api.http) = { get: "/tasks/{id=*}" additional_bindings: { get: "/{tenant}/tasks/{id=*}" } }; option (google.api.method_signature) = "id"; } // Lists tasks that match the specified filter. rpc ListTasks(ListTasksRequest) returns (ListTasksResponse) { option (google.api.http) = { get: "/tasks" additional_bindings: { get: "/{tenant}/tasks" } }; } // Cancels a task in progress. rpc CancelTask(CancelTaskRequest) returns (Task) { option (google.api.http) = { post: "/tasks/{id=*}:cancel" body: "*" additional_bindings: { post: "/{tenant}/tasks/{id=*}:cancel" body: "*" } }; } // Subscribes to task updates for tasks not in a terminal state. // Returns `UnsupportedOperationError` if the task is already in a terminal state (completed, failed, canceled, rejected). rpc SubscribeToTask(SubscribeToTaskRequest) returns (stream StreamResponse) { option (google.api.http) = { get: "/tasks/{id=*}:subscribe" additional_bindings: { get: "/{tenant}/tasks/{id=*}:subscribe" } }; } // (-- api-linter: client-libraries::4232::required-fields=disabled // api-linter: core::0133::method-signature=disabled // api-linter: core::0133::request-message-name=disabled // aip.dev/not-precedent: method_signature preserved for backwards compatibility --) // Creates a push notification config for a task. rpc CreateTaskPushNotificationConfig(TaskPushNotificationConfig) returns (TaskPushNotificationConfig) { option (google.api.http) = { post: "/tasks/{task_id=*}/pushNotificationConfigs" body: "*" additional_bindings: { post: "/{tenant}/tasks/{task_id=*}/pushNotificationConfigs" body: "*" } }; option (google.api.method_signature) = "task_id,config"; } // Gets a push notification config for a task. rpc GetTaskPushNotificationConfig(GetTaskPushNotificationConfigRequest) returns (TaskPushNotificationConfig) { option (google.api.http) = { get: "/tasks/{task_id=*}/pushNotificationConfigs/{id=*}" additional_bindings: { get: "/{tenant}/tasks/{task_id=*}/pushNotificationConfigs/{id=*}" } }; option (google.api.method_signature) = "task_id,id"; } // Get a list of push notifications configured for a task. rpc ListTaskPushNotificationConfigs(ListTaskPushNotificationConfigsRequest) returns (ListTaskPushNotificationConfigsResponse) { option (google.api.http) = { get: "/tasks/{task_id=*}/pushNotificationConfigs" additional_bindings: { get: "/{tenant}/tasks/{task_id=*}/pushNotificationConfigs" } }; option (google.api.method_signature) = "task_id"; } // Gets the extended agent card for the authenticated agent. rpc GetExtendedAgentCard(GetExtendedAgentCardRequest) returns (AgentCard) { option (google.api.http) = { get: "/extendedAgentCard" additional_bindings: { get: "/{tenant}/extendedAgentCard" } }; } // Deletes a push notification config for a task. rpc DeleteTaskPushNotificationConfig(DeleteTaskPushNotificationConfigRequest) returns (google.protobuf.Empty) { option (google.api.http) = { delete: "/tasks/{task_id=*}/pushNotificationConfigs/{id=*}" additional_bindings: { delete: "/{tenant}/tasks/{task_id=*}/pushNotificationConfigs/{id=*}" } }; option (google.api.method_signature) = "task_id,id"; } } // Configuration of a send message request. message SendMessageConfiguration { // A list of media types the client is prepared to accept for response parts. // Agents SHOULD use this to tailor their output. repeated string accepted_output_modes = 1; // Configuration for the agent to send push notifications for task updates. // Task id should be empty when sending this configuration in a `SendMessage` request. TaskPushNotificationConfig task_push_notification_config = 2; // The maximum number of most recent messages from the task's history to retrieve in // the response. An unset value means the client does not impose any limit. A // value of zero is a request to not include any messages. The server MUST NOT // return more messages than the provided value, but MAY apply a lower limit. optional int32 history_length = 3; // If `true`, the operation returns immediately after creating the task, // even if processing is still in progress. // If `false` (default), the operation MUST wait until the task reaches a // terminal (`COMPLETED`, `FAILED`, `CANCELED`, `REJECTED`) or interrupted // (`INPUT_REQUIRED`, `AUTH_REQUIRED`) state before returning. bool return_immediately = 4; } // `Task` is the core unit of action for A2A. It has a current status // and when results are created for the task they are stored in the // artifact. If there are multiple turns for a task, these are stored in // history. message Task { // Unique identifier (e.g. UUID) for the task, generated by the server for a // new task. string id = 1 [(google.api.field_behavior) = REQUIRED]; // Unique identifier (e.g. UUID) for the contextual collection of interactions // (tasks and messages). string context_id = 2; // The current status of a `Task`, including `state` and a `message`. TaskStatus status = 3 [(google.api.field_behavior) = REQUIRED]; // A set of output artifacts for a `Task`. repeated Artifact artifacts = 4; // protolint:disable REPEATED_FIELD_NAMES_PLURALIZED // The history of interactions from a `Task`. repeated Message history = 5; // protolint:enable REPEATED_FIELD_NAMES_PLURALIZED // A key/value object to store custom metadata about a task. google.protobuf.Struct metadata = 6; } // Defines the possible lifecycle states of a `Task`. enum TaskState { // The task is in an unknown or indeterminate state. TASK_STATE_UNSPECIFIED = 0; // Indicates that a task has been successfully submitted and acknowledged. TASK_STATE_SUBMITTED = 1; // Indicates that a task is actively being processed by the agent. TASK_STATE_WORKING = 2; // Indicates that a task has finished successfully. This is a terminal state. TASK_STATE_COMPLETED = 3; // Indicates that a task has finished with an error. This is a terminal state. TASK_STATE_FAILED = 4; // Indicates that a task was canceled before completion. This is a terminal state. TASK_STATE_CANCELED = 5; // Indicates that the agent requires additional user input to proceed. This is an interrupted state. TASK_STATE_INPUT_REQUIRED = 6; // Indicates that the agent has decided to not perform the task. // This may be done during initial task creation or later once an agent // has determined it can't or won't proceed. This is a terminal state. TASK_STATE_REJECTED = 7; // Indicates that authentication is required to proceed. This is an interrupted state. TASK_STATE_AUTH_REQUIRED = 8; } // A container for the status of a task message TaskStatus { // The current state of this task. TaskState state = 1 [(google.api.field_behavior) = REQUIRED]; // A message associated with the status. Message message = 2; // ISO 8601 Timestamp when the status was recorded. // Example: "2023-10-27T10:00:00Z" google.protobuf.Timestamp timestamp = 3; } // `Part` represents a container for a section of communication content. // Parts can be purely textual, some sort of file (image, video, etc) or // a structured data blob (i.e. JSON). message Part { oneof content { // The string content of the `text` part. string text = 1; // The `raw` byte content of a file. In JSON serialization, this is encoded as a base64 string. bytes raw = 2; // A `url` pointing to the file's content. string url = 3; // Arbitrary structured `data` as a JSON value (object, array, string, number, boolean, or null). google.protobuf.Value data = 4; } // Optional. metadata associated with this part. google.protobuf.Struct metadata = 5; // An optional `filename` for the file (e.g., "document.pdf"). string filename = 6; // The `media_type` (MIME type) of the part content (e.g., "text/plain", "application/json", "image/png"). // This field is available for all part types. string media_type = 7; } // Defines the sender of a message in A2A protocol communication. enum Role { // The role is unspecified. ROLE_UNSPECIFIED = 0; // The message is from the client to the server. ROLE_USER = 1; // The message is from the server to the client. ROLE_AGENT = 2; } // `Message` is one unit of communication between client and server. It can be // associated with a context and/or a task. For server messages, `context_id` must // be provided, and `task_id` only if a task was created. For client messages, both // fields are optional, with the caveat that if both are provided, they have to // match (the `context_id` has to be the one that is set on the task). If only // `task_id` is provided, the server will infer `context_id` from it. message Message { // The unique identifier (e.g. UUID) of the message. This is created by the message creator. string message_id = 1 [(google.api.field_behavior) = REQUIRED]; // Optional. The context id of the message. If set, the message will be associated with the given context. string context_id = 2; // Optional. The task id of the message. If set, the message will be associated with the given task. string task_id = 3; // Identifies the sender of the message. Role role = 4 [(google.api.field_behavior) = REQUIRED]; // Parts is the container of the message content. repeated Part parts = 5 [(google.api.field_behavior) = REQUIRED]; // Optional. Any metadata to provide along with the message. google.protobuf.Struct metadata = 6; // The URIs of extensions that are present or contributed to this Message. repeated string extensions = 7; // A list of task IDs that this message references for additional context. repeated string reference_task_ids = 8; } // Artifacts represent task outputs. message Artifact { // Unique identifier (e.g. UUID) for the artifact. It must be unique within a task. string artifact_id = 1 [(google.api.field_behavior) = REQUIRED]; // A human readable name for the artifact. string name = 2; // Optional. A human readable description of the artifact. string description = 3; // The content of the artifact. Must contain at least one part. repeated Part parts = 4 [(google.api.field_behavior) = REQUIRED]; // Optional. Metadata included with the artifact. google.protobuf.Struct metadata = 5; // The URIs of extensions that are present or contributed to this Artifact. repeated string extensions = 6; } // An event sent by the agent to notify the client of a change in a task's status. message TaskStatusUpdateEvent { // The ID of the task that has changed. string task_id = 1 [(google.api.field_behavior) = REQUIRED]; // The ID of the context that the task belongs to. string context_id = 2 [(google.api.field_behavior) = REQUIRED]; // The new status of the task. TaskStatus status = 3 [(google.api.field_behavior) = REQUIRED]; // Optional. Metadata associated with the task update. google.protobuf.Struct metadata = 4; } // A task delta where an artifact has been generated. message TaskArtifactUpdateEvent { // The ID of the task for this artifact. string task_id = 1 [(google.api.field_behavior) = REQUIRED]; // The ID of the context that this task belongs to. string context_id = 2 [(google.api.field_behavior) = REQUIRED]; // The artifact that was generated or updated. Artifact artifact = 3 [(google.api.field_behavior) = REQUIRED]; // If true, the content of this artifact should be appended to a previously // sent artifact with the same ID. bool append = 4; // If true, this is the final chunk of the artifact. bool last_chunk = 5; // Optional. Metadata associated with the artifact update. google.protobuf.Struct metadata = 6; } // Defines authentication details, used for push notifications. message AuthenticationInfo { // HTTP Authentication Scheme from the [IANA registry](https://www.iana.org/assignments/http-authschemes/). // Examples: `Bearer`, `Basic`, `Digest`. // Scheme names are case-insensitive per [RFC 9110 Section 11.1](https://www.rfc-editor.org/rfc/rfc9110#section-11.1). string scheme = 1 [(google.api.field_behavior) = REQUIRED]; // Push Notification credentials. Format depends on the scheme (e.g., token for Bearer). string credentials = 2; } // Declares a combination of a target URL, transport and protocol version for interacting with the agent. // This allows agents to expose the same functionality over multiple protocol binding mechanisms. message AgentInterface { // The URL where this interface is available. Must be a valid absolute HTTPS URL in production. // Example: "https://api.example.com/a2a/v1", "https://grpc.example.com/a2a" string url = 1 [(google.api.field_behavior) = REQUIRED]; // The protocol binding supported at this URL. This is an open form string, to be // easily extended for other protocol bindings. The core ones officially // supported are `JSONRPC`, `GRPC` and `HTTP+JSON`. string protocol_binding = 2 [(google.api.field_behavior) = REQUIRED]; // Optional. An opaque string used for routing requests to a specific agent // or tenant when multiple agents are served behind a single A2A endpoint. // When set, clients MUST include this value in the `tenant` field of all // request messages sent to this interface. The server is responsible for // interpreting the value and routing requests accordingly; the protocol // does not define its format or semantics. string tenant = 3; // The version of the A2A protocol this interface exposes. // Use the latest supported minor version per major version. // Examples: "0.3", "1.0" string protocol_version = 4 [(google.api.field_behavior) = REQUIRED]; } // A self-describing manifest for an agent. It provides essential // metadata including the agent's identity, capabilities, skills, supported // communication methods, and security requirements. // Next ID: 20 message AgentCard { // A human readable name for the agent. // Example: "Recipe Agent" string name = 1 [(google.api.field_behavior) = REQUIRED]; // A human-readable description of the agent, assisting users and other agents // in understanding its purpose. // Example: "Agent that helps users with recipes and cooking." string description = 2 [(google.api.field_behavior) = REQUIRED]; // Ordered list of supported interfaces. The first entry is preferred. repeated AgentInterface supported_interfaces = 3 [(google.api.field_behavior) = REQUIRED]; // The service provider of the agent. AgentProvider provider = 4; // The version of the agent. // Example: "1.0.0" string version = 5 [(google.api.field_behavior) = REQUIRED]; // A URL providing additional documentation about the agent. optional string documentation_url = 6; // A2A Capability set supported by the agent. AgentCapabilities capabilities = 7 [(google.api.field_behavior) = REQUIRED]; // The security scheme details used for authenticating with this agent. map security_schemes = 8; // Security requirements for contacting the agent. repeated SecurityRequirement security_requirements = 9; // protolint:enable REPEATED_FIELD_NAMES_PLURALIZED // The set of interaction modes that the agent supports across all skills. // This can be overridden per skill. Defined as media types. repeated string default_input_modes = 10 [(google.api.field_behavior) = REQUIRED]; // The media types supported as outputs from this agent. repeated string default_output_modes = 11 [(google.api.field_behavior) = REQUIRED]; // Skills represent the abilities of an agent. // It is largely a descriptive concept but represents a more focused set of behaviors that the // agent is likely to succeed at. repeated AgentSkill skills = 12 [(google.api.field_behavior) = REQUIRED]; // JSON Web Signatures computed for this `AgentCard`. repeated AgentCardSignature signatures = 13; // Optional. A URL to an icon for the agent. optional string icon_url = 14; } // Represents the service provider of an agent. message AgentProvider { // A URL for the agent provider's website or relevant documentation. // Example: "https://ai.google.dev" string url = 1 [(google.api.field_behavior) = REQUIRED]; // The name of the agent provider's organization. // Example: "Google" string organization = 2 [(google.api.field_behavior) = REQUIRED]; } // Defines optional capabilities supported by an agent. message AgentCapabilities { // Indicates if the agent supports streaming responses. optional bool streaming = 1; // Indicates if the agent supports sending push notifications for asynchronous task updates. optional bool push_notifications = 2; // A list of protocol extensions supported by the agent. repeated AgentExtension extensions = 3; // Indicates if the agent supports providing an extended agent card when authenticated. optional bool extended_agent_card = 4; } // A declaration of a protocol extension supported by an Agent. message AgentExtension { // The unique URI identifying the extension. string uri = 1; // A human-readable description of how this agent uses the extension. string description = 2; // If true, the client must understand and comply with the extension's requirements. bool required = 3; // Optional. Extension-specific configuration parameters. google.protobuf.Struct params = 4; } // Represents a distinct capability or function that an agent can perform. message AgentSkill { // A unique identifier for the agent's skill. string id = 1 [(google.api.field_behavior) = REQUIRED]; // A human-readable name for the skill. string name = 2 [(google.api.field_behavior) = REQUIRED]; // A detailed description of the skill. string description = 3 [(google.api.field_behavior) = REQUIRED]; // A set of keywords describing the skill's capabilities. repeated string tags = 4 [(google.api.field_behavior) = REQUIRED]; // Example prompts or scenarios that this skill can handle. repeated string examples = 5; // The set of supported input media types for this skill, overriding the agent's defaults. repeated string input_modes = 6; // The set of supported output media types for this skill, overriding the agent's defaults. repeated string output_modes = 7; // Security schemes necessary for this skill. repeated SecurityRequirement security_requirements = 8; } // AgentCardSignature represents a JWS signature of an AgentCard. // This follows the JSON format of an RFC 7515 JSON Web Signature (JWS). message AgentCardSignature { // (-- api-linter: core::0140::reserved-words=disabled // aip.dev/not-precedent: Backwards compatibility --) // Required. The protected JWS header for the signature. This is always a // base64url-encoded JSON object. string protected = 1 [(google.api.field_behavior) = REQUIRED]; // Required. The computed signature, base64url-encoded. string signature = 2 [(google.api.field_behavior) = REQUIRED]; // The unprotected JWS header values. google.protobuf.Struct header = 3; } // A container associating a push notification configuration with a specific task. message TaskPushNotificationConfig { // Optional. Opaque routing identifier. Must match the `tenant` value from // the selected `AgentInterface` in the Agent Card when that field is set. string tenant = 1; // The push notification configuration details. // A unique identifier (e.g. UUID) for this push notification configuration. string id = 2; // The ID of the task this configuration is associated with. string task_id = 3; // The URL where the notification should be sent. string url = 4 [(google.api.field_behavior) = REQUIRED]; // A token unique for this task or session. string token = 5; // Authentication information required to send the notification. AuthenticationInfo authentication = 6; } // protolint:disable REPEATED_FIELD_NAMES_PLURALIZED // A list of strings. message StringList { // The individual string values. repeated string list = 1; } // protolint:enable REPEATED_FIELD_NAMES_PLURALIZED // Defines the security requirements for an agent. message SecurityRequirement { // A map of security schemes to the required scopes. map schemes = 1; } // Defines a security scheme that can be used to secure an agent's endpoints. // This is a discriminated union type based on the OpenAPI 3.2 Security Scheme Object. // See: https://spec.openapis.org/oas/v3.2.0.html#security-scheme-object message SecurityScheme { oneof scheme { // API key-based authentication. APIKeySecurityScheme api_key_security_scheme = 1; // HTTP authentication (Basic, Bearer, etc.). HTTPAuthSecurityScheme http_auth_security_scheme = 2; // OAuth 2.0 authentication. OAuth2SecurityScheme oauth2_security_scheme = 3; // OpenID Connect authentication. OpenIdConnectSecurityScheme open_id_connect_security_scheme = 4; // Mutual TLS authentication. MutualTlsSecurityScheme mtls_security_scheme = 5; } } // Defines a security scheme using an API key. message APIKeySecurityScheme { // An optional description for the security scheme. string description = 1; // The location of the API key. Valid values are "query", "header", or "cookie". string location = 2 [(google.api.field_behavior) = REQUIRED]; // The name of the header, query, or cookie parameter to be used. string name = 3 [(google.api.field_behavior) = REQUIRED]; } // Defines a security scheme using HTTP authentication. message HTTPAuthSecurityScheme { // An optional description for the security scheme. string description = 1; // The name of the HTTP Authentication scheme to be used in the Authorization header, // as defined in RFC7235 (e.g., "Bearer"). // This value should be registered in the IANA Authentication Scheme registry. string scheme = 2 [(google.api.field_behavior) = REQUIRED]; // A hint to the client to identify how the bearer token is formatted (e.g., "JWT"). // Primarily for documentation purposes. string bearer_format = 3; } // Defines a security scheme using OAuth 2.0. message OAuth2SecurityScheme { // An optional description for the security scheme. string description = 1; // An object containing configuration information for the supported OAuth 2.0 flows. OAuthFlows flows = 2 [(google.api.field_behavior) = REQUIRED]; // URL to the OAuth2 authorization server metadata [RFC 8414](https://datatracker.ietf.org/doc/html/rfc8414). // TLS is required. string oauth2_metadata_url = 3; } // Defines a security scheme using OpenID Connect. message OpenIdConnectSecurityScheme { // An optional description for the security scheme. string description = 1; // The [OpenID Connect Discovery URL](https://openid.net/specs/openid-connect-discovery-1_0.html) for the OIDC provider's metadata. string open_id_connect_url = 2 [(google.api.field_behavior) = REQUIRED]; } // Defines a security scheme using mTLS authentication. message MutualTlsSecurityScheme { // An optional description for the security scheme. string description = 1; } // Defines the configuration for the supported OAuth 2.0 flows. message OAuthFlows { oneof flow { // Configuration for the OAuth Authorization Code flow. AuthorizationCodeOAuthFlow authorization_code = 1; // Configuration for the OAuth Client Credentials flow. ClientCredentialsOAuthFlow client_credentials = 2; // Deprecated: Use Authorization Code + PKCE instead. ImplicitOAuthFlow implicit = 3 [deprecated = true]; // Deprecated: Use Authorization Code + PKCE or Device Code. PasswordOAuthFlow password = 4 [deprecated = true]; // Configuration for the OAuth Device Code flow. DeviceCodeOAuthFlow device_code = 5; } } // Defines configuration details for the OAuth 2.0 Authorization Code flow. message AuthorizationCodeOAuthFlow { // The authorization URL to be used for this flow. string authorization_url = 1 [(google.api.field_behavior) = REQUIRED]; // The token URL to be used for this flow. string token_url = 2 [(google.api.field_behavior) = REQUIRED]; // The URL to be used for obtaining refresh tokens. string refresh_url = 3; // The available scopes for the OAuth2 security scheme. map scopes = 4 [(google.api.field_behavior) = REQUIRED]; // Indicates if PKCE (RFC 7636) is required for this flow. // PKCE should always be used for public clients and is recommended for all clients. bool pkce_required = 5; } // Defines configuration details for the OAuth 2.0 Client Credentials flow. message ClientCredentialsOAuthFlow { // The token URL to be used for this flow. string token_url = 1 [(google.api.field_behavior) = REQUIRED]; // The URL to be used for obtaining refresh tokens. string refresh_url = 2; // The available scopes for the OAuth2 security scheme. map scopes = 3 [(google.api.field_behavior) = REQUIRED]; } // Deprecated: Use Authorization Code + PKCE instead. message ImplicitOAuthFlow { // The authorization URL to be used for this flow. This MUST be in the // form of a URL. The OAuth2 standard requires the use of TLS string authorization_url = 1; // The URL to be used for obtaining refresh tokens. This MUST be in the // form of a URL. The OAuth2 standard requires the use of TLS. string refresh_url = 2; // The available scopes for the OAuth2 security scheme. A map between the // scope name and a short description for it. The map MAY be empty. map scopes = 3; } // Deprecated: Use Authorization Code + PKCE or Device Code. message PasswordOAuthFlow { // The token URL to be used for this flow. This MUST be in the form of a URL. // The OAuth2 standard requires the use of TLS. string token_url = 1; // The URL to be used for obtaining refresh tokens. This MUST be in the // form of a URL. The OAuth2 standard requires the use of TLS. string refresh_url = 2; // The available scopes for the OAuth2 security scheme. A map between the // scope name and a short description for it. The map MAY be empty. map scopes = 3; } // Defines configuration details for the OAuth 2.0 Device Code flow (RFC 8628). // This flow is designed for input-constrained devices such as IoT devices, // and CLI tools where the user authenticates on a separate device. message DeviceCodeOAuthFlow { // The device authorization endpoint URL. string device_authorization_url = 1 [(google.api.field_behavior) = REQUIRED]; // The token URL to be used for this flow. string token_url = 2 [(google.api.field_behavior) = REQUIRED]; // The URL to be used for obtaining refresh tokens. string refresh_url = 3; // The available scopes for the OAuth2 security scheme. map scopes = 4 [(google.api.field_behavior) = REQUIRED]; } // Represents a request for the `SendMessage` method. message SendMessageRequest { // Optional. Opaque routing identifier. Must match the `tenant` value from // the selected `AgentInterface` in the Agent Card when that field is set. string tenant = 1; // The message to send to the agent. Message message = 2 [(google.api.field_behavior) = REQUIRED]; // Configuration for the send request. SendMessageConfiguration configuration = 3; // A flexible key-value map for passing additional context or parameters. google.protobuf.Struct metadata = 4; } // Represents a request for the `GetTask` method. message GetTaskRequest { // Optional. Opaque routing identifier. Must match the `tenant` value from // the selected `AgentInterface` in the Agent Card when that field is set. string tenant = 1; // The resource ID of the task to retrieve. string id = 2 [(google.api.field_behavior) = REQUIRED]; // The maximum number of most recent messages from the task's history to retrieve. An // unset value means the client does not impose any limit. A value of zero is // a request to not include any messages. The server MUST NOT return more // messages than the provided value, but MAY apply a lower limit. optional int32 history_length = 3; } // Parameters for listing tasks with optional filtering criteria. message ListTasksRequest { // Optional. Opaque routing identifier. Must match the `tenant` value from // the selected `AgentInterface` in the Agent Card when that field is set. string tenant = 1; // Filter tasks by context ID to get tasks from a specific conversation or session. string context_id = 2; // Filter tasks by their current status state. TaskState status = 3; // The maximum number of tasks to return. The service may return fewer than this value. // If unspecified, at most 50 tasks will be returned. // The minimum value is 1. // The maximum value is 100. optional int32 page_size = 4; // A page token, received from a previous `ListTasks` call. // `ListTasksResponse.next_page_token`. // Provide this to retrieve the subsequent page. string page_token = 5; // The maximum number of messages to include in each task's history. optional int32 history_length = 6; // Filter tasks which have a status updated after the provided timestamp in ISO 8601 format (e.g., "2023-10-27T10:00:00Z"). // Only tasks with a status timestamp time greater than or equal to this value will be returned. google.protobuf.Timestamp status_timestamp_after = 7; // Whether to include artifacts in the returned tasks. // Defaults to false to reduce payload size. optional bool include_artifacts = 8; } // Result object for `ListTasks` method containing an array of tasks and pagination information. message ListTasksResponse { // Array of tasks matching the specified criteria. repeated Task tasks = 1 [(google.api.field_behavior) = REQUIRED]; // A token to retrieve the next page of results, or empty if there are no more results in the list. string next_page_token = 2 [(google.api.field_behavior) = REQUIRED]; // The page size used for this response. int32 page_size = 3 [(google.api.field_behavior) = REQUIRED]; // Total number of tasks available (before pagination). int32 total_size = 4 [(google.api.field_behavior) = REQUIRED]; } // Represents a request for the `CancelTask` method. message CancelTaskRequest { // Optional. Opaque routing identifier. Must match the `tenant` value from // the selected `AgentInterface` in the Agent Card when that field is set. string tenant = 1; // The resource ID of the task to cancel. string id = 2 [(google.api.field_behavior) = REQUIRED]; // A flexible key-value map for passing additional context or parameters. google.protobuf.Struct metadata = 3; } // Represents a request for the `GetTaskPushNotificationConfig` method. message GetTaskPushNotificationConfigRequest { // Optional. Opaque routing identifier. Must match the `tenant` value from // the selected `AgentInterface` in the Agent Card when that field is set. string tenant = 1; // The parent task resource ID. string task_id = 2 [(google.api.field_behavior) = REQUIRED]; // The resource ID of the configuration to retrieve. string id = 3 [(google.api.field_behavior) = REQUIRED]; } // Represents a request for the `DeleteTaskPushNotificationConfig` method. message DeleteTaskPushNotificationConfigRequest { // Optional. Opaque routing identifier. Must match the `tenant` value from // the selected `AgentInterface` in the Agent Card when that field is set. string tenant = 1; // The parent task resource ID. string task_id = 2 [(google.api.field_behavior) = REQUIRED]; // The resource ID of the configuration to delete. string id = 3 [(google.api.field_behavior) = REQUIRED]; } // Represents a request for the `SubscribeToTask` method. message SubscribeToTaskRequest { // Optional. Opaque routing identifier. Must match the `tenant` value from // the selected `AgentInterface` in the Agent Card when that field is set. string tenant = 1; // The resource ID of the task to subscribe to. string id = 2 [(google.api.field_behavior) = REQUIRED]; } // Represents a request for the `ListTaskPushNotificationConfigs` method. message ListTaskPushNotificationConfigsRequest { // Optional. Opaque routing identifier. Must match the `tenant` value from // the selected `AgentInterface` in the Agent Card when that field is set. string tenant = 4; // The parent task resource ID. string task_id = 1 [(google.api.field_behavior) = REQUIRED]; // The maximum number of configurations to return. int32 page_size = 2; // A page token received from a previous `ListTaskPushNotificationConfigsRequest` call. string page_token = 3; } // Represents a request for the `GetExtendedAgentCard` method. message GetExtendedAgentCardRequest { // Optional. Opaque routing identifier. Must match the `tenant` value from // the selected `AgentInterface` in the Agent Card when that field is set. string tenant = 1; } // Represents the response for the `SendMessage` method. message SendMessageResponse { // The payload of the response. oneof payload { // The task created or updated by the message. Task task = 1; // A message from the agent. Message message = 2; } } // A wrapper object used in streaming operations to encapsulate different types of response data. message StreamResponse { // The payload of the stream response. oneof payload { // A Task object containing the current state of the task. Task task = 1; // A Message object containing a message from the agent. Message message = 2; // An event indicating a task status update. TaskStatusUpdateEvent status_update = 3; // An event indicating a task artifact update. TaskArtifactUpdateEvent artifact_update = 4; } } // Represents a successful response for the `ListTaskPushNotificationConfigs` // method. message ListTaskPushNotificationConfigsResponse { // The list of push notification configurations. repeated TaskPushNotificationConfig configs = 1; // A token to retrieve the next page of results, or empty if there are no more results in the list. string next_page_token = 2; }