Real tools aren't pure functions, they send emails, charge cards, and write databases.Treat them as repeatable and a retry or re-plan does the action twice; fragment the work across agents without shared state and they diverge and conflict (Cognition, Don't Build Multi-Agents, 2025). One unhandled side effect turns the plan into an audit log of damage.

Key facts.
- Side-effecting tools, send, charge, write, provision, aren't repeatable: a retry or re-plan of a non-idempotent call does the action twice, so side effects need idempotency keys and saga-style compensation (distributed-systems transaction patterns).
- Fragmenting work across agents without shared state and compensation leads to divergence and conflicting actions, the orchestrator can't reconcile what each agent actually did (Cognition, Don't Build Multi-Agents, 2025).
- A durable execution engine records which steps completed so a restart replays results instead of re-executing side effects, the basis for exactly-once orchestration (durable-execution practice, e.g. Temporal).
Why does the pure-function assumption break?
Because the orchestration model borrows its intuition from code where calling a function twice is safe. In a notebook, a tool is a pure mapping from input to output: run it again and nothing changes. Production tools are writes against live systems, send an email, charge a card, create an order, terminate an instance, and they're often non-idempotent, so calling one twice does it twice. The agent's control flow makes that easy: it retries on a timeout, re-plans after a partial failure, or runs branches in parallel, and each attempt is a real side effect. Treating a stateful, irreversible action as a repeatable function is the bug, and the orchestrator's confident plan becomes a record of duplicated and unintended actions.
What goes wrong on a partial failure?
Inconsistent state that nobody reconciles. A multi-step plan, reserve inventory, charge the card, create the shipment, can fail at step three with the first two already committed. A pure-function orchestrator has no notion of rolling those back, so the system is left with a charge and no shipment, or a reservation and no order. Retrying the whole plan re-runs the committed steps and duplicates them; doing nothing leaves the inconsistency. this is where coordination and verification failures concentrate, the orchestrator doesn't track which side effects actually happened, so it can't undo or complete them coherently. The plan assumed every step was reversible and free. None of them were.
# Model side-effecting work as a saga: each step has a compensating action saga = [ Step(do=reserve_inventory, undo=release_inventory), Step(do=charge_card, undo=refund_card, idempotency_key=key), Step(do=create_shipment, undo=cancel_shipment), ] run_saga(saga) # on failure at step N, run undo for steps N-1..1; retries replay via keys
How do you orchestrate real side effects safely?
Stop pretending tools are pure. Make every mutating tool idempotent with a stable key so a retry or a re-plan can't duplicate the action. Model any multi-step, side-effecting workflow as a saga: an ordered sequence where each step has an explicit compensating action, so a failure at step three triggers the undos for steps two and one and leaves the system consistent. Run it on a durable execution engine that records which steps completed, so a restart replays results instead of re-executing side effects. Add dry-run modes, rate limits, and monitoring for anomalous action volume, and gate the irreversible steps. The orchestrator then plans over actions whose effects are tracked, undoable, and safe to retry.

Pure-function assumption versus saga orchestration
| Reality | Pure-function orchestrator | Saga orchestration |
|---|---|---|
| Tool has side effects | Treated as repeatable | Tracked, with compensation |
| Non-idempotent call | Retry duplicates it | Idempotency key replays result |
| Partial failure | Inconsistent state left behind | Compensating actions roll back |
| Restart after crash | Re-runs side effects | Durable replay of completed steps |
| Irreversible step | Runs freely | Gated, monitored, dry-run first |
Treat tools as pure and one re-plan double-charges a card; a stronger model re-plans more, so it compounds. (cognition.ai)
The pattern is that orchestration assumes pure functions and production gives you stateful, irreversible, non-idempotent tools, so a naive orchestrator duplicates actions and strands the system in inconsistent state. Make calls idempotent, model side-effecting workflows as sagas with compensation, and run them durably, and the orchestrator handles real side effects without multiplying them. Treating the tool boundary as stateful and undoable rather than pure is reliability at the pattern level, which is what VibeModel builds as the Pattern Intelligence Layer.
Frequently asked questions
what's a saga in one line?
An ordered sequence of steps where each has a compensating action, so a failure partway through is undone step by step to leave the system consistent, instead of half-done.
Why not just retry the whole plan?
Because retrying re-runs the steps that already committed their side effects, duplicating charges or orders. Use idempotency keys so completed steps replay, and compensation to undo what shouldn't stand.
Do I need a workflow engine for this?
A durable execution engine makes it far easier by recording completed steps and replaying them after a crash. At minimum you need idempotency keys and explicit compensating actions for every side-effecting step.

