Metadata-Version: 2.4
Name: transient-trace
Version: 0.1.0a4
Summary: Python SDK for transient trace ATP reference implementation
Author: Transient Intelligence
Keywords: atp,trace,ed25519,rfc8785,governance
Requires-Python: >=3.9
Description-Content-Type: text/markdown
Requires-Dist: PyNaCl>=1.5.0
Requires-Dist: rfc8785>=0.1.2
Requires-Dist: typing_extensions>=4.6.0
Requires-Dist: python-ulid>=3.0.0
Provides-Extra: dev
Requires-Dist: pytest>=8.0; extra == "dev"

# transient-trace

Governance SDK for AI agents. Intercepts, evaluates, and audits every action an agent takes, with policy enforcement, tamper-evident receipts, and a self-learning rule engine.

Part of [Transient](https://github.com/james-transient/transient), the trust infrastructure for autonomous agents.

## Install

```bash
pip install transient-trace
```

## Quickstart

The fastest path to governed agents is the `wrap` command. It installs a
persistent shell shim so every invocation of the binary goes through
governance automatically — no prefix required.

```bash
# Wrap Claude Code and add shims to your shell RC file
transient-trace wrap install claude --auto-rc

# Restart your shell (or source the RC file)
source ~/.zshrc
```

That's it. Every `claude` invocation is now governed with a full receipt trail.

```bash
# Check governance is active
transient-trace wrap status

# View recent receipts
transient-trace receipts list --since 30m

# Summary with deny rate
transient-trace receipts summary --since 1h
```

---

## Enforce a policy

By default, transient-trace runs in **audit mode** — records everything,
blocks nothing. To enforce a policy, switch to **strict mode**:

```bash
cat > my-policy.json << 'EOF'
{
  "version": 1,
  "defaultAction": "deny",
  "rules": [
    { "id": "allow-git",       "action": "allow", "actionClasses": ["read", "write_low"] },
    { "id": "allow-anthropic", "action": "allow", "actionClasses": ["network"],
      "hosts": ["api.anthropic.com"] }
  ]
}
EOF

transient-trace run --mode strict --policy "$(cat my-policy.json)" claude -p "..."
```

Or set strict mode as the permanent default:

```bash
transient-trace config set mode strict
```

---

## How transient-trace intercepts agent actions

transient-trace uses three complementary interception layers:

1. **PATH shims** — thin bash scripts for `git`, `curl`, and other monitored
   binaries are prepended to PATH. Shell-resolved calls are caught here.

2. **Popen hook** — `sitecustomize.py` is injected via `PYTHONPATH` into every
   Python subprocess. It monkey-patches `subprocess.Popen` to catch calls that
   use absolute binary paths, bypassing PATH. This is why transient-trace works
   inside Claude Code without any changes to Claude Code itself.

3. **Inherited environment** — both mechanisms are inherited by child processes,
   giving coverage across nested agents and subprocesses.

---

## Python SDK

For direct integration into Python agents:

```python
from transient_trace import Client

policy = {
    "version": 1,
    "defaultAction": "allow",
    "rules": [{"id": "allow-all", "action": "allow"}]
}

client = Client({"agentId": "my-agent", "policy": policy})

result = client.executeActionWithReceipt(
    lambda: {"ok": True},
    {"target": "resource-1", "action_class": "write_low"}
)

print(result["receipt"]["receipt_id"])       # TR-...
print(result["receipt"]["signature"]["alg"]) # Ed25519
print(result["decision"]["outcome"])         # allow
```

If policy returns `deny`, raises `RuntimeError: Denied: <reason_code>`.

## Further reading

- [Transient](https://github.com/james-transient/transient) — full product docs, Recall, Intelligence, receipt bus
- [ATP 1.0](https://github.com/james-transient/transient-atp) — the open protocol specification underlying every receipt

### Key differences from the TypeScript SDK

- **Synchronous API** — no `await`, no `asyncio`
- **Config is a dict** — `Client({"agentId": "..."})`, not keyword args
- **Default policy is deny-all** — pass a policy or set `ATP_POLICY_PATH`

---

## Interoperability with TypeScript SDK

Receipt signatures are cross-verifiable — a receipt signed by the Python SDK
can be verified by the TypeScript SDK and vice versa.

- Canonicalization: RFC 8785 JCS (both SDKs, action receipts)
- Signing: Ed25519 via PyNaCl (Python) / @noble/curves (TypeScript)
