Core concepts
Architecture
Antraft is a small set of composable pieces around one chokepoint: every action an agent wants to take is evaluated before it runs.
The flow
flow
Agent ──proposes──> Action / Thought │ ▼Runtime ──evaluate(JSON)──> Guard ──> PolicyEngine (allow | deny | pause) │ │ │ if allowed └── Auditor (tamper-evident trail) ▼Tool Gateway ── validate args → RBAC → retries/timeout → execute │ ▼Guardrails screen result ──> Agent observes ──> next stepComponents
| Piece | Responsibility |
|---|---|
Agent | Proposes the next Action or Thought. |
Runtime | Drives the loop, calls the Guard, enforces decisions. |
Guard | JSON-in/JSON-out facade over the policy engine. |
PolicyEngine | Allow/deny/pause, DSL rules, budgets, prerequisites. |
ToolGateway | The only place actions execute; validation, RBAC, retries. |
Guardrails | Screen content flowing in and out of the agent. |
Auditor | Records every decision; optionally hash-chained. |
The Guard is the keystone
Enforcement is reachable only through one contract — a pure JSON evaluate() call. That is why the same policy engine governs an in-process Python agent and a remote JavaScript agent: both speak the identical contract, so in-process and sidecar enforcement can never drift.
guard
from antraft import Guard guard = Guard({"allow": ["read"], "deny": ["delete"]})guard.evaluate({"action": {"name": "read", "params": {}}, "context": {}})# -> EvaluateResponse(decision="allow", reason="...")Provider- and tool-neutral
Agents emit a neutral Action/Thought, models normalize into the same types, and every tool source becomes one Tool shape. The runtime never sees provider or tool-source differences — which is what keeps governance uniform across all of them.