How it works
A proposal hash binds an approval to one exact representation of a proposed action. The harness first builds a canonical proposal containing every execution-relevant field: operation, target, arguments, resource identifiers, constraints, and any expected state version. It serializes that proposal deterministically and computes a cryptographic digest. The approval record stores the digest alongside the reviewer decision and relevant authorization context.
Before execution, especially after a pause or resume, the harness rebuilds the proposal from authoritative state and computes the digest again. Execution proceeds only when the new digest matches the approved digest.
A typical control sequence is:
- Construct a complete proposal from authoritative workflow state.
- Canonicalize it so equivalent data has one stable representation.
- Hash the canonical bytes and store the digest with the approval.
- Reconstruct and rehash the proposal immediately before execution.
- Reject or request new approval when the digests differ.
The hash is only as meaningful as the proposal envelope. If a destination account, file path, quantity, permission scope, or state precondition can change the action's effect, it belongs inside the hashed representation. Human-readable summaries may accompany the proposal, but they must not replace the execution-bound data being hashed.
Why it matters in an agent harness
Approval introduces a time gap between intent and execution. During that gap, an agent may revise its plan, context may be compacted, a worker may resume on another process, or external state may change. Without an integrity check, the system can execute an action that resembles the reviewed proposal while differing in a consequential field.
A proposal hash turns that ambiguity into a deterministic control boundary. The reviewer is not approving a general direction such as “update the record.” The reviewer is approving a particular operation against a particular target under particular constraints. Any mutation to that approval-bound material invalidates the prior decision.
This improves several operating properties:
- Control: authorization applies to a defined action rather than the agent's evolving interpretation of an instruction.
- Failure containment: stale or mutated proposals stop before a side effect crosses the boundary.
- Observability: traces can show the proposed digest, approved digest, execution-time digest, and mismatch reason.
- Resumability: a worker does not need to trust transient conversational context when recovering an approved action.
- Evaluation: tests can mutate individual fields and verify that execution fails closed.
The mechanism does not prove that the proposal was wise, safe, or correctly understood by the reviewer. It proves only that the execution-bound representation matches the approved representation. The surrounding harness must still enforce permissions, validate targets, authenticate the reviewer, and check whether the action remains valid against current state.
External state deserves special treatment. Suppose a reviewer approves replacing version 12 of a configuration, but the live configuration reaches version 13 before execution. The proposal hash may still match because the proposal itself did not change. A state version or comparable precondition should therefore be included in the proposal and checked at execution time. Integrity without freshness can preserve an obsolete decision perfectly.
Proposal hash vs idempotency key
These mechanisms may use similar-looking identifiers, but they answer different questions.
| Mechanism | Question answered | Typical failure prevented |
|---|---|---|
| Proposal hash | Does this execution match the action that was approved? | Executing a mutated or substituted proposal |
| Idempotency key | Has this logical operation already been accepted or performed? | Repeating the same side effect after a retry |
A robust harness may need both. The proposal hash protects approval integrity. The idempotency key protects retry behavior. Reusing one value for both roles can obscure their different lifecycles and validation rules. An unchanged proposal may still be unsafe to repeat, while a new proposal may intentionally describe a replacement for an earlier operation.
The Rifty take
We treat approval as authorization for an execution-bound object, not as encouragement to continue in roughly the same direction. We accept the cost of reapproval when a meaningful field changes because silent proposal drift is harder to inspect and contain. The boundary is simple: if the harness cannot reconstruct what was approved, it must not spend that approval.
Implementation checks
- Define which fields can alter the action's effect and include all of them in the canonical proposal.
- Use deterministic serialization with explicit handling for key order, numbers, omitted values, and text encoding.
- Store the proposal or a durable reference to it, not only the digest.
- Bind the approval record to the reviewer, policy, workflow, and intended execution scope.
- Recompute the digest from authoritative state immediately before the side effect.
- Include state versions or preconditions when approval depends on a mutable resource.
- Fail closed on missing proposals, unsupported serialization versions, or digest mismatches.
- Record mismatches as visible control events rather than silently generating a replacement approval.
- Test field mutation, stale state, replay, resume, and serialization-version changes independently.
Frequently asked questions
Should the harness store the original proposal as well as its hash?
Yes. Store the canonical proposal, or a durable reference that can recover it, alongside the hash. A digest can confirm equality but cannot explain what was approved. Retaining the proposal supports review, debugging, audit trails, serialization migration, and clear mismatch reports without treating transient agent context as authoritative.
Which fields belong inside a proposal hash?
Include every field that can change the action's target, effect, authority, timing constraints, or safety conditions. Common examples are operation names, resource identifiers, arguments, permission scopes, quantities, destinations, and expected state versions. Exclude display-only metadata only when changing it cannot alter execution or reviewer interpretation.
What should happen when the execution-time hash does not match?
The harness should stop the action, record the mismatch, and create a new proposal for review when execution is still desired. It should not patch the stored digest or infer that the difference is harmless. Any exception policy must be deterministic, narrow, and visible in the approval record.
Does a matching proposal hash make an action safe to execute?
No. A match establishes integrity between the approved proposal and the execution candidate. It does not establish that the reviewer had authority, the proposal was safe, external state remains valid, or execution is permitted now. Those checks belong to authorization, validation, freshness, and policy controls around the hash comparison.
How should proposal hashes handle schema changes?
Version the canonical proposal format and bind that version into the hashed representation. On resume, use the same version to reconstruct the proposal or require new approval when faithful reconstruction is impossible. Silently reserializing an old proposal under new rules can create false mismatches or, worse, conceal changed semantics.