- Documentation
- Workflows
- Workflow Nodes
- Voice Agent node
Voice Agent node
Answer a phone call with a realtime AI voice agent that can speak, listen, call your app actions mid-call, and hand a transcript to the rest of the workflow.
The Voice Agent node answers a phone call. A caller dials your number, the agent greets them, the two of them talk, and when the call ends the rest of the workflow runs with the transcript, a summary and any structured data the agent captured.
It is the only node that can answer a Twilio Phone Call trigger — and a Phone Call trigger is the only thing it can answer.
The Voice Agent and the Phone Call trigger are in beta and are enabled per environment. If you do not see "Voice Agent" in the Add Node panel, the lane is not turned on for your workspace yet.
What it does
- A call arrives on your Twilio number and the Phone Call trigger fires.
- Within 10 seconds, the Voice Agent answers and the caller is connected to the model.
- The agent speaks your greeting, then listens. The caller can interrupt it mid-sentence.
- When the agent needs something from one of your apps, such as an order status or a booking slot, it calls one of its tools, which is an ordinary app action. When the caller needs a person, the agent can transfer them to one of your team's numbers.
- The call ends. The transcript and (optionally) the recording land on the step output.
- The workflow continues with the steps after the Voice Agent.
Build one
Start from a Phone Call trigger
Add the Twilio Phone Call trigger and pick the number this workflow answers.
Add the Voice Agent
Add a Voice Agent node downstream of the trigger. Keep the path between them short — see The 10-second answer window.
Add your model key
The agent talks through a realtime voice model on your own key: Gemini Live or OpenAI Realtime. For Gemini, create a key in Google AI Studio and add it on the Google Gemini page under Apps; the key's project also needs Live API access, which only the first call can confirm. For OpenAI, add an OpenAI API key on the OpenAI page under Apps; its project needs access to the realtime model you pick. TaskJuice checks that the provider accepts the key before saving it.
Attach a model
Drag from the Voice Agent's model port to add a Model sub-node, pick your Google Gemini or OpenAI key as the connection, and choose a model. The sub-node lists that provider's realtime models only, such as
gpt-realtimefor OpenAI; a text-only model cannot hold a conversation over audio. Attach the key you added under Apps: a key pasted straight into the node cannot be used for a call.Write the system prompt
The System prompt field sits at the top of the Voice Agent's panel. Write who the agent is and what it is allowed to do, exactly as you would for an AI Agent. You can bind a prompt from the prompt library instead of typing it inline.
Attach tools (optional)
Click the tools port to add a Tool sub-node per app action the agent may call during the call. Each tool has its own Delivery setting. To let the agent put callers through to your team, add Transfer to a person from the same port.
Publish
Publishing points the number's voice URL at this workflow. Unpublishing restores whatever it pointed at before.
Fields
| Field | Type | Default | What it does |
|---|---|---|---|
| Greeting | text | none | Spoken first, before the caller says anything. Supports {{ }} references to the trigger, so you can greet a known caller. |
| Variables | key/value | none | Values resolved once when the call is answered and available to the model as {{ name }} inside the prompt. |
| Language | select | English (US) | The language the agent speaks and listens in. |
| Barge-in | Enabled / Disabled | Enabled | Lets the caller interrupt the agent mid-sentence. Disabled makes the agent finish every sentence before it listens. |
| Let the agent end the call | Enabled / Disabled | Enabled | The agent hangs up after saying goodbye, or when the caller asks it to. Disabled: only the caller, an operator or Max seconds ends the call. |
| Recording | Enabled / Disabled | Disabled | Records the call audio and stores it with the run. |
| Max seconds | number | 900 | Hard ceiling on the agent's conversation, 30–900 seconds. The call ends at this limit whatever is being said, unless the agent has already transferred the caller. |
The model, tools and memory are sub-nodes on the canvas, not fields in this panel — the same composition the AI Agent node uses.
Whether you may record a call, and whether you must announce it, depends on where the caller is. Announcing it is your responsibility — put it in the greeting.
Tools and Delivery
A Voice Agent's tools are app actions, plus one built-in Transfer to a person tool. A sub-workflow or a think tool is refused at publish. Each app-action Tool sub-node carries a Delivery setting, which decides what happens to the conversation while the action runs:
| Delivery | What the caller hears | Use it for |
|---|---|---|
| Let the agent keep talking (default) | The agent carries on; the result is spoken when it lands. | Anything the agent can talk around — "let me check that for you…". |
| Wait for result | The agent pauses until the action finishes, up to 8 seconds. | A short lookup whose answer is the next thing the agent must say. |
| Run after the call | Nothing — the action runs once the call has ended. | Work the caller does not need to wait for: a CRM note, a follow-up email. |
Every app-action tool call becomes a real step on the run, with its own cost and audit trail. Voice tools do not pause for approval: a live call cannot wait for one. A transfer is not a step; see Rules the tool follows.
Transfer to a person
The Transfer to a person tool lets the agent hand the caller to someone on your team. You decide who can be called; the agent decides when. It picks a destination by its label and never sees the phone numbers, so nothing a caller says can make it dial a number you did not list.
A transfer is a second, separate phone call: TaskJuice keeps the caller on the line and calls the person, and the two calls are joined when the person answers.
Set it up
Attach the tool
Click the Voice Agent's tools port and choose Transfer to a person on the Utilities tab. A tile appears under the agent.
Say when to transfer
Open the tile and fill in When to transfer, for example Transfer when the caller asks for a person, or when you can't help them. The agent reads this to decide when to use the tool.
Add the destinations
Add up to 10 destinations. Each needs a phone number in E.164 (international) format, such as
+14155550123. With more than one destination, give each a unique Label such as Sales or Support: the agent picks by label.Publish
Publishing checks every setting. A number that is not in E.164 format is refused, and the error names the destination by its place in the list, for example Destination 2 phone number for the second one.
| Field | Type | Default | What it does |
|---|---|---|---|
| When to transfer | text | none | Up to 1,024 characters. Tells the agent when to use the tool. |
| Destinations | list | none (required) | 1 to 10 E.164 numbers, each different. A label (up to 40 characters) is required once there are two, and labels must be unique. |
| Ring for | select | 30 seconds | 10, 15, 20, 30, 45 or 60 seconds. Twilio may ring up to 5 seconds longer. |
| Tell the person why before connecting | Enabled / Disabled | Enabled | The person hears a short spoken note before the caller joins. |
| Show the caller's number | Enabled / Disabled | Enabled | Disabled shows your Twilio number instead. See Caller ID. |
| If nobody answers | text | Sorry, nobody is available to take your call right now. We'll get back to you as soon as we can. Goodbye. | Up to 500 characters, spoken to the caller before the call ends. Supports {{ }} references. Leave it empty to hang up without a message. |
Destination numbers are fixed. They cannot contain {{ }} references, because the number TaskJuice dials must be the one you reviewed when you published.
What the caller and the person hear
When the agent decides to transfer, it is told to say one short sentence, such as Connecting you to Sales now, and stop talking. The caller cannot interrupt it. After at most about 12 seconds the agent is off the line, whatever it is still saying, and the person's phone rings.
When the person answers, and Tell the person why before connecting is Enabled, they hear Transferred call from your voice agent. followed by the agent's one-sentence reason for the transfer. The whole note, its fixed opening included, is spoken in the agent's language. Then the caller joins and the two of them talk directly. The agent is no longer on the call.
A transferred call can last up to 4 hours. The steps after the Voice Agent run when it ends, with the step's outcome set to transferred.
If nobody answers
If the person does not pick up within the ring time, is busy, or the number cannot be reached, the caller hears your If nobody answers message and the call ends. The agent does not come back on the line.
The steps after the Voice Agent start as soon as the ringing ends, so they run while the caller is still hearing the message. Branch on $steps.<node>.data.transfer.answered (here false) or $steps.<node>.data.transfer.status (here no_answer, busy, failed or canceled) to follow up, for example by creating a callback task or sending the caller an SMS. unknown means the phone provider never reported how the ringing ended.
Caller ID
By default the person sees the caller's number, so they know who is on the line before they answer. Some carriers block a forwarded caller number, and the transfer then fails to connect. If transfers to a destination do not connect, choose Disabled for Show the caller's number: the person then sees the Twilio number the caller dialled. If Twilio reports no dialled number, or one that is not a phone number (such as a SIP address), the person sees the caller's number either way.
Billing and recording
Twilio bills the transfer as its own outgoing call, on top of the inbound call the agent answered. Its estimated cost is included in the call's spend on the run. See Transfers on the Twilio page for how Twilio bills it and how the estimate differs.
Nothing after the transfer is recorded or transcribed. The transcript and the recording end when the agent hands the caller over.
Rules the tool follows
- One Transfer to a person tool per Voice Agent. Put every number on it as a destination. The tools menu disables a second one, and publishing refuses it.
- The tool works only on a Voice Agent. On an AI Agent node the tile shows Transfer to a person works only on a Voice Agent. Remove it from this agent. and publishing is refused.
- A destination that is the same number the call came in on is skipped for that call, so the agent cannot transfer a caller back to itself.
- Transfers are not approval-gated. The numbers are fixed and reviewed when you publish.
- A transfer and the agent ending the call exclude each other. Once the agent has started a transfer it cannot also hang up, and once it has started to say goodbye it cannot transfer.
Unless Let the agent end the call is Disabled, the agent can also hang up by itself (a built-in end_call tool, recorded in tools). Tell it in the prompt when a conversation is finished.
The 10-second answer window
A telephony provider will not wait long for a workflow to answer. TaskJuice has about 10 seconds from the moment the call arrives to the moment the Voice Agent picks up, and everything between the trigger and the Voice Agent runs inside that window.
That is usually plenty — but an HTTP call to a slow API, or an AI step, can spend it. When the publish bar sees one of those on the path it warns you: "… runs before the Voice Agent and may take longer than the 10-second answer window. The caller hears an error if it does."
If you need to enrich the call with slow data, do it after the Voice Agent, or push it into a tool with Delivery set to Run after the call.
What the node outputs
The steps after the Voice Agent read its output as $steps.<node>.data:
| Field | Type | Description |
|---|---|---|
callSid | string | The provider's id for the call. |
from / to | string | The two numbers, in E.164. |
durationSec | number | How long the call lasted. |
outcome | string | How it ended — see below. |
transcript | array | The turns, each { role, text, at }. A long transcript is stored alongside the run and hydrated on demand. |
tools | array | One entry per mid-call tool call, with its status and duration. |
recordingRef | string | Where the recording is stored, when recording was on. |
transfer | object | Present when the agent asked for a transfer. See The transfer record. |
To summarise a call or pull structured fields out of it, add an AI step after the Voice Agent that reads $steps.<node>.data.transcript.
Outcomes
outcome | Meaning |
|---|---|
caller_hung_up | The caller ended the call. The most common outcome. |
agent_ended | The agent said goodbye and hung up. |
agent_hung_up | An operator pressed Hang up in the run detail. |
completed | The call reached Max seconds and was ended. |
transferred | TaskJuice dialled the person the agent chose. See the transfer record for who, and whether they answered. |
timed_out | The step reached its time limit before the end of the call was reported: Max seconds plus a two-minute grace, and, when the agent can transfer, the ring time (plus up to 5 seconds) and the 4-hour transfer limit on top. The transcript is what was captured. |
provider_error | The model or the telephony provider failed mid-call. |
gateway_lost | The call ended, but the agent's side of it never reported how, or the agent asked for a transfer that TaskJuice could not place. The transcript is what was captured up to that point. |
no_transport | The node ran with no call attached — a node test, a manual Run now, or after the caller was answered elsewhere. |
refused_capacity | The workspace was already at its concurrent-call limit. The caller heard a busy message. |
A step that never placed a call still completes — no_transport and refused_capacity are outcomes, not failures — so the steps after it run and can react.
When the agent asked for a transfer that was never dialled, transfer is still present with status not_dialled, and the outcome says why: caller_hung_up when the caller hung up first, timed_out when the end of the call was never reported, or gateway_lost when TaskJuice could not place it.
The transfer record
| Field | Type | Description |
|---|---|---|
destination.label | string | The destination's label, when it has one. |
destination.number | string | The destination's number. Empty when TaskJuice could not find the destination the agent chose. |
destination.index | number | The destination's position among the ones offered on this call, starting at 0. A destination skipped because it is the number the call came in on is not counted. |
reason | string | The agent's one-sentence reason, when it gave one. |
requestedAt | string | When the agent asked for the transfer, as an ISO 8601 timestamp. |
answered | boolean | Whether the person picked up. |
status | string | How the transfer ended. See below. |
talkSec | number | How long the person and the caller talked, in seconds. 0 when nobody answered. |
status | Meaning |
|---|---|
answered | The person picked up and was connected to the caller. |
no_answer | Nobody picked up within the ring time. |
busy | The line was busy. |
failed | The number could not be reached. |
canceled | The call to the person was cancelled at the phone provider before anyone answered. |
not_dialled | The agent asked for a transfer, but the number was never dialled. |
unknown | The number was dialled, but the phone provider never reported how it ended. |
Watching a call
A run that answered a call shows two extra cards under Monitor → Runs:
- The Call card on the run overview: from, to, duration, the call id, and a live "Call in progress" badge while the caller is still on the line. The call's spend is the run's BYOK cost on the metadata card above it, not a second figure here. While the call is live, a Hang up button sits beside Cancel. It ends the call within a few seconds, even mid-sentence; the run then continues with the steps after the Voice Agent.
- The Call transcript card: the turns with visible speaker labels, and the recording player when recording was on.
A transferred call adds a Transfer row to the Call card: the destination's label (or its number), the result, and the talk time when the person answered. From the moment the agent starts a transfer, Hang up can no longer end the call. During the agent's closing sentence it has no effect; once the agent has handed the caller over, clicking it shows This call was transferred to a person and can't be ended from here.
To find call runs specifically, open More filters on the runs list and set Trigger to Phone call.
Limits
- Inbound only. Placing a call is not available yet.
- 900 seconds is the hard ceiling on the agent's part of a call. A call the agent transfers can then continue for up to 4 hours.
- Tools must be app actions, plus one Transfer to a person tool. Sub-workflows and think tools are refused at publish.
- Transfers are cold. The agent does not stay on the line or talk to the person. The optional spoken note is the only introduction, and the agent cannot take the caller back if nobody answers.
- One response point. A Respond node between the trigger and the Voice Agent is refused — the Voice Agent must answer the call itself.
- Concurrent calls are capped per workspace. Past the cap, the caller hears a busy message and the run records
refused_capacity.