agenthub · automation.fanout
Turn a list of rows into one agent run each. It is what makes for-each work without a loop on the canvas.
Why the node earns its place
The batch pipeline's terminal step. For every row it produces one job describing an agent run to launch, and the pipeline itself stays single-pass — there is no loop construct in the graph at all.
Like Outcome, it is passive: it does not enqueue or run anything. It emits the jobs, and the automation runtime reads them, queues them, and drives one run per row on the owner's identity and wallet. Keeping the node side-effect-free is what stops a graph reaching into the queue directly.
How it works at run time
rows, else rows_path into data.agent_id to run, the channel to reply on, and the row itself as the run's seed context.address_field on each row and make it that run's channel address.output.jobs [{agent_id, channel: {kind, channel_id, address}, seed: {…row}}]
output.count how many runs will startWhat you wire
Configuration
| Key | Type | Default & options | What it does |
|---|---|---|---|
| rows_path | string | — | Path to the array inside the wired input `data`. Ignored when the `rows` input is wired directly. |
| agent_id * | string | — | The agent to run once per row (e.g. the per-contact onboarding decider that picks what to send). |
| channel_kind | string | default "whatsapp" | Channel each spawned run sends on (e.g. 'whatsapp'). Seeded as the run's channel so output.outcome can mirror it. |
| channel_id | string | — | The sending channel id (e.g. the WhatsApp channel). Applied to every job. |
| address_field | string | default "phone" | Field on each row holding the recipient address (E.164 phone). Becomes the run's channel address. |
What usually goes wrong
Watch for this
Each row becomes the spawned run's context, which is what lets the per-row agent greet someone by name without any extra wiring. Filter first: every row that reaches this node is a billed run, and there is no undo once the jobs are dispatched.
Behaviour & provenance