Metadata-Version: 2.4
Name: zanii-blackbox
Version: 0.1.0
Summary: The flight recorder for AI agents: sessions, a zero-loss spool, framework hooks, approvals, and offline verification of the gateway's hash-chained record.
Keywords: ai-agents,observability,audit,flight-recorder,llm,mcp,langgraph,openai-agents,tamper-evident,compliance
Author: Zanii
Author-email: Zanii <info@zanii.agency>
License-Expression: Apache-2.0
License-File: LICENSE
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Software Development :: Libraries
Classifier: Topic :: System :: Logging
Classifier: Topic :: Security
Classifier: Typing :: Typed
Requires-Dist: zanii>=0.25.1,<0.26
Requires-Python: >=3.11
Project-URL: Homepage, https://zanii.agency
Description-Content-Type: text/markdown

# zanii-blackbox

The Python SDK for [Zanii Blackbox](https://zanii.agency), the flight recorder for AI agents.

Blackbox records every model call and tool call your agent makes, from a gateway that runs outside the agent's process. The records are hash-chained, so an edit or a deletion shows, and anchored as receipts that anyone can verify offline. This SDK is optional. It adds what only the agent knows (steps, its own tools, its checks, the outcome) as a second, independent record, and it reads and verifies what the gateway recorded.

```sh
pip install zanii-blackbox
# or
uv add zanii-blackbox
```

Python 3.11 or later. Fully typed.

## Before you start

You need a running Blackbox gateway, self-hosted with Docker, Kubernetes or from source. A hosted UAE region is planned; write to [info@zanii.agency](mailto:info@zanii.agency) for early access. The gateway holds your provider keys. Your agent gets a session token instead, and its model calls go through the gateway:

```sh
export BLACKBOX_URL=https://blackbox.example.com
export BLACKBOX_ADMIN_KEY=...     # or a tenant key (bbxt_...)
```

## Record a run

```python
import os

import anthropic
from zanii_blackbox import session

url = os.environ["BLACKBOX_URL"]

with session(
    url=url,
    admin_key=os.environ["BLACKBOX_ADMIN_KEY"],
    label="refund-agent",
    budget_usd="2.00",
    flight_plan={
        "objective": "Process today's refund queue",
        "expected_tools": ["lookup_order", "issue_refund"],
    },
) as s:
    # Model calls go through the gateway with the session's token, never your provider key.
    client = anthropic.Anthropic(base_url=f"{url}/anthropic", api_key=s.token)

    s.step("load queue")
    s.tool_call("lookup_order", {"order": 8812})
    s.tool_result("lookup_order", {"ok": True})
    s.verify("amount-matches-invoice", True)  # your own check, recorded as evidence

    # A risky tool waits for a person, who sees the arguments in the cockpit.
    answer = s.request_approval(
        "issue_refund",
        reason="Damaged on delivery",
        args={"order": 8812, "amount_aed": "1250.00"},
    )
    if answer == "approved":
        ...  # issue the refund

    s.close("success")
```

`answer` is only `"approved"` when a person approved it. `"rejected"`, `"timeout"` and `"error"` all mean don't run the tool.

With asyncio, use `s = await asession(...)` and `async with`. The calls that wait on the gateway have async versions: `aflush`, `astate`, `arequest_approval` and `aclose`.

## What the SDK guarantees

- **It never raises into your agent.** If the gateway is down, the session keeps recording to disk and reports the problem in `s.stats.last_error`.
- **It loses nothing it accepted.** Every event is written to a local spool before it is sent, numbered without gaps, and resent until the gateway confirms it. After a crash, `blackbox drain` sends what's left.
- **It stays out of the way.** Recording is non-blocking with bounded memory. A recorded call costs about 0.4 ms (measured over 20,000 calls on a laptop); shipping happens in the background.
- **It has one runtime dependency:** the Zanii core library.

## Frameworks

| Framework | Use |
|---|---|
| LangChain / LangGraph | `BlackboxCallbackHandler(s)`, `BlackboxAgentMiddleware`, `BlackboxCheckpointSaver` (from `zanii_blackbox.hooks.langgraph_checkpoint`), and `blackbox_hitl` for human-in-the-loop |
| OpenAI Agents SDK | `Runner.run(agent, ..., hooks=BlackboxRunHooks(s))` |
| Claude Agent SDK | `BlackboxAgentHooks(s)` |
| CrewAI | `attach_crewai(s)` |
| Pydantic AI | `record_pydantic_ai(result, s)` |
| Provider clients | `wrap_anthropic`, `wrap_openai`, `wrap_gemini`, `wrap_bedrock` link each call to the gateway's record |

The framework integrations are imported lazily, so installing this package doesn't pull any of them in.

## Command line

The package installs a `blackbox` command:

```sh
blackbox sessions                     # the newest sessions, and whether each record verifies
blackbox tail ses_...                 # follow a session live
blackbox export ses_... --out run.json
blackbox verify run.json              # verify an audit bundle offline, anywhere
blackbox reconcile ...                # check an agent's own logs against the gateway's record
blackbox mcp-wrap --server files -- python server.py   # record a local stdio MCP server
blackbox drain                        # send spooled events left by a stopped agent
```

## Verify a record offline

```python
from zanii_blackbox import verify_bundle
```

An audit bundle carries the events, the chain and the anchors. Checking it needs no account and no network, so an auditor or a regulator can check it independently.

## Also in TypeScript

[`@zanii/blackbox`](https://www.npmjs.com/package/@zanii/blackbox) has the same API in camelCase. Both SDKs must produce the same output on the same shared test vectors.

## Support

- Website: [zanii.agency](https://zanii.agency)
- Email: [info@zanii.agency](mailto:info@zanii.agency)
- Security reports: [info@zanii.agency](mailto:info@zanii.agency), privately, not in a public issue

Licensed under [Apache-2.0](https://www.apache.org/licenses/LICENSE-2.0).
