car-a2a 0.17.0

Bridge between Common Agent Runtime and the Linux Foundation Agent2Agent (A2A) v1.0 protocol
Documentation

car-a2a

Agent2Agent (A2A) v1.0 bridge for Common Agent Runtime.

What it does

Exposes a CAR runtime as an A2A-compliant agent so peer agents — built on any A2A SDK (Python, JavaScript, Java, Go, .NET, or one of the Rust crates) — can discover the runtime via an Agent Card and submit work as A2A Tasks.

A2A is the Linux Foundation's open protocol for agent-to-agent interoperability. The full spec lives at https://a2a-protocol.org/latest/specification/.

Mapping

A2A CAR
Agent Card Manifest of registered tools + host metadata
Task One-shot wrapper around an ActionProposal
Message (parts) Free-form input from the peer; structured data parts become tool calls
Artifact One per ActionResult returned by the runtime
TaskState SUBMITTED → WORKING → COMPLETED/FAILED Lifecycle of Runtime::execute

Surface

Item Purpose
A2aDispatcher Transport-neutral JSON-RPC dispatcher for the 11 A2A methods
AgentCardSource Trait the dispatcher calls to (re)build the agent card on demand
TaskStore / InMemoryTaskStore Pluggable task persistence
message_to_proposal Compile an A2A Message into a CAR ActionProposal
action_results_to_artifacts Convert a ProposalResult into A2A Artifacts

Methods supported

  • message/send
  • tasks/get
  • tasks/list
  • tasks/cancel
  • tasks/pushNotificationConfig/{set,get,list,delete}
  • agent/getAuthenticatedExtendedCard

Out of scope for this prototype:

  • message/stream and tasks/resubscribe (Server-Sent Events)
  • gRPC and HTTP+JSON/REST transport bindings
  • Outbound A2A client calls — for those, use a2a-protocol-client or a2a-client from crates.io.

Status

Prototype. The dispatcher is exercised by unit tests against an in-process Runtime and InMemoryTaskStore. It is not yet wired into car-server-core::handler::run_dispatch or fronted by an HTTP listener — embedders pick the transport.

Example

use std::sync::Arc;
use car_a2a::{A2aDispatcher, AgentCard, InMemoryTaskStore};
use car_engine::Runtime;

let runtime = Arc::new(Runtime::new());
let store = Arc::new(InMemoryTaskStore::new());
let card_factory = Arc::new(|| AgentCard {
    name: "CAR runtime".into(),
    // ...fill in skills from runtime.tool_schemas() at refresh time
    # version: "1.0.0".into(),
    # description: String::new(),
    # url: String::new(),
    # provider: car_a2a::types::AgentProvider { organization: "you".into(), url: None },
    # capabilities: car_a2a::AgentCapabilities::default(),
    # default_input_modes: vec!["text".into()],
    # default_output_modes: vec!["text".into()],
    # skills: vec![],
    # additional_interfaces: vec![],
    # preferred_transport: Some("JSONRPC".into()),
    # protocol_version: "1.0".into(),
    # security_schemes: Default::default(),
    # supports_authenticated_extended_card: false,
    # security_requirements: vec![],
    # signatures: vec![],
});

let dispatcher = A2aDispatcher::new(runtime, store, card_factory);

// A peer's JSON-RPC request:
let result = dispatcher
    .dispatch("agent/getAuthenticatedExtendedCard", serde_json::Value::Null)
    .await
    .unwrap();