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 — MIME types, extension URIs, and the DataPart shape — 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.
extensions The four custom DataPart conventions: MIME + card-URI constants, payload types, emit_* / 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 — MIME constantsCOST_MIME, CONFIDENCE_MIME, WORLDSTATE_DELTA_MIME, TOOL_CALL_MIME

Extensions — card URIsCOST_EXT_URI, CONFIDENCE_EXT_URI, WORLDSTATE_DELTA_EXT_URI, TOOL_CALL_EXT_URI, ALL_EXTENSION_URIS

Extensions — emitemit_cost, emit_confidence, emit_worldstate_delta, emit_tool_call

Extensions — parseparse_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

The wire shape (A2A 1.0)

A custom DataPart is the member-discriminated union the JS reference emits:

{
  "content": { "$case": "data", "value": <payload> },
  "metadata": { "mimeType": "<MIME>" },
  "filename": "",
  "mediaType": "application/json"
}

The discriminator is metadata.mimeType; the payload lives at content.value. parts.data_part(payload, mime) produces exactly this; parts.read_data(part) returns (mime, payload). read_* also accepts the flattened proto3-JSON form ({"data": …}) that a2a-sdk's protobuf serializer emits, so a part produced by either runtime parses.

Serializer note. a2a-sdk 1.1 represents Part as a protobuf message and serializes it with proto3-JSON, which flattens the content oneof to a top-level data (or text) field — i.e. {"data": …, "metadata": …, "mediaType": …}, NOT the content.$case/content.value form above. The content.$case form is the TypeScript (ts-proto) in-memory/JSON encoding. The payloads, MIME types, and extension URIs are identical across both; only the part-envelope key differs. Build outbound parts with parts.data_part to get the protoLabs (content.$case) wire shape; parse inbound with parts.read_data, which is tolerant of both.

The four extensions

Extension MIME (metadata.mimeType) Card URI (capabilities.extensions[].uri)
cost-v1 application/vnd.protolabs.cost-v1+json https://proto-labs.ai/a2a/ext/cost-v1
confidence-v1 application/vnd.protolabs.confidence-v1+json https://proto-labs.ai/a2a/ext/confidence-v1
worldstate-delta-v1 application/vnd.protolabs.worldstate-delta-v1+json https://proto-labs.ai/a2a/ext/worldstate-delta-v1
tool-call-v1 application/vnd.protolabs.tool-call-v1+json https://proto-labs.ai/a2a/ext/tool-call-v1

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

# Emit extension DataParts (returns wire-shaped dicts):
cost = pa.emit_cost({"input_tokens": 1500, "output_tokens": 420}, duration_ms=900, cost_usd=0.01, success=True)
conf = pa.emit_confidence(0.92, explanation="high coverage")
delta = pa.emit_worldstate_delta([{"domain": "board", "path": "data.backlog", "op": "inc", "value": 1}])
tool = pa.emit_tool_call("call_1", "file_bug", "completed", result="BUG-12")

# Parse (returns the typed payload iff the MIME matches, else None):
payload = pa.parse_cost(cost)

# 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.

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.1.tar.gz (14.2 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.1-py3-none-any.whl (13.8 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: protolabs_a2a-0.2.1.tar.gz
  • Upload date:
  • Size: 14.2 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.1.tar.gz
Algorithm Hash digest
SHA256 af732899f88939058016ad85e7a49bd48076b26a5ab5284e72075e4d0d21d5db
MD5 70a4bc255cec0be7ae9ce781087fc62e
BLAKE2b-256 0eb089f81b1b07af16ad9c9b2071323be54b42edead4ed6c839095595fdfec67

See more details on using hashes here.

Provenance

The following attestation bundles were made for protolabs_a2a-0.2.1.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.1-py3-none-any.whl.

File metadata

  • Download URL: protolabs_a2a-0.2.1-py3-none-any.whl
  • Upload date:
  • Size: 13.8 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.1-py3-none-any.whl
Algorithm Hash digest
SHA256 5af4b2c6f28fb76021b1a0b1c1c0a4f0ee44cf4ebed488bc6390de8f4063c6dc
MD5 4a349fc67c55da89910a950396d4f535
BLAKE2b-256 ea97e9c20db44d1b69e7c4bc59d6ca6d1e79de2eeee483d8cece5daa7fa474a1

See more details on using hashes here.

Provenance

The following attestation bundles were made for protolabs_a2a-0.2.1-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