Skip to main content

Federated agent identity in a single function call — Python SDK for the Carapace Protocol

Project description

carapace — Python SDK

Federated agent identity in a single function call.

pip install carapace-sdk

Status: Alpha — API is stable, ARIA registry live at https://api.relayforge.tools/aria/v1.


Quick start

import os
from carapace import Carapace

# One-time setup — auto-generates a keypair when owner_key is omitted
carapace = Carapace.create(
    registry_url="https://api.relayforge.tools/aria/v1",
    owner_key=os.environ.get("CARAPACE_OWNER_KEY")  # optional — auto-generates if absent
)

# Register an agent — one function call
card = carapace.register(
    name="MyAgent",
    description="A helpful research agent",
    framework="langchain",
    capabilities=[
        {"id": "research", "name": "Research", "description": "Searches and summarizes topics"}
    ],
    endpoints=[
        {"protocol": "a2a", "url": "https://my-server.example.com/agent"}
    ]
)

# Verify another agent — one function call
result = carapace.verify(card.id)
print(result.verified)  # True

# Discover agents by capability — one function call
peers = carapace.discover(capability="research")

# Verify offline — no network needed
ok = carapace.verify_local(card, card.signature, card.owner.public_key)

What the SDK handles silently:

  • Ed25519 key generation and derivation (private key never leaves your process)
  • JCS canonicalization (RFC 8785) before signing
  • Identity card construction from minimal input
  • Signature verification

API reference

Carapace.create(registry_url, owner_key=None) → Carapace

Factory constructor. Auto-generates an Ed25519 keypair when owner_key is omitted.

# With an existing key (production):
c = Carapace.create(registry_url=url, owner_key=os.environ["CARAPACE_OWNER_KEY"])

# Auto-generate key (quick test / one-off):
c = Carapace.create(registry_url=url)
print(c.public_key())  # store or share the public key

Carapace(registry_url, owner_key=None)

Direct constructor. Offline operations (verify_local) work even without owner_key; signing and registering raise a ValueError with a clear message if owner_key is absent.

carapace.register(...) → AgentCard

Build, sign, and register a new agent in one call.

Param Type Required
name str Yes
description str Yes
framework str Yes
capabilities list[dict] Yes
endpoints list[dict] Yes
version str No
tags list[str] No
metadata dict No

carapace.verify(agent_id) → VerifyResult

Registry round-trip: fetch card, re-verify signature.

result = carapace.verify("agent-uuid")
print(result.verified)   # bool
print(result.agent)      # AgentCard | None

carapace.discover(...) → list[AgentCard]

Search the registry. All params optional.

peers = carapace.discover(capability="research", framework="langchain", limit=10)

carapace.verify_local(card, signature, public_key) → bool

Ed25519 verification — fully offline, no network call.

ok = carapace.verify_local(card, card.signature, card.owner.public_key)

carapace.get(agent_id) → AgentCard

Fetch a card directly from the registry by UUID.

carapace.public_key() → str

Return the hex-encoded public key derived from owner_key.


Key management

Generate a keypair once; store the private key in a secrets manager or environment variable.

from carapace.keys import generate_key_pair

kp = generate_key_pair()
print(kp.private_key)  # 64-char hex — keep secret, store in env/vault
print(kp.public_key)   # 64-char hex — safe to share

A2A compatibility

Generate a valid A2A Agent Card for /.well-known/agent.json discovery:

from carapace.a2a import generate_well_known_card
import json

a2a = generate_well_known_card(card)
# Serve as JSON at /.well-known/agent.json
print(json.dumps(a2a.to_dict(), indent=2))

MCP compatibility

Export capabilities as an MCP tools/list response:

from carapace.mcp import generate_tools_list, generate_mcp_server_config
import json

tools = generate_tools_list(card)         # {"tools": [...]}
config = generate_mcp_server_config(card) # claude_desktop_config.json entry

print(json.dumps(tools.to_dict(), indent=2))

Async support (AsyncCarapaceClient)

Use AsyncCarapaceClient for FastAPI, LangChain async chains, CrewAI async tasks, or any other async-first Python framework. It has an identical API to CarapaceClient but all network calls are async def.

import asyncio
import os
from carapace import AsyncCarapaceClient

async def main():
    async with AsyncCarapaceClient(
        registry_url="https://api.relayforge.tools/aria/v1",
        owner_private_key=os.environ["CARAPACE_OWNER_KEY"],
    ) as client:
        card = await client.register(
            name="MyAsyncAgent",
            description="Runs in an async event loop",
            framework="fastapi",
            capabilities=[{"id": "query", "name": "Query", "description": "Handles queries"}],
            endpoints=[{"protocol": "https", "url": "https://my-api.example.com"}],
        )
        result = await client.verify(card.id)
        agents = await client.discover(capability="query")

asyncio.run(main())

FastAPI tip: inject AsyncCarapaceClient as a dependency and reuse a single httpx.AsyncClient across requests for connection pooling.


Low-level API (CarapaceClient)

For advanced use or custom signing flows, the lower-level sync client is available:

from carapace import CarapaceClient
from carapace.keys import generate_key_pair

kp = generate_key_pair()
client = CarapaceClient(
    registry_url="https://api.relayforge.tools/aria/v1",
    owner_private_key=kp.private_key
)

card = client.register(name="MyAgent", ...)
result = client.verify("agent-uuid")
agents = client.discover(capability="research")

Security model

  • Private key never leaves your process. Only the derived public key is sent to the registry.
  • Signatures use Ed25519 (RFC 8032) over JCS-canonical (RFC 8785) JSON.
  • No registry dependency for verification. Use verify_local or carapace.crypto.verify_payload offline.
  • Revocation is soft-delete — card stays in registry with status: "revoked".

Development

git clone https://github.com/ryan10sa-star/relayforge
cd relayforge/carapace-protocol/sdk/python
pip install -e ".[dev]"
pytest

Roadmap

  • ✅ Ed25519 + JCS signing (PyNaCl)
  • ✅ Key generation helper (generate_key_pair)
  • Carapace convenience class — directive-spec API
  • register() / verify() / discover() / verify_local()
  • generate_well_known_card() — A2A /.well-known/agent.json
  • generate_tools_list() — MCP tools/list
  • ✅ Cross-language interop verified (Python ↔ JS byte-identical signatures)
  • ✅ GitHub Actions CI (Python 3.10, 3.11, 3.12)
  • ✅ PEP 561 typed package (py.typed marker)
  • ✅ Async client (AsyncCarapaceClient) for FastAPI, LangChain, CrewAI
  • ✅ ARIA registry live at https://api.relayforge.tools/aria/v1 (2026-03-18)
  • ⏩ Publish alpha to PyPI (awaiting PyPI token)

MIT License — RelayForge

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

carapace_sdk-0.2.0.tar.gz (25.8 kB view details)

Uploaded Source

Built Distribution

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

carapace_sdk-0.2.0-py3-none-any.whl (24.4 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: carapace_sdk-0.2.0.tar.gz
  • Upload date:
  • Size: 25.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for carapace_sdk-0.2.0.tar.gz
Algorithm Hash digest
SHA256 12124326523b548439404059e0ddf5e3f58b1c9512781d6b47576976796c2b59
MD5 1d10374bab6db90cb78b1a1091a262ed
BLAKE2b-256 fb20f160633aafb6ac6ea0baa71eed7dfa6c6ca5f4cceef08881c60715b62214

See more details on using hashes here.

File details

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

File metadata

  • Download URL: carapace_sdk-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 24.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for carapace_sdk-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 51e9a77358523839ab05d493e72a62e1555c4cfc2094f00a6fdad2e66ea12783
MD5 f64d279ef0fae212388c7fdabcf9aa40
BLAKE2b-256 5ae8a8f38bdee148f618e839558e2ddfb3e9952bc5ea413f50d3fc324a9ce779

See more details on using hashes here.

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