EFFECT LIFECYCLE

Effect contracts

The action leaves once, and success is what a second pinned tool observed.

Effect contracts govern the actions that change something outside the gateway: a payment, a ticket transition, a deployment, a database write. A contract pins one action tool and a different verifier tool to their exact descriptor digests, and a successful action response never completes the run on its own: the verifier is called afterwards, its observation must be fresh and post-dispatch, and every postcondition must match before the effect is recorded as committed. A durable claim on the business idempotency value is taken before a byte leaves, so a lost response is reconciled by a read rather than a replay.
Contract
Pinned action, pinned verifier, optional compensation pair
Language
JSON Pointers and six operators; no code, no templates
Claim
One durable row per effect name and idempotency digest
Receipt
Ed25519, verified from its bytes and a key you supply
Not exactly-onceThe downstream must enforce the idempotency key you send
the problem

A tool that returned 200 has not proved that anything happened.

The inline decision point answers whether an agent may attempt an action. It does not answer whether the action happened, whether it happened once, or whether it stayed inside the bounds the person who approved it had in mind. Treating the response as completion proves the transport worked and nothing else.

The dangerous case is not failure, it is ambiguity. A timeout hides two outcomes needing opposite responses — nothing happened, or everything happened and the acknowledgement was lost — and an agent framework’s default is to retry. Retrying a read is free. Retrying a payment is a second payment.

the mechanism

How it works

Step 9 of the request path, and the durable recovery after it. The order is encoded in the evaluator, and where each step sits is the reason the guarantee holds.

  1. 01

    A contract is drafted against exact descriptor digests

    The draft names an action tool and a different verifier tool by server, tool name and the exact SHA-256 of the approved descriptor, plus, where compensation exists, a distinct compensation verifier. Activation refuses unless every binding is present, pinned and matching.
  2. 02

    Preconditions run, the claim is taken, the action leaves once

    Policy, data controls and the payload-bound approval inspect the exact payload the contract will send. The claim on the business key is taken last, after redaction and before the first byte leaves, in the transaction that writes the run and outbox rows. A second delivery of the same key is refused as a non-retryable conflict, and a transport timeout moves the run to verifying and never back to dispatch.
  3. 03

    The verifier is called, and the predicates decide

    The verifier is invoked with arguments mapped from the original request, and its result must carry an observation timestamp that is post-dispatch and no older than the freshness bound. Every postcondition and invariant must match. A pending answer is polled again inside a bounded cap; exhaustion parks the run for manual review rather than replaying a mutating stage.
the order is the guarantee
  1. beat 01
    Name the caller
    • 1Authenticate
    • 2Resolve the agent

    Nothing is decided for an anonymous caller. The key resolves to one registered agent with a named owner, and its roles, its ceilings and any stop switch in force are read live from the store on every request, not from a cached copy, so a suspension takes effect on the next call instead of after a redeploy.

  2. beat 02
    Start the record, then read what is being sent
    • 3Open the trace
    • 4Sanitise
    • 5Scan

    The trace is opened before anything can refuse the request, which is why a blocked call is recorded as thoroughly as one that went through. Only then is the text normalised and scanned, in that order, so the detectors see what the model will read rather than what a human reviewer can see.

  3. beat 03
    Decide once
    • 6Govern
    • 6bIntersect with the named human
    • 7Enact

    One function returns one verdict: allow, block, or hold it for a named person to approve. Every check lives in that one place rather than scattered along the path, which is what makes it possible to read your rules and know what they do.

  4. beat 04
    Send it, and only then spend the money
    • 8Route
    • 9Call upstream

    Routing fixes which provider and model will serve the call, so where an agent has a USD ceiling it is tested against the price you will pay, not the one the caller typed. Routing is also the last step that can still refuse locally: after it, the request has left your network.

  5. beat 05
    Govern the answer, then count the cost
    • 10Govern the response
    • 11Meter and record

    A tool call the model proposes is judged before it reaches your agent. Metering runs last and on every ending, including the refusals and the streams a client abandoned halfway, because the tokens were spent either way and a partial trace is still evidence.

Step names and their grouping are the product’s own, and the order is encoded in the evaluator rather than drawn for the page.

A closed language: six operators, no code.

Values move between stages only by RFC 6901 JSON Pointer copies, and conditions use exactly six operators. There is no expression language, no template interpolation and no way to run code: the alternative considered and rejected was a second sandbox platform inside the governance boundary. Pointer resolution is unforgiving: only own data properties are read, prototype segments are refused, and predicates do not coerce types.

No stage may read the action’s response
Every set evaluated after dispatch reads the verifier’s result and nothing else, because the action response is what a timeout loses.
Four distinct tools
Validation refuses a contract whose action and verifier are the same tool, or whose compensation stages target the action, the verifier or each other.
Versions, never rewrites
Editing a contract’s semantics creates version N+1 and never rewrites N. Lifecycle status is outside the digest, so retiring a revision blocks new dispatch without destroying the digest historical runs name.
The whole contract language, in one screen
action                  serverId + toolName + descriptorHash + mappings
verifier                a DIFFERENT pinned tool
compensation?           optional, and requires the next line
compensationVerifier?   a fourth distinct pinned tool

idempotencyKeyPointer          /request_id     non-root
verificationTimestampPointer   /observed_at    non-root
onVerificationFailure          compensate | manual_review

preconditions               over original_arguments
postconditions              over verifier_result, at least one
invariants, failureConditions, compensationPostconditions

operators  exists  equals  not_equals
           greater_than  less_than  contains

no expressions   no templates   no code   unknown fields invalid

Success is what a second pinned tool observed.

Token Observe deduplicates on a value your own system already knows. A non-root pointer names the business idempotency value, and every stage must carry it: a verifier addressable by a different identity than the action it verifies is not a verifier. The value is reduced to an HMAC digest and never stored raw, and a unique index on it holds across agents, teams and revisions.

The agent does not receive the action’s response until the effect is proved; if verification does not pass, the caller is refused and told not to retry. Automatic compensation is opted into twice: the contract must carry a compensation tool and a distinct compensation verifier, and a separate set of failure conditions must match fresh evidence. Without that proof the run goes to manual review, because compensating an effect that has merely not appeared yet is a second unauthorised action against the same account. A compensation response is recorded as accepted; the run reads compensated only once the compensation verifier observes it landed.

The durable run graph, and the only legal moves in it
pending -> reserved -> executing -> executed -> verifying
                                    verified -> committed

executing -> verifying          action response ambiguous

reserved..verified -> compensation_required -> compensating
                        -> compensation_verifying -> compensated
                        -> compensation_failed
reserved..verified -> manual_review_required

manual_review_required -> operator_attested_committed
                       -> operator_attested_not_committed

terminal   committed   compensated   both attestations

Each line closes off an assumption a reader would otherwise carry into a proof of concept.

What this does not do

How is this different from retrying with an idempotency key?

An idempotency key asks the downstream system to deduplicate. An effect contract deduplicates before the request is sent, then checks what happened: a unique durable claim on the business key is taken before the first byte leaves, and a different pinned tool then observes the result. The key still has to be honoured downstream; the difference is that a lost response leads to a read rather than a retry.

What happens when the action times out?

The run moves from executing to verifying and the verifier is called. Nothing is re-dispatched, because a timeout hides two opposite outcomes and both blind retry and assumed failure are unsafe, so the state graph offers neither move. If the verifier proves the effect, the run commits and the caller is told the response was lost but the effect stands. Otherwise it enters manual review with the ambiguity visible.

What stops someone writing a verifier that always says yes?

Nothing in the product. A verifier is a contract-bound read-after-write check by a different pinned tool: separation of role, not an independent trust authority. What is enforced is narrower and still useful: a distinct tool pinned to an exact descriptor digest, unable to read the action’s response, and required to observe freshly and post-dispatch.

Ask about this capability
Ask how this one works, where it sits in the request path, or what it will not do. Answers stay inside what this page claims.

Prefer to ask a person? Write to James

Your next step

Bring us the agent you are least comfortable with.

Create a cloud account and workspace. No card or server installation. Model calls and Google BigQuery scans can incur separate provider charges.