Skip to main content
By default a study runs in linear mode: it asks its question list in order. An interview flow (client.graph) replaces that list with a graph of steps, so the interview can branch on answers, capture structured values, pull in outside data and notify your systems as it goes.

Step types

Each type has its own config fields. Get the full schema before you author a flow:

Start from your question list

The easiest way in is to convert the existing linear questions into a straight-line flow, then edit it. Each question captures its answer as q1, q2, and so on.

Write a whole flow

Flows can be plain dicts in the API’s JSON shape, or the typed FlowDocument, FlowNode and FlowEdge models. from and class are Python keywords, so on the models they’re from_ and class_.
This flow is illustrative: the exact config each step needs, including how a question names the variable it captures, comes from describe_node_types(). Run check() first and it will tell you anything that’s missing.
Check it without saving, then save it:

Branching rules

  • A condition is a single test: {"var": ..., "op": ..., "value": ...}. Operators are eq, neq, in, contains, gt, gte, lt, lte, is_set and not_set. For compound logic, chain two decision steps.
  • On an llm_classifier decision, each outgoing edge sets class (class_ on the model) to the label it handles.
  • A decision with several paths needs exactly one default path, unless its conditions cover every possible answer of a choices or scale question.
  • priority sets the evaluation order of paths out of the same decision; lowest first.
  • Every step inside a loop needs max_revisits. Once a step has run that many times, the interview takes the default path out.
  • extract, webhook and context_fetch steps never appear in edges. Attach them with after or before.

Edit with patches

patch applies targeted edits instead of rewriting the whole flow. Operations run in order and the end state is validated as a whole.

Safe concurrent edits

Every successful save increments graph_version. Pass the version you last read as expected_graph_version to set or patch. If someone else has saved in the meantime, the write is refused with ConflictError rather than overwriting their change.
set and patch never save an invalid flow. An invalid result raises ValidationError, and the stored flow is untouched.

Activate the flow

Saving a flow doesn’t change what interviews run. Switch modes explicitly:
A flow must have compiled cleanly (has_compiled_ir on graph.get) before you can activate it. An open study’s flow is locked, so pause it to edit.

Signals

A webhook step sends a signed POST to your endpoint mid-interview. Get each step’s signing secret with get_signals, then verify deliveries with deutero.webhooks.unwrap:
Simulated interviews don’t deliver signals to real endpoints unless you pass deliver_signals=True to simulations.run.

Inspect what happened

For any interview, see the variables it captured and the branches it took, plus what its fetches and signals did: