Once nodes and edges are in place, you compile the graph and register it.Documentation Index
Fetch the complete documentation index at: https://docs.waniwani.ai/llms.txt
Use this file to discover all available pages before exploring further.
.compile() returns a RegisteredFlow that maps onto the standard server.registerTool(name, config, handler) contract.
Compile
.compile() validates the graph (see Edges) and throws immediately if the graph is malformed. Accepts one optional argument for a custom state store:
WaniwaniFlowStore, which uses the WaniWani API as a key-value store keyed by session id. It reads WANIWANI_API_KEY and WANIWANI_API_URL from env.
The RegisteredFlow shape
Registering
Use theregister shortcut for the common case:
server.registerTool directly if you prefer:
Registering widget display tools alongside flows
When a flow usesshowWidget("name", ...), the named display tool must be registered on the same server. Use Skybridge’s server.registerWidget(name, meta, schema, handler) — it binds the widget name to the matching React component under web/src/widgets/<name>.tsx and emits the widget-rendering metadata that ChatGPT, Claude, and other MCP clients understand. You don’t need to set _meta.openai/outputTemplate by hand.
Minimal end-to-end wiring
A completeserver/src/app.ts looks like this:
server/src/app.ts
withWaniwani is idempotent — calling it twice on the same server is a no-op. The skybridge/server import is what the MCP distribution template uses as the dev/build runtime; it provides the .registerWidget(...) fluent API plus widget mounting for the React components under web/src/widgets/.
Debugging a compiled flow
Inspect the graph
flow.graph() returns a Mermaid diagram of the compiled flow. Log it at startup in development:
Unit-test with createFlowTestHarness
The SDK ships a test harness that drives a compiled flow without spinning up a real transport or store. Import it from @waniwani/sdk/mcp:
start(intent, stateUpdates?): begins a run.intentis positional.continueWith(stateUpdates?): resumes the paused run.lastState(): returns the persistedFlowTokenContentwhen a store is passed viacreateFlowTestHarness(flow, { stateStore }).
FlowTestResult that is the parsed FlowContent (interrupt, widget, complete, or error) plus a decodedState field populated when a store is supplied. Use it to write deterministic tests for branching, validation, and state transitions.