Execution trace

June 15, 2026 · View on GitHub

Every FlowExecutor.execute_flow call produces an ExecutionResult with a structured trace. The trace is a Pydantic model — JSON-serializable, replay-compatible, and stable across releases.

ExecutionResult

FieldTypeMeaning
flow_namestrName of the executed flow.
successboolTrue when all steps completed without error.
final_outputdict | NoneMerged execution context, or None on failure.
execution_loglist[StepRecord]Ordered per-step records.
trace_idstrUUID4 hex assigned at execution start.
started_at / ended_atdatetimeUTC timestamps.
total_duration_msfloatWall-clock duration in milliseconds.

StepRecord

FieldTypeMeaning
step_indexintZero-based position (-1 for input-validation record).
tool_namestrConfigured primary tool for the step. Remains stable when a fallback runs.
inputsdictValidated inputs passed to the tool.
outputsdict | NoneValidated outputs, or None on failure.
error_typestr | NoneException class name on failure.
error_messagestr | NoneHuman-readable error message on failure.
successboolStep status.
started_at / ended_atdatetimeUTC timestamps.
duration_msfloatWall-clock duration in milliseconds.
fallback_usedboolWhether the step attempted its configured on_error fallback.
fallback_tool_namestr | NoneName of the fallback target, or None when no fallback ran.

Serialization

result = executor.execute_flow("calc", {"number": 5})

# To JSON
payload = result.model_dump_json(indent=2)

# Back from JSON
from chainweaver import ExecutionResult

round_tripped = ExecutionResult.model_validate_json(payload)

Errors are stored as error_type / error_message strings rather than live Exception instances so the trace round-trips cleanly through any JSON pipeline.

Replay

A serialized trace can be re-executed:

from chainweaver import ReplayMode

replay = executor.replay_flow(
    trace=result,
    mode=ReplayMode.VERIFY,
)
assert replay.all_steps_match  # outputs identical to recorded trace

ReplayMode.VERIFY re-runs the flow and records StepDiff entries for changed output fields. ReplayMode.EXECUTE re-runs the trace without comparison (useful for checking whether the current tools still complete). STRICT and SKIP_VALIDATION remain compatibility aliases for VERIFY and EXECUTE.

Out-of-band capture

If you have agent traffic that does not go through FlowExecutor (ad-hoc tool calls made by an LLM-driven loop, for instance), use TraceRecorder from chainweaver.observation to capture an ObservedTrace manually. The same ObservedStep fields apply; downstream analysis with ChainAnalyzer finds promotable patterns.