Skip to content

An agent proposes. Something else decides.

Four stages, always in order. No way around them.

The four stages

Propose / evaluate / execute / record
Proposal
Your rule · example rule
The engine
The connector
Propose / evaluate / execute / record
  1. 01Agentproposes · holds no credentials
  2. 02Decision enginepermit · hold · deny · your rules, not the model
  3. 03Executepermit → Connector
  4. 04A personhold
  5. 05Nothing happensdeny
Record: 0 rows
  1. Propose

    An agent names an action. Nothing more.

  2. Evaluate

    The engine answers permit, hold or deny.

  3. Execute

    Only a clean permit reaches the connector.

  4. Record

    Every verdict goes to a hash chain.

After a permit

  1. ATTEMPT 1 OF 3
  2. ATTEMPT 2 OF 3
  3. ATTEMPT 3 OF 3
  4. Dead letter

Nothing reached the connector.

Each row carries the hash of the row before it. The real trail is kept and verified by the decision engine.

Change a word, then verify

Pick a row and change its verdict. It keeps the hash it was written with, so the hash no longer matches what the row says.

Propose something first. The chain starts with the first verdict.

Checked against backend/app/agents/executor.pyRuns in your browser on the illustration's data. Nothing is sent and no engine is called.

Two fixed contracts, no free-text channel.

What an agent proposes

action
"messaging.send"The abstract operation. Never a vendor name.
parameters
{"to": "demo-ent-marcela", "body": "demo-draft-0421"}What it needs. Structured and validated.
agent_id
"demo-agent-support"Who proposed it.
tenant_id
"demo-tenant"Whose workspace. Rules resolve per tenant.
context
{"open_conversation": true, "last_inbound_at": "2026-08-21T02:14:00Z"}What the agent saw. A reviewer reads this.
idempotency_key
"demo-reply-marcela-1"The intent's identity. Two deliveries run once.

What comes back

decision
"hold"permit, hold or deny. Nothing partial.
reason
"example_rule.hold_reply_open_conversation"Why, in terms of the rule.
trace_id
"demo-trace-0001"Ties the verdict to its audit entry.
latency_ms
nullDecision time. Null here: no engine is called.
active_campaigns
[]Standing rules in force, kill switch included.
shadow
falseWhether rules are being proven, not enforced.

Around the seam

  • The review queue

    Built and tested

    A hold carries the proposal, context and rule. Approving releases one action.

  • Holds resolve asynchronously

    Built and tested

    Webhooks and polling both. An unanswered day becomes an insight.

  • Shadow mode

    Built and tested

    Not a dry run: the action runs, the verdict is only written down.

  • The decision trail

    Built and tested

    Append-only and hash-chained, with a verify endpoint.

  • Outside assistants

    Built and tested

    Same four stages, strictly fewer permissions than an agent here.

  • Decisions stay human

    Built and tested

    No permission accepts a decision, answers a hold or executes.

Where this stands today

  • The seam

    Built and tested

    Agents cannot build an executor; the test suite enforces it.

  • Two gates, one interface

    Built and tested

    Production calls the engine. Local permits all, shown as ungoverned.

  • Your actions and guardrails

    Not built

    Written with you. Until then, rules propose only human work.

Read the rules before you trust them.