A2A Server
Publish Agent Cards and accept task submissions
A2A Client
Discover external agents and send tasks to them
Agent Card
An Agent Card is a JSON document that describes an agent’s identity, capabilities, and supported interaction modes. It is served at the well-known path/.well-known/agent.json per the A2A specification.
Agent Card Structure
Agent Capabilities
Agent Skills
A2A skills are capability descriptors, not the same as OpenFang skills. These describe what the agent can do for cross-framework discovery.
Example Agent Card
build_agent_card(). Each tool in the agent’s capability list becomes an A2A skill descriptor.
A2A Server
OpenFang serves A2A requests through the REST API:Agent Card
Publication at
/.well-known/agent.jsonAgent Listing
All agents at
/a2a/agentsTask Tracking
Via
A2aTaskStoreA2aTaskStore
TheA2aTaskStore is an in-memory, bounded store for tracking A2A task lifecycle:
Key Properties
- Bounded: When reaching
max_tasks, evicts oldest completed/failed/cancelled task (FIFO) - Thread-safe: Uses
Mutex<HashMap>for concurrent access - Kernel field: Stored as
kernel.a2a_task_store
Methods
insert(task)
insert(task)
Add a new task, evicting old ones if at capacity
get(task_id)
get(task_id)
Retrieve a task by ID
update_status(task_id, status)
update_status(task_id, status)
Change a task’s status
complete(task_id, response, artifacts)
complete(task_id, response, artifacts)
Mark as completed with response
fail(task_id, error_message)
fail(task_id, error_message)
Mark as failed with error
cancel(task_id)
cancel(task_id)
Mark as cancelled
Task Submission Flow
WhenPOST /a2a/tasks/send is called:
Handle response
On success: complete task with agent’s response
On failure: fail task with error message
On failure: fail task with error message
A2A Client
TheA2aClient struct discovers and interacts with external A2A agents:
Methods
discover(url)
Fetches
{url}/.well-known/agent.json and parses the Agent Cardsend_task(...)
Sends a JSON-RPC task submission
get_task(...)
Polls for task status
Auto-Discovery at Boot
When the kernel starts and A2A is enabled with external agents configured:Failed discoveries are logged as warnings but do not prevent boot.
Sending Tasks to External Agents
Task Lifecycle
AnA2aTask tracks the full lifecycle of a cross-agent interaction:
Task States
| Status | Description |
|---|---|
Submitted | Task received but not yet started |
Working | Task is being actively processed by the agent |
InputRequired | Agent needs more information from the caller |
Completed | Task finished successfully |
Cancelled | Task was cancelled by the caller |
Failed | Task encountered an error |
Message Format
Messages use an A2A-specific format with typed content parts:Artifacts
Tasks can produce artifacts (files, structured data) alongside messages:A2A Configuration
A2A is configured inconfig.toml under the [a2a] section:
Configuration Fields
| Field | Type | Default | Description |
|---|---|---|---|
enabled | bool | false | Whether A2A endpoints are active |
listen_path | String | "/a2a" | Base path for A2A endpoints |
external_agents | Vec<ExternalAgent> | [] | External agents to discover at boot |
External Agent Configuration
| Field | Type | Description |
|---|---|---|
name | String | Display name for this external agent |
url | String | Base URL where the agent’s card is published |
If
a2a is None (not present in config), all A2A features are disabled. The A2A endpoints are always registered in the router but discovery and task store functionality requires enabled = true.A2A API Endpoints
| Method | Path | Description |
|---|---|---|
GET | /.well-known/agent.json | Agent Card for the primary agent |
GET | /a2a/agents | List all agent cards |
POST | /a2a/tasks/send | Submit a task to an agent |
GET | /a2a/tasks/{id} | Get task status and messages |
POST | /a2a/tasks/{id}/cancel | Cancel a running task |
GET /.well-known/agent.json
Returns the Agent Card for the first registered agent. If no agents are spawned, returns a placeholder card.GET /a2a/agents
Lists all registered agents as Agent Cards:POST /a2a/tasks/send
Submit a task. Request body follows JSON-RPC 2.0 format:GET /a2a/tasks/
Poll for task status. Returns404 if the task is not found or has been evicted.
POST /a2a/tasks//cancel
Cancel a running task. Sets its status toCancelled. Returns 404 if the task is not found.
Security
Rate Limiting
A2A endpoints go through the same GCRA rate limiter as all other API endpoints.
API Authentication
When
api_key is set in kernel config, all API endpoints (including A2A) require Authorization: Bearer <key> header. Exception: /.well-known/agent.json and health endpoint.Task Store Bounds
A2aTaskStore is bounded (default 1000 tasks) with FIFO eviction of completed/failed/cancelled tasks, preventing memory exhaustion.External Agent Discovery
A2aClient uses 30-second timeout and sends User-Agent: OpenFang/0.1 A2A header. Failed discoveries are logged but do not block kernel boot.Kernel-Level Protection
A2A tool execution flows through the same security pipeline as all other tool calls: capability-based access control, tool result truncation (50K character hard cap), universal 60-second timeout, loop guard detection, and taint tracking.
Source Files
- Protocol types and logic:
crates/openfang-runtime/src/a2a.rs - API routes:
crates/openfang-api/src/routes.rs - Config types:
crates/openfang-types/src/config.rs