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 step

Components

PieceResponsibility
AgentProposes the next Action or Thought.
RuntimeDrives the loop, calls the Guard, enforces decisions.
GuardJSON-in/JSON-out facade over the policy engine.
PolicyEngineAllow/deny/pause, DSL rules, budgets, prerequisites.
ToolGatewayThe only place actions execute; validation, RBAC, retries.
GuardrailsScreen content flowing in and out of the agent.
AuditorRecords 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.