Executable behavior contract schema (the YAML object the workbench evaluates against traces)." />

Schema · stable URL · part of the Raising Agents system contract layer. Markdown source on GitHub: system/schema/_src/agent-behavior-contract-v0.md.

agent-behavior-contract/v0

JSON schema for behavior contracts on raisingagents.is.

Read by: system/assets/contract-evaluator.js (pure function), wired into the OPBR verdict-flip on lab/opbr.html. Written by: the workbench (Round 06+) and human authors (Round 05).

Companion to agent-behavior-trace/v0. The trace says what happened; the contract says what was required. The evaluator compares them and reports the violation.


1 — Top-level shape

{
  "schema": "agent-behavior-contract/v0",   // required · identity
  "id": "refund.commit_after_checks",       // required · contract name
  "domain": "refund",                       // required · short tag
  "summary": "Refunds must commit only…",   // optional · one-line description
  "clauses": [Clause, …]                    // required · 1 or more
}

2 — Clause kinds

The schema supports a small fixed vocabulary of clause kinds. Round 05 implements only the first; later rounds extend.

side_effect_after_preconditions (Round 05)

{
  "id": "P2",                                 // required · clause label
  "kind": "side_effect_after_preconditions",  // required
  "side_effect": "refund_commit",             // required · tool name
  "preconditions": ["read_policy", "fraud_check"], // required · ordered list
  "message_template":
    "{clause_id} violation — side effect ({side_effect}) precedes precondition check ({violating_precondition})"
}

Semantics: every named precondition must appear in the trace at a step index strictly less than the side_effect’s step index. If any precondition does not satisfy this, the clause is violated.

Reported violating_precondition: the first precondition in the declared order whose step index is >= side_effect’s. This makes the message stable and predictable when more than one precondition is out of order.

Future kinds (deferred)

The Round 05 evaluator ignores unknown clause kinds with a console warning. Unknown kinds do not produce a violation.


3 — Evaluator contract

// system/assets/contract-evaluator.js

evaluateRail(contract, rail) → Result

Inputs

Output

{
  "violated": true,                         // boolean
  "clause_id": "P2",                        // string or null
  "side_effect_step": 2,                    // 1-based step number, or null
  "violating_precondition": "fraud_check",  // string or null
  "violating_precondition_step": 3,         // 1-based step number, or null
  "message": "P2 violation — side effect (refund_commit) precedes precondition check (fraud_check)"
}

For a non-violating rail:

{ "violated": false, "clause_id": null, "message": "Behavior contract passes." }

Determinism: evaluator is a pure function. Same inputs → same output, every call. No timing, no randomness, no IO.

Annotation pipeline: the evaluator also exposes annotateRail(contract, rail) → annotatedRail — same steps, but with .consequential and .in_violation recomputed from the evaluation. The verdict-flip uses this to push fresh data into the <trace-diff> component on each drag commit.


4 — Versioning

The evaluator rejects unknown schema values: console.warn and return { violated: false, message: "[unsupported contract schema]" }.