Input
startbegins a new run with empty state.intentis a short summary of why the user triggered the flow.startmerges nostateUpdates.continueresumes the current run with the answers to the questions on the table, keyed by each question’sfield.resetrestarts from the beginning with a corrected value for a field the user already answered. Every other answer is kept.
What a call can write
The tool listing names no state field.stateUpdates is an untyped record, the same for every flow, so none of your field names, descriptions or enum values appear in tools/list. Each interrupt or widget response names the fields it asks for, with a fieldSchema (type, allowed values, description) taken from your state schema, and that response is where the model learns them.
The engine accepts a value only for a field the run has asked for, and drops every other key before the merge. Two cases follow from that:
- A value for a question that comes later is dropped. When the flow asks that question, the model answers it from what the user already said, without asking again.
- A field the flow computes for itself, such as an id an action node resolves or a computed price, is never asked, so no call can set it.
asked.
Tool definition metadata
The tool definition’s_meta carries the flow graph (and the list of fields marked redacted()) for withWaniwani to read on the server. Both are wrapped so JSON serialization drops them: tools/list never sends them to a client.
Tool description
The registered tool’s description is thedescription you passed to createFlow, plus one sentence stating that the tool runs a multi-step flow and that each response describes the next call. Nothing else.
Operating instructions stay out of it on purpose. A description that prescribes conversation behavior, tool sequencing, or required follow-up calls is what prompt-injection classifiers look for, and ChatGPT raises a Suspicious Instruction warning on the connector approval card when it finds one — the user is asked to approve a tool that looks like it is trying to steer the model. Write your description as a description of what the flow does, in one or two sentences.
The protocol the assistant needs travels on the response instead, as nextStep.
Response statuses
Every tool call drives the engine until it hits one of four outcomes:
Between pause points, the engine auto-advances through action nodes (nodes that return a plain state update). No round-trip to the model. A single tool call can run several action nodes before hitting the next pause.
Response fields added by the engine
Three keys are attached by the engine rather than by a node:nextStep is generated by the engine. It is not configurable, and a node cannot set it.
State persistence
State persists between calls in the flow store, keyed by the session id extracted from_meta. Default behavior is described in the Platform overview:
- Without an explicit
storeand withoutWANIWANI_API_KEY,.compile()throws at compile time. - With an explicit
store: KvStore, state lives wherever your adapter writes. - With
WANIWANI_API_KEYand no explicitstore, the SDK selectsWaniwaniKvStoreand state lives onapp.waniwani.ai.
state, a session record carries step, the field being asked, the widget awaiting interaction, the fields the run has asked (asked), and an internal object of engine bookkeeping keyed per feature (currently intro.delivered). A store adapter persists the record as given and never needs to interpret it. A write keeps what it loaded, so a field a newer version wrote survives a call served by an older one and a deploy mid-conversation does not strand a session.
See State for the state schema side of the contract, and KV store adapters for backend options.