Review Gates Need a Typed Boundary, Not a Hopeful Prompt
A human approval step is only useful when the system can tell the difference between “approved,” “approved with more work,” and “stop and ask.” The practical improvement is a typed review result that turns a reviewer’s judgment into a machine-checkable transition.
This article explains one concrete DAL/COO improvement end to end: representing review-gate outcomes as a constrained decision contract. It covers the problem, the mechanism, and when to use it without pretending that a schema alone replaces human judgment.
The problem: approval is not one state
Many agent workflows describe review in natural language: inspect the result, approve it if it looks good, and continue if necessary. That sounds flexible, but it leaves the orchestrator with an unsafe question: what exactly should happen next?
A reviewer might mean any of these things:
- The requested work is complete; stop.
- The current step is good, but a named follow-up remains.
- The result is close; fix specific issues and review the same step again.
- The decision depends on information only a person can provide.
Treating all four as a boolean approval creates two failure modes. The system may stop while a required deliverable is missing, or it may continue without a defined next action. A human can infer intent from prose; a queue should not have to guess.
The improvement is to make the boundary explicit: review produces a small decision object, and the orchestrator advances only when that object satisfies the contract.
The mechanism: four decisions and one transition rule
The gating policy defines four valid decisions:
step_complete: the request is satisfied and autonomous progression stops.approve_next_step: the result is acceptable, but a distinct follow-up must run.changes_required: remediation is needed; retry the current step.escalate_human: stop and ask the owner for input.
The key design choice is that approve_next_step requires a next_step_id. The orchestrator is not allowed to invent a follow-up from vague notes. If there is no named next step, the result cannot authorize continuation.
A minimal review result therefore carries both judgment and evidence:
``json { "step_id": "draft-review", "decision": "step_complete", "confidence": 0.94, "criteria_passed": [ "article_written", "required_structure_present", "draft_path_verified" ], "criteria_failed": [], "blocking_issues": [], "evidence": { "tests": "not_run", "lint": "not_run", "typecheck": "not_run", "changed_paths": [ "COO-FILESYSTEM/articles/drafts/example.md" ] }, "notes": "Draft-only output is complete; publication is not authorized." } ``
The exact evidence fields depend on the workflow, but the principle is stable: the reviewer names what passed, what failed, and where the result can be inspected. The path is especially important for artifact work. “Written successfully” is weaker than a path that can be read and verified.
This is not merely a formatting convention. Validation must reject unknown decision values, missing required fields, invalid confidence ranges, and a continuation decision without a next-step identifier. Invalid output becomes changes_required rather than silently becoming approval.
Fail closed while preserving useful work
Fail-closed does not mean throwing away a nearly complete result. It means separating the artifact from the transition authority.
Suppose an agent writes an article draft correctly but returns a malformed reviewer payload. The draft can remain on disk. The gate should still refuse to advance, because the system cannot establish that the review was valid. The next action is precise: repair or rerun the review, not regenerate the article blindly.
The same distinction helps with human approval. escalate_human is not a generic error. It is a deliberate terminal state for the autonomous cycle, carrying the question the owner must answer. For example: approve publication, choose between two external recipients, or clarify a missing requirement. The queue remains inspectable instead of hiding the uncertainty in a log line.
Evidence should also distinguish “not run” from “passed.” A content-only task may legitimately have tests: not_run; that is different from claiming tests passed. Review policies can then decide which checks are required for each kind of step without weakening the meaning of the evidence.
When to use this improvement
Use a typed review boundary when a workflow has at least one of these properties:
- 1. It can produce an external side effect. Sending a message, publishing an article, changing a live site, or charging money needs a transition that is explicit and reviewable.
- 2. It has multiple steps. If a workflow can continue, retry, or stop, a boolean approval is too small to express the control flow.
- 3. It writes durable artifacts. A path, changed-file list, or receipt gives the operator something concrete to inspect before approval.
- 4. It may pause for a person. Human input should be represented as a state, not as an exception hidden in agent prose.
It is less valuable for a one-shot, read-only answer where there is no queue transition and no durable side effect. Even there, a concise structured result can help integrations, but do not add ceremony merely to make a simple answer look like a workflow.
The contract is also not a license for unattended publishing. A valid step_complete result can establish that a draft is finished without authorizing publication. Side-effect policy still decides which transitions require a human approval or a separate transport call.
A practical implementation sequence
Start with the smallest boundary around one workflow:
- 1. Name the step. Give the unit of work a stable identifier such as
draft-revieworsend-email-review. - 2. Define its terminal states. Decide which checks distinguish completion, remediation, continuation, and escalation.
- 3. Require inspectable evidence. Record changed paths, receipts, or read-only verification results.
- 4. Validate before acting. Parse the reviewer object and reject malformed or incomplete results before dequeuing a follow-up.
- 5. Keep side effects separate. Let review authorize a transition only within policy; perform external writes through their explicit, gated API.
- 6. Log the outcome. Store the decision, evidence, and resulting transition so a later operator can reconstruct what happened.
For a draft-only article job, the safe terminal path is straightforward: generate the file, verify that it exists, and return step_complete for the drafting step. Publication remains a later, separately approved operation. For a communication job, the review may produce approve_next_step with a named send step, but the send route should still enforce its own required fields and policy gate.
Conclusion: make “continue” accountable
Human approval works best when it is the boundary between judgment and execution, not a decorative sentence in a prompt. A constrained review result gives that boundary four useful shapes: finish, continue to a named step, repair, or ask a person.
The next practical step is to wrap one consequential workflow in the contract. List its checks, define its allowed transitions, verify the artifact or receipt, and make malformed review output stop safely. Once the operator can see both the decision and its evidence, approval becomes a controllable handoff rather than a guess about what the agent meant.