Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

a2a-cpp C++20 Agent2Agent (A2A) SDK Documentation

a2a-cpp is a C++20 SDK for building Agent2Agent (A2A) protocol clients and servers. The current documented release focuses on production-oriented protocol coverage: REST, JSON-RPC, and gRPC transports; Agent Card discovery; task lifecycle APIs; streaming; push notification configuration APIs; authentication metadata propagation; interceptors; CMake package exports; and vcpkg-oriented packaging.

What is included

  • Client API: SendMessage, GetTask, ListTasks, CancelTask, streaming send/subscribe, and task push-notification config lifecycle calls.
  • Server API: executor-driven dispatch for REST, JSON-RPC, and gRPC transports.
  • Discovery: public and extended Agent Card fetch plus preferred-interface resolution.
  • Streaming: client observers, cancellable stream handles, and server stream sessions.
  • Authentication hooks: client credential providers and server request metadata extraction.
  • Operational extensions: client/server interceptors, required-extension validation, task stores, task history ordering, UUIDv7 task IDs, and optional PostgreSQL stores.
  • Build integration: CMake 3.25+, C++20, installable CMake package exports, generated protobuf headers, and vcpkg overlay/public-registry preparation.
  1. Installation and Build for toolchain requirements and CMake options.
  2. Quickstart for a copy/paste example flow.
  3. Client Overview or Server Overview, depending on your integration role.
  4. Transports, Streaming, and Authentication for runtime design decisions.
  5. API Reference when you need generated public-header details.

Version and support notes

  • See Releases and Versions for current release details and versioning guidance.
  • The SDK is C++20-only and exports CMake targets under the a2a:: namespace.
  • Package documentation describes vcpkg workflows only.
  • Examples are deterministic and are intended to run without external services unless the example README says otherwise.

Installation and Build

This page reflects the current build surface for the latest documented release.

Choose an integration method

Use the workflow that matches your application:

  • Build the SDK directly from source as described below.
  • Use CMake FetchContent and pin a release tag or reviewed commit.
  • Install the SDK as a CMake package and consume it with find_package.
  • Consume the repository-local vcpkg overlay port.

Prerequisites

Install these tools before configuring the repository:

  • CMake 3.25 or newer.
  • A C++20 compiler: GCC, Clang, AppleClang, or Visual Studio 2022.
  • Protobuf with protoc.
  • gRPC C++ with grpc_cpp_plugin.
  • libcurl when using the built-in HTTP, JSON-RPC, or SSE clients.
  • clang-format and clang-tidy for contributor validation.
  • Optional: Doxygen for API reference generation.
  • Optional: PostgreSQL client libraries when building PostgreSQL-backed stores.

Debian or Ubuntu

./scripts/install_build_deps.sh
cmake --version

The installer supports Debian and Ubuntu. Confirm that the installed CMake version is 3.25 or newer. Some older distributions, including Ubuntu 22.04, provide an older CMake package and require a newer CMake installation from another source.

The same script also supports Windows when run from Git Bash.

macOS

brew install cmake ninja protobuf grpc re2 abseil curl

When enabling PostgreSQL-backed stores, also install the PostgreSQL client package:

brew install libpq

Windows Git Bash

Install Visual Studio 2022 with the Desktop development with C++ workload and Git for Windows. Open Git Bash in the repository root and run:

./scripts/install_build_deps.sh

The script first checks VCPKG_ROOT, then searches for vcpkg.exe or vcpkg on PATH, and then checks $HOME/vcpkg. It clones and bootstraps vcpkg under ${VCPKG_ROOT:-$HOME/vcpkg} only when an existing installation is not found. It installs the dependencies declared by the root vcpkg.json and prints the resolved VCPKG_ROOT, target triplet, and host triplet when it finishes.

Override VCPKG_ROOT, VCPKG_TARGET_TRIPLET, or VCPKG_HOST_TRIPLET before running the script when needed. Keep the resolved VCPKG_ROOT value for the CMake configuration step below; do not reset it to $HOME/vcpkg when the script found vcpkg elsewhere.

The root manifest does not install PostgreSQL client libraries. For PostgreSQL-enabled Windows builds, use a vcpkg manifest that includes libpq, or consume the SDK through the repository overlay port with its postgres-store feature. See Build with vcpkg.

Configure from source

On Linux:

cmake -S . -B build \
  -DCMAKE_BUILD_TYPE=RelWithDebInfo \
  -DCMAKE_EXPORT_COMPILE_COMMANDS=ON

On macOS, use the same Homebrew prefixes validated by CI:

cmake -S . -B build -G Ninja \
  -DCMAKE_BUILD_TYPE=RelWithDebInfo \
  -DCMAKE_EXPORT_COMPILE_COMMANDS=ON \
  -DCMAKE_PREFIX_PATH="$(brew --prefix);$(brew --prefix curl)"

When A2A_ENABLE_POSTGRES_STORE=ON, append $(brew --prefix libpq) to CMAKE_PREFIX_PATH.

On Windows Git Bash, set VCPKG_ROOT to the value printed by install_build_deps.sh or to an existing vcpkg checkout:

export VCPKG_ROOT="/path/to/vcpkg"
export VCPKG_TARGET_TRIPLET="${VCPKG_TARGET_TRIPLET:-x64-windows}"
export VCPKG_HOST_TRIPLET="${VCPKG_HOST_TRIPLET:-$VCPKG_TARGET_TRIPLET}"
cmake -S . -B build -G "Visual Studio 17 2022" -A x64 \
  -DCMAKE_TOOLCHAIN_FILE="$VCPKG_ROOT/scripts/buildsystems/vcpkg.cmake" \
  -DVCPKG_TARGET_TRIPLET="$VCPKG_TARGET_TRIPLET" \
  -DVCPKG_HOST_TRIPLET="$VCPKG_HOST_TRIPLET"

If a build directory was first configured without the vcpkg toolchain, delete it before reconfiguring. CMake caches the toolchain during the first configure.

Useful options:

OptionDefaultPurpose
A2A_ENABLE_TESTINGONBuilds unit and integration tests.
A2A_BUILD_EXAMPLESONKeeps the root project compatible with example-related CI messaging; curated examples are built as standalone consumers.
A2A_BUILD_BENCHMARKSOFFBuilds the optional Google Benchmark suite.
A2A_ENABLE_LIBCURLONEnables default outbound HTTP and SSE support when CURL::libcurl is found.
A2A_ENABLE_POSTGRES_STOREOFFBuilds PostgreSQL task and push-notification stores.

Build and test

Linux or macOS:

cmake --build build --parallel
ctest --test-dir build --output-on-failure

Windows Visual Studio generators are multi-configuration; run these commands from Git Bash:

cmake --build build --config RelWithDebInfo --parallel
ctest --test-dir build -C RelWithDebInfo --output-on-failure

Generate only protobuf outputs when needed:

cmake --build build --target a2a_proto_codegen

Generated A2A headers are written under build/generated/a2a/v1/. Generated Google API annotation headers are written under build/generated/google/api/. Both sets are installed with the SDK.

Install CMake package artifacts

cmake --install build --prefix /tmp/a2a-cpp-install

On a Visual Studio build, also pass --config RelWithDebInfo.

The install tree includes public headers, generated protobuf headers, libraries, and CMake package files under ${CMAKE_INSTALL_LIBDIR}/cmake/a2a_cpp, commonly lib/cmake/a2a_cpp.

Contributor validation

For code changes in a Linux CI-compatible environment, run the canonical validation script before opening or updating a PR:

./scripts/verify_changes.sh

The script runs the same main validation categories as CI: formatting, configure/build, tests, and clang-tidy. It runs clang-format -i first and can modify tracked C and C++ files, so review git diff after it completes.

The current script assumes a Unix environment with nproc and a single-configuration build. On macOS or Windows, use the platform-specific configure, build, and test commands above and run the required formatting and clang-tidy checks separately.

For documentation-only mdBook changes, build the book:

mdbook build book

Quickstart: Build and Run Examples

The curated examples build app sources the same way downstream applications consume the SDK.

1. Install dependencies

Follow the platform instructions in Installation and Build. On Windows, run the repository helper from Git Bash before the example runner:

./scripts/install_build_deps.sh

2. Run the smallest end-to-end example

Linux or macOS:

./scripts/run_examples.sh build-example hello_agent

Windows Git Bash cleanup and rebuild:

rm -rf build-example-hello_agent
./scripts/run_examples.sh build-example hello_agent

The executable is written to build-example-hello_agent/a2a_example on single-configuration generators and to build-example-hello_agent/RelWithDebInfo/a2a_example.exe with Visual Studio.

hello_agent creates a minimal in-process client/server flow and exits deterministically.

3. Try transport-specific examples

./scripts/run_examples.sh build-example rest_server json_rpc_server grpc_server

These examples cover server transport setup and deterministic request handling across REST, JSON-RPC, and gRPC.

4. Try streaming, push, and auth examples

./scripts/run_examples.sh build-example streaming_client streaming_server push_notifications auth_policy_server

Use these when validating event streams, webhook configuration flows, or server-side auth metadata policy shapes. On Windows, the runner automatically forwards the vcpkg toolchain and locates the Visual Studio configuration output when VCPKG_ROOT is set.

5. Consume an installed SDK package

After installing the SDK into a prefix, build the same app source with find_package(a2a_cpp CONFIG REQUIRED):

cmake -S examples/installed_package_consumer -B build-installed-example \
  -DCMAKE_PREFIX_PATH=/tmp/a2a-cpp-install \
  -DA2A_EXAMPLE_APP=hello_agent
cmake --build build-installed-example --parallel
./build-installed-example/a2a_example

For Visual Studio, add --config RelWithDebInfo to the build and run build-installed-example/RelWithDebInfo/a2a_example.exe.

6. Validate your local checkout

./scripts/verify_changes.sh

For documentation-only edits, use mdbook build book instead of the full code validation flow.

Client Overview

Use a2a::client::A2AClient with a concrete ClientTransport to call A2A servers.

Client capabilities

  • SendMessage
  • GetTask
  • ListTasks
  • CancelTask
  • SendStreamingMessage
  • SubscribeTask
  • CreateTaskPushNotificationConfig
  • GetTaskPushNotificationConfig
  • ListTaskPushNotificationConfigs
  • DeleteTaskPushNotificationConfig
  • Client interceptors via ClientInterceptor
  • Per-call settings through CallOptions

Typical flow

  1. Fetch an Agent Card with DiscoveryClient.
  2. Select an endpoint with AgentCardResolver::SelectPreferredInterface.
  3. Construct HttpJsonTransport, JsonRpcTransport, or GrpcTransport.
  4. Create A2AClient with the transport.
  5. Invoke task, streaming, or push-notification APIs.
  6. Call Destroy() during shutdown when you need transport cleanup.

Default outbound HTTP

When libcurl is available and A2A_ENABLE_LIBCURL=ON, default constructors/factories can perform buffered outbound REST, JSON-RPC, and discovery calls. For tests, custom TLS policy, mTLS, retries, or embedded runtimes, inject your own requester/fetcher callbacks.

Runnable examples

  • examples/apps/hello_agent/main.cpp
  • examples/apps/simple_client/main.cpp
  • examples/apps/streaming_client/main.cpp
  • examples/apps/push_notifications/main.cpp

Sending Messages

A2AClient::SendMessage starts or continues a task by sending a protobuf lf::a2a::v1::SendMessageRequest through the configured transport.

Request construction guidance

  • Set a stable message.message_id for idempotency and diagnostics.
  • Let the server generate a task ID for new work unless you are intentionally continuing an existing task.
  • Attach push-notification config only when the target Agent Card advertises support and your server policy allows it.
  • Use CallOptions for per-call deadlines, metadata, or auth settings where supported by the transport.

Response handling

The response can contain immediate task state and output data. Persist task identifiers in logs/telemetry so later GetTask, CancelTask, streaming subscription, or push-notification calls can be correlated.

Failure paths to test

  • Network or HTTP/gRPC transport failure.
  • Serialization or protocol validation failure.
  • Auth policy rejection.
  • Unsupported operation or required extension mismatch.
  • Duplicate/retry behavior for repeated message IDs.

Discovery and Agent Cards

Discovery resolves server capabilities before constructing a client transport.

Public and extended cards

DiscoveryClient supports:

  • Fetch(base_url) for the standard Agent Card.
  • FetchExtendedAgentCard(base_url) for the extended Agent Card endpoint.

Fetched cards are cached for kDefaultDiscoveryCacheTtl (300 seconds) unless a different TTL is supplied.

Interface resolution

AgentCardResolver::SelectPreferredInterface(card, preferred) selects a ResolvedInterface for one of:

  • PreferredTransport::kRest
  • PreferredTransport::kJsonRpc
  • PreferredTransport::kGrpc

The result includes the transport, URL, security requirements, and security schemes needed to configure a client.

Operational guidance

  • Validate and log the selected endpoint during startup.
  • Prefer an explicit fallback order when cards advertise multiple transports.
  • Treat discovery metadata as untrusted input until validated.
  • Refresh cached cards after deployment or capability changes.
  • include/a2a/client/discovery.h
  • include/a2a/core/agent_card/agent_card_provider.h
  • include/a2a/server/agent_card/agent_card_serializer.h

Get Task and List Tasks

GetTask retrieves a single task by ID. ListTasks returns a paginated list of tasks through the client abstraction and supported transports.

GetTask flow

  1. Store the task ID from SendMessage or a stream event.
  2. Build lf::a2a::v1::GetTaskRequest.
  3. Call A2AClient::GetTask.
  4. Interpret task status, artifacts, and history according to your application policy.

ListTasks flow

a2a::client::ListTasksRequest contains:

  • page_size
  • page_token

The response includes task values plus next_page_token.

An omitted page size requests the protocol default of at most 50 tasks. Explicit page sizes must be between 1 and 100. Continue until next_page_token is empty:

a2a::client::ListTasksRequest request{.page_size = 50};
do {
  const auto page = client.ListTasks(request);
  if (!page.ok()) {
    return page.error();
  }
  for (const auto& task : page.value().tasks) {
    ProcessTask(task);
  }
  request.page_token = page.value().next_page_token;
} while (!request.page_token.empty());

Keep pages bounded (normally no more than 100 tasks) and request a small history_length, often 0 or 1, unless deeper history is required. CPU cost grows with both the returned task count and retained history. Oversized results also increase protobuf allocations and copies, response memory, serialized payload size, transport latency, and timeout risk. In-memory stores hold their shared read lock longer while materializing a result, so writes may wait longer. Full history projection can dominate the list operation.

Operational guidance

  • Use bounded polling with backoff when not using streaming.
  • Enforce authorization checks on server-side task visibility.
  • Avoid exposing full task history to clients that do not need it.

Cancel Task

A2AClient::CancelTask asks the server to cancel in-flight work.

When to use cancellation

  • A user aborts an operation.
  • A deadline expires upstream.
  • Supervising logic needs to reclaim compute or queue capacity.

Semantics

Cancellation is best-effort. A task can complete before the cancellation request is processed, and servers can reject cancellation for completed, unknown, or policy-protected tasks.

  • Make higher-level cancellation idempotent.
  • Return or display the latest task state after cancellation attempts.
  • Preserve enough audit data to explain whether the task was canceled, completed, or rejected.

Server Overview

Server integrations implement a2a::server::AgentExecutor and route protocol requests through Dispatcher plus one or more transports.

Server capabilities

  • REST server transport.
  • JSON-RPC server transport.
  • gRPC service transport.
  • Public and extended Agent Card dispatch when a provider is installed.
  • Required extension validation.
  • Server interceptors.
  • Streaming through ServerStreamSession.
  • Task lifecycle helpers, in-memory task store, and optional PostgreSQL stores.
  • Push-notification config CRUD and delivery service abstractions.

Core flow

  1. Implement an executor for task and message behavior.
  2. Create a Dispatcher with the executor and optional Agent Card provider/interceptors.
  3. Attach REST, JSON-RPC, or gRPC transport adapters.
  4. Convert inbound framework requests into transport calls.
  5. Return structured protocol errors instead of transport-specific ad hoc errors.

Task IDs

When an incoming message does not carry message.task_id, the SDK service layer can generate server-side task IDs using UUIDv7. UUIDv7 is sortable and operationally useful, but it leaks approximate creation time. Inject a custom task ID generator if your deployment needs opaque identifiers.

Custom Executors

Implement a2a::server::AgentExecutor to define application behavior.

Required methods

Executors implement task/message operations including:

  • SendMessage
  • SendStreamingMessage
  • GetTask
  • ListTasks
  • CancelTask

Push-notification config methods have default PushNotificationNotSupported behavior and should be overridden only when the server actually supports them.

Request context

Every executor method receives RequestContext. Use it for auth metadata, transport metadata, and request-scoped policy decisions. Treat metadata as untrusted until validated.

Design guidance

  • Keep executor methods small and deterministic.
  • Validate inputs at the boundary.
  • Return a2a::core::Result<T> with structured errors.
  • Avoid shared mutable state unless synchronized and documented.
  • Unit-test executor behavior separately from transport mapping.

REST Server Transport

RestServerTransport maps HTTP+JSON requests onto dispatcher operations.

Responsibilities

  • Validate HTTP method, path, and content type.
  • Parse JSON request bodies into protobuf messages.
  • Populate RequestContext, including auth metadata.
  • Serialize protocol responses and errors back to HTTP responses.

Supported operation shape

REST transport covers core task lifecycle operations, streaming-compatible endpoints where wired by the hosting environment, Agent Card routes, and push-notification config APIs exposed by the dispatcher/executor.

Hosting guidance

The SDK provides protocol mapping, not a full production web server framework. In production, place it behind an HTTP runtime that owns TLS, connection limits, request-size limits, access logs, and graceful shutdown.

Example

See examples/apps/rest_server/main.cpp.

JSON-RPC Server Transport

JsonRpcServerTransport maps JSON-RPC 2.0 method calls to dispatcher operations.

Responsibilities

  • Validate the jsonrpc, id, method, and params envelope fields.
  • Route supported A2A methods to the dispatcher.
  • Return JSON-RPC error objects for invalid requests, unknown methods, and executor failures.
  • Preserve request metadata for auth and audit policy.

Use cases

Use JSON-RPC when method-based routing is easier to integrate than resource-oriented REST paths or when another system already standardizes on JSON-RPC 2.0.

Example

See examples/apps/json_rpc_server/main.cpp.

Push Notifications

The SDK includes task push-notification configuration APIs and server-side delivery abstractions.

Client API surface

A2AClient exposes:

  • CreateTaskPushNotificationConfig
  • GetTaskPushNotificationConfig
  • ListTaskPushNotificationConfigs
  • DeleteTaskPushNotificationConfig

Use these only when the target Agent Card and server policy indicate push-notification support.

Server components

  • PushNotificationService coordinates stored configs and delivery.
  • PushNotificationStore persists webhook configs.
  • PushNotificationDeliveryClient abstracts outbound delivery.
  • HttpPushNotificationDeliveryClient provides a simple libcurl-backed synchronous delivery path when libcurl support is enabled.
  1. Persist task state in your TaskStore or TaskLifecycleService.
  2. Register inline configs from SendMessageRequest when present.
  3. Call NotifyTaskUpdated(task) after status changes.
  4. Propagate delivery failures instead of silently dropping them.
  5. Override push-config CRUD executor methods only when push support is fully configured.

Production guidance

For production, prefer a durable queued delivery client with retries, backoff, webhook URL validation, SSRF controls, credential protection, and delivery telemetry. Keep TLS policy at least as strong as the built-in delivery client, which requires TLS 1.2 or newer for HTTPS URLs.

Example

See examples/apps/push_notifications/main.cpp.

Server Interceptors

Server interceptors let deployments attach cross-cutting behavior around dispatcher operations.

Common uses

  • Authorization and policy checks.
  • Request/response telemetry.
  • Audit logging.
  • Metrics and latency measurement.
  • Required extension enforcement in combination with transport validators.

Design guidance

  • Keep interceptors deterministic and low-latency.
  • Avoid logging secrets or raw credential values.
  • Use structured errors so transports can map failures consistently.
  • Prefer composition: keep business behavior in AgentExecutor and cross-cutting behavior in interceptors.
  • a2a::server::ServerInterceptor
  • a2a::server::Dispatcher::AddInterceptor
  • a2a::client::ClientInterceptor for client-side call hooks

Transports Overview

The SDK separates protocol operations from transport adapters. Applications choose the transport that best matches their deployment boundary and interoperability needs.

Available transports

  • REST: HTTP+JSON resource-oriented integration for clients and servers.
  • JSON-RPC: JSON-RPC 2.0 method dispatch over HTTP-style request handling.
  • gRPC: protobuf/gRPC service integration with unary and streaming RPCs.

Choosing a transport

  • Choose REST when your platform already standardizes on HTTP routing, gateways, or resource-style APIs.
  • Choose JSON-RPC when method-style dispatch is easier to interoperate with or proxy.
  • Choose gRPC when you want protobuf-native contracts, gRPC streaming, or a service mesh that already supports gRPC well.

Shared operational concerns

Regardless of transport, define these policies explicitly:

  • Authentication and authorization boundaries.
  • Protocol version and required-extension handling.
  • Request deadlines and payload limits.
  • Retry and idempotency behavior.
  • Telemetry, audit logs, and stable task/request identifiers.

REST Transport

REST is the HTTP+JSON transport path for clients and servers.

Client side

Use HttpJsonTransport with A2AClient. When libcurl is enabled and found, default outbound buffered HTTP can be used. Otherwise inject an HttpRequester implementation.

Server side

Use RestServerTransport to translate inbound framework requests into dispatcher calls.

Operational considerations

  • Enforce TLS and auth policy at your edge or hosting layer.
  • Set explicit request deadlines and payload limits.
  • Log stable task IDs and request IDs.
  • Validate protocol version headers where required.
  • Prefer injected requesters for custom retry, proxy, mTLS, or observability policy.

JSON-RPC Transport

JSON-RPC transport supports A2A method dispatch over JSON-RPC 2.0 envelopes.

Client side

Use JsonRpcTransport with A2AClient. Default buffered outbound HTTP is available when libcurl is enabled and found; otherwise inject a requester.

Server side

Use JsonRpcServerTransport to decode envelopes, dispatch operations, and encode JSON-RPC responses.

Operational considerations

  • Validate envelope fields strictly.
  • Preserve client-provided request IDs in responses.
  • Map structured SDK errors to consistent JSON-RPC error responses.
  • Include auth metadata in RequestContext only after policy validation.

gRPC Transport

gRPC support is first-class for client and server integrations.

Client side

Use a2a::client::GrpcTransport with a resolved interface and either:

  • a std::shared_ptr<grpc::Channel> for real gRPC calls, or
  • a custom GrpcTransport::RpcClient for tests and embedded adapters.

The transport supports unary task operations, streaming send, task subscription, and push-notification config lifecycle calls.

Server side

a2a::server::GrpcServerTransport implements lf::a2a::v1::A2AService::Service and routes RPCs to the dispatcher.

It supports:

  • SendMessage
  • SendStreamingMessage
  • GetTask
  • ListTasks
  • CancelTask
  • SubscribeToTask
  • Push-notification config RPCs
  • GetExtendedAgentCard

Metadata and extensions

The server transport recognizes A2A metadata such as a2a-version and can validate required extensions through GrpcServerTransportOptions::required_extensions.

Example

See examples/apps/grpc_server/main.cpp.

Streaming

Streaming is available through all production client transports:

  • gRPC native server streaming;
  • HTTP+JSON SSE;
  • JSON-RPC response envelopes carried in SSE data: fields.

Servers should advertise capabilities.streaming: true in their Agent Card.

Client APIs

  • A2AClient::SendStreamingMessage(request, observer, options)
  • A2AClient::SubscribeTask(request, observer, options)

Implement a2a::client::StreamObserver:

  • OnEvent(const StreamResponse&) for each decoded event.
  • OnError(const core::Error&) once for transport or protocol failure.
  • OnCompleted() once after a clean remote close.

Both calls return a StreamHandle. Call Cancel() to request cancellation and IsActive() to check handle state. Destruction also cancels the request and joins its worker.

Threading contract

Observer callbacks run on transport-managed background threads. Keep observers alive until stream completion, cancellation, or handle destruction. Callback code should be thread-safe, fast, and non-blocking.

Build the streaming client example

The SDK requires gRPC and Protobuf at configure time. The default HTTP streaming transports also require libcurl.

Linux or macOS:

./scripts/run_examples.sh build-example streaming_client

Windows Git Bash:

./scripts/install_build_deps.sh
rm -rf build-example-streaming_client
./scripts/run_examples.sh build-example streaming_client
./build-example-streaming_client/RelWithDebInfo/a2a_example.exe --help

See Installation and Build and vcpkg for dependency and toolchain details.

Server side

Executors return std::unique_ptr<ServerStreamSession> from SendStreamingMessage and, optionally, SubscribeTask. A stream session publishes StreamResponse values until it returns an empty optional or an error.

Examples

  • examples/apps/streaming_client/main.cpp
  • examples/apps/streaming_server/main.cpp

Authentication and Authorization Hooks

The SDK provides hooks for carrying credentials and auth metadata. Your application remains responsible for credential storage, verification, authorization decisions, and audit policy.

Client credential providers

include/a2a/client/auth.h includes providers for:

  • API key headers.
  • Bearer token headers.
  • Custom header credentials.
  • OAuth2 bearer token extension points.

Use these with transport call options or request construction paths that support metadata injection.

Server metadata

REST, JSON-RPC, and gRPC server paths populate RequestContext with transport metadata. Executor or interceptor code can read this metadata to make authorization decisions.

Policy guidance

  • Never hardcode secrets in source, examples, or tests.
  • Validate credentials before trusting request metadata.
  • Normalize auth failures so callers receive consistent protocol errors.
  • Avoid logging raw credentials.
  • Prefer short-lived tokens and managed secret storage.
  • Document how TLS or mTLS identity is terminated and propagated into the SDK boundary.

Example

See examples/apps/auth_policy_server/main.cpp for an auth-policy shape.

Releases and Versions

This documentation is intended to stay version-aware without embedding a release number in every page title.

Current documented release

The current documented release is v0.4.0 and is recommended for new consumers.

Highlights since v0.3.0

  • Configurable PostgreSQL connection pool capacity through PostgresStoreOptions::connection_pool_size, with the backward-compatible default of 4.
  • Shared configured PostgreSQL pools for task and push-notification stores created through CreateStoreBundle().
  • PostgreSQL operation-phase diagnostics, pool-size metadata, median aggregates, and query-plan evidence in performance reports.
  • Removal of executor-wide request serialization that limited independent concurrent operations.
  • Bounded protocol-facing ListTasks pagination across HTTP+JSON, JSON-RPC, and gRPC, with a default page size of 50 and a maximum of 100.
  • Optimized in-memory task listing, pagination, filtering, artifact exclusion, and history projection, backed by expanded benchmark thresholds.
  • Interruptible gRPC stream cancellation watching, eliminating the previous approximately 50 ms normal stream-completion floor.
  • Deterministic follow-up and decomposed push-notification performance scenarios with clearer workload attribution.
  • Expanded normal and PostgreSQL-tail performance matrices, reports, tests, and parallel CI execution.
  • Centralized HTTP server response construction and reusable server-side A2A-Version header validation.
  • Corrected benchmark-runner module paths and refreshed README, installation, storage, pagination, and performance documentation.

Compatibility notes

There are no intentional public API removals in v0.4.0.

Protocol-facing ListTasks requests are now bounded consistently across transports. An omitted page size returns at most 50 tasks, explicit values must be between 1 and 100, and callers must follow next_page_token to retrieve additional pages. Internal store calls may still use the documented unbounded sentinel where appropriate.

The PostgreSQL connection pool still defaults to 4, so existing applications retain their previous capacity unless they explicitly configure a different value. Applications should size the pool for expected concurrent database operations while respecting PostgreSQL connection limits.

Built-in HTTP+JSON and JSON-RPC SSE clients continue to require libcurl support. Custom HTTP requester and streaming requester implementations remain supported for consumers that need alternative transport stacks.

Previous release: v0.3.0

v0.3.0 introduced production-ready SSE streaming for HTTP+JSON and JSON-RPC, end-to-end streaming and subscriptions across all supported transports, report-only performance testing, repository-local vcpkg overlay packaging, and expanded build and platform documentation.

Its TCK validation snapshot was:

  • 249 tests passed
  • 16 tests skipped
  • 0 executed test failures
  • 100.0% compatibility for tested, non-skipped requirements

Versioning guidance

  • Pin CMake FetchContent integrations to a release tag such as v0.4.0 or to a reviewed commit.
  • Prefer find_package(a2a_cpp CONFIG REQUIRED) for installed SDK packages.
  • Keep generated protobuf headers and linked SDK libraries from the same installed package or build tree.
  • Review release notes before upgrading between minor versions.

Documentation policy

Page titles and navigation should remain mostly version agnostic. Release-specific notes belong on this page or in clearly marked compatibility sections.

Build with CMake

a2a-cpp is a C++20 SDK built and packaged with CMake. The project can be used directly from source with FetchContent, installed into a CMake package prefix, or built with dependencies supplied by vcpkg.

Requirements

  • CMake 3.25 or newer.
  • A C++20 compiler.
  • Protobuf and gRPC development packages.
  • Optional: libcurl for the default buffered outbound HTTP implementation.
  • Optional: PostgreSQL client libraries when A2A_ENABLE_POSTGRES_STORE=ON.

On Ubuntu-like systems, the repository helper installs the dependencies used by CI:

./scripts/install_build_deps.sh

On macOS, install equivalent packages with Homebrew:

brew install cmake ninja protobuf grpc re2 abseil curl

On Windows, install Visual Studio 2022 with the Desktop development with C++ workload and Git for Windows. Then run the repository dependency helper from Git Bash:

./scripts/install_build_deps.sh

Configure from source

The default source build enables tests, keeps the curated example apps out of the top-level build, and enables libcurl-backed HTTP support when CMake can find CURL::libcurl.

cmake -S . -B build \
  -DCMAKE_BUILD_TYPE=Debug \
  -DCMAKE_EXPORT_COMPILE_COMMANDS=ON \
  -DA2A_ENABLE_TESTING=ON

When dependencies are installed outside standard search paths, pass a CMake prefix path:

cmake -S . -B build \
  -DCMAKE_BUILD_TYPE=RelWithDebInfo \
  -DCMAKE_PREFIX_PATH="/opt/homebrew;/opt/homebrew/opt/curl"

Build and test

Single-configuration generators:

cmake --build build --parallel
ctest --test-dir build --output-on-failure

Visual Studio generators from Git Bash:

cmake --build build --config RelWithDebInfo --parallel
ctest --test-dir build -C RelWithDebInfo --output-on-failure

For the repository’s full local code validation flow, run:

./scripts/verify_changes.sh

That script runs the same main gates expected before a code PR: formatting, configure/build, tests, and clang-tidy.

CMake options

OptionDefaultDescription
A2A_ENABLE_TESTINGONBuilds unit and integration tests and enables CTest.
A2A_BUILD_EXAMPLESONCompatibility/message-only option for the root build today; curated examples are built as standalone consumers from examples/fetch_content_consumer or examples/installed_package_consumer.
A2A_BUILD_BENCHMARKSOFFBuilds benchmark targets under benchmarks/.
A2A_ENABLE_LIBCURLONEnables the default libcurl-backed outbound HTTP implementation when libcurl is found. Disable it to require injected requesters/fetchers.
A2A_ENABLE_POSTGRES_STOREOFFBuilds PostgreSQL-backed store targets when PostgreSQL dependencies are available.

Generated protobuf headers

The SDK generates A2A protocol C++ sources during the build. Primary generated A2A headers are written under build/generated/a2a/v1/, and generated Google API annotation headers are written under build/generated/google/api/.

Those generated headers are installed with the SDK, so downstream projects should include headers from the installed package rather than copying build-tree generated files.

Install as a CMake package

Install the SDK to a prefix:

cmake --install build --prefix /tmp/a2a-cpp-install

The install tree includes public headers, generated protobuf headers, libraries, and package configuration files under lib/cmake/a2a_cpp.

A downstream project can then consume the installed package:

cmake_minimum_required(VERSION 3.25)
project(my_a2a_app LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

find_package(a2a_cpp CONFIG REQUIRED)

add_executable(my_a2a_app main.cpp)
target_link_libraries(my_a2a_app PRIVATE a2a::client a2a::server a2a::core)

Configure that downstream project with CMAKE_PREFIX_PATH pointing at the install prefix:

cmake -S path/to/app -B build-app \
  -DCMAKE_PREFIX_PATH=/tmp/a2a-cpp-install
cmake --build build-app --parallel

FetchContent consumer

For application projects that prefer source integration, use CMake FetchContent and pin GIT_TAG to a release tag or reviewed commit:

include(FetchContent)

set(A2A_ENABLE_TESTING OFF CACHE BOOL "" FORCE)
set(A2A_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE)
set(A2A_BUILD_BENCHMARKS OFF CACHE BOOL "" FORCE)
set(A2A_ENABLE_POSTGRES_STORE OFF CACHE BOOL "" FORCE)

FetchContent_Declare(
  a2a_cpp
  GIT_REPOSITORY https://github.com/MisterVVP/a2a-cpp.git
  GIT_TAG v0.4.0
)
FetchContent_MakeAvailable(a2a_cpp)

target_link_libraries(my_a2a_app PRIVATE a2a::client a2a::server a2a::core)

See examples/fetch_content_consumer/ for a minimal runnable consumer.

Exported targets

Common exported targets include:

  • a2a::core for shared core types and utilities.
  • a2a::client for client APIs.
  • a2a::server for server APIs.
  • a2a::http for HTTP support internals used by higher-level targets.
  • a2a::proto_generated for generated protobuf bindings.
  • a2a::store_postgres when PostgreSQL store support is enabled.

Most applications should link the smallest set they use. The examples link a2a::client, a2a::server, and a2a::core for a combined client/server sample.

Build the curated examples

Use the repository runner for FetchContent examples:

./scripts/run_examples.sh build-example hello_agent

When VCPKG_ROOT is set, the runner forwards the vcpkg toolchain and optional target/host triplets. It builds RelWithDebInfo by default and finds either build-example-hello_agent/a2a_example or the Visual Studio output at build-example-hello_agent/RelWithDebInfo/a2a_example.exe.

Windows Git Bash:

./scripts/install_build_deps.sh
rm -rf build-example-hello_agent
./scripts/run_examples.sh build-example hello_agent

Platform notes

  • Linux CI configures with CMake and validates build, tests, examples, clang-format, clang-tidy, coverage, and selected sanitizer/interop flows.
  • macOS CI builds with Homebrew-provided dependencies and Ninja.
  • Windows CI and local Windows builds use vcpkg manifest dependencies and the Visual Studio 2022 generator. See vcpkg for the helper script, manifest, triplet, and overlay details.

Build with vcpkg

a2a-cpp provides vcpkg metadata for two related workflows:

  1. Manifest dependency mode for building this repository with vcpkg-supplied third-party dependencies.
  2. Overlay port mode for consuming a2a-cpp itself as a vcpkg package before it is available from a public registry.

The repository root vcpkg.json pins the dependency baseline and declares the SDK’s third-party dependencies: protobuf, gRPC, and curl.

Prerequisites

Install or clone vcpkg and bootstrap it:

git clone https://github.com/microsoft/vcpkg.git "$HOME/vcpkg"
"$HOME/vcpkg/bootstrap-vcpkg.sh"

On Windows PowerShell:

git clone https://github.com/microsoft/vcpkg.git C:\vcpkg
C:\vcpkg\bootstrap-vcpkg.bat

Set VCPKG_ROOT for convenience:

export VCPKG_ROOT="$HOME/vcpkg"
$env:VCPKG_ROOT = 'C:\vcpkg'

Repository helper on Windows Git Bash

From the repository root, the Bash helper clones, bootstraps, and installs the vcpkg manifest dependencies:

./scripts/install_build_deps.sh

The default vcpkg checkout is $HOME/vcpkg; no fixed C:/vcpkg location is required. Override the root or triplets with environment variables:

export VCPKG_ROOT=/d/tools/vcpkg
export VCPKG_TARGET_TRIPLET=x64-windows-static
export VCPKG_HOST_TRIPLET=x64-windows
./scripts/install_build_deps.sh

Build this repository with manifest dependencies

From the repository root, let vcpkg install the manifest dependencies and then configure CMake with the vcpkg toolchain file:

"$VCPKG_ROOT/vcpkg" install
cmake -S . -B build-vcpkg \
  -DVCPKG_MANIFEST_MODE=ON \
  -DCMAKE_TOOLCHAIN_FILE="$VCPKG_ROOT/scripts/buildsystems/vcpkg.cmake" \
  -DCMAKE_BUILD_TYPE=RelWithDebInfo \
  -DA2A_ENABLE_TESTING=ON
cmake --build build-vcpkg --parallel
ctest --test-dir build-vcpkg --output-on-failure

On multi-config generators such as Visual Studio, pass the configuration during build and test:

& "$env:VCPKG_ROOT\vcpkg.exe" install
cmake -S . -B build-vcpkg -G "Visual Studio 17 2022" -A x64 `
  -DVCPKG_MANIFEST_MODE=ON `
  -DCMAKE_TOOLCHAIN_FILE="$env:VCPKG_ROOT\scripts\buildsystems\vcpkg.cmake"
cmake --build build-vcpkg --config RelWithDebInfo --parallel
ctest --test-dir build-vcpkg -C RelWithDebInfo --output-on-failure

Use a specific triplet

Pass the same target triplet to vcpkg and CMake. For native builds, use the same value for the host triplet so host tools such as protoc and grpc_cpp_plugin are resolved consistently:

"$VCPKG_ROOT/vcpkg" install --triplet x64-linux --host-triplet x64-linux
cmake -S . -B build-vcpkg \
  -DCMAKE_TOOLCHAIN_FILE="$VCPKG_ROOT/scripts/buildsystems/vcpkg.cmake" \
  -DVCPKG_TARGET_TRIPLET=x64-linux \
  -DVCPKG_HOST_TRIPLET=x64-linux

Windows CI uses the repository triplet triplets/ci-x64-windows-release.cmake to build release-only dependencies and reduce dependency build time:

$env:VCPKG_OVERLAY_TRIPLETS = "$PWD\triplets"
& "$env:VCPKG_ROOT\vcpkg.exe" install --triplet ci-x64-windows-release --host-triplet ci-x64-windows-release
cmake -S . -B build -G "Visual Studio 17 2022" -A x64 `
  -DCMAKE_TOOLCHAIN_FILE="$env:VCPKG_ROOT\scripts\buildsystems\vcpkg.cmake" `
  -DVCPKG_TARGET_TRIPLET=ci-x64-windows-release `
  -DVCPKG_HOST_TRIPLET=ci-x64-windows-release

Build standalone FetchContent examples on Windows

The example runner uses the already-installed root manifest dependencies. It automatically passes the vcpkg toolchain and triplets when VCPKG_ROOT is set:

./scripts/install_build_deps.sh
rm -rf build-example-streaming_client
./scripts/run_examples.sh build-example streaming_client
./build-example-streaming_client/RelWithDebInfo/a2a_example.exe --help

Delete a build directory that was configured before the toolchain was supplied; changing CMAKE_TOOLCHAIN_FILE in an existing CMake cache is not reliable.

Consume a2a-cpp through the repository overlay port

The repository includes an overlay port at vcpkg-overlay-ports/a2a-cpp. A downstream manifest can depend on a2a-cpp and point vcpkg at that overlay.

vcpkg.json:

{
  "name": "my-a2a-app",
  "version-string": "0.4.0",
  "dependencies": [
    "a2a-cpp"
  ]
}

vcpkg-configuration.json:

{
  "default-registry": {
    "kind": "builtin",
    "baseline": "3426db05b996481ca31e95fff3734cf23e0f51bc"
  },
  "overlay-ports": [
    "path/to/a2a-cpp/vcpkg-overlay-ports"
  ]
}

Then configure the application with the vcpkg toolchain file on the first CMake configure and use the installed CMake package:

find_package(a2a_cpp CONFIG REQUIRED)
target_link_libraries(my_a2a_app PRIVATE a2a::client a2a::server a2a::core)

A complete example is available in examples/installed_package_consumer/.

Enable PostgreSQL store support

The overlay port exposes a postgres-store feature. Enable it in manifest mode when your application needs PostgreSQL-backed stores:

{
  "name": "my-a2a-app",
  "version-string": "0.4.0",
  "dependencies": [
    {
      "name": "a2a-cpp",
      "features": ["postgres-store"]
    }
  ]
}

When the feature is enabled, link the additional target where needed:

target_link_libraries(my_a2a_app PRIVATE a2a::store_postgres)

Classic mode smoke install

For a direct overlay smoke test, run classic mode from a directory that does not contain a vcpkg.json manifest:

mkdir -p /tmp/a2a-vcpkg-smoke
cd /tmp/a2a-vcpkg-smoke
"$VCPKG_ROOT/vcpkg" install a2a-cpp --overlay-ports=/path/to/a2a-cpp/vcpkg-overlay-ports

Add a triplet if needed:

"$VCPKG_ROOT/vcpkg" install a2a-cpp:x64-linux --overlay-ports=/path/to/a2a-cpp/vcpkg-overlay-ports

Binary caching

Large dependencies such as gRPC and protobuf can take time to build. Enable binary caching for local and CI runs:

export VCPKG_BINARY_SOURCES="clear;files,$HOME/.cache/vcpkg-binary-cache,readwrite"
mkdir -p "$HOME/.cache/vcpkg-binary-cache"

On Windows PowerShell:

$env:VCPKG_BINARY_SOURCES = 'clear;files,C:\vcpkg-binary-cache,readwrite'
New-Item -ItemType Directory -Force C:\vcpkg-binary-cache | Out-Null

Troubleshooting

  • CMake cannot find gRPC or Protobuf: confirm CMAKE_TOOLCHAIN_FILE points to scripts/buildsystems/vcpkg.cmake before the first configure. If you configured without it, delete the build directory and configure again.
  • Unexpected manifest behavior in classic mode: classic vcpkg install a2a-cpp should be run outside directories containing vcpkg.json, otherwise vcpkg switches to manifest mode.
  • Different host and target triplets: pass both VCPKG_TARGET_TRIPLET and VCPKG_HOST_TRIPLET when cross-compiling or when CI uses a custom host triplet.
  • Slow clean builds: enable binary caching and prefer release-only dependency triplets for CI jobs that only link release configurations.
  • Example executable is not in the build root on Windows: Visual Studio is multi-configuration; use build-example-<app>/RelWithDebInfo/a2a_example.exe, or let scripts/run_examples.sh locate and run it.
  • The dependency helper reports an unsupported shell on Windows: run scripts/install_build_deps.sh from Git Bash rather than another Windows shell.

API Reference

The generated C++ API reference is built from public headers under include/a2a/**.

Generated reference

When published with the documentation site, open:

Generate locally

./scripts/generate_api_reference.sh

The script writes generated pages to book-build/api/cpp.

Public API areas

  • a2a::core: results, errors, protocol constants, JSON/protobuf helpers, Agent Card support, task state helpers, and versioning.
  • a2a::client: A2AClient, transports, discovery, auth hooks, call options, interceptors, and streaming observers.
  • a2a::server: executor, dispatcher, transports, interceptors, task stores, task lifecycle helpers, push notifications, and Agent Card serialization.
  • a2a::http: shared outbound HTTP client abstraction used by default REST/JSON-RPC/discovery/push paths when libcurl is enabled.