> ## Documentation Index
> Fetch the complete documentation index at: https://docs.erdo.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# The review queue

> The queue of things an agent wants a human to decide — knowledge the critic proposes, investigations it opens, and the failure signals it keeps counting — readable and answerable over the app, MCP, REST, and the CLI.

# The review queue

As agents work they accumulate two kinds of loose end that a machine shouldn't close on its own.
The first is a **proposal**: an agent learned something durable — "this column is the revenue
metric", "this API caps page size at 100" — and wants it written into [Knowledge](/knowledge) so the
next thread doesn't relearn it. The second is a **failure it couldn't fix in the moment**: an eval
regressed, a run died on a runtime error, an automation broke. Neither should silently become truth
or silently disappear, so both queue into **Review** — one place where a human accepts what's right,
declines what isn't, and decides what to chase.

The queue used to be reachable only from the web app. It is now the same surface over **MCP**, the
**REST API**, and the **CLI**, so a headless caller — a scheduled agent, a CI job, your own
automation — can read what's waiting and decide it without opening a browser. Every item is
org-scoped and RBAC'd: you only ever see and decide your own organization's queue, exactly as the
app enforces it.

## What lands in the queue

Items fall into two families, and the queue keeps the **decision items above the failure signals**
so a proposal waiting on you is never buried under noise, whatever their relative priority.

**Decision items** are the ones an agent is explicitly asking a human to rule on:

* A **knowledge patch** — a new or edited Knowledge object the agent proposes. Because approving one
  changes what every agent and person in your workspace treats as true, it carries the whole proposed
  body: the target object, the new title and markdown, the problem it fixes, the evidence behind it,
  and the impact it expects. You read that before you apply it, and applying it is the same
  human-in-the-loop step as an [approval](/approvals) on an action — the difference is that here the
  thing being approved is a fact, not a side effect.
* An **investigation** — a request for an engineer to dig into a root cause and come back with a code
  fix or a concrete finding, carrying links to the run, thread, and eval that motivated it.

**Failure signals** are raised automatically when work breaks — a failed eval case, a failed
top-level run, a failed automation, or answer feedback. These **deduplicate**: repeated failures of
the same class count *up* on one item (its `occurrence_count`) rather than spawning a fresh row every
time, so a persistently broken path reads as one loud item instead of a hundred quiet ones. A signal
resolves when the underlying condition clears — an eval-failure item closes once the same case passes
again — or ages out of the queue if it goes stale.

## Deciding an item

A decision is one of four actions:

* **Apply** — for a knowledge patch only: create or update the proposed Knowledge object, then close
  the item as resolved. The apply is atomic — two callers racing to apply the same patch can't
  produce a duplicate object, and if the Knowledge write fails the item reopens so you can retry.
* **Resolve** — close the item as handled without applying a patch (the right action for a failure
  signal you've dealt with elsewhere, or an investigation you've completed).
* **Reject** — close the item as declined. A rejected patch is not written to Knowledge.
* **Snooze** — hide the item until later. It takes an optional number of minutes and defaults to
  seven days, after which it returns to the open queue.

You can attach a **note** to any decision, which is recorded on the item as the resolution note.

## Programmatic access

The queue is readable and answerable over MCP, REST, and the CLI. A review item has no slug, so it's
referenced by its **id** — you list the queue, read the one you care about, and decide it by that id,
all within the one surface.

```bash theme={null}
# read the queue
erdo reviews list                          # the open queue (decision items first)
erdo reviews list --type knowledge_patch   # only proposed knowledge
erdo reviews list --status resolved        # a different status; '' for all

# read one item's full payload (the proposed patch body for a knowledge_patch)
erdo reviews show <id>

# decide it
erdo reviews decide <id> --apply           # apply a knowledge patch, then resolve
erdo reviews decide <id> --resolve --note "handled in PR #123"
erdo reviews decide <id> --reject
erdo reviews decide <id> --snooze 1440     # snooze for 24 hours
```

### MCP tools

| Tool                      | What it does                                                     |
| ------------------------- | ---------------------------------------------------------------- |
| `erdo_list_review_items`  | List the queue, filtered by `status` (default `open`) or `type`. |
| `erdo_get_review_item`    | Get one item with its full payload (the proposed patch body).    |
| `erdo_decide_review_item` | Decide an item: `apply`, `resolve`, `reject`, or `snooze`.       |

### REST

Base URL `https://api.erdo.ai`. `Authorization: Bearer <token>` + `X-Organization-ID`.

| Method | Path                          |
| ------ | ----------------------------- |
| `GET`  | `/v1/review-items`            |
| `GET`  | `/v1/review-items/:id`        |
| `POST` | `/v1/review-items/:id/decide` |

`GET /v1/review-items` takes optional `status` (default `open`; pass `status=` for all), `type`,
`limit`, and `offset` query parameters. `POST /v1/review-items/:id/decide` takes `action` (`apply`,
`resolve`, `reject`, or `snooze`), an optional `minutes` (for `snooze`), and an optional `note`.
