Metadata-Version: 2.4
Name: zanii-agents
Version: 0.10.0
Summary: Runtime for accountable AI agents: signed receipts for every action, human gates, injection defenses, hiring per proven task. Standard library only.
Author-email: Zanii <info@zanii.agency>
License: MIT
Project-URL: Homepage, https://www.agents.zanii.agency
Project-URL: Company, https://www.zanii.agency
Project-URL: Ledger, https://ledger.zanii.agency
Project-URL: Documentation, https://www.agents.zanii.agency/docs
Project-URL: Contact, https://www.zanii.agency/contact
Keywords: ai-agents,agent,llm,proof-of-action,zanii,agentcv,escrow,mcp,a2a
Classifier: Development Status :: 4 - Beta
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 :: Software Development :: Libraries
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Provides-Extra: zanii
Requires-Dist: zanii>=0.24.0; extra == "zanii"
Provides-Extra: memory
Requires-Dist: zaniidb-agent-memory>=0.12.0; extra == "memory"
Provides-Extra: bench
Requires-Dist: agentdojo==0.1.35; extra == "bench"
Provides-Extra: postgres
Requires-Dist: psycopg[binary]>=3.1; extra == "postgres"
Provides-Extra: idp
Requires-Dist: cryptography>=42; extra == "idp"
Provides-Extra: server
Requires-Dist: zanii>=0.24.0; extra == "server"
Requires-Dist: psycopg[binary]>=3.1; extra == "server"
Requires-Dist: cryptography>=42; extra == "server"
Dynamic: license-file

<p align="center">
  <img src="https://www.agents.zanii.agency/assets/banner.svg" alt="zanii-agents" width="100%">
</p>

<p align="center">
  <a href="https://pypi.org/project/zanii-agents/"><img alt="PyPI" src="https://img.shields.io/pypi/v/zanii-agents.svg"></a>
  <a href="https://pypi.org/project/zanii-agents/"><img alt="Python" src="https://img.shields.io/pypi/pyversions/zanii-agents.svg"></a>
  <a href="https://pypi.org/project/zanii-agents/"><img alt="License" src="https://img.shields.io/pypi/l/zanii-agents.svg"></a>
</p>

# zanii-agents

`zanii-agents` is a Python runtime for AI agents that a company can hire for a defined job and hold to account afterwards. Each tool call, human approval and run outcome is recorded as a signed, hash-chained receipt. With the optional [Zanii](https://www.zanii.agency) packages, those receipts go to a public transparency log, the agent carries a signed CV built from the log, and payment is released per task only when the receipt is proven.

The package has no dependencies. It runs offline with a built-in mock model, and it connects to any OpenAI-compatible endpoint for real work.

## Installation

```bash
pip install zanii-agents                 # runtime only, standard library
pip install "zanii-agents[zanii]"        # ledger, identity, escrow, industry profiles
pip install "zanii-agents[memory]"       # long-term memory with a firewall (ZaniiDB)
```

Python 3.10 or newer. The import name is `agents_standard`.

## Quickstart

```python
from agents_standard import Agent, ModelGateway, MockProvider, Router, Tool, ToolRegistry

def track_order(order_id: str) -> dict:
    return {"order_id": order_id, "status": "delivered"}

registry = ToolRegistry()
registry.register(Tool("track_order", track_order, "Look up an order",
                       {"type": "object", "properties": {"order_id": {"type": "string"}}},
                       permissions=frozenset({"read:orders"})))

agent = Agent("tracker", "You track orders and report their status.",
              ModelGateway([MockProvider()]), registry, {"read:orders"}, keywords=["track"])

result = Router([agent]).run("track order ORD-100")
print(result.ok, result.output, result.receipt)
```

To use a real model, replace `MockProvider()` with `OpenAICompatProvider("model-name", base_url="https://.../v1")`. The gateway accepts a list of providers and falls back in order.

## What the runtime does

<p align="center">
  <img src="https://www.agents.zanii.agency/assets/architecture.svg" alt="Task flow" width="90%">
</p>

| Concern | Mechanism |
|---|---|
| Least privilege | A tool declares the permissions it needs; an agent only sees tools whose permissions it holds. |
| Bounded runs | Step, cost and latency budgets per run; identical repeated calls end the run. |
| Prompt injection | Untrusted text is scanned, quarantined and, when flagged, summarised by a separate model before the planner sees it. Values that first appeared inside an injection cannot be used as write arguments. |
| Hallucination | Sampled self-agreement and a fact check against tool data; low agreement routes to a human instead of shipping an answer. |
| Human oversight | A confidence floor and a signed rulebook decide which actions need approval. Every decision is receipted. |
| Proof of action | Every tool call, approval, disclosure and run outcome is a receipt in a hash chain. Locally: HMAC over a JSONL file. With Zanii: Ed25519 did:key signatures on a public Merkle log. |
| Kill switch | The owner revokes the delegation; the next run ends with `halted` and executes nothing. Peers over A2A receive a distinct error. |
| Memory | Bounded episodic and procedural memory in a JSON file, or ZaniiDB per client with a memory firewall. |
| Interop | MCP tool-server client with size caps; A2A agent card and JSON-RPC server with bearer auth, rate limiting and health endpoints. |

## Measured behaviour

The numbers below come from the benchmark scripts in `bench/` and can be reproduced against any OpenAI-compatible model. They are for `glm-4.7-flash` on the AgentDojo suites, `important_instructions` attack, defenses off and on.

| Suite | Attacked runs | Attack success, off | Attack success, on |
|---|---|---|---|
| slack | 105 | 52% | 5% |
| banking | 144 | 22% | under 1% |
| workspace | 560 | 3% | 0% |
| travel | 140 | 24% | 1% |

Utility under attack costs between zero and five points on three suites. On workspace an early version of the taint rule blocked legitimate writes; the corrected rule recovered utility from 44% to 76% on a 168-case sample with attacks still at zero. Both result files are kept.

A load test of the A2A server sustains 100 requests per second at a p99 of 28 ms on the mock model. With a live model the ceiling is model latency, roughly one task every ten seconds per process. Details, caveats and the resilience probes are in `docs/readiness-report.md` in the source distribution.

## Hiring an agent for a defined job

With the `zanii` extra, a job is a signed set of artifacts rather than a prompt.

```python
from agents_standard.core.job import Job, Offer
from agents_standard.profiles import PROFILES

job = PROFILES["logistics"].job(
    "cold-chain-monitoring",
    scopes=["tool.read_temperature_log", "tool.flag_violation", "run.*"],
    require_approval=["tool.flag_violation"],
    rate="2.00", currency="AED",
)
offer = Offer.from_files(job, "agent-identity.sealed.json", "owner-identity.sealed.json")

engagement = offer.hire(client)                  # screening, then co-signed terms
escrow = engagement.escrow_for_task(task)        # released only on a proven run.ok
agent = Agent(..., recorder=offer, policy=offer.policy)
result = agent.run(task)
engagement.settle(escrow, result.receipt)        # Merkle proof checked, client signs
```

| Job field | Backed by | Enforced |
|---|---|---|
| `scopes` | owner-signed delegation certificate | the ledger rejects receipts outside the scope |
| `forbid`, `require_approval`, `wall` | signed rulebook, hash stamped on every receipt | before each tool call, and audited afterwards |
| `deny_list` | counterparty screening | before any terms are signed |
| `rate`, commitments | co-signed SLA and per-task escrow, integer minor units | compliance computed from the receipt chain |

Seven industry profiles ship with the regulator's rule as code: public sector, healthcare, finance, tax, real estate, logistics and consumer operations. Each has a test that proves its load-bearing rule, for example that a public-sector decision cannot be issued without a rulebook hash, or that a clinical recommendation requires a named clinician's signature.

## Evidence for insurers and regulators

`agents_standard.packs` builds evidence packs from receipts: an underwriter questionnaire, DIFC Regulation 10, UAE PDPL Article 18, CBUAE guidance and the EU AI Act. Controls the runtime cannot evidence are marked as missing rather than omitted.

## Specifications and conformance

Two documents define the interoperable parts: `spec/agentcv-v1.md` (AgentCV v1) and `spec/engagement-v1.md` (Engagement v1), both in the source distribution and at https://www.agents.zanii.agency. Conformance vectors are generated from the Python reference, and an independent TypeScript implementation in `conformance/ts` passes 103 of 103 checks against them.

## Repository layout

```
agents_standard/     runtime, profiles, packs, control, identity, payments, a2a, mcp
agents_standard/     service (multi-tenant A2A), tenancy, db + migrations, idp (Zanii ID),
                     console_api + console/ (client web console), payout
bench/               benchmarks and their results
spec/                AgentCV v1, Engagement v1, conformance vectors
conformance/ts/      TypeScript conformance runner
deploy/              container image, compose file, host overlay, backup and restore scripts
docs/                API reference, runbooks, deployment guide, readiness report
examples/            live runs against the Zanii ledger
pilot/               client-side signer and pilot runbook
```

## Development

```bash
pip download zanii-agents --no-binary :all: --no-deps   # or work from the source distribution
tar xzf zanii_agents-*.tar.gz && cd zanii_agents-*
pip install -e ".[zanii,memory,postgres,idp]"
for t in standard profiles money future ops hardening idp_payout db service console; do python test_$t.py; done
```

Tests that need an optional extra skip when it is absent. The CI workflow runs the same suites, the TypeScript conformance runner, ruff, bandit, pip-audit and a secrets scan.

## Hosted service

`deploy/serve.py` runs the hosted shape behind agents.zanii.agency: one multi-tenant A2A listener (`service.AgentService`) with the client console mounted on it. A client signs in with Zanii ID, picks a job from the catalogue, signs the SLA and each task's escrow in the browser with a key that never leaves it, sends tasks over JSON-RPC with an API token, verifies each release request against the ledger's Merkle proof before signing it, and is paid out over a bank reference or x402 rail. Tasks, engagements, escrows, releases, API tokens and an append-only audit trail live in Postgres (sqlite for development) through `agents_standard.db`. `docs/BACKEND-PLAN.md` has the design, `docs/API.md` the routes, `deploy/host/README.md` the rollout.

## Status

Version 0.10.0. The runtime and the hosted service are complete and verified against the public ledger with test identities, including the full client loop (hire, task, escrow, release, payout receipt). The production readiness gate in `docs/readiness-report.md` records 31 requirements passing, 5 not applicable and 11 open; the open items need the deployed host, its Postgres, a restore drill or an external penetration test rather than code changes.

## License

MIT. See the `LICENSE` file. Contact: info@zanii.agency. Product site: https://www.agents.zanii.agency.
