Skip to main content
SuperDialog ships two engines, one entry point. DialogMachine is the recommended way in; it drives either engine behind the same Agent protocol - the Playbook engine by default, the legacy graph runtime with engine="flow".

DialogMachine (unified entry point)

Construction

source is the artifact: a path string, a parsed dict, or an object. The unified loader auto-detects full playbooks, the simple format, and legacy flow JSON (compiled transparently), so you never route by format. Engine selection (engine="auto", the default): a Flow / FlowSet object keeps the legacy graph engine (back-compat); a Playbook object, a path string, or a parsed dict runs the Playbook engine. Override with:
  • engine="playbook" - force the Playbook engine (compiling a flow if needed)
  • engine="flow" - force the legacy graph runtime (ValueError on a Playbook)
In Playbook mode, llm is the Talker and the Director unless director_llm splits them; a missing llm raises a clear ValueError. Graph-only methods (switch_flow, seed, load_flow_state) raise NotImplementedError in Playbook mode, and flow_state returns None.

turn

The primary method. Always async - drive it from asyncio.run(...) or any async runtime.
Turn carries text, tool_calls, and metadata. On the Playbook engine, metadata includes checkpoint, version, ended, and (on terminal checkpoints) outcome.
Streaming is real on the Playbook engine. PlaybookAgent yields live provider tokens as the Talker produces them. The legacy graph engine resolves the turn in one shot and surfaces whitespace-delimited chunks (the StreamChunk(text, done, turn) shape is stable).

start / reset / set_llm / assist

switch_flow (graph engine only)

Raises NotImplementedError on the Playbook engine - use multiple journeys and advance rules instead.

Creating agents

generate_simple_playbook (default)

Bootstrap a validated simple-format playbook from a description. The output is parsed and compiled before return, so a successful return is always loadable. CLI equivalent: superdialog generate "<prompt>" --output playbook.yaml.

create_dialog_flow (legacy)

Bootstrap a legacy flow graph from a prompt. Prefer generate_simple_playbook for new agents; generated flows still run on the Playbook engine by default. The llm is used only at construction.

Playbook engine

Import from superdialog.playbook. Checkpoint-compound journeys: a fast Talker streams every spoken turn while an async Director extracts slots, judges advancement, and runs tools over an append-only event log.

Playbook

The authored artifact. Load it - all loaders auto-detect the simple format and legacy flow JSON:
Top-level fields: persona, journeys (≥1), dispatch, tools, pipelines, handlers, interrupts, policies, middleware, env, views, initial. Validation runs on construction and raises on unknown checkpoint/pipeline/tool refs, duplicate ids, undeclared requires keys, and the reserved pipeline result key.

PlaybookAgent

The engine behind the Agent protocol - drop it into SessionWorker and every host adapter unchanged. Use it directly when you want explicit Talker/Director LLMs or a custom HTTP executor.
  • async turn(text, *, stream=False) - Agent protocol. With stream=True the iterator yields live provider tokens, then any pass-through say_verbatim lines, then the done=True chunk.
  • Barge-in safety - aborting the stream interrupts speech, not the state machine: the Director runs to completion in a shielded scope.
  • assist, chat_ctx / load_chat_ctx, event_log / load_event_log, runtime - system inject, transcript view, the lossless log, and the PlaybookRuntime.

The artifact model

Checkpoint

SlotSpec

type (str int float bool date enum array object), required, values (enum), authoritative (tool / pipeline / expr-set writes only), invalidates (slots/results cleared when this value changes), description.

AdvanceRule

when (prose for judge: llm, expr text for judge: expr), judge (llm/expr), to (target ref), requires (slots that must be filled at soft gates, confirmed at hard gates), set (confirmed slot writes on advance). Verdict-extracted slots are provisional at hard gates - a single verdict can never confirm its own requires in one shot.

ToolSpec / PipelineSpec

ToolSpec: type (http/python), method/url/headers/body (sandboxed Jinja over {slots, env, results}), store_response_as, env_updates, run_once, when, timeout, args. PipelineSpec: ordered steps, each with typed on: {ok, failed, http_<code>} branches and a capped RetrySpec (retry ≤ 10). Tool failures are recorded as failed result events - data, never a crash.

Protocols: CompletesLLM, StreamsLLM, HttpFn, PythonToolFn

httpx_http is the production HttpFn backed by httpx. Any superdialog.llm.LLMProvider (the litellm-backed one behind model URIs) adapts to the Talker/Director protocols in a few lines - see Embedding Guides.

The expr language

Used by judge: expr rules, ToolSpec.when, and Playbook.views. A safe, LLM-free, restricted Python expression over state:
Helpers (the only callables): len, first, last, pluck, unique, min, max, any, all. Forbidden (raises ExprError): arithmetic, comprehensions, lambdas, dict literals, f-strings, any _-prefixed name, non-whitelisted calls, expressions over 4096 chars. Missing values evaluate to None (falsy), never an exception.

Migrating flows

compile_flow is lossless by construction: Deterministic edge conditions (X.success == true, X.status == 404) compile to judge: expr; everything else stays judge: llm with the prose verbatim. coverage_report lists anything that didn’t map (any unmapped_* entry is a compiler bug) - run it in CI.

EventLog and ConversationState

The event log is the single source of truth; state is a pure fold over it.
EventLog is append-only with contiguous versions from 1. Events are frozen, discriminated on type: utterance, slot_write, advance, steering_note, tool_call, tool_result, env_write, scratchpad, summary, external, degraded, session_end. ConversationState.fold derives checkpoint_id, slots (value + provisional/confirmed status), transcript, env, tool_results, ended, outcome, and helpers slot_value, confirmed, filled.

replay and the eval bridge

replay re-runs the Director over recorded utterances under a (possibly edited) playbook and diffs decisions - regression evidence for prompt or model changes. The eval bridge scores persona self-play from the same logs.

Sessions (v0.2)

Sessions add lifecycle and persistence on top of any Agent-protocol brain - PlaybookAgent (default) and the legacy DialogMachine alike.

Agent Protocol

SessionWorker / SessionHandle

agent_factory is called once per new session; acquire(session_id) loads or creates the session, locks it for the block, and persists on exit. Different ids run in parallel; same id serialises. SessionHandle exposes turn, assist, state.

Session stores and lock backends

SessionWorker’s SessionRecord persists chat_ctx / flow_state only. For durable Playbook-engine resume, persist agent.event_log.to_jsonl() and restore with load_event_log - see Sessions.

Other agent brains


Tools

PythonTool, HttpTool, and MCPTool implement the Tool ABC and are passed through DialogMachine(tools=[...]) on either engine. On the Playbook engine, prefer declaring tools in the playbook’s process layer (see Tools).
HTTP auth accepts {"type": "bearer", "token": "..."} in v0.2 (basic, api_key, callable planned).

LLM provider registration

Process-global. Once registered, custom/<name>/<model> works in DialogMachine(llm=...), set_llm(), and create_dialog_flow(llm=...).

Adapters

See Embedding Guides for complete integration examples per host.