Escrow Queue
When Sentinel returns a HELD verdict, the action is placed in the escrow queue. Escrow is the mechanism that provides human-in-the-loop governance -- it ensures that supervised actions cannot execute until a human has reviewed and explicitly approved them.
Why Escrow Exists
Many regulatory frameworks and enterprise security policies require human oversight of AI actions, especially in production environments. Escrow provides this oversight with full auditability:
- HIPAA requires human authorization for PHI access patterns.
- SOC 2 requires change management controls for production systems.
- PCI-DSS requires approval workflows for cardholder data environments.
- EU AI Act requires human oversight for high-risk AI systems.
Escrow is not just a technical queue -- it is a compliance mechanism that produces auditable evidence of human review.
Escrow Lifecycle
Action arrives with HELD verdict
|
v
+-------------------+
| ESCROW CREATED |
+-------------------+
| escrow_id assigned|
| timeout_at set |
| status: PENDING |
+-------------------+
|
+------------+------------+
| | |
v v v
+-----------+ +-----------+ +-----------+
| RELEASE | | KILL | | TIMEOUT |
+-----------+ +-----------+ +-----------+
| Human | | Human | | Timer |
| approves | | rejects | | expires |
+-----------+ +-----------+ +-----------+
| | |
v v v
+-----------+ +-----------+ +-----------+
| CLEARED | | BLOCKED | | BLOCKED |
+-----------+ +-----------+ +-----------+
| Agent may | | Agent must| | Agent must|
| execute | | not exec | | not exec |
+-----------+ +-----------+ +-----------+
| | |
v v v
+-----------------------------------+
| AUDIT RECORD UPDATED |
| Original HELD + final outcome |
+-----------------------------------+Escrow Record Structure
When an action enters escrow, a record is created with the following fields:
| Field | Type | Description |
|---|---|---|
escrow_id | string | Unique identifier for this escrow record (e.g., esc_abc123) |
agent_id | string | The agent that submitted the action |
action_type | string | The type of action being held |
target_service | string | The service the action targets |
environment | string | The environment (production, staging, etc.) |
confidence | object | The agent's reported confidence scores |
reasoning | string | The agent's reasoning for the action |
payload | object | The full action payload |
policies_fired | array | CHAM policies that contributed to the HELD verdict |
sentinel_reasoning | string | Sentinel's explanation of why this action was held |
status | string | Current status: PENDING, RELEASED, KILLED, TIMED_OUT |
timeout_at | timestamp | When the escrow expires if no human acts |
created_at | timestamp | When the escrow record was created |
decided_at | timestamp | When a human made a decision (null if still pending or timed out) |
decided_by | string | Who made the decision (null if still pending or timed out) |
decision_reasoning | string | The human reviewer's reasoning for their decision |
seq | number | The audit sequence number from the original HELD verdict |
Three Outcomes
Release (Human Approves)
A human reviewer examines the escrowed action and determines it is safe to execute.
POST /escrow/:escrow_id/release
Content-Type: application/json
{
"decided_by": "admin@company.com",
"reasoning": "Reviewed deployment plan and rollback strategy. Approved for production."
}What happens:
- Escrow status changes to
RELEASED. - The
decided_atanddecided_byfields are populated. - A new audit record is created with verdict
CLEAREDand a reference to the original escrow. - The agent's next status poll returns
CLEARED-- the agent may now execute the action.
TIP
The release includes a decision acknowledgment -- the human reviewer must provide reasoning for their approval. This reasoning is recorded in the audit trail, creating a complete chain from agent intent through human review to execution.
Kill (Human Rejects)
A human reviewer examines the escrowed action and determines it should not execute.
POST /escrow/:escrow_id/kill
Content-Type: application/json
{
"decided_by": "admin@company.com",
"reasoning": "Deployment targets wrong database instance. Agent should resubmit with corrected target."
}What happens:
- Escrow status changes to
KILLED. - The
decided_atanddecided_byfields are populated. - A new audit record is created with verdict
BLOCKEDand a reference to the original escrow. - The agent's next status poll returns
BLOCKED-- the agent must not execute the action.
Timeout (Expires Without Decision)
If no human acts within the configured timeout window, the escrow automatically expires.
What happens:
- Escrow status changes to
TIMED_OUT. - A new audit record is created with verdict
BLOCKEDand reasonescrow_timeout. - The agent's next status poll returns
BLOCKED.
WARNING
Timeout always results in BLOCKED, not CLEARED. This is a fail-closed property -- inaction never equals approval. If the action is genuinely needed, the agent must resubmit it and a human must actively approve it.
Timeout Configuration
Default timeout values:
| Tier | Default Timeout | Rationale |
|---|---|---|
| B (Supervised) | 10 minutes | Supervised actions are expected to be routine; a short window prevents queue buildup. |
| C (Controlled) | 30 minutes | Controlled actions are higher risk and may require more review time. |
Timeouts can be customized per tenant:
{
"escrow_config": {
"timeout_b_tier_minutes": 15,
"timeout_c_tier_minutes": 60,
"notification_channels": ["slack", "email"],
"escalation_after_minutes": 5
}
}| Field | Description |
|---|---|
timeout_b_tier_minutes | Timeout for Tier B escrow records |
timeout_c_tier_minutes | Timeout for Tier C escrow records |
notification_channels | Where to send notifications when new actions enter escrow |
escalation_after_minutes | If no reviewer has looked at the escrow after this many minutes, escalate the notification |
Agent Polling
After receiving a HELD verdict, the agent can poll the escrow status:
GET /escrow/:escrow_idResponse while pending:
{
"escrow_id": "esc_abc123",
"status": "PENDING",
"timeout_at": "2026-04-10T15:10:00Z",
"time_remaining_seconds": 342
}Response after release:
{
"escrow_id": "esc_abc123",
"status": "RELEASED",
"verdict": "CLEARED",
"decided_by": "admin@company.com",
"decided_at": "2026-04-10T15:04:18Z",
"decision_reasoning": "Approved for production deployment."
}Response after kill or timeout:
{
"escrow_id": "esc_abc123",
"status": "KILLED",
"verdict": "BLOCKED",
"decided_by": "admin@company.com",
"decided_at": "2026-04-10T15:06:30Z",
"decision_reasoning": "Wrong target instance. Resubmit with corrected configuration."
}Listing the Escrow Queue
Reviewers can list all pending escrow records:
GET /escrow?status=PENDINGResponse:
{
"escrow_records": [
{
"escrow_id": "esc_abc123",
"agent_id": "agt_deploy_bot",
"action_type": "code_deploy",
"target_service": "payment-api",
"environment": "production",
"confidence": { "incident": 0.92, "fix": 0.87, "containment": 0.95 },
"reasoning": "Deploying hotfix for payment timeout bug",
"sentinel_reasoning": "Tier B: production deployment requires human approval",
"timeout_at": "2026-04-10T15:10:00Z",
"created_at": "2026-04-10T15:00:00Z"
}
],
"total": 1,
"pending": 1
}Escrow Integrity (SGP-6)
Escrow records are protected by SGP-6 (Escrow Integrity):
- Immutable after creation: The original action details, confidence scores, and Sentinel reasoning cannot be modified after the escrow record is created.
- Release or kill only: The only mutations allowed are changing the status to
RELEASEDorKILLED(orTIMED_OUTby the system). - No re-opening: Once an escrow record reaches a terminal state (
RELEASED,KILLED, orTIMED_OUT), it cannot be re-opened or changed. - No agent manipulation: Agents cannot release or kill their own escrow records. Only authenticated human reviewers can.
Escrow Metrics
The escrow queue tracks operational metrics:
| Metric | Description |
|---|---|
pending_count | Current number of pending escrow records |
avg_decision_time | Average time between creation and human decision |
release_rate | Percentage of escrow records that are released (approved) |
kill_rate | Percentage that are killed (rejected) |
timeout_rate | Percentage that expire without a decision |
oldest_pending | Age of the oldest pending escrow record |
WARNING
A high timeout rate indicates that human reviewers are not monitoring the escrow queue. This is a governance risk -- it means agents are being blocked not by deliberate human decision but by neglect. If your timeout rate exceeds 10%, investigate your review workflow.
Best Practices
- Set up notifications: Configure Slack, email, or webhook notifications for new escrow records so reviewers are alerted immediately.
- Keep timeouts reasonable: Too short and reviewers cannot respond in time; too long and agents are blocked unnecessarily.
- Provide reviewer training: Reviewers should understand the action types, confidence scores, and policies that led to the HELD verdict.
- Monitor timeout rates: A high timeout rate means your review process needs attention.
- Use AUDIT_ONLY mode first: Test your tier mappings and policies in AUDIT_ONLY mode to see what would be held before enforcing, so you can calibrate your escrow volume.