HCC Docs

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 chainIn a generator
.onAnswerThe main function
.onAgentEndThe code after c.connect
.onTransferFailedtry and catch around c.transfer
.on('name', schema, fn)events: ['name'], then until or c.event
ctx.stateA 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 .on handler 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 newer ctx.state, up to three runs, each with the whole timeout. Nothing overwrites anything. A handler that changed no state and returned no actions never runs again.
  • Pass ctx.eventId to 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, onTransferFailed and onError. Past that the fallback answers at once, and connecting an agent has until 13 s. An agent's tool call keeps to one timeout, 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 run onError, and then the number's Default flow. Each fallback is published as a call.flow.fallback Event.
  • 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 to ctx.state is dropped if another event changed the call while it ran, and the flow event is recorded with stateDropped.
  • 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, with ctx.replaying set, so skip side effects then. They are not synced to platforms that keep tools on the agent, so prefer tool().