Skip to main content

A2A-SDL: agent-to-agent self-describing protocol reference implementation

Project description

A2A-SDL (Reference Implementation)

A2A-SDL is a machine-optimized, self-describing protocol for cross-agent communication with strict validation, canonical encoding, and optional cryptographic security.

This repository implements:

  • Envelope validation and limits (max_bytes, max_depth, max_array_len)
  • JSON canonical encoding and optional canonical CBOR
  • Embedded/URI schema descriptors with content-hash checks
  • Optional JSON Schema validation (when jsonschema is installed)
  • Ed25519 signing/verification
  • X25519 + ChaCha20-Poly1305 payload encryption
  • Replay nonce cache
  • HTTP transport (stdlib server/client + optional FastAPI app)
  • Local IPC transport binding (length-prefixed uint32_be frames)
  • CLI for send/serve/keys/validation
  • Structured error mapping for protocol validation failures (UNSUPPORTED_CT, SCHEMA_INVALID, SECURITY_UNSUPPORTED)
  • HTTP client retries/backoff and configurable timeout (a2a send --timeout --retry-attempts --retry-backoff-s)
  • Optional server-side replay enforcement (a2a serve --replay-protection)
  • Trace enforcement with hop limits (trace.root_id, trace.span_id, trace.hops) and derived child trace on responses
  • Optional automatic content-type negotiation fallback (a2a send --auto-negotiate)
  • Secure policy mode for mandatory enc+sig+replay, key-based authz, and allowlisted agents
  • Tamper-evident hash-chained audit log with optional Ed25519-signed audit receipts
  • WebSocket transport processing now matches HTTP validation/security behavior with structured error.v1 responses
  • Built-in multi-buddy swarm command (a2a swarm, 2+ buddies) that coordinates Codex buddies through A2A envelopes
  • Executable toolcall.v1 path with built-in tools (sys.ping, math.add)
  • Pluggable request handlers via a2a serve --handler-spec <ct>=<module>:<callable>
  • Ingress hardening: oversized Content-Length rejected before body read
  • URI-schema hardening: untrusted URI descriptors rejected on HTTP/WS/IPC ingress and transport client preflight
  • Key lifecycle policy support: key rotation sets, revoked key IDs, and per-kid expiry checks
  • Plugin safety controls: deny-by-default tool execution and strict custom handler module/manifest validation
  • Stress and fuzz testing for malformed envelopes and concurrent HTTP load
  • Durable replay protection via optional SQLite-backed nonce cache (--replay-db-file)
  • Distributed replay protection via optional Redis backend (--replay-redis-url)
  • Production transport controls: TLS/mTLS options and production deployment profile
  • Outbound HTTPS client mTLS controls for a2a send (--tls-ca-file, client cert/key options)
  • Admission control with concurrency + token-bucket rate limiting
  • Optional admin observability endpoints (/healthz, /readyz, /metrics) with Prometheus-compatible metrics output
  • Audit signature verification support for signed audit chains
  • Optional external audit hash anchoring (--audit-anchor-url) with fail-open/fail-closed modes
  • Runtime capability-version enforcement (cap.a2a_sdl.v) for peer compatibility checks
  • Runtime migration/deprecation policy enforcement via --version-policy-file
  • Dynamic trust lifecycle protocol (trustsync.v1) with signed registry update proposals
  • Negotiated session binding handshake (session.v1) with optional detached Ed25519 binding signature
  • Fine-grained tool authorization (per-agent grants and required scopes via --tool-policy-file)

How It Works

At runtime, every message is an envelope with:

  • Identity (from, to) for routing and access-policy checks
  • Payload type (ct) for handler dispatch and schema validation
  • Payload (payload) with request/response body
  • Schema descriptor (schema) for self-describing validation
  • Security (sec) for signatures, encryption metadata, and replay tokens
  • Trace (trace) for request lineage and hop control

Typical request flow:

  1. Build envelope with build_envelope(...).
  2. Canonically encode (json, optional cbor) with deterministic ordering.
  3. Optionally encrypt payload and attach replay nonce/expiry.
  4. Optionally sign envelope.
  5. Send over transport (HTTP, WS, or local IPC).
  6. Receiver validates envelope, capability version compatibility, security policy, replay cache, and schema.
  7. Handler returns a typed response envelope (toolresult.v1, task.v1, or error.v1).

Project Structure

Core modules:

  • a2a_sdl/envelope.py: envelope construction, validation limits, trace checks.
  • a2a_sdl/schema.py: builtin descriptors, hash checks, JSON schema integration.
  • a2a_sdl/codec.py: canonical JSON/CBOR encode/decode.
  • a2a_sdl/security.py: Ed25519 signatures and X25519+ChaCha20-Poly1305 encryption.
  • a2a_sdl/policy.py: secure-required policy enforcement (enc+sig+replay, key allowlists).
  • a2a_sdl/replay.py: nonce cache for replay protection.
  • a2a_sdl/transport_http.py: stdlib server/client, retries, fallback negotiation.
  • a2a_sdl/transport_ws.py: websocket payload processing with protocol-aligned errors.
  • a2a_sdl/transport_ipc.py: length-prefixed local IPC transport.
  • a2a_sdl/swarm.py: multi-buddy Codex orchestration over A2A envelopes.
  • a2a_sdl/handlers.py: content-type router, builtin handlers, and tool registry.
  • a2a_sdl/cli.py: operational entrypoints (send, serve, swarm, keygen, etc).

Tests:

  • tests/ contains unit coverage for envelope rules, security, transports, policy, and swarm convergence behavior.

Installation

Recommended (isolated CLI install with uv):

uv tool install "a2acrpt[full]"
uv tool update-shell

From local checkout (editable dev install as a tool):

uv tool install --editable "/path/to/crpt[full]"

From GitHub (without publishing to PyPI):

uv tool install "git+https://github.com/psspssr/crpt.git"

One-off command execution without permanent install:

uv tool run --from "a2acrpt[full]" a2a --help

Alternative installers:

pip install "a2acrpt[full]"
pipx install "a2acrpt[full]"

Useful extras:

  • a2acrpt[cbor] for CBOR codec support
  • a2acrpt[schema] for JSON Schema validation
  • a2acrpt[http] for FastAPI/uvicorn adapter
  • a2acrpt[ws] for websocket transport
  • a2acrpt[redis] for distributed replay cache backend

Quick Start

uv tool install --force "/root/crpt[full]"
a2a keygen --out-dir .keys

Send a task over HTTP:

a2a serve --host 127.0.0.1 --port 8080 --deployment-mode dev --allow-insecure-http
# in another shell:
a2a send --url http://127.0.0.1:8080/a2a --ct task.v1 --payload-file a2a_sdl/examples/task_min_payload.json --timeout 30 --retry-attempts 2 --retry-backoff-s 0.25 --auto-negotiate

Secure server mode (mandatory encrypted/signed inbound requests + audit log):

# trusted_signing_keys.json: { "<sender-kid>": "<ed25519-public-key>" }
# decrypt_keys.json: { "<server-recipient-kid>": "<x25519-private-key>" }
# agent_kid_map.json: { "<sender-agent-id>": "<sender-kid>" }

a2a serve \
  --host 127.0.0.1 --port 8080 \
  --deployment-mode prod \
  --secure-required \
  --tls-cert-file /etc/a2a/tls/server.crt \
  --tls-key-file /etc/a2a/tls/server.key \
  --replay-db-file /var/lib/a2a/replay.db \
  --trusted-signing-keys-file trusted_signing_keys.json \
  --decrypt-keys-file decrypt_keys.json \
  --agent-kid-map-file agent_kid_map.json \
  --allowed-agent did:key:sender-agent \
  --audit-log-file /tmp/a2a_audit.log

Key lifecycle controls (rotation + revocation):

# key_registry.json may include:
# trusted_signing_keys, required_kid_by_agent, allowed_kids_by_agent,
# revoked_kids, kid_not_after, decrypt_private_keys
a2a serve \
  --host 127.0.0.1 --port 8080 \
  --deployment-mode prod \
  --tls-cert-file /etc/a2a/tls/server.crt \
  --tls-key-file /etc/a2a/tls/server.key \
  --replay-db-file /var/lib/a2a/replay.db \
  --key-registry-file key_registry.json

Secure sender mode (enc+sig+replay auto-applied):

a2a send \
  --url https://127.0.0.1:8080/a2a \
  --ct task.v1 \
  --payload-file a2a_sdl/examples/task_min_payload.json \
  --secure \
  --sign-key .keys/ed25519_private.pem \
  --sign-kid did:key:sender-agent#sig1 \
  --encrypt-kid did:key:server#enc1 \
  --encrypt-pub .keys/x25519_public.b64

Production hardening knobs:

a2a serve \
  --deployment-mode prod \
  --tls-cert-file /etc/a2a/tls/server.crt \
  --tls-key-file /etc/a2a/tls/server.key \
  --tls-ca-file /etc/a2a/tls/ca.crt \
  --tls-require-client-cert \
  --replay-db-file /var/lib/a2a/replay.db \
  --admission-max-concurrent 256 \
  --admission-rate-rps 400 \
  --admission-burst 800

Distributed replay on Redis:

a2a serve \
  --deployment-mode prod \
  --tls-cert-file /etc/a2a/tls/server.crt \
  --tls-key-file /etc/a2a/tls/server.key \
  --replay-redis-url redis://redis.internal:6379/0 \
  --replay-redis-prefix a2a:replay:prod

Sender-side HTTPS + mTLS:

a2a send \
  --url https://a2a.example.com/a2a \
  --ct task.v1 \
  --payload-file a2a_sdl/examples/task_min_payload.json \
  --tls-ca-file /etc/a2a/tls/ca.crt \
  --tls-client-cert-file /etc/a2a/tls/client.crt \
  --tls-client-key-file /etc/a2a/tls/client.key

Operational observability endpoints:

# Enable GET /healthz, /readyz, /metrics
a2a serve --deployment-mode dev --allow-insecure-http --admin-endpoints

# Protect /readyz and /metrics with a token
a2a serve --deployment-mode dev --allow-insecure-http --admin-token secret123
curl -H "Authorization: Bearer secret123" http://127.0.0.1:8080/readyz
curl -H "Authorization: Bearer secret123" http://127.0.0.1:8080/metrics

Transport Details

  • HTTP: reference request/response transport, retry/backoff support, content-type negotiation fallback, optional TLS/mTLS, and admission control.
  • WS: same protocol validation path as HTTP; protocol violations map to structured error.v1.
  • IPC: local framed transport (uint32_be + payload bytes), useful for same-host agent orchestration.

All transports converge on shared envelope validation and handler semantics to keep behavior consistent.

Handler Extensibility (New)

Two extensibility layers are built in:

  • Tool registry for toolcall.v1:
    • sys.ping: liveness + echo payload
    • math.add: numeric aggregation from args.values
  • Content-type router:
    • default implementation for task.v1, toolcall.v1, negotiation.v1, trustsync.v1, session.v1
    • custom content types can be registered at server startup

Protocol metadata improvement:

  • response envelopes now advertise available tools in cap.tools
  • negotiation responses include payload.available_tools

Example custom handler wiring:

a2a serve \
  --host 127.0.0.1 --port 8080 \
  --allow-handler-module-prefix myproject.handlers \
  --handler-spec artifact.v1=myproject.handlers:artifact_handler

artifact_handler(request) must return a valid A2A response envelope.

By default, tool execution is deny-by-default in a2a serve. Allow tools explicitly:

a2a serve --allow-tool sys.ping --allow-tool math.add

Fine-grained tool authorization policy file:

{
  "allowed_tools_by_agent": {
    "did:key:planner-a": ["math.add", "sys.ping"]
  },
  "required_scopes_by_tool": {
    "math.add": "tool:math.add"
  }
}
a2a serve --tool-policy-file tool_policy.json

Use --unsafe-allow-unmanifested-handlers only for trusted local development.

Security Model

--secure-required mode on server enforces all of:

  • encrypted payload (enc)
  • valid trusted signature (sig)
  • replay token with nonce + expiry (replay)
  • sender identity/key mapping and optional allowlisted agent IDs

--deployment-mode prod behavior:

  • treats secure mode as required
  • requires TLS cert/key unless explicitly overridden with --allow-insecure-http
  • requires durable replay storage (--replay-db-file) unless overridden

Operational components:

  • ReplayCache (memory), SQLiteReplayCache (durable), or RedisReplayCache (distributed) blocks duplicate nonce usage.
  • Audit chain persists tamper-evident events, can verify Ed25519 signatures over entries, and can anchor entry hashes to external HTTP(S) sinks.
  • Structured errors intentionally avoid leaking sensitive internals.

Trust lifecycle sync:

  • trustsync.v1 supports discover snapshots and signed propose registry updates.
  • Configure update verification key with --trust-sync-verify-key-file.

Session binding handshake:

  • session.v1 establishes a negotiated binding ID over profile+nonce(+expiry).
  • Configure detached signature on binding acknowledgements with --session-binding-signing-key-file.

Runtime migration/deprecation policy:

  • Load with --version-policy-file.
  • Supports min/max peer protocol bounds, required peer version presence, deprecation deadlines, and allowed content-type version ranges.

Programmatic local IPC usage:

from a2a_sdl.handlers import default_handler
from a2a_sdl.transport_ipc import IPCServer, send_ipc
from tests.test_helpers import make_task_envelope

server = IPCServer("127.0.0.1", 9099, handler=default_handler)
# run server.serve_forever() in a background thread/process
response = send_ipc("127.0.0.1", 9099, make_task_envelope(), encoding="json")

Multi-buddy autonomous swarm (Codex-backed, A2A toolcall envelopes):

a2a swarm \
  --goal "Drive protocol to near-final feature completeness." \
  --ports 8211,8212 \
  --rounds 8 \
  --near-final-rounds 2 \
  --workdir /root/crpt

Swarm report fields:

  • converged=true, mode=near_final: majority of buddies reported near_final for the configured streak.
  • converged=true, mode=stabilized_working: buddies remained working for multiple rounds with no major new feature movement.
  • converged=false, mode=not_converged: max rounds reached without either condition.

Swarm behavior notes:

  • Each buddy runs as an A2A HTTP endpoint backed by a codex exec call.
  • Coordinator sends toolcall.v1 requests round-by-round with handoff text chaining.
  • Near-final convergence uses majority voting across 2+ buddies.
  • If buddies stabilize in working state for repeated rounds, coordinator marks stabilized_working to avoid endless loops.

Test

python3 -m unittest discover -s tests -v

Release (Maintainers)

One-time setup:

  1. Create a PyPI project named a2acrpt.
  2. In PyPI, add a Trusted Publisher for this GitHub repo/workflow.
  3. In GitHub repo settings, create environment pypi (optional protection rules).

Automated release:

  1. Bump version in pyproject.toml.
  2. Commit and push to main.
  3. Create and push a version tag (for example v0.1.1): git tag v0.1.1 && git push origin v0.1.1
  4. GitHub Actions workflow .github/workflows/publish-pypi.yml builds and publishes to PyPI.

CI hardening workflow:

  • .github/workflows/ci.yml runs lint (ruff), type checks (mypy), unit tests (3.11/3.12), and validates that v* tags match pyproject.toml version.

Manual local release check:

python -m pip install -U build twine
python -m build
python -m twine check dist/*

Notes

  • CBOR support requires pip install -e .[cbor].
  • JSON Schema validation requires pip install -e .[schema].
  • FastAPI server adapter requires pip install -e .[http].
  • Versioning policy details: docs/versioning-policy.md.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

a2acrpt-0.1.0.tar.gz (72.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

a2acrpt-0.1.0-py3-none-any.whl (58.7 kB view details)

Uploaded Python 3

File details

Details for the file a2acrpt-0.1.0.tar.gz.

File metadata

  • Download URL: a2acrpt-0.1.0.tar.gz
  • Upload date:
  • Size: 72.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for a2acrpt-0.1.0.tar.gz
Algorithm Hash digest
SHA256 6fd21df183229ebd0c00c747d94cb64d6e90cebe795f7d77c45bfc730fb27fea
MD5 f4398c832882b1ca548d64ae4f712831
BLAKE2b-256 23f81668a8632b9ab4d0cc727c5560a1fd99815e4b485985b1933f368a7dcee2

See more details on using hashes here.

Provenance

The following attestation bundles were made for a2acrpt-0.1.0.tar.gz:

Publisher: publish-pypi.yml on psspssr/crpt

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file a2acrpt-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: a2acrpt-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 58.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for a2acrpt-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 34d9e9b308e0b8e25a375c19c77d6531d0d8c39b6b3ffeb0e101281ae86a42de
MD5 18e879e0c696a6179fa768e9921eaaed
BLAKE2b-256 60e27259da2259a43910c55e4ecd2fa54d76da32ac71803dd51ad6322df3fd1a

See more details on using hashes here.

Provenance

The following attestation bundles were made for a2acrpt-0.1.0-py3-none-any.whl:

Publisher: publish-pypi.yml on psspssr/crpt

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page