# How to Implement Approval Gates with Human Review in Archon Workflows

> Learn how to implement approval gates with human review in Archon workflows. Pause execution, get reviewed, and approve or reject via CLI commands for seamless process control.

- Repository: [Cole Medin/Archon](https://github.com/coleam00/Archon)
- Tags: how-to-guide
- Published: 2026-04-10

---

**Archon implements approval gates with human review by modeling them as special DAG nodes that pause execution via the `pauseWorkflowRun` method, emit an `approval_requested` event to UI clients, and resume only after a reviewer invokes `approve` or `reject` commands via the CLI.**

Archon’s workflow engine represents every step as a node in a directed-acyclic graph (DAG). When you need to inject human oversight into an automated sequence, you configure an **approval node**—a specialized DAG node defined in [`packages/workflows/src/schemas/dag-node.ts`](https://github.com/coleam00/Archon/blob/main/packages/workflows/src/schemas/dag-node.ts) that halts the executor until manual validation is received.

## Schema Definition for Approval Nodes

The shape of an approval node is enforced by the `ApprovalNodeSchema` in [`packages/workflows/src/schemas/dag-node.ts`](https://github.com/coleam00/Archon/blob/main/packages/workflows/src/schemas/dag-node.ts) (lines 247-259). This Zod schema requires a `message` string to display to the reviewer and optionally accepts an `on_reject` sub-object.

The `on_reject` configuration includes:

- A `prompt` string to re-engage the AI if the reviewer rejects
- A `max_attempts` integer to limit retry cycles
- A `capture_response` boolean to persist the reviewer’s comment as node output

## Persistence and Pause Handling

When the DAG executor encounters an approval node, it invokes `pauseWorkflowRun` from [`packages/workflows/src/store.ts`](https://github.com/coleam00/Archon/blob/main/packages/workflows/src/store.ts) (lines 55-58). This method writes a pause record to the workflow-run store, capturing the node ID, type `"approval"`, and metadata such as whether to capture the response or how to handle rejections.

The workflow remains in a **paused** state until external intervention, with the executor returning early and preserving the current execution context in the store.

## Execution Flow in the DAG Executor

The core logic resides in [`packages/workflows/src/dag-executor.ts`](https://github.com/coleam00/Archon/blob/main/packages/workflows/src/dag-executor.ts), specifically within the `executeDagWorkflow` function (lines 2310-2339). The executor performs three critical actions when handling approval nodes:

1. **Message dispatch** – Builds a human-readable string (`⏸ **Approval required**: …`) and sends it via `safeSendMessage` through the platform adapter.
2. **Event emission** – Fires an `approval_requested` event (lines 2320-2325) so UI clients can render approval buttons or dedicated review views.
3. **Metadata marking** – Tags the run with `{ type: "approval", nodeId, captureResponse, onReject… }`.

Upon re-entry, the `isApprovalContext` guard (lines 2210-2225) validates the resume context. If the user approves, the metadata clears and execution continues. If `capture_response` is true, the reviewer’s comment is stored as `$nodeId.output` for downstream consumption.

If the reviewer rejects and an `on_reject` block exists, the executor re-prompts the AI using the configured `on_reject.prompt`, increments the attempt counter, and aborts with a cancellation event after exceeding `max_attempts`.

## Practical Configuration Examples

### Minimal Approval Node

Define a basic gate that captures the reviewer’s comment:

```yaml

# .archon/workflows/example-approval.yaml

name: example-approval
nodes:
  - id: generate-plan
    prompt: |
      Write a short plan to add a logging utility.
  - id: human‑review
    approval:
      message: "Please review the plan above and type **approve** or **reject**."
      capture_response: true
  - id: implement
    bash: |
      # Use the plan stored in $generate-plan.output

      echo "Implementing..."

```

### Approval with Rejection Handling

Configure automatic retries when reviewers request changes:

```yaml
name: approval‑with‑reject
nodes:
  - id: draft
    prompt: "Draft a README for the new feature."
  - id: review
    approval:
      message: "Does the draft look good?"
      capture_response: true
      on_reject:
        prompt: "Please rewrite the README based on the reviewer’s feedback."
        max_attempts: 2
  - id: commit
    bash: |
      git add README.md
      git commit -m "Add updated README"

```

### Resuming Workflows from the CLI

Reviewers interact with paused runs using the Archon CLI:

```bash

# List runs that are waiting for approval

archon workflow list --status paused

# Approve a specific run (the reviewer’s comment will be stored as $review.output)

archon workflow approve <run-id> "Looks fine, proceed."

# Or reject with a custom reason (triggers the on_reject prompt)

archon workflow reject <run-id> "Missing section on installation."

```

## Summary

- **Schema**: Approval nodes are defined by `ApprovalNodeSchema` in [`packages/workflows/src/schemas/dag-node.ts`](https://github.com/coleam00/Archon/blob/main/packages/workflows/src/schemas/dag-node.ts), requiring a `message` and optional `on_reject` policy.
- **Persistence**: The `pauseWorkflowRun` function in [`packages/workflows/src/store.ts`](https://github.com/coleam00/Archon/blob/main/packages/workflows/src/store.ts) creates a durable pause record with type `"approval"`.
- **Execution**: The `executeDagWorkflow` logic in [`packages/workflows/src/dag-executor.ts`](https://github.com/coleam00/Archon/blob/main/packages/workflows/src/dag-executor.ts) handles pausing, emits `approval_requested` events, and manages resumption via `isApprovalContext`.
- **Rejection Handling**: Configurable `on_reject` prompts allow the AI to retry generation up to `max_attempts` before workflow cancellation.
- **CLI Integration**: Reviewers use `archon workflow approve` or `reject` commands to resume execution and optionally provide feedback captured as node output.

## Frequently Asked Questions

### What happens when a workflow reaches an approval node?

The DAG executor pauses the run by calling `pauseWorkflowRun`, which persists the pause state to the workflow-run store with type `"approval"`. The executor then emits an `approval_requested` event and returns early, leaving the workflow in a paused state until human intervention occurs.

### How does Archon store reviewer feedback?

If the `capture_response` flag is set to `true` in the approval node schema, the reviewer’s comment from the `approve` or `reject` command is stored as `$nodeId.output` in the workflow context. Downstream nodes can reference this value using the node ID variable syntax.

### Can I limit the number of rejection retries?

Yes. The `on_reject` configuration accepts a `max_attempts` integer. When a reviewer rejects and provides feedback, the executor re-prompts the AI with the `on_reject.prompt` text up to the specified limit before aborting the workflow with a cancellation event.

### How do I resume a paused workflow?

Use the Archon CLI commands `archon workflow approve <run-id>` to continue execution or `archon workflow reject <run-id>` to trigger rejection handling. Both commands accept an optional comment argument that becomes node output when `capture_response` is enabled.