Agentic Atlas patterns for agentic design
current field map
  1. example of Effect Discipline

    The Unsent Thunderstorm

    Hook

    one rejected weather bulletin shows when to discard, retry, undo, or stop before acting

    Thesis

    Reject handles the answer and effect discipline handles what the answer already did, so a rejected run's legal recovery (discard, retry, undo, or stop) is decided by what was arranged before the action, not by a generic retry-on-failure rule.

    Laws & fences

    • When validation runs last, throwing away the rejected answer changes nothing to its left: the duplicate preview remains, the invalid page is live, and the forecast has already gone out.
    • The five outcomes are different permissions rather than stronger and weaker versions of one: the keyed preview may remain, the staged draft may be discarded, the live page must be restored, and the subscriber forecast must never be sent before the check.
    • Idempotence protects the retry, not the discard; the keyed preview still remains after rejection, while isolation makes discard legal because the candidate was never promoted.
    • When no compensator is in the contract, the check must precede authority to act; for the append-only forecast log the legal move is a gate, not a more elaborate apology after releasing indoor thunder.

    When to reach

    • Reach for it when asking what reject and retry mean once an agent can do more than return text, such as updating a preview, publishing a live page, or sending to subscribers, since those actions survive the rejected draft.
    • Reach for it past the release furniture, which is incidental: the same distinctions govern database upserts, generated artifacts, deployment APIs, shared state, and outbound messages.
    • Skip it as proof that real message delivery is irreversible in every system; the append-only log is a local stand-in, and what the fixture proves is the placement decision.
  2. Effect Discipline

The card, in place · its connections drawn edges from atlas_links unsent-thunderstorm

Context

context.md

This example explains one problem: what does “reject and retry” mean after an agent has already changed the world?

Pocket Weather sells forecasts in jars to people who find the sky needlessly large. An agent writes its release bulletin; a validator rejects the draft because it still contains a TODO:

# Pocket Weather 1.4

TODO: confirm the indoor thunder limit.

If the agent only returned text, the workflow could throw the draft away and try again. But the task also lets the agent update a preview, publish the live page, and send the forecast to subscribers. Those actions survive after the draft is rejected.

The same invalid draft is used in every arm below. Only the way one action is prepared changes, so each recovery difference has one cause.

Problem signal

problem-signal.md

The unsafe baseline checks last:

agent ──▶ write preview ──▶ publish page ──▶ send forecast ──▶ validate
                                                                      │
                                                                      └── REJECT

At REJECT, throwing away the answer changes none of the things to its left. The duplicate preview remains, the invalid page is live, and the forecast has already gone out. Discarding the text does not put the thunder back in its jar.

Choice

choice.md

Before granting each action, decide what must happen if validation later says no:

Arrange this before the action The rejected run can now… Class name
Give the agent no write authority Be thrown away; nothing happened Pure / read-only
Update one stable preview key Run again without creating another preview Idempotent
Write only to a private stage Have its whole stage thrown away Isolated
Save the exact page being replaced Restore that page, then try again Reversible-at-a-cost
Validate before sending Be stopped before an action that cannot be undone Irreversible

The class name is shorthand for the recovery in the middle column. A generic “retry on failure” rule cannot replace this decision: retry is safe for the keyed preview, but it cannot unsend a forecast.

Before

before.md

demo.py makes the unsafe baseline concrete. After the invalid draft is rejected, four facts remain in its temporary world: a draft file, two preview entries, an invalid live page, and one sent forecast. The baseline has no single cleanup action because those effects do not share a recovery shape.

Implementation

implementation.md

demo.py first reproduces the raw baseline, then starts each shifted arm in a freshly seeded world with the same candidate. Each arm changes one boundary decision.

Shift 1 — return a plan, do not act (pure)

describe_only() returns the intended operations without executing them. The fixture snapshots every file before and after the call and asserts byte-for-byte equality. The dispatch is pure, so rejection licenses discard.

Shift 2 — make repeated previews converge (idempotent)

upsert_preview() replaces the value at pocket-weather-1.4. Calling it twice leaves one preview, which makes retry free. The preview remains after rejection — idempotence protects the retry, not the discard.

Shift 3 — keep the draft off the live page (isolated)

write_isolated() writes under staging/pocket-weather-1.4/. Validation rejects the candidate, the stage is removed, and the live page retains its original bytes. Isolation makes discard legal because the candidate was never promoted.

Shift 4 — save what the publish replaces (reversible-at-a-cost)

publish_with_snapshot() is still a raw live write, but its footprint is one named file and its exact prior bytes are captured first. Rejection invokes compensate_release(), which restores those bytes. The effect is reversible-at-a-cost; compensation pays for the discard.

Shift 5 — check before sending (irreversible)

The append-only forecast log has no compensator. The workflow checks the bulletin and confirmation before it calls send_forecast(). The invalid payload therefore never reaches the irreversible boundary. The legal move is a gate, not a more elaborate apology after releasing indoor thunder.

Result

result.md

One rejected draft now produces five different, checkable outcomes:

baseline              ──▶ REJECT   every raw effect remains
pure                  ──▶ DISCARD  nothing happened
idempotent            ──▶ RETRY    one keyed preview remains
isolated              ──▶ DISCARD  private stage removed
reversible-at-a-cost  ──▶ UNDO (compensate)  exact live page restored
irreversible          ──▶ STOP (gate)        forecast never sent

These are different permissions, not stronger and weaker versions of one permission. The preview may remain because retrying is safe. The staged draft may be discarded because it never became live. The live page must be restored. The subscriber forecast must never be sent before the check.

Verification

verification.md

Run the example from its directory:

python3 demo.py

The script uses only the Python standard library and writes only inside temporary directories. It first asserts that the rejected baseline leaves its draft, duplicate previews, live-page mutation, and sent-forecast entry behind. The five independent arms then assert that description is byte-preserving, duplicate preview retries converge to one keyed record, rejected staged work never reaches the live page, compensation restores the exact pre-dispatch bytes, and the gated bulletin sends no forecast.

The append-only log is a local stand-in for an irreversible effect; the fixture does not prove that real message delivery is irreversible in every system. It proves the placement decision: when no compensator is in the contract, the check must precede authority to act.

Lessons

lessons.md

Decide how failure recovers before uncorking the weather. “Reject” handles the answer; effect discipline handles what the answer already did. It changes what the workflow prepares up front: no authority, a stable key, a private stage, an exact undo, or a check before action.

The release furniture is incidental. The same distinctions govern database upserts, generated artifacts, deployment APIs, shared state, and outbound messages. A rejected return tells you that recovery is needed; the effect class tells you which recovery is still legal.

The relationships ledger

Evidence-bearing references

Relationships

Every connection keeps the section where it was found. The map above orients; this ledger carries the evidence.

Outbound references 0

  1. No outbound references.

Inbound references 1

  1. in-slice · occurrence 1

    Effect Discipline

    one rejected weather bulletin shows when to discard, retry, undo, or stop before acting

    Evidence: Evidence · occurrence 1

↑ back to the top ← the survey

Node unsent-thunderstorm · corpus 31de4cb · Catalog revision 35263c4c415da742953d0462804fb14424e2244dae4c63efd27e468988de70ab