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, registry endpoint coming soon.


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://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://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://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 endpoint live at relayforge.tools
  • ⏩ Publish alpha to PyPI

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.1.0.tar.gz (22.4 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.1.0-py3-none-any.whl (20.9 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: carapace_sdk-0.1.0.tar.gz
  • Upload date:
  • Size: 22.4 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.1.0.tar.gz
Algorithm Hash digest
SHA256 130d32f869414352adf90c0e61d4b54a7a9fe48c0bd6afc4c046321ba6a149d4
MD5 c248374472152ab43644e3d93e3162e2
BLAKE2b-256 58cefd9986e7d6170a3e8ecc0d1784a8d155676e3946693552c53135a85bb878

See more details on using hashes here.

File details

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

File metadata

  • Download URL: carapace_sdk-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 20.9 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.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 9c118b1de1a5f0622ac2c358be649de9479e3d09c527472a4abf0dacbd45e2e1
MD5 856c2dc6e885fbe454cf6c4f2b44630f
BLAKE2b-256 ae457359d453ecf16bed00cd0adab83b150e53fcd1f9133d8ee9107bbb09b63b

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