Skip to main content

protoLabs A2A conventions layer (Python) — the 4 custom extensions + agent-card + auth, on top of a2a-sdk. Mirrors @protolabs/a2a (TS, in protoWorkstacean).

Project description

protolabs-a2a

A thin Python conventions layer on top of the official a2a-sdk (A2A spec 1.0). a2a-sdk owns every piece of protocol mechanics — JSON-RPC dispatch, SSE streaming, the task lifecycle, push-notification delivery. This package owns only what is specific to the protoLabs fleet, so every agent (in-process Ava, roxy, ORBIS, pwnDeck, protoAgent) interoperates byte-for-byte.

It is the Python mirror of the TypeScript reference layer @protolabs/a2a, which lives in protoWorkstacean (packages/a2a / the @protolabs/a2a workspace). The wire contract below — extension URIs, payload shapes, and the metadata convention — is shared verbatim across both. Change one, change the other.

Install

pip install git+https://github.com/protoLabsAI/protolabs-a2a.git

Or pin it as a git dependency (e.g. in pyproject.toml):

dependencies = [
    "protolabs-a2a @ git+https://github.com/protoLabsAI/protolabs-a2a.git",
]

Requires Python >=3.11 and pulls in a2a-sdk>=1.1.

What's in it

Module Responsibility
parts Build / read the A2A 1.0 member-discriminated Part shape (generic content parts).
extensions The four custom metadata conventions: extension-URI constants (the metadata key + card declaration), payload types, *_metadata / parse_*.
agent_card build_agent_card(...) — provider, JSONRPC interface, extension declarations, auth schemes.
auth The apiKey (X-API-Key) and bearer security-scheme builders.

Public API

Everything below is exported at the top level (import protolabs_a2a as pa):

Partstext_part, data_part, read_text, read_data, part_mime, MIME_KEY, DATA_MEDIA_TYPE

Extensions — URIs (the metadata key and the card declaration) — COST_EXT_URI, CONFIDENCE_EXT_URI, WORLDSTATE_DELTA_EXT_URI, TOOL_CALL_EXT_URI, ALL_EXTENSION_URIS, EXTENSION_DESCRIPTIONS

Extensions — build metadata fragmentscost_metadata, confidence_metadata, worldstate_delta_metadata, tool_call_metadata, merge_extension_metadata

Extensions — parse (read a metadata map) — parse_cost, parse_confidence, parse_worldstate_delta, parse_tool_call

Extensions — payload typesCostUsage, CostPayload, ConfidencePayload, WorldstateDelta, WorldstateDeltaPayload, ToolCallPayload

Agent cardbuild_agent_card, protolabs_provider, jsonrpc_interface, PROVIDER_ORGANIZATION, PROVIDER_URL

Authsecurity_schemes, security_requirements, api_key_scheme, bearer_scheme, API_KEY_SCHEME_NAME, BEARER_SCHEME_NAME, API_KEY_HEADER

Extension data: the metadata convention

Each extension contributes its payload to the metadata map of a core A2A object, keyed by the extension URI:

"metadata": {
  "https://proto-labs.ai/a2a/ext/cost-v1": { "usage": { "input_tokens": 1500, "output_tokens": 420 }, "costUsd": 0.01, "success": true }
}

This is the convention the A2A spec prescribes — "Extensions should place custom attributes in the metadata map present on core data structures" (extensions.md → Limitations) — and the one the official Timestamp extension follows verbatim. The same URI is both the metadata key and the capabilities.extensions[].uri card declaration, with the version encoded in the URI (…-v1).

Each *_metadata helper returns a one-key fragment {<EXT_URI>: <payload>}; merge it into the target object's metadata (merge_extension_metadata combines several). parse_* reads a metadata map and returns the payload iff its URI key is present. Where each attaches:

Extension URI (metadata key + card declaration) Attaches to
cost-v1 https://proto-labs.ai/a2a/ext/cost-v1 terminal Artifact.metadata
confidence-v1 https://proto-labs.ai/a2a/ext/confidence-v1 terminal Artifact.metadata
worldstate-delta-v1 https://proto-labs.ai/a2a/ext/worldstate-delta-v1 terminal Artifact.metadata
tool-call-v1 https://proto-labs.ai/a2a/ext/tool-call-v1 status-frame Message.metadata

Payload shapes:

  • cost-v1{usage:{input_tokens, output_tokens, cache_creation_input_tokens?, cache_read_input_tokens?}, durationMs?, costUsd?, success?}
  • confidence-v1{confidence, explanation?, success?}
  • worldstate-delta-v1{deltas:[{domain, path, op:"set"|"inc"|"push", value}]}
  • tool-call-v1{toolCallId, name, phase:"started"|"completed"|"failed", args?, result?, error?}

Usage

import protolabs_a2a as pa
from a2a.types import AgentSkill

# Build extension metadata fragments and merge them into the terminal Artifact's
# metadata map (each fragment is {<EXT_URI>: <payload>}):
artifact.metadata = pa.merge_extension_metadata(
    pa.cost_metadata({"input_tokens": 1500, "output_tokens": 420}, duration_ms=900, cost_usd=0.01, success=True),
    pa.confidence_metadata(0.92, explanation="high coverage"),
    pa.worldstate_delta_metadata([{"domain": "board", "path": "data.backlog", "op": "inc", "value": 1}]),
)

# A streaming tool-call event rides on the status update's Message.metadata:
status_message.metadata = pa.tool_call_metadata("call_1", "file_bug", "completed", result="BUG-12")

# Parse (returns the typed payload iff the extension's URI key is present, else None):
payload = pa.parse_cost(artifact.metadata)

# Build a 1.0 agent card with the fleet conventions:
card = pa.build_agent_card(
    name="protoagent",
    description="…",
    url="http://protoagent:7870/a2a",
    version="1.0.0",
    skills=[AgentSkill(id="chat", name="Chat", description="…", tags=["chat"])],
    bearer=True,          # advertise the bearer scheme
)

The agent owns which extensions it emits — pass extension_uris=[…] to build_agent_card to declare a subset; it defaults to all four.

Generic parts. parts (text_part, data_part, read_text, read_data) still builds/reads the A2A 1.0 member-discriminated Part shape for real content (and is reused by skills). The four extensions above are telemetry about a task, so they live in metadata, not in parts[].

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

protolabs_a2a-0.2.0.tar.gz (15.6 kB view details)

Uploaded Source

Built Distribution

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

protolabs_a2a-0.2.0-py3-none-any.whl (14.9 kB view details)

Uploaded Python 3

File details

Details for the file protolabs_a2a-0.2.0.tar.gz.

File metadata

  • Download URL: protolabs_a2a-0.2.0.tar.gz
  • Upload date:
  • Size: 15.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for protolabs_a2a-0.2.0.tar.gz
Algorithm Hash digest
SHA256 1464f095af797fdd1c587ac8fbe63dc1bb950e9fc761a49680873f30b8f3dbd4
MD5 42f4252a6a4e9b9d07762fc3c44e66e0
BLAKE2b-256 86c06c39abc4d258767678d411cf6f53cb233f051447ece29d4e2a503afc6e85

See more details on using hashes here.

Provenance

The following attestation bundles were made for protolabs_a2a-0.2.0.tar.gz:

Publisher: publish.yml on protoLabsAI/protolabs-a2a

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

File details

Details for the file protolabs_a2a-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: protolabs_a2a-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 14.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for protolabs_a2a-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 d7297615048583c3e4a5df34a9ac1f09421ad072d3af099acbce646fa0217825
MD5 7375a05fd08923e9269afe81bfb0c002
BLAKE2b-256 655638b4e9dd390f82dd53fe6cdcef7ac91614273cb9b6502e78d31a96eaf4ce

See more details on using hashes here.

Provenance

The following attestation bundles were made for protolabs_a2a-0.2.0-py3-none-any.whl:

Publisher: publish.yml on protoLabsAI/protolabs-a2a

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