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

# Designing Work Around Queues and Cases

> Structure producer and consumer Agents so every Case ends somewhere definite, waiting periods work with the platform, and nothing silently disappears.

When work arrives as a stream of items — orders, tickets, invoices, requests — put it in a [Queue](/user-guide/assignment-features/case-queue) and let your Agents process it as Cases. This page covers the design rules that keep a Queue healthy once real volume flows through it. For what Queues and Cases are and how to set them up, start with the [Queue](/user-guide/assignment-features/case-queue) guide.

## One Case per Run

A consumer Agent processes exactly one Case from start to finish, and the platform handles everything around it: picking up the next Case, running several in parallel, and re-dispatching postponed ones. Write the AOP for a single item and let Duvo iterate — a batch loop in the AOP hides per-item failures inside one Run and breaks per-Case tracking. This is the same rule as [Writing Effective AOPs](/best-practices/writing-effective-aops), applied to Queues.

## Split Producers from Consumers

A healthy Queue has two distinct roles, and usually two distinct Agents:

* The **producer** finds work and adds Cases to the Queue. Its job ends when the Cases are added — it never claims or processes them.
* The **consumer** claims one Case, works it, and settles it.

<Warning>
  Duvo does not deduplicate Cases. If a producer adds the same item twice, the Queue holds two Cases and the consumer will process both. Deduplication is the producer's job: have it check the Queue for an existing Case before adding a new one, especially when it runs on a frequent schedule.
</Warning>

## Close Every Case, Every Time

Every Case a consumer claims must end in exactly one of four ways: **completed**, **failed** (with a reason), **postponed** for a later retry, or **handed over** to another Agent.

If a Run ends without settling its Case, Duvo marks the Case as Failed automatically — with no reason attached. In practice this is the most common failure mode for Queue-driven Agents: the AOP covered the happy path, an odd Case took an uncovered branch, and the Case shows up Failed with nothing to explain why. The fix is in the AOP: give every branch an explicit ending.

```mermaid theme={"dark"}
flowchart TD
    A[Consumer claims one Case] --> B{How does this branch end?}
    B -->|Work is done| C[Complete the Case]
    B -->|Cannot be done at all| D[Fail the Case<br/>with the reason]
    B -->|Cannot be done yet| E[Postpone the Case<br/>to retry later]
    B -->|Another Agent should take it| F[Hand the Case over]
```

## Postpone or Fail: Choose Deliberately

Postpone and fail look similar in the moment ("I can't finish this Case now") but mean opposite things:

| Situation                                                    | Right ending |
| ------------------------------------------------------------ | ------------ |
| Waiting on a reply, an external process, or a scheduled date | Postpone     |
| Rate-limited by an external system                           | Postpone     |
| Required data is missing or invalid and won't fix itself     | Fail         |
| A credential or Connection the work depends on isn't working | Fail         |

Postponing a permanent problem is the trap to avoid: the Case comes back, hits the same wall, gets postponed again, and loops forever without anyone noticing. If retrying won't change the outcome, fail the Case with a clear reason so a person can step in.

<Note>
  Postpones have a minimum wait — very short postpone times are rounded up to your workspace's minimum. Don't design flows that depend on retrying within a few minutes.
</Note>

## The Waiting Pattern

For any step that means "wait N days, then act" — follow-ups, reminders, escalation timers — use postpone with a marker on the Case:

1. On the first pickup, record a marker in the Case data (for example `reminder_sent: true`), then postpone the Case for the waiting period.
2. On the next pickup, the marker is there, so the AOP skips ahead and does the real work.

Use a different marker for each waiting phase if the flow has several. This keeps a multi-day process inside one Agent, instead of spawning a separate Agent per stage.

## Update the Case as You Go

Anything you record on a Case — progress notes, intermediate results, markers — survives postpones and handovers. The next Run picks up where the last one left off, and a teammate looking at the Queue can see where each Case stands. Update the Case at meaningful milestones, not just at the end; a Case that fails halfway through with no notes is as opaque as one that never updated at all.

## Handing Over Is Its Own Ending

Handover passes the Case to a different Agent after the current Run finishes — use it when a specialist Agent is better placed to continue. It is one of the four endings, not something you combine with the others: a branch that hands the Case over must not also complete, fail, or postpone it, or the receiving Agent never gets the Case.

## Watch the Throughput, Not Just the Cases

Cases process in parallel up to the consuming Agent's concurrency limit. When the Agent is at capacity, new Cases simply wait as Pending until a Run finishes — nothing is lost, but a slow AOP quietly turns into a growing backlog. If Pending keeps climbing, make each Case's work shorter, or split the process into stages with [Multi-Agent Process Decomposition](/user-guide/building-assignments/process-decomposition).

And give each Queue exactly one consuming Agent. If two Agents both have triggers on the same Queue, Duvo won't pick a winner — conflicted Cases don't run at all. The trigger setup warns you about this; take the warning seriously.

## Related

<CardGroup cols={2}>
  <Card title="Queue" icon="layers" href="/user-guide/assignment-features/case-queue">
    What Queues and Cases are, statuses, and how to set them up.
  </Card>

  <Card title="Writing Effective AOPs" icon="pen-line" href="/best-practices/writing-effective-aops">
    The principles behind AOPs that close every branch.
  </Card>

  <Card title="Choosing How Your Agent Starts" icon="play" href="/best-practices/choosing-how-runs-start">
    Schedules, triggers, Queues, and manual Runs — picking the right one.
  </Card>

  <Card title="Multi-Agent Process Decomposition" icon="split" href="/user-guide/building-assignments/process-decomposition">
    When one Agent is doing too much, split it into stages.
  </Card>
</CardGroup>
