Most of what Airlock captures is access. An agent read a document, called a
tool, hit a host. Decision events are different: they’re for the narrower
case of an agent (yours, running anywhere — it doesn’t have to be inside an
Airlock sandbox) making a call that has real consequences attached, and you
want that call visible and, later, automatically flagged if it looks
unreliable.
Consider, for example, a system that uses an AI agent to resolve
prediction-market contracts. A wrong resolution can move real money, so the
agent reporting how it decided (what it cited, how confident it was)
matters as much as what it decided.
Sending a decision event
Decision events go through the same ingestion endpoint as every other event
kind, authenticated with a bearer token (an admin mints one for your agent
identity via POST /api/v1/admin/users/:id/tokens).
Fields
dedupe_key (on the envelope, not the decision object) works the same as
every other event kind: retrying the same POST with the same key is a no-op,
so it’s safe to retry on a timeout without double-reporting a decision.
Keep target stable across agents, not just across retries. Pointing two
independent resolvers at the same targets is the cheapest cross-check
available - no shared prompt or failure mode. A stable
target is what lets their answers be lined up against each other.
What happens to it right now
Today: it’s stored, queryable via GET /api/v1/events?kind=decision and
GET /api/v1/sessions/:id, and shows up in the dashboard timeline like any
other event. What it does not do yet: automatically flag anything.
Access and chat events use the same endpoint with kind set accordingly —
the CLI’s airlock publish is just another client of this contract. See
audit log for what it ships.