Executing Flows
Learn how to execute flows and customize behavior.
Flows are executed via execute(), which runs the entire flow to completion and returns an ExecuteResult (or a PausedResult when the flow pauses for tool calls).
Basic execution
Get a flow proxy and call execute() with a message. The recommended pattern is to set org and project defaults when constructing the client:
message is the flow's first input. It is a shorthand for parameters={"message": "..."} — see below for details on how parameters compose.
You can also override the defaults with a fully-qualified flow identifier or per-call kwargs (see Per-call overrides at the end of this guide).
Execution options
execute() accepts the following keyword arguments:
message and parameters — the flow's initial inputs
A flow has a set of named initial inputs declared in its definition. message is just the conventional name for the first one. To pass additional initial inputs, use parameters as a flat dict mapping input name → value (not nested by block):
block_overrides — per-step config overrides
To override the config of an individual step (e.g. swap the prompt template, change the model on a single LLM block) use block_overrides, keyed by step ID:
parameters is a flat map of flow-level inputs; block_overrides is keyed by step ID and overrides that step's config. They are not interchangeable.
version — which version of the flow to run
version accepts:
"draft"(default) — the in-progress draft"production"— the currently promoted production version- An integer
N— a specific published version number (e.g.version=3)
Strings other than "draft" and "production" (including "main") raise ValueError.
tools and tool_handler
tools accepts OpenAI-format tool definitions. With tool_handler set, the SDK loops automatically: the server pauses for tool calls, the handler runs, the SDK resumes — up to max_tool_rounds (default 10). Without tool_handler, the SDK returns a PausedResult for the caller to drive manually. See Tool calls for the full pattern.
trace
When True, the server captures full input/output snapshots in the trace. Timing, token counts and cost are recorded either way — trace adds the snapshots used to debug bad outputs. Retrieve the trace via flow.run(execution_id).trace() after execution; see Tracing & debugging.
Results
A successful execute() returns an ExecuteResult:
ExecuteResult does not embed the trace inline. To fetch timing/cost/tokens, look up the execution by ID:
Paused results (tool calls)
If the flow pauses for tool calls and you did not provide a tool_handler, execute() returns a PausedResult instead. Check requires_tool_calls:
Async submission (execute_async)
For long-running flows you can submit to a server-side queue and poll for completion:
The _async suffix refers to the server-side execution model (queue-backed), not the client's async/await. Tool calls are not supported on this path.
Error handling
execute() raises typed exceptions on failure. See Errors & retries for the full hierarchy.
Per-call overrides
When your client has org and project defaults, you can still override them per-call using a fully-qualified identifier or kwargs:
Next steps
- Stream step-by-step: See Step-by-step iteration
- Handle tool calls: See Tool calls
- Inspect execution: See Tracing & debugging