Metadata-Version: 2.4
Name: carapace-sdk
Version: 0.1.0
Summary: Federated agent identity in a single function call — Python SDK for the Carapace Protocol
Project-URL: Homepage, https://relayforge.tools
Project-URL: Repository, https://github.com/ryan10sa-star/relayforge
Project-URL: Documentation, https://relayforge.tools/docs/carapace
Author-email: RelayForge <hello@relayforge.tools>
License: MIT
Keywords: a2a,agent,ai,carapace,ed25519,identity,mcp,sdk
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Security :: Cryptography
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Typing :: Typed
Requires-Python: >=3.10
Requires-Dist: httpx>=0.25.0
Requires-Dist: pynacl>=1.5.0
Provides-Extra: dev
Requires-Dist: pytest-asyncio>=0.21; extra == 'dev'
Requires-Dist: pytest>=7.0; extra == 'dev'
Requires-Dist: respx>=0.20; extra == 'dev'
Description-Content-Type: text/markdown

# carapace — Python SDK

**Federated agent identity in a single function call.**

```bash
pip install carapace-sdk
```

> **Status:** Alpha — API is stable, registry endpoint coming soon.

---

## Quick start

```python
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.

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

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

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

Search the registry. All params optional.

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

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

Ed25519 verification — **fully offline**, no network call.

```python
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.

```python
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:

```python
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:

```python
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`.

```python
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:

```python
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

```bash
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
