Each Run Starts Fresh — Decide Where State Lives
Runs do not share context with each other. Whatever the next Run needs to know, the current Run has to record somewhere durable, and the AOP has to say where to look for it. Duvo gives you three places to keep state, each for a different purpose:
For “don’t repeat what previous Runs did,” the middle row is the one that matters: put the workflow’s history in a system of record your team can open, audit, and correct — a Google Sheet, a Drive folder, a database table. If a person can’t see the state, they can’t fix it when it’s wrong.
Make the Archive the Memory
The strongest version of externalized state is when the workflow’s own output is its memory. In the promo selection playbook, each cycle writes its shortlist to an archived sheet, and the next cycle builds its exclusion list by reading the last N archived sheets. There is no separate “already used” list to maintain, because the archive is the list. This closes the loop by construction:- Self-maintaining — producing output and updating memory are the same action, so the memory can’t silently go stale
- Auditable — anyone can open the archive and see exactly why an item was excluded
- Correctable — a human can delete a row to make an item eligible again, without touching the Agent
Exclude at the Source, Not After
Apply non-repetition filters inside the source query — aNOT IN clause in the WHERE — rather than fetching results and filtering them afterward:
Validate Before You Write
Recurring workflows drift. The exclusion window grows, the eligible pool shrinks, an upstream table changes — and one cycle, the query quietly returns less than the workflow needs. Add a validation gate between reading and writing: if the result doesn’t match expectations (too few rows, missing fields, out-of-range values), stop and request human review instead of writing output. Partial output is worse than no output, because downstream consumers can’t tell partial from complete — a pricing Agent fed half a shortlist prices half a promotion with no warning. A hard stop with a clear question (“[actual] of [expected] returned — shrink the shortlist, narrow the exclusion window, or widen the scope?”) turns silent drift into a decision someone actually makes.Keep the Selection Logic in the AOP
Ranking expressions, thresholds, and exclusion windows belong in the AOP — not in a spreadsheet formula, a saved query, or the head of whoever ran the process last. In the AOP, the logic is versioned with the Agent, visible to anyone who opens it, and changed by deliberate edit rather than drift. When the reviewer asks “why did it pick these?”, the answer is readable in one place.Let Reviewers Adjust, Not Redo
An approval gate that only offers approve or deny forces the reviewer to reject a whole batch over one bad item — so they stop rejecting, and the gate stops working. Instead, design the approval to accept small corrections in the response. Responses to requests are free text, so the AOP can define simple commands:Do and Don’t
Related
Promo Product Selection
The full worked example: a promo selection Agent with a non-repetition filter
Agent Memory
The per-user personalization layer — and why it isn’t workflow state
Queue
Cases, statuses, and handing work between Agents
Designing Human-in-the-Loop Workflows
Choosing approval shapes and escalation behavior
Scheduling Agents
Running an Agent on a recurring cadence