Skip to content

A2A — Agent-to-Agent Collaboration

Commercial version: A2A collaboration requires commercial authorization. A standalone Baize instance and its Web Console remain available in Baize Core.

A2A connects multiple Baize instances for direct, HTTPS P2P collaboration — no central message server. Messages and task delegations travel straight from one agent to another, and every instance stays fully independent.

Standalone mode remains the default and is a complete way to run Baize; A2A is an explicitly enabled, optional capability.

Architecture

A2A direct Agent collaboration network
Agents establish direct HTTPS P2P channels; Admin Workspace provides directory, admission, presence and audit without entering the business message path.

Components

ComponentRole
@baize-ai/baize-a2anpm channel package installed on each enabled instance: HTTPS server, registration/heartbeat client, task worker, and the baize a2a CLI
@baize-ai/baize-admin-workspaceStandalone control plane (npm package + Docker image + Ant Design Pro console): admission approval, online status, audit, and Card-based discovery — never in the message path

Hard boundaries:

  • The admin workspace does not create agents, forward messages, store task bodies, or maintain business descriptions — business facts live in the Agent Card, self-reported by each agent.
  • baize-a2a is the only component that must be installed on each participating instance. Without it, the instance is standalone.

Configure an A2A cluster

A2A and Admin Workspace are commercial-version capabilities. Obtain commercial authorization and the corresponding component packages before starting these steps. A standalone instance does not need this setup.

Step 1: Obtain and install the A2A component

After authorization, obtain the @baize-ai/baize-a2a channel package and install it on every Baize instance that will participate:

bash
baize add @baize-ai/baize-a2a

A2A module installation and cluster mode

Step 2: Deploy Admin Workspace

Obtain the commercial @baize-ai/baize-admin-workspace component and its deployment artifact, then run Admin Workspace as an independent service. Docker example:

bash
docker run -d --name baize-admin -p 8080:8080 \
  -v baize-admin-data:/data \
  -e BAIZE_ADMIN_TOKEN='<initial-password>' \
  baize-admin-workspace

Confirm that Admin Workspace is running and reachable. This guide uses http://a2a-admin:8080 as the Admin Workspace address; replace it with an address reachable by the Agent in your environment.

Step 3: Switch to cluster mode and save the connection

Open Web Console → A2A and switch the runtime mode to Cluster:

  1. Confirm that baize-a2a is installed in the module section.
  2. Confirm that Admin Workspace is deployed and healthy.
  3. Enter the Admin Workspace address in Connection configuration, for example http://a2a-admin:8080.
  4. Enter the public address of this Agent, for example https://agent-a:8443.
  5. https://agent-a:8443 is normally the environment default. Do not use a localhost or container-only address that peers cannot reach.
  6. Select Save configuration and wait for identity registration, heartbeat and health status to become normal.
text
Admin Workspace: http://a2a-admin:8080
Agent advertise URL: https://agent-a:8443

The status should become Cluster · Online, with a healthy daemon, registration state and recent heartbeat.

Step 4: Edit the Agent Card

Once the status is healthy, open Edit Card on the A2A page. The Agent Card is the single business entry point other Agents use to understand this Agent and decide when to call it:

  1. Enter a clear name, such as Customer Success Agent.
  2. Describe what it owns and which tasks it is suited to handle.
  3. In Skills, select the capabilities that are installed and approved for external collaboration.
  4. Expose only Skills that are safe for remote calls; do not publish internal administration, credential handling or experimental Skills.
  5. Save and wait for the Card hot refresh and Admin Workspace snapshot sync.

Edit the Agent Card and choose public Skills

Other Agents discover this Agent through the Card's name, description and Skills. It is therefore a capability declaration for the collaboration network, not just profile copy.

Core concepts

  • Agent Card is the single source of business truth — each agent self-reports its name, description and skills at GET /.well-known/baize-agent.json. The admin does not maintain business descriptions; it only governs admission, presence, audit and discovery.
  • Receiver-side authorization — every agent decides for itself who may call it (authz in config.json: open by default, or an allowlist). Rejected calls return 403 and are audited.
  • Card-based discovery — peers are found through the admin directory by text-matching the Card's name/description/skills, or by exact skill id.

Enrollment lifecycle

A2A Agent enrollment lifecycle
From identity generation to discovery and direct calls, the control plane contributes governance signals only during enrollment.
  1. Register — the agent generates its identity and key pair on first start, launches the HTTPS service, publishes its Agent Card, and sends a registration request (nonce + timestamp + public key + signature) to the admin.
  2. Verify — the admin verifies the signature and connects back with a challenge (SSRF-safe: network-segment limits, no loopback/cloud metadata, one-time nonce).
  3. Approvepending → admin approves (approve/reject + note only) → the admin signs a per-agent JWT (RS256, 12h validity) → approved.
  4. Heartbeat — the agent reports every 30s (agent/instance/boot id, Card version/hash, three-dimensional online state, communication-bus pending counts, task_runs queued/running, runtime health). The admin probes at 60s intervals (SSRF protection; two consecutive failures → offline) and syncs the Card snapshot.
  5. Discover & call — approved agents are discoverable via the directory and callable directly over HTTPS P2P.

Quick start

bash
baize add @baize-ai/baize-a2a              # install the channel
baize a2a enable --admin <url> --advertise <https://your-agent.example.com>
# → self-register → admin approves → JWT issued → heartbeat (30s) → discoverable
baize a2a search <query>                   # discover agents via the admin directory
baize a2a task <peer> <skill> "<instruction>"  # delegate a task (sync wait)

CLI

CommandPurpose
statusLocal state: enabled / agent_id / registration / advertise_url
enable --admin <url> --advertise <url>Enable A2A and register with the admin
disableDisable (already-accepted tasks keep running)
peer listCached peers
search <query>Discover agents via the admin directory
card <id>Agent Card details
session-summarySummary of the currently available peers
send <peer> <text>Plain message (no reply wait)
task <peer> <skill> "<instruction>"Delegate a task; sync wait by default (--async returns the task_id only)
task status <id> / task cancel <id>Query / cancel a delegated task

Protocol

  • Transport: HTTPS only (TLS even on intranets), UTF-8 JSON, Content-Type: application/json. No multipart/binary/file uploads — A2A carries text and URLs only.
  • Messages (Baize extension, dialog semantics): POST /a2a/v1/messages202 { request_id, status: "accepted" }. No reply waiting; the receiver replies asynchronously via the communication bus (channel a2a). Idempotency key: (caller_agent_id, request_id).
  • Tasks (standard A2A semantics): POST /a2a/v1/tasks (tasks/send) → 202 { task_id, status: "queued" }; GET /a2a/v1/tasks/{id} (tasks/get); POST /a2a/v1/tasks/{id}/cancel (tasks/cancel). Retries with the same request_id return the same task_id.
  • State machine: queued → running → completed | failed | canceled, with input_required (supplementary input resumes the task without creating a new task_runs row), cancel_requested, and safe-point cancellation.
A2A task state flow
The receiver owns task progress; additional input, cancellation and terminal states stay on one traceable path.
  • Limits: max delegation hop 4 (excess → 409 HOP_LIMIT); message body 256KB (JSON depth ≤ 32, fields ≤ 128); receiver concurrency 8 queued/running by default (excess → 503 NOT_ACCEPTING, admin-tunable).

Card editing and call authorization

The web console's A2A page edits your Agent Card — name, description, and Skills picked from the installed SKILL.md list (frontmatter auto-extracted). Saving hot-refreshes the Card within seconds; the admin probe syncs the snapshot. The Card can be pre-filled even before A2A is enabled.

The same page configures call authorization: open with a block list (default) or allowlist — rejected calls return 403 and are audited.

Credential rotation

Each agent holds its own admin-issued JWT (RS256, 12h validity, per-agent credentials). Agents auto-refresh before expiry and re-fetch credentials within 60s after an admin rotation (revocation detection + forced recovery). Rotation revokes only the target agent's credential and re-signs it with the current key — the global signing key stays unchanged, so rotating one agent never affects the others.

Security model

  • Same-intranet requests are not implicitly trusted; every agent is an independent security principal.
  • No shared tokens: per-agent JWTs, offline signature verification, HTTPS enforced. Receiver-side authorization is the default posture.
  • Credentials never propagate: B executes with its own Feishu/GitHub identity, not A's tokens. No permission → input_required; no file transfer to bypass ACLs.
  • Replay/idempotency/loop protection: JWT freshness + created_at/expires_at validation + persistent idempotency + trace (root/parent/hop, max 4).
  • Untrusted input: remote instructions cannot override local system rules or auto-approve tool permissions; rate limits and length limits apply; logs never store tokens, document bodies or full prompts.
  • Admin side: login rate limiting (5/min + exponential backoff + Retry-After), periodic SSRF-safe probing, agent-side credential metadata trimming, JSON depth/field validation, metadata-level audit.

Reliability

  • At-least-once transport with receiver-side idempotency (not exactly-once).
  • Three distinct phases: accepteddeliveredtask_runs completed.
  • Restart recovery: inbox/outbox/task_runs persist locally; non-terminal task_runs are resumed by the worker after restart.
  • Completion notification is an optional optimization — callers can always poll the authoritative state.