Chain flows
Chain flows go away before launch. Write new flows as generators.
This is the older style, with one handler per event. It still runs, and a campaign's own hooks use it.
export const hello = defineCallFlow('hello')
.onAnswer((call) => call.say('One moment.').transfer(queue(sales)))
.onTransferFailed((_event, call) => call.say('Nobody is available right now.').hangup());| In a chain | In a generator |
|---|---|
.onAnswer | The main function |
.onAgentEnd | The code after c.connect |
.onTransferFailed | try and catch around c.transfer |
.on('name', schema, fn) | events: ['name'], then until or c.event |
ctx.state | A local variable |
A tool returning call.transfer(...) | A tool returning handoff(name), and c.transfer after c.connect |
- A chain call isn't pinned to a version. If its version is gone, it runs the current code, and the SDK logs a warning.
- A
.onhandler can act at any moment of the call. A generator hears an event only at a wait that names it: see Transfers. - Handlers can run again, with the same
ctx.eventId. Events of one call don't wait for each other, so a keypress never waits on a slow custom event. If another event changes the call while yours runs, what yours returned is thrown away and it runs again on the newerctx.state, up to three runs, each with the wholetimeout. Nothing overwrites anything. A handler that changed no state and returned no actions never runs again. - Pass
ctx.eventIdto whatever your handler calls, so a repeat is safe. Don't answer from a cache of your own keyed on it: the second run has to answer for the newer state. - While a caller waits on a webhook, your handlers have 10 s in all: their runs,
onTransferFailedandonError. Past that the fallback answers at once, and connecting an agent has until 13 s. An agent's tool call keeps to onetimeout, and a lost race past it tells the agent the tool failed. - Fallbacks. When a live handler times out or fails, we run its
fallback(.onAnswer(fn, { fallback: actions().connect(agent('agt_backup')) })). If there is none, we runonError, and then the number's Default flow. Each fallback is published as acall.flow.fallbackEvent. - A tool can return actions (
call.transfer(...),call.hangup()), and then it runs again like any other handler. What a tool that returns JSON did toctx.stateis dropped if another event changed the call while it ran, and the flow event is recorded withstateDropped. - Legacy session tools.
call.connect(agent(id)).onToolCall(name, schema, handler)still works on platforms that take tools per call. We find a session's handlers again by re-running the handler that connected it, withctx.replayingset, so skip side effects then. They are not synced to platforms that keep tools on the agent, so prefertool().