Agent node - capabilities
What an Agent node has at its disposal: the tools it can call, the rich media it can show, and the variables it can read and write.
Nothing you change in the drawer is committed until you press Save; Cancel discards the lot.
Capabilities
Tools, Rich media and Allowed variables sit together in one panel in the drawer, because they answer the same question: what does this step have at its disposal? Each is covered in full below.
One rule applies to all three: attach only what this step needs. A node with one tool and two variables is predictable. A node carrying everything the assistant can do is slower, costs more per turn, and picks wrong more often. They're shared definitions, so attaching the same tool to five nodes is free and correct - never widen one node so it can serve several steps.
Tools
Workflows and tools this agent can call.
The actions this step is allowed to take: run a workflow, search a knowledge base, escalate to a human. Tools are defined once under AI Agent → Tools; here you pick which of them this step can reach, with + Add tool.
What attaching actually does
Four things, and only the first is obvious:
- It puts the tool within reach for this step. While this node holds the conversation, these are the tools on offer. When the flow moves on, they're withdrawn and the next node's set takes over - a tool attached here is not available two nodes later.
- It makes the tool
@-mentionable in the Instructions. - It makes the tool eligible as a Tool exit. The exits picker only offers tools attached to this node.
- It does not make the tool run. Nothing here causes a call. The agent decides, based on your Instructions and the tool's own description.
That last point is the one to internalise. Attaching is a grant; the Instructions are the trigger. They're two separate decisions, and a tool attached but never mentioned is a coin flip - it may fire at the wrong moment, or never.
If a tool must always run, say so plainly: "Always call @Check Eligibility before answering."
Some tools may be published to every agent centrally, so a node can have a few beyond the ones you attached here. If an agent is calling something you didn't add, that's where to look.
Per-tool settings
Each attached tool has its own configuration, opened from its row:
| Setting | What it does |
|---|---|
| Inputs mapping | Supplies the tool's inputs - from a variable, from the session, or a fixed value. A workflow with no declared inputs has nothing to map, and the panel tells you so. |
| Store output in | Writes the tool's result into a variable instead of handing the payload back to the agent. |
| Acknowledgement | What the customer hears while the tool runs. Either intelligent (generated to fit the moment) or a static list you write. |
| Fallback settings | What happens if the tool fails: send an AI-powered apology, and optionally raise a ticket. |
Store output in deserves attention, because it's the one that changes behaviour most and is easiest to miss.
By default a tool's result goes back to the agent, which reads it and decides what to say. That's right when the result is small and the agent needs to reason about it - an eligibility flag, a balance, a yes/no.
It's wrong when the result is a large payload. The agent then has a wall of JSON in its context: it costs more, it distracts from the procedure, and it invites the agent to narrate raw fields at the customer. Storing the output instead writes it to a variable, hands the agent a short confirmation, and leaves the value available to the rest of the flow.
Acknowledgement is about perceived latency. A tool that takes three seconds feels broken in silence and fine with "Let me check that for you". This matters most on voice, where dead air has no spinner to explain it.
What happens when a tool fails
A tool failure does not send the flow down on_error. This is the most consequential thing on this page after the empty-Instructions trap.
What actually happens: the agent is told the call failed and carries on. It can retry, take a different route, or tell the customer - and it's instructed never to read raw error text aloud. With Send AI-powered apology enabled it also sends a contextual apology automatically ("Sorry, I'm having trouble fetching plans right now"), and the error policy can raise a ticket instead.
The consequence for you: your Instructions decide the recovery. If a failed tool ought to end the step, you have to write that - add a branch and say when to take it. Left unwritten, the agent improvises, and the flow carries on as though nothing happened.
Call @Check Return Eligibility with the order ID.
If the tool fails or returns nothing, apologise briefly and finish on
`system_unavailable`. Do not guess whether the order is eligible.
Good use
| Pattern | Why it works |
|---|---|
One tool, @-mentioned, with a stated trigger - "Always call @Check Eligibility before answering" | The grant and the trigger both exist. No ambiguity about when. |
| A big lookup with Store output in set, and a later node reading the variable | Keeps the payload out of the conversation and passes the value on properly. |
| The escalation tool attached and wired as a Tool exit | The action and the outcome are the same event, so the exit carries the flow onward. |
| An acknowledgement on anything slow | Covers the wait. Essential on voice. |
| Explicit ordering in the Instructions when two tools must run in sequence | Tool descriptions don't convey order. Your numbered steps do. |
Problems
| Pattern | What goes wrong |
|---|---|
| Attaching every available tool | More options means worse selection. The agent picks the wrong one, the prompt is longer, and every turn costs more. |
| Attaching a tool and never mentioning it | It may fire at the wrong moment or never fire at all. Nothing warns you. |
| Mentioning a tool you haven't attached | The reference doesn't resolve, and the agent is left with a fragment it can't act on. |
Expecting a failed tool to take on_error | It doesn't. The agent continues. Write the failure path yourself. |
| Letting a large payload back into the conversation | The agent reads out fields, or paraphrases them wrongly. Use Store output in. |
| Two tools that do nearly the same thing | The agent chooses between them inconsistently, and the behaviour looks random. Attach one. |
| Assuming the tool description conveys sequencing | It describes what the tool is for, not when it runs relative to another. Put the order in the Instructions. |
How to think about it
Grant and trigger are separate decisions. Attaching answers "may it?"; the Instructions answer "when?". Almost every tool problem is one of those two missing.
Attach the fewest tools that make the step possible. Not the fewest that make it convenient - a tool the step could theoretically use is a tool it can misuse.
Decide who the result is for. If the agent needs to reason about it, let it come back. If the flow needs it - a later node, a condition, a record - store it in a variable.
A tool that ends the step is an exit, not just a tool. If calling it means this step is over, make it a Tool exit so the flow moves on properly rather than leaving the agent to work out that it's finished.
Write the failure path. The happy path is easy to imagine and easy to test. The tool-is-down path is neither, and it's the one that will page you.
Rich media
Quick replies, widgets and workflows the agent can show.
The visual elements this step can put in the chat instead of plain text - tappable options, a card or carousel, a formatted response.
The three kinds
| Kind | What it is | How many |
|---|---|---|
| Quick replies | Tappable option buttons alongside a message. | Once per node |
| Widget | A saved widget - cards, carousels, formatted layouts. You give each one a description telling the agent when to use it. | As many as you need |
| Workflow | A workflow that builds a rich response. | As many as you need |
What attaching actually does
The same grant-not-trigger rule as Tools, with one extra consequence that catches people out:
- It makes the element available to this step, and
@-mentionable in the Instructions. It doesn't make it appear - the agent shows it when your Instructions say to. - Showing rich media ends the turn. The agent displays the element and stops - it doesn't display buttons and then carry on talking, and it won't take an exit in the same breath. The node hands back and waits for the user. This is almost always what you want (you're offering a choice, so you want the choice made) but it does mean "show the options and then confirm and finish" can't happen in one turn.
Where the content comes from
This is the part that surprises people, and it differs from First response.
You don't type quick-reply options into this panel. Attaching Quick replies grants the ability to show buttons; the actual options are supplied by the agent at the moment it shows them - and it's explicitly constrained to use only options that came from your Instructions or from a tool result. It must not make them up.
So the options live in your Instructions:
Ask which size they'd like and offer @Quick Replies with exactly these
options: Small, Medium, Large, Extra Large.
Attach the capability, then say what goes in it. Attaching Quick replies and writing only "offer some quick replies" leaves the agent with nothing legitimate to render - and inconsistent buttons between runs is the symptom.
For widgets, the equivalent lever is the description you write when attaching. That description is what the agent reads to decide whether this widget fits the moment, so "the order summary card, showing line items and total" works and "card" does not.
Compare with First response, where you do type the options into the UI - because that message is scripted and never involves the agent. Same buttons, opposite authoring model.
On voice, this does nothing
Rich media is skipped entirely on voice calls - there's no screen to render it on. A voice step built around tappable options doesn't fail loudly, it just talks.
If a flow serves both chat and voice, write instructions that stand on their own without the buttons - "ask which size they'd like: small, medium, large or extra large, and offer @Quick Replies". The chat customer taps; the voice caller hears the options and answers. One set of instructions, both channels.
Good use
| Pattern | Why it works |
|---|---|
| Quick replies for a closed set of choices, with the options listed in the Instructions | The agent has a legitimate source for the buttons, so they're identical every run. |
| Quick replies whose options come from a tool result - available appointment slots, the customer's orders | Genuinely dynamic buttons, still not invented. |
| A widget with a description that says when to use it, not just what it is | Description is the whole selection signal. |
| Wording that works spoken as well as tapped | Survives the voice channel. |
| Offering options at a decision point that maps to your exits | The taps line up with the branches, so routing gets easier and more accurate. |
Problems
| Pattern | What goes wrong |
|---|---|
| Attaching quick replies, never listing the options | Nothing legitimate to show. Buttons vary run to run, or don't appear. |
| Expecting the agent to keep talking after showing rich media | It won't - the turn ends there. Say what you need said in the same message as the buttons. |
| Designing a voice step around quick replies | Silently degrades to plain speech. Nothing in the drawer warns you. |
A widget described as card or info | The agent has no basis to pick it, so it picks badly or not at all. |
| Long button labels | Trimmed at 40 characters. Write short ones rather than discovering the cut. |
| Attaching a widget but never mentioning it | Same as an unmentioned tool - it may never be shown. |
| Options that don't match your exits | The customer taps "Speak to an agent" and the node has no branch for it. |
How to think about it
Attach the capability, author the content. The panel grants; the Instructions supply. Every quick-replies problem is one of those two halves missing.
Rich media is a turn-ender, so put it where the conversation should pause. It fits a question that needs an answer, not a mid-turn flourish.
Make the options and the exits match. If you offer four buttons, the node should be able to handle all four outcomes. Buttons that lead nowhere are worse than no buttons - the customer picked something and the flow ignored it.
Write for the channel that can't see it. Instructions that read fine aloud work everywhere; instructions that depend on buttons work in one place.
Allowed variables
Context the agent can read. Make a variable writable to let the agent fill it during the conversation.
This is an allowlist. A variable existing in the conversation does not mean this step can see it - if it isn't in this list, the agent has no idea it exists. The panel says as much: "This agent can only read the variables and user properties you add here."
The two states
Every variable you add sits in one of two states, shown as a badge on its chip:
| Badge | What the agent can do | Toggle |
|---|---|---|
| Read-only | See the current value and use it in its reasoning and replies. | The agent reads this value. |
| Agent fills this | See it and set it from the conversation. The value goes back to the flow when the step ends. | Let the agent set this too |
Read-only is the default, and most attached variables should stay that way. The writable ones are the point of the step - what it's there to collect.
Read-only is not "the agent will fill it anyway"
Adding a variable and leaving it read-only, while expecting the agent to populate it, is the most common mistake on this panel. Nothing is written, no error appears, and the variable is simply empty when a later node reads it. The symptom shows up somewhere else entirely - a downstream condition that never matches, or a message with a blank in it.
If this step is meant to capture something, the variable needs Agent fills this turned on. Read-only means read-only.
What has to be true before a variable can be writable
Four gates, each with its own message in the UI when it blocks you:
| Requirement | Why | If it's not met |
|---|---|---|
| It has a description | The description is the agent's only guidance for what to put in the slot - the drawer asks you to "Describe this variable for the agent" before it will let you. | You're prompted to write one first |
| A fillable type | Text, number, yes/no, and list. | "Only text, number, yes/no and list variables can be filled by the agent" |
| A fillable scope | Global and journey variables only - user properties are a customer's profile, and a step doesn't rewrite those. | "The agent can only fill in global and journey variables." |
| Under the limit | Five writable variables per node. | "Write limit of 5 reached" |
That scope row is a decision, not just a constraint. The picker lists globals, journey variables and user properties together, each tagged with its scope, and which one you attach decides who sees the value afterwards: a global reaches every other agent, a journey variable dies with this flow run. If a later agent needs what this step collects, it has to be global - see which scope it belongs in.
The description requirement is worth dwelling on. It isn't paperwork - it's the entire instruction the agent gets about that slot. postcode tells it nothing; "the customer's delivery postcode, UK format, e.g. SW1A 1AA" tells it what counts as valid, what shape to store, and when it's got one.
Writable is a slot, not a promise
Marking a variable writable gives the agent permission and a place to put a value. It does not guarantee a value arrives. If the conversation never surfaces the postcode, the variable stays empty and the step can still exit.
So if a value is required before moving on, that belongs in your Instructions - "Do not finish until you have their postcode; if they won't give one after three attempts, finish on max_retry." The panel grants; the Instructions insist.
Three ways a value gets written - pick the right one
Much of the confusion here is the write toggle being asked to do jobs that belong elsewhere:
| To capture… | Use | Configured on |
|---|---|---|
| Something the customer said | Agent fills this | This panel |
| A tool's result | Store output in | The tool's own settings (Tools) |
| Something derived after the turn | A workflow that writes a variable | Lifecycle Hooks |
If you're trying to save what an API returned, the write toggle is the wrong lever - that's Store output in on the tool.
Scopes
The picker groups variables by where they live:
| Scope | Lifetime | Writable by the agent |
|---|---|---|
| Journey | This flow run | Yes |
| Global | The wider conversation and customer memory | Yes |
| User | The customer's profile properties | No - read-only |
Example
An address-collection node:
| Variable | State | Why |
|---|---|---|
customer_name | Read-only | So it can address the customer properly. Nothing here sets it. |
shipping_address | Agent fills this | The thing this step exists to collect. Described as "the full delivery address including postcode". |
delivery_country | Agent fills this | Needed by the eligibility check two nodes later. |
account_tier | Read-only | Changes the wording for premium customers. The step has no business editing it. |
Problems
| Pattern | What goes wrong |
|---|---|
| Left read-only, expected to be filled | Nothing is written. Silent, and the symptom appears in a later node. |
| Not attached at all | The agent can't see the value even though it exists, and will ask for something it was already told. |
| Writable with a vague description | The agent fills the slot with something loosely related. Worse than empty, because it looks fine. |
| Using the write toggle for a tool result | Wrong mechanism - see Store output in. |
| Everything marked writable | You'll hit the five-variable limit, and each extra slot is another thing the agent can fill wrongly. |
| Treating writable as guaranteed | It's permission, not enforcement. Requiring a value is a job for the Instructions. |
| Re-collecting a value a previous node already wrote | Attach it read-only instead. Asking twice reads as not listening. |
How to think about it
Attach what the step must know; make writable what the step must learn. Two different questions, asked in the same panel, and worth answering separately.
Write the description for someone who can't see your flow. The agent has your description and nothing else to go on for that slot.
Pass decisions forward. If this node worked out return vs exchange, store it. A later node re-deriving it will sometimes disagree with this one.
Keep the writable set small on purpose. The limit is five, but two is a healthy node. A step collecting five separate things is usually several steps.
Variables and exits - which one do I want?
These two get conflated constantly, because both feel like "the output of the step". They do completely different jobs.
| Exit | Variable | |
|---|---|---|
| Answers | Where does the conversation go next? | What does the rest of the flow know? |
| How many per step | Exactly one, when the step finishes | None to five, during the step |
| Shows on the canvas | Yes - it's a branch you wire | No |
| Affects routing | That's its only job | Never |
They aren't alternatives. Most collect steps want both: write shipping_address, and finish on collected. Reaching for one instead of the other is where it goes wrong.
The test:
- Does the next step differ depending on the answer? → that's an exit.
- Does anything later need the value? → that's a variable.
- Both? → do both. That's normal.
The trap: exits used as data. A node collecting a country with exits uk, us, france, germany, spain. It reads naturally and it's wrong: you hit the five-branch ceiling immediately, the canvas becomes unreadable, and adding a country means editing the flow. If every branch would go to the same next node, they aren't outcomes - they're a value. Use one variable and one exit.
Flip it round and the same rule holds: if the branches genuinely go to different places, they are outcomes, and burying them in a variable to fork later hides your routing from the canvas.
Worth knowing: the exit a node takes decides the edge and nothing more - it isn't readable later as a value. So if a downstream step needs to know which way this node went, write that decision to a variable as well as exiting on it. This is the clearest case where you genuinely need both.