Module 5: Dependencies Between Workflows
7. Delegation across multiple agents without duplicating work
Description
By the end of this lesson you will be able to take a system where one AI Agent delegates work to another — the "an agent as another's tool" pattern you saw in the chatbots guide — and guarantee that no effect fires twice because of the delegation, even if two agents decide to do the same thing, even if an agent retries, or even if they fall into a redelegation loop. You will see why agents are especially dangerous for correctness (they're non-deterministic: two runs can decide different things), and you will learn the strategy that resolves it without killing the autonomy that makes an agent useful: don't try to make agents not duplicate — make their effects idempotent so it doesn't matter if they do. The tools are the usual ones — Module 2's idempotency key, Module 4's ledger as shared memory, lesson 6's outbox — plus two brakes specific to agents: the iteration limit and a tool for checking what's already been done.
This matters because multi-agent systems are the frontier where a duplicated effect sneaks in most easily, and where it's hardest to debug. An agent doesn't execute a fixed plan: it reasons, chooses, and sometimes chooses differently the second time. If its tool is "issue a refund" and for whatever reason the agent calls it twice — because it retried, because another agent already did it, because the reasoning loop went one turn too many — you get a duplicated refund fired by a decision that wasn't even deterministic. The good news is that everything you built in this module applies unchanged: an agent's effect is an effect, and an effect gets protected the same way whether it comes from an IF node or from a model reasoning.
Connection to the module: this lesson applies everything so far to a concrete, current case. Lesson 6's outbox is the correct way for an agent to fire a dangerous effect: the agent doesn't call the gateway, it writes a ticket. Lesson 1's and Module 4's ledger — the shared whiteboard — is what keeps two agents from repeating each other's work. And it leans on the sister chatbots guide, Module 5: that's where the AI Agent Tool node, the $fromAI() mechanism, the Max Iterations parameter, and delegation loops come from. Here we're not teaching how to build the multi-agent system again — that's that guide's job — here we make it correct: making sure its effects don't duplicate.
Why an agent is more dangerous than an IF
Let's start by understanding what makes an agent special — and risky — compared to everything we've seen so far.
An IF node, a Switch, a chain of nodes: these are deterministic. Given the same input data, they do exactly the same thing, always. If a deterministic flow decides to issue a refund, the only way for it to issue it twice is for it to run twice — the duplicate problem you already know how to handle.
An AI Agent is different: it's non-deterministic. You give it the same case twice and it can reason through two different paths, choose different tools, reach different conclusions. That's exactly its virtue — it adapts to what you didn't anticipate — and it's its danger for correctness. Think of it with two new employees you tell "resolve this customer's problem." One employee looks it over, sees a refund is warranted, and issues it. The other employee, with the same case, looks it over, and also decides to issue the refund — maybe through a different reasoning path, but arriving at the same effect. If both act, there are two refunds. Not because either one failed: both did their job well. The problem is that no one coordinated that the effect was already done.
That scene — two who correctly do the same thing without knowing about each other — is lesson 1's disaster 3, the duplicated effect, in its hardest-to-prevent version, because the actors reason and you can't predict exactly what they'll decide. And it gets worse with delegation: when one agent delegates to another, new paths open up for the same effect to fire twice.
A reminder of native delegation
To talk about the risks we need the mechanism fresh in mind. It comes from the chatbots guide, Module 5, and we summarize it here without re-teaching it.
In n8n 2.0, a whole agent can be connected as a tool of another agent, using the AI Agent Tool node (its internal type is @n8n/n8n-nodes-langchain.agentTool). It connects to the calling agent's ai_tool port, the same way you'd connect a Gmail node. From the caller's point of view — the orchestrator — it's one more tool: it has a Description that says when to use it, and it receives its assignment through a $fromAI("task", ...). The difference is that on the other end of the wire there isn't a fixed action, but another agent that reasons, chooses among its own tools, and returns a result.
At Cumbre, imagine a triage_agent (the orchestrator, which talks to the customer) that delegates to a billing_agent (the billing and refunds specialist). When the customer says "I got overcharged for order ORD-2041," triage_agent decides to delegate to billing_agent, passing it a self-contained assignment. billing_agent reasons, checks, and at some point decides to issue a refund. That "issue a refund" is an effect, and that's where this lesson comes in.
Three pieces from that guide that here act as correctness brakes:
Max Iterations: how many reason-act-observe turns an agent can take before giving up. It comes with a default value — 10 on theAI Agentnode. It's the brake against infinite loops.- Delegation loops: a multi-agent system has nested loops — each agent's internal one, the orchestrator's, and the dangerous redelegation loop, where two specialists bounce the same case back and forth ("this is billing" / "this is order handling") and the orchestrator redelegates without end.
- The rule that workers don't delegate to each other directly: to keep the agent graph free of cycles, a specialist doesn't call another specialist; everything goes through the orchestrator. It's the same anti-cycle discipline from lesson 3, applied to agents.
With that fresh, let's look at the new paths through which an agent's effect gets duplicated.
The three paths to a duplicate in a multi-agent system
Path 1 — The agent retries its own tool
An agent calls its "issue refund" tool, the call takes too long, the agent — or the engine — retries, and there are two calls to the effect for the same order. It's Module 1's classic duplicate, inside an agent's reasoning. Since the agent doesn't itself carry a durable record of "I already issued this refund," it has no way of knowing whether the first call may have actually worked.
Path 2 — Two agents decide on the same effect
The orchestrator delegates the case to billing_agent, which issues the refund. But the assignment was ambiguous and the orchestrator, not receiving a clear confirmation, delegates again — maybe to the same agent, maybe to another one — which issues the refund again. Two delegations, two refunds. It's the scene of the two employees: each delegation did its job, no one coordinated that it was already done.
Path 3 — The redelegation loop
The case falls on a fuzzy border between two specialists. order_agent says "this is billing," the orchestrator delegates to billing_agent, which says "this is order handling," the orchestrator delegates back to order_agent... and if on any of those turns someone fires an effect "just in case," the effect repeats on every loop turn. This loop, besides duplicating, burns money and time — each turn is a model call — and, as you saw in the chatbots guide, produces no error at all: the system looks like it's "thinking" while spinning in place.
The three paths share the same root: the effect gets fired by an actor that doesn't know, durably and in a shared way, whether that effect has already happened. And therefore they share the same cure.
The strategy: don't trust the agent, shield the effect
Here's the lesson's central idea, and it's a mindset shift. The temptation is to try to make agents not duplicate: write perfect prompts, set rules so the orchestrator never redelegates twice, fine-tune the boundaries between specialists. All of that helps — and it should be done — but that's not where the guarantee lives, for a fundamental reason: the agent is non-deterministic, so you're never going to be able to guarantee by prompt that it will never fire an effect twice. A prompt reduces the probability; it doesn't bring it to zero.
The guarantee lives elsewhere: make the effect idempotent, so it doesn't matter how many times the agent fires it. If "issue the refund for ORD-2041" is idempotent — it happens exactly once no matter how many times it's requested — then all three duplicate paths stop doing damage. The agent can retry (path 1), the orchestrator can redelegate (path 2), the loop can spin (path 3): every attempt to issue the refund, after the first, does nothing. Correctness doesn't depend on the agent behaving well; it depends on the effect being shielded.
Think of it this way: instead of asking the two employees to coordinate perfectly with each other — which is fragile — you put a rule at the counter where refunds get issued: "one refund per order number, and that's it." It doesn't matter how many employees come to request the refund for order ORD-2041; the counter issues it once. Coordinating actors is hard and fragile; shielding the shared resource is robust.
And you already have this built. Both mechanisms come from this module:
An agent's tool is not the raw effect — it's the idempotent effect. When you connect an "issue refund" tool to billing_agent, that tool should not be a direct HTTP Request to the gateway. It should be the idempotent path you built: either the issue-refund sub-workflow that checks the ledger before issuing, or — better for a dangerous effect — a ticket in the outbox. That way, when the agent "issues the refund," it's actually writing an idempotent ticket per order_id, and the relay executes it exactly once. The agent believes it issued the refund; what it did was register an intent that the system executes exactly once.
The ledger is the shared memory between agents. Lesson 1's kitchen whiteboard, now between agents. Before issuing a refund, an agent can — and should be able to — check the ledger: "has ORD-2041's refund already been issued?" If yes, it doesn't try. This gets given to the agent as a read tool ("check order status"), and it's what cuts off path 2 and path 3 at their source: the second agent about to issue the refund checks the board, sees it's already done, and doesn't. It's cheaper than letting it fire and having the effect reject it, and it gives the agent the information to reason correctly.
Notice these are two layers: the agent checks the ledger before acting (avoids wasted work and extra model calls), and the effect is idempotent regardless (guarantees correctness even if the agent, being non-deterministic, ignores what it saw in the ledger). The first layer is efficiency; the second is the guarantee. Never depend only on the first: the agent can check the ledger and still decide to issue the refund, because it's non-deterministic. The net below — the idempotent effect — is what never fails.
Worked example: the refund billing_agent cannot duplicate
Let's build the complete case and test it against all three paths.
The setup. triage_agent (orchestrator) has billing_agent connected as an AI Agent Tool. billing_agent, in turn, has two tools:
- A read tool:
get_order_status, a sub-workflow that checks the ledger and returns the order's status, including whether a refund has already been issued or decided. - An effect tool:
request_refund, which does not call the gateway directly. It's a sub-workflow that writes a ticket to theoutboxfor the refund, atomically and idempotently byorder_id, as in lesson 6. It returns "refund registered" or "refund was already registered."
billing_agent's System Message includes the policy:
# billing_agent's System Message (correctness excerpt)
Before requesting a refund, ALWAYS check get_order_status first.
If the order already has a refund issued or decided, do NOT
request it again: report that it was already done.
To request a refund use request_refund with the order_id. This
tool is idempotent: if you call it twice for the same order,
the refund happens only once. Even so, avoid calling it if you
already know it's done.
Notice what that prompt does: it tells the agent to check first (layer 1, efficiency) and it informs it the tool is idempotent (so it doesn't fear a duplicate if something goes wrong). Both layers, declared.
The idempotent effect, on the inside. The request_refund tool is lesson 6's sub-workflow:
# Sub-workflow: request_refund (Execute Sub-workflow Trigger)
# input (contract): order_id, amount, currency
1. Postgres (atomic): register the refund decision in the ledger
AND insert the ticket into the outbox, with
idempotency_key = 'refund:' + order_id,
ON CONFLICT DO NOTHING.
2. Return: "registered" if it was new, "already registered" if the ON CONFLICT skipped it.
The relay issues the real refund afterward, with the Idempotency-Key. billing_agent never touches the gateway; it only registers the intent. Remember the n8n 2.0 rules: the external effect (the gateway) is done by an HTTP Request in the relay, not a Code node; the outbox write is done by a Postgres node. The agent decides; the dedicated nodes execute.
What to expect, path by path.
Path 1 — the agent retries request_refund. billing_agent calls request_refund for ORD-2041; the call takes too long; the agent retries. Both calls insert with the same idempotency_key = 'refund:ORD-2041'. The first inserts the ticket; the second collides with the ON CONFLICT and inserts nothing. There's one ticket in the outbox, the relay issues one refund. The agent's retry did no harm.
Path 2 — the orchestrator redelegates. triage_agent delegates to billing_agent, which registers the refund. Due to an ambiguity, triage_agent delegates again. The second billing_agent, following its prompt, checks get_order_status first, sees the refund is already decided, and does not call request_refund — it reports it was already done. Layer 1 (checking first) cut off the wasted work. And if, being non-deterministic, it had called request_refund anyway, the ON CONFLICT would have skipped it: layer 2 covers it. One refund.
Path 3 — the redelegation loop. The case bounces between billing_agent and order_agent. Two brakes act here: the orchestrator's Max Iterations cuts off the loop before it spins endlessly (a brake from the chatbots guide), and even if on some turn an agent called request_refund, idempotency by order_id guarantees a single refund. The loop burns some money in model calls before cutting off — which is why clear boundaries between specialists matter — but it does not produce duplicate refunds. The loop's damage stays bounded to cost, not effects.
On all three paths, exactly one refund. And notice the pattern: prompts and limits reduce duplicate attempts (efficiency, cost), but the guarantee that the effect happens once comes from idempotency by order_id, not from the agent's behavior. That's the lesson.
Setting the brakes: iterations, keys, and shared memory
Let's summarize the concrete brakes, which combine this guide with the chatbots one:
Iteration limit (Max Iterations). Every agent and the orchestrator carry a cap on turns. Without it, the redelegation loop spins until it exhausts the budget. With it, the system gives up in a controlled way and — well configured with an honesty instruction in the prompt — says "I couldn't resolve this, escalating it" instead of spinning. Calibrate it with your traces, as the chatbots guide teaches: count the real iterations of a typical case and give it margin.
Idempotency key per task/effect. Every effect an agent can fire has its own stable key, derived from the business: refund:ORD-2041, inventory:ORD-2041:CF-ARA-500. The key is what deduplicates no matter how many agents or turns fire it. The key goes by the effect (the order_id, the sku), not by the agent's run — if you derived it from the agent execution's identifier, two runs would have different keys and would deduplicate nothing.
The ledger as shared memory. Give agents a read tool for the ledger, so they check what's already done before acting. It's the common memory that keeps two agents from repeating each other's work. And keep it as the source of truth: an order's state lives in the ledger, not in an agent's conversational memory — which is ephemeral and not shared.
Against the redelegation loop, clear boundaries and a counter. The cause of loop 3 is almost always a fuzzy boundary between two specialists. The first defense is a good tool design (scope descriptions with an explicit "don't use this for...," as the chatbots guide teaches). The second, a redelegation counter in the orchestrator's prompt or in the ledger: "if this case has already bounced twice between specialists, escalate to a human instead of continuing to delegate."
A note on models and dates
The specific models you use for each agent — which one goes in the orchestrator, which in the specialist — change often, and recommendations age fast. As of writing this guide, mid-2026, common practice is a fast, cheap model in the orchestrator (which only decides who to delegate to) and a more capable one in the specialists that make costly decisions — like issuing money. But the exact names and specific capabilities you should verify in the documentation and in your instance's panel when you build this: what doesn't change is the correctness architecture — idempotent effects, shared ledger, iteration limits — which is independent of whatever model you put behind it. A system with the best model on the market but no idempotent effects duplicates refunds; one with a modest model but shielded effects doesn't. Correctness isn't given by the model.
Common mistakes
Trying to prevent the duplicate with only the prompt (conceptual). What happens: someone writes a careful System Message — "never issue a refund twice," "coordinate with the other specialists" — and trusts that as a guarantee. It works in testing, and one day, under some rare case, the agent issues the refund twice anyway, because it's non-deterministic and the prompt only lowers the probability. Why it happens: a well-written prompt reduces duplicates so much it creates the illusion of having eliminated them. How to detect it: ask yourself "if the agent, for whatever reason, fires this effect twice, what stops it?" If the only answer is "the prompt told it not to," there's no guarantee. How to fix it: the prompt is the efficiency layer; the guarantee is the effect being idempotent by its business key. Write good prompts and shield the effects; never only the first.
Connecting the raw effect as the agent's tool (practical). What happens: an HTTP Request gets connected directly to the payment gateway as billing_agent's "issue refund" tool. Since the tool is the raw effect, every time the agent calls it — from a retry, a redelegation, a loop — a real refund gets issued. A non-deterministic agent over a non-idempotent effect is the recipe for a duplicate. Why it happens: it's the most direct thing to do — the agent needs to "issue a refund," you connect the node that issues refunds. How to detect it: if an agent's effect tool is an external call with no idempotency (no Idempotency-Key, no ledger check, no outbox), it's raw. How to fix it: an agent's effect tool is always the idempotent path — a sub-workflow that checks the ledger or writes a ticket to the outbox — never the raw effect; the agent registers intents, the system executes them once.
Deriving the idempotency key from the agent's execution instead of the business (practical). What happens: someone builds the refund's key from the agent run's identifier or the conversation, thinking "this way each attempt has its own key." The result is the opposite of what was wanted: since each redelegation or retry is a different run, each one has a different key, and all of them go through — several refunds get issued, each "idempotent" relative to itself but not to the order. Why it happens: "one key per attempt" sounds like idempotency, but idempotency is defined relative to the business effect, not the attempt. How to detect it: if two attempts of the same effect (same order) produce different keys, the key is derived wrong. How to fix it: the key comes from the business — refund:ORD-2041 — stable across every attempt of the same effect, no matter which agent, which run, or which loop turn fires it.
Letting one specialist delegate to another specialist (conceptual). What happens: to "coordinate better," someone connects billing_agent as a tool of order_agent and vice versa. A cycle forms in the agent graph, and direct circular delegation shows up: billing_agent calls order_agent, which calls billing_agent, without the orchestrator ever finding out, spinning and potentially duplicating effects on every turn. Why it happens: it seems efficient for two specialists to talk directly instead of bringing everything back to the orchestrator. How to detect it: check the agent graph (or the exported JSON); if a specialist has another specialist as a tool, there's a possible cycle. How to fix it: apply the chatbots guide's rule — workers don't delegate to each other; everything goes through the orchestrator — which keeps the agent graph acyclic the same way lesson 3 keeps the workflow graph acyclic. With no cycles, circular delegation is impossible by construction.
Exercises
Exercise 1 — Identify which layer failed. For each situation, say which defense layer was missing — the prompt/prior check (efficiency) or the idempotent effect (guarantee) — and which one would have prevented the damage:
(a) The agent checked the ledger, saw there was no refund, but between that check and its action another agent had already issued it; the agent issued a second refund.
(b) The agent had a refund tool idempotent by order_id, but it called the gateway on every attempt anyway; there was never a duplicate, just extra calls to the gateway that it rejected.
(c) There was no prior check and no idempotency; the redelegation loop spun six times and issued six refunds.
See solution
(a) The guarantee failed (the idempotent effect). The prior check — layer 1 — isn't enough, because time passed between "I checked and there wasn't one" and "I acted," and in that gap another agent acted. This is exactly the "check then act" problem from Module 2: the check and the action aren't atomic. What would have prevented it is layer 2: if request_refund were idempotent by order_id, the second refund would have collided with the key and never been issued, regardless of the gap between check and action.
(b) Here nothing about correctness failed — there was no duplicate, the guarantee worked; what was missing was layer 1's efficiency. The agent didn't check first, so it made extra calls that the gateway had to reject. It isn't a correctness bug, it's waste: layer 2 protected the outcome, but without layer 1, useless calls were spent. It's worth adding the prior check to avoid bothering the gateway, but the system is correct.
(c) Both layers were missing. Without a prior check, every loop turn attempted the refund; without idempotency, every attempt actually issued it. Six turns, six refunds. Either layer would have reduced the damage — layer 1 would have prevented the attempts, layer 2 would have deduplicated the effects — but the guarantee is layer 2: with it, six turns would have produced a single refund, though it still would have been worth cutting the loop with Max Iterations.
Why this works: telling apart which layer failed tells you what to fix. If the problem is "extra work/calls but a correct result," efficiency is missing (layer 1). If the problem is "duplicated effect," the guarantee is missing (layer 2). Case (a) is the most instructive: it shows why the prior check isn't enough — it isn't atomic — and why the effect's idempotency is what really guarantees.
Exercise 2 — Design an agent's effect tool. Cumbre wants order_agent to be able to cancel an order when a customer requests it, and cancelling an order triggers two effects: restocking reserved inventory and notifying the warehouse. Design the cancel_order tool you'd connect to the agent, so it's safe even if the agent calls it several times. Say what it should NOT be, what it SHOULD be, and what idempotency keys you'd use.
See solution
What it should not be: cancel_order should not be a flow that calls the inventory system and the warehouse directly on the spot. That would be the raw effect: if the agent calls it twice (retry, redelegation, loop), it restocks inventory twice and notifies twice.
What it should be: a sub-workflow that, atomically, registers the cancellation decision in the ledger and writes the two effects' tickets to the outbox — restocking inventory and notifying the warehouse — with ON CONFLICT DO NOTHING on the decision so two calls don't write two sets of tickets. The relay executes each ticket idempotently. The tool returns "cancellation registered" or "was already cancelled."
Idempotency keys:
- The cancellation decision:
cancel:ORD-2041(one per order). - The inventory restock:
restock:ORD-2041:CF-ARA-500(one per line, lesson 4's granularity). - The warehouse notification:
warehouse_notify:ORD-2041(one per order).
That way, if the agent calls cancel_order for ORD-2041 three times, the first writes the decision and the tickets, the other two collide with the ON CONFLICT and write nothing; the relay executes each effect once. And since cancellation is a state effect, it's also worth having the ledger let get_order_status report "cancelled," so the agent checks first (layer 1) and doesn't attempt it if it's already done.
Why this works: you applied the central strategy — an agent's tool is not the raw effect, it's the idempotent path via outbox — to a case with two effects, with keys at the right granularity, and with the decision's idempotency (ON CONFLICT) protecting against the agent's multiple firing. That's exactly what shields an agent's effect.
Exercise 3 — Cut the redelegation loop. At Cumbre, the case "I got charged for shipping twice" falls on the fuzzy border between billing_agent (there's a charge) and order_agent (shipping is logistics), and both bounce it back to the orchestrator saying "not mine." Describe the two defenses you'd put in place — one design, one limit — so this loop doesn't spin forever, and explain why, even if the loop did spin, no duplicate refunds would be issued.
See solution
Design defense (the root cause): draw the boundary explicitly for this case. The two specialists' Descriptions should resolve who keeps "I got charged for shipping twice" — for example, deciding that anything involving a duplicate charge belongs to billing_agent, and stating it in both descriptions with an explicit "don't use this for... / use this when..." A redelegation loop is almost always a poorly drawn boundary; fixing the boundary eliminates it at its source.
Limit defense (the safety net): a redelegation counter. In the orchestrator's prompt or in the ledger, keep count of how many times this case has bounced between specialists; if it goes past a threshold (two, say), instead of delegating again, escalate to a human. Complemented by the orchestrator's Max Iterations, which cuts the loop even if the counter fails. The honesty instruction helps: "if you can't decide whose case this is after two attempts, escalate it, don't keep delegating."
Why there would be no duplicate refunds even if the loop spun: because the effect — request_refund — is idempotent by order_id. Even if billing_agent issued the refund on one turn and another turn tried to issue it again, the key refund:ORD-XXXX deduplicates: a single refund. The loop wastes money on model calls — hence the two defenses to cut it — but the damage stays bounded to cost, not duplicated effects. That separation is the lesson's thesis: agent brakes control cost and efficiency; effect idempotency controls correctness.
Why this works: you gave the two correct defenses (a clear boundary for the cause, a limit for the net) and — most importantly — articulated that the no-duplicate guarantee doesn't depend on cutting the loop, but on the effect's idempotency. A system that cuts the loop but doesn't shield the effect is still at risk; one that shields the effect is safe even if the loop escapes it.
Summary and next step
In this lesson you applied the whole module to systems where one agent delegates to another. You saw why an agent is more dangerous than a deterministic flow — it's non-deterministic, so two runs can decide on the same effect through different paths — and the three paths through which an agent's effect gets duplicated: the agent retries its tool, two agents decide the same thing, or the redelegation loop spins. The strategy that resolves it is a mindset shift: don't try to keep agents from duplicating — you can't guarantee that by prompt — make their effects idempotent so it doesn't matter if they do. Concretely, two layers: the agent checks the ledger before acting (efficiency layer, avoids wasted work) and the effect is idempotent regardless (guarantee layer, the one that never fails). An agent's effect tool is never the raw effect: it's the idempotent path — a sub-workflow that checks the ledger or writes a ticket to lesson 6's outbox — with a key derived from the business (refund:ORD-2041), not from the agent's run. And the agent-specific brakes — Max Iterations, clear boundaries between specialists, the rule that workers don't delegate to each other — control cost and the loop, while idempotency controls correctness.
Before moving on to lesson 8 you should be able to: explain why a prompt alone isn't enough to prevent duplicates; describe the two layers (checking the ledger, idempotent effect) and which one gives the guarantee; explain why the idempotency key goes by the business and not by the agent's run; and say how an idempotent effect bounds a redelegation loop's damage to cost instead of effects.
Lesson 8 brings the whole module together in a project. You're going to build a director, an outbox, and an idempotent executor that coordinate Cumbre's three dependent sub-workflows — check-credit, issue-refund, and inventory-sync — and you're going to prove that a mid-chain crash neither duplicates nor loses effects on retry. The deliverable is two things: the dependency graph you learned to draw in lesson 3, and the system running, with evidence it survives all three disasters. It's the whole module turned into something you can show.
Resources
- AI Agent Tool node — n8n Docs — the sub-node that connects a whole agent as another's tool; its
Description, its$fromAI(), and itsMax Iterations. The chatbots guide (Module 5) teaches it in depth; here only its effects get shielded. - AI Agent node — n8n Docs — the orchestrator's node, with its
Max Iterationsparameter (default 10) that bounds reasoning and redelegation loops. - Use AI for parameters ($fromAI) — n8n Docs — the mechanism the orchestrator uses to build the assignment it passes to the specialist; a self-contained assignment with the correct
order_idis what lets the idempotency key be derived correctly. - Execute Sub-workflow node — n8n Docs — the way to expose an effect to the agent as an idempotent sub-workflow (
request_refund,cancel_order) instead of the raw effect. - Postgres node — n8n Docs — the node the agent's read tool uses to check the ledger (shared memory) and the one the effect tool uses to write the idempotent ticket to the outbox.