How to Configure User Gates and Approval Workflows in LoopX

LoopX treats every human decision point as a durable user_gate todo that blocks agent execution until an explicit decision outcome—approve, reject, or defer—is recorded via the CLI or dashboard.

Configuring user gates and approval workflows in LoopX centers on creating specialized todos that integrate with the control plane's quota kernel. When the system encounters a user_gate task class, as defined in docs/project-agent-todo-contract.md, it projects an interaction contract that pauses the agent's lane until an operator resolves the gate. This pattern ensures critical oversight points receive explicit human approval while maintaining workflow durability through the state management system.

What Is a User Gate?

A user gate is a specialized todo with task_class="user_gate" that represents a concrete decision requiring human judgment. According to the project-agent-todo-contract specification, these gates are durable state objects that the control plane projects into an agent's lane, effectively halting progress until resolved.

The system supports three scoping modes:

  • Agent-scoped: Uses --blocks-agent $AGENT_ID to restrict resolution to a specific agent
  • Global: Uses --global-gate=true for approvals affecting the entire goal
  • Unscoped: Multi-agent gates that any eligible agent may resolve

When open, the quota kernel treats these gates as hard blocks (interaction_blocking_user_gate), surfacing them via interaction contracts while optionally applying notification cooldowns to prevent operator spam.

Creating User Gates via the LoopX CLI

You configure approval workflows by creating gates using the loopx todo add command. The CLI automatically emits a surface_user_gate packet that the quota kernel interprets to pause lane execution.

Agent-Scoped Gates

Create a blocking gate tied to a specific agent when you need granular approval control:

loopx todo add \
  --goal-id $GOAL_ID \
  --role user \
  --task-class user_gate \
  --blocks-agent ci-runner-01 \
  --text "Approve deployment of artifact v2.1 to staging?"

The --blocks-agent parameter ensures only ci-runner-01 execution is paused while other agents may continue processing independent work.

Global Approval Gates

For decisions affecting the entire goal—such as production releases or merge approvals—omit the agent scoping and use the global flag:

loopx todo add \
  --goal-id $GOAL_ID \
  --role user \
  --task-class user_gate \
  --global-gate=true \
  --text "Approve production release of version 1.2.3?"

Global gates, as documented in docs/state-interaction-model.md, block all progress on the goal until the decision outcome is recorded.

How Gates Are Surfaced to Operators

When the quota kernel encounters a user_gate, it generates an interaction contract with kind=surface_user_gate that projects the gate into the presentation layer (apps/presentation/dashboard). The contract includes the mode, decision scope, and response plan.

The system emits a gate packet structure resembling:

{
  "interaction_contract": {
    "kind": "surface_user_gate",
    "mode": "user_gate",
    "response_plan": {
      "kind": "surface_user_gate",
      "decision_outcome": null
    }
  },
  "notification_cooldown": {
    "notification_suppressed": false,
    "deadline": "2026-09-01T12:00:00Z"
  },
  "scoped_user_gate_fallback": null
}

Notification Cooldown: To prevent spamming operators while a gate remains open, the system creates a user_gate_notification_cooldown_v0 packet, as specified in docs/status-data-contract.md, suppressing duplicate notices until the deadline expires.

Scoped Fallbacks: When a gate blocks the main lane but independent work can proceed safely, the control plane may project a scoped_user_gate_fallback, allowing side-track execution while maintaining the gate block on the critical path.

Resolving Gates with Decision Outcomes

Operators resolve gates using the loopx todo complete command, writing a durable decision_outcome back into the todo. This triggers the quota kernel to consume the gate and resume execution.

Recording an Approval

loopx todo complete \
  --todo-id $TODO_ID \
  --decision-outcome approve \
  --comment "Reviewed and approved by product owner"

Upon resolution, the control plane:

  1. Consumes the gate, removing it from the agent's lane
  2. Clears the notification_cooldown state
  3. Advances the workflow to the next lane, or projects any pending scoped_user_gate_fallback work

Deferring Decisions

When immediate approval isn't possible, defer the gate to establish a cooling-off period:

loopx todo complete \
  --todo-id $TODO_ID \
  --decision-outcome defer \
  --comment "Pending security review, will revisit tomorrow"

Setting decision_outcome=defer creates a new user_gate_notification_cooldown packet, respecting the chosen cadence before resurfacing the gate.

Common Approval Workflow Patterns

Global Release Gates

Use global gates for high-stakes decisions requiring centralized oversight. According to docs/product/core-control-plane/state-definitions.md, these gates ensure no agent proceeds past critical checkpoints without explicit sign-off:

loopx todo add \
  --goal-id $GOAL_ID \
  --task-class user_gate \
  --global-gate=true \
  --text "Approve merge of feature branch to main?"

Scoped Fallback with Independent Monitoring

When the main lane requires approval but monitoring tasks can run safely, implement the scoped fallback pattern. The runtime logic in loopx/control_plane/todos/user_gate.py supports projecting parallel work via apply_scoped_user_gate_fallback_projection while keeping the critical path blocked.

Multi-Agent Resolution

For gates resolvable by any member of a team, omit --blocks-agent but avoid ambiguity by specifying clear decision scopes. The repair-patterns.md reference warns against "unscoped_multi_agent_user_gate" configurations that lack explicit resolution criteria.

Exact Decision Scope Overrides

In complex workflows, enforce precise control using exact_user_gate_decision_scope_override, documented in docs/reference/protocols/decision-scope-v0.md, ensuring only intended agents or specific global contexts can resolve the gate.

Summary

  • User gates are durable todos with task_class="user_gate" that create hard blocks in the agent execution lane pending human decision
  • Create gates using loopx todo add with --blocks-agent for scoped approvals or --global-gate for goal-wide decisions
  • Surface mechanism relies on interaction contracts (kind=surface_user_gate) projected by the quota kernel to the dashboard, with optional user_gate_notification_cooldown_v0 to manage notification frequency
  • Resolve gates via loopx todo complete --decision-outcome, supporting outcomes of approve, reject, or defer, which triggers consumption of the gate and workflow resumption
  • Advanced patterns include scoped fallbacks for parallel execution and exact decision scope overrides for security-sensitive approvals

Frequently Asked Questions

What is the difference between a scoped gate and a global gate in LoopX?

A scoped gate uses --blocks-agent to pause execution for a specific agent while allowing other agents to continue, whereas a global gate (--global-gate=true) blocks all progress on the entire goal until resolved. Scoped gates support parallelism through scoped_user_gate_fallback projections, while global gates enforce synchronized checkpoints across the workflow.

How do I defer a user gate decision instead of approving it immediately?

Use loopx todo complete --todo-id $TODO_ID --decision-outcome defer to record a deferral. This creates a new user_gate_notification_cooldown packet that suppresses gate notifications until the specified deadline, allowing operators to revisit the decision after gathering additional information or completing external reviews.

What happens to agent execution when a user gate is open?

When a gate is open, the quota kernel treats it as an interaction_blocking_user_gate, pausing the affected agent's lane projection. The agent cannot advance past the gate until the operator records a decision outcome. If configured, scoped_user_gate_fallback may allow independent side-track work to proceed while maintaining the block on the critical path.

Where is the user gate runtime logic implemented in the LoopX source code?

The core projection, fallback handling, and cooldown management logic resides in loopx/control_plane/todos/user_gate.py, while the data contracts governing todo structure are defined in docs/project-agent-todo-contract.md and interaction semantics are specified in docs/state-interaction-model.md.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →