Skip to main content

Human review

A hold pauses one proposed tool call while a person approves or rejects it. The original tool executes only when the same waiting runtime receives a valid approval before expiry.

Review lifecycle

The review record contains tool identity, value-free reasons, a redacted proposed-effect preview, timestamps, and optional reviewer metadata. Raw tool arguments stay in the waiting agent process.

What can create a hold

  • a deterministic policy violation;
  • a grounding check configured with on_fail: hold;
  • a Source error configured with retry.on_error: hold.

Use hold for an intentional exception process. Do not use it as the default for failures that should never be approved, such as cross-customer ownership mismatch.

Runtime behavior

Console-managed enforce() creates a ReviewClient automatically. A held synchronous tool call waits on its request thread. A held async tool runs the wait outside the event loop.

Defaults:

agent = enforce(
agent,
agent_id=agent_id,
api_key=agent_key,
review_timeout=300,
review_poll=2,
)

An approval releases the original call and executes the tool with the arguments already held in that process. A rejection, expiry, timeout, or unavailable review service leaves the tool unexecuted.

Local config= mode without a control plane cannot park a remote review. It returns a held result immediately.

Result codes

CodeMeaningTool executed?
ACTIONRAIL_REJECTEDA person rejected the review.No.
ACTIONRAIL_REVIEW_UNAVAILABLEThe review could not be opened, or connectivity was unavailable at the deadline.No.
ACTIONRAIL_HELDThe review timed out, expired, or remains an unresolved hold without remote review.No.

These codes let application logic distinguish human rejection from infrastructure failure without exposing private decision values to the model.

Console outage behavior

Review is the intentional exception to local-only enforcement because a person must communicate a decision to the waiting runtime.

  • If the review cannot be opened, the runtime fails closed immediately.
  • A transient polling failure after creation does not discard the review; the runtime keeps waiting.
  • If connectivity is still unavailable at the deadline, the runtime returns ACTIONRAIL_REVIEW_UNAVAILABLE.
  • Server-side expiry prevents a late approval from releasing a call after the runtime deadline.

Process lifetime

The proposed call is held in runtime memory. It is not a durable workflow job.

If the agent process restarts or the request is cancelled, that exact call cannot safely resume from the Console record alone. The review expires and a new agent action must be proposed and evaluated again.

Do not design multi-hour or offline approval workflows around the current synchronous review mechanism.

Capacity planning

Each pending review consumes a waiting request/thread context and retains proposed arguments in process memory. Set review_timeout according to:

  • normal operator response time;
  • application request deadlines;
  • worker/thread capacity;
  • deployment termination and autoscaling behavior;
  • the risk of executing an action after facts have become stale.

For high-volume exception workflows, keep rules narrow enough that holds remain exceptional. A surge in pending reviews is an operational issue, not normal throughput.

Reviewer guidance

Reviewers should see enough redacted context to understand the proposed effect without needing raw Source records. If a decision cannot be made safely from the approved metadata, reject it and investigate in an authorized system rather than adding broad values to report_args by default.