Documentation
¶
Overview ¶
Package graph provides the StateGraph durable execution runtime.
Index ¶
- Constants
- func ApprovalSignal(sessionID string) string
- type AppendReducer
- type CheckpointCommitter
- type CompiledGraph
- type Edge
- type EdgeCondition
- type EntrypointFunc
- type GraphResolver
- type GraphView
- type GraphViewEdge
- type GraphViewNode
- type MergeFunc
- type MergeMapReducer
- type Message
- type Node
- type NodeFunc
- type QueuedExecutor
- type Reducer
- type ReducerFunc
- type ReplaceReducer
- type RunPayload
- type RunState
- type RunStatus
- type Runner
- func (r *Runner) ForkFrom(ctx context.Context, checkpointID string, stateUpdate map[string]any) (*RunState, error)
- func (r *Runner) ReplayFrom(ctx context.Context, checkpointID string) (*RunState, error)
- func (r *Runner) Resume(ctx context.Context, sessionID string) (*RunState, error)
- func (r *Runner) ResumeFromCheckpoint(ctx context.Context, checkpointID string) (*RunState, error)
- func (r *Runner) Run(ctx context.Context, sessionID string, initial State) (*RunState, error)
- func (r *Runner) Stream() <-chan StreamEvent
- func (r *Runner) WithBroker(b *stream.Broker) *Runner
- func (r *Runner) WithMaxSteps(n int) *Runner
- func (r *Runner) WithNodeTimeout(d time.Duration) *Runner
- func (r *Runner) WithTracer(t Tracer) *Runner
- type State
- type StateGraph
- func (g *StateGraph) AddConditionalEdge(from string, condition EdgeCondition) *StateGraph
- func (g *StateGraph) AddEdge(from, to string) *StateGraph
- func (g *StateGraph) AddInterruptNode(id string, fn NodeFunc) *StateGraph
- func (g *StateGraph) AddNode(id string, fn NodeFunc) *StateGraph
- func (g *StateGraph) AddSubgraph(id string, sub *CompiledGraph) *StateGraph
- func (g *StateGraph) Compile() (*CompiledGraph, error)
- func (g *StateGraph) SetEntryPoint(nodeID string) *StateGraph
- func (g *StateGraph) SetFinishPoint(nodeID string) *StateGraph
- type StateSchema
- type StreamEvent
- type TaskFunc
- type ToolCallRecord
- type Tracer
- type UsageStats
Constants ¶
const ( StartNode = "__start__" EndNode = "__end__" )
const DefaultMaxSteps = 1000
DefaultMaxSteps bounds the number of node executions in a single run to guard against cyclic graphs looping forever.
Variables ¶
This section is empty.
Functions ¶
func ApprovalSignal ¶ added in v0.4.0
ApprovalSignal is the signal name a parked human-in-the-loop run waits on. A webhook handler resumes the run by delivering this signal for the session.
Types ¶
type AppendReducer ¶ added in v0.3.0
type AppendReducer struct{}
AppendReducer appends update elements to an existing slice. If the existing value is not a slice, it is replaced. If the update is a single value, it is wrapped in a slice and appended.
func (AppendReducer) Reduce ¶ added in v0.3.0
func (AppendReducer) Reduce(existing, update any) any
type CheckpointCommitter ¶ added in v0.4.0
type CheckpointCommitter interface {
SaveCheckpointAndEvent(ctx context.Context, cp *storage.Checkpoint, evt *storage.Event) error
}
CheckpointCommitter is an optional interface a storage.Storage implementation may satisfy to persist a checkpoint and its ledger event atomically in a single transaction. When the configured store implements it, the runner uses it so a crash between the two writes cannot desync the checkpoint from the event ledger. Stores that do not implement it fall back to two idempotent calls.
type CompiledGraph ¶
type CompiledGraph struct {
ID string
Nodes map[string]*Node
AdjList map[string][]*Edge // from -> edges
Entry string
}
CompiledGraph is the immutable, validated graph ready for execution.
func RegisterEntrypoint ¶ added in v0.3.0
func RegisterEntrypoint(name string, fn EntrypointFunc) (*CompiledGraph, error)
RegisterEntrypoint wraps a Go function as a graph entrypoint. The returned CompiledGraph has a single node that runs the function, integrating with checkpointing and durable execution.
func TaskGraph ¶ added in v0.3.0
func TaskGraph(id string, tasks map[string]TaskFunc) (*CompiledGraph, error)
TaskGraph creates a CompiledGraph from a sequence of named tasks. Tasks are chained linearly: the output of each becomes the input of the next.
func (*CompiledGraph) ToDOT ¶ added in v0.3.0
func (cg *CompiledGraph) ToDOT() string
ToDOT generates a Graphviz DOT format representation of the compiled graph.
func (*CompiledGraph) ToJSON ¶ added in v0.13.0
func (cg *CompiledGraph) ToJSON() GraphView
ToJSON returns a serializable view of the graph's topology.
func (*CompiledGraph) ToMermaid ¶ added in v0.3.0
func (cg *CompiledGraph) ToMermaid() string
ToMermaid generates a Mermaid flowchart definition of the compiled graph.
type Edge ¶
type Edge struct {
From string
To string // static target (mutually exclusive with Condition)
Condition EdgeCondition // dynamic routing (mutually exclusive with To)
}
Edge represents a transition between nodes.
type EdgeCondition ¶
EdgeCondition decides which node to transition to based on state. Returns the target node ID.
type EntrypointFunc ¶ added in v0.3.0
EntrypointFunc is a function that serves as a graph entrypoint.
type GraphResolver ¶ added in v0.4.0
type GraphResolver func(graphID string) (*CompiledGraph, error)
GraphResolver returns the compiled graph for a graph ID. A distributed worker uses it to look up the graph definition it must execute for a claimed run.
func SingleGraphResolver ¶ added in v0.4.0
func SingleGraphResolver(g *CompiledGraph) GraphResolver
SingleGraphResolver returns a resolver that always yields g.
type GraphView ¶ added in v0.13.0
type GraphView struct {
ID string `json:"id"`
Entry string `json:"entry"`
Nodes []GraphViewNode `json:"nodes"`
Edges []GraphViewEdge `json:"edges"`
}
GraphView is a JSON-serializable description of a compiled graph's topology (nodes + edges), for clients — such as the dashboard UI (os/dashboard) — that render their own visualization instead of parsing Mermaid/DOT text. Synthetic start/end markers are included so a renderer can draw the same entry/exit points ToMermaid/ToDOT show.
type GraphViewEdge ¶ added in v0.13.0
type GraphViewEdge struct {
From string `json:"from"`
To string `json:"to,omitempty"`
Conditional bool `json:"conditional"`
}
GraphViewEdge describes one transition in a GraphView. To is empty when Conditional is true and the target is decided at runtime (see EdgeCondition); a renderer should badge such a node rather than draw an arrow to an unknown destination.
type GraphViewNode ¶ added in v0.13.0
GraphViewNode describes one node in a GraphView. Kind is "start", "end", "interrupt", or "node".
type MergeFunc ¶ added in v0.3.0
MergeFunc combines the results of parallel branches into a single state. It receives the original pre-fork state and the results from each branch.
type MergeMapReducer ¶ added in v0.3.0
type MergeMapReducer struct{}
MergeMapReducer performs a shallow merge of two maps. Update keys overwrite existing keys. Non-map values are replaced.
func (MergeMapReducer) Reduce ¶ added in v0.3.0
func (MergeMapReducer) Reduce(existing, update any) any
type Node ¶
type Node struct {
ID string
Fn NodeFunc
// Interrupt, if true, causes the runner to checkpoint and pause before executing this node.
Interrupt bool
}
Node represents a node in the state graph.
type NodeFunc ¶
NodeFunc is the function signature for a graph node. It receives the current state and returns updated state.
func FanOut ¶ added in v0.3.0
FanOut creates a NodeFunc that executes multiple node functions in parallel. Each function receives a copy of the input state. Results are merged back using a MergeFunc.
func RegisterTask ¶ added in v0.3.0
RegisterTask marks a function as a checkpoint-able task. The result is automatically cached by task name and input hash. If the task was already completed in a previous run (via checkpoint), the cached result is returned without re-executing the function.
func SubgraphNode ¶ added in v0.3.0
func SubgraphNode(sub *CompiledGraph) NodeFunc
SubgraphNode wraps a CompiledGraph as a NodeFunc so it can be used as a node within another graph. The subgraph executes inline, sharing the parent's state.
type QueuedExecutor ¶ added in v0.4.0
type QueuedExecutor struct {
// contains filtered or unexported fields
}
QueuedExecutor bridges the durable work queue to the existing graph Runner. It implements the intake/execution split: producers enqueue runs and this executor — invoked by any queue.Worker — runs or resumes the graph via a freshly constructed Runner, exactly as a synchronous caller would. The public Runner API is unchanged; this only calls it.
func NewQueuedExecutor ¶ added in v0.4.0
func NewQueuedExecutor(store storage.Storage, resolve GraphResolver) *QueuedExecutor
NewQueuedExecutor constructs a QueuedExecutor. store is the durable checkpoint store the Runner uses; resolve maps a run's GraphID to its compiled graph.
func (*QueuedExecutor) Executor ¶ added in v0.4.0
func (qe *QueuedExecutor) Executor() queue.Executor
Executor returns a queue.Executor that runs/resumes the graph for a claimed run. Wire it into a queue.Worker: queue.NewWorker(q, qe.Executor(), cfg).
func (*QueuedExecutor) WithMaxSteps ¶ added in v0.4.0
func (qe *QueuedExecutor) WithMaxSteps(n int) *QueuedExecutor
WithMaxSteps bounds node executions per attempt (see Runner.WithMaxSteps).
type Reducer ¶ added in v0.3.0
Reducer defines how a state value is combined when a node returns an update. The default behavior (nil reducer) is full replacement, but specific keys can be configured to append to slices, merge maps, etc.
type ReducerFunc ¶ added in v0.3.0
ReducerFunc is a convenience adapter for functions.
func (ReducerFunc) Reduce ¶ added in v0.3.0
func (f ReducerFunc) Reduce(existing, update any) any
type ReplaceReducer ¶ added in v0.3.0
type ReplaceReducer struct{}
ReplaceReducer always replaces the existing value with the update. This is the default behavior when no reducer is configured.
func (ReplaceReducer) Reduce ¶ added in v0.3.0
func (ReplaceReducer) Reduce(_, update any) any
type RunPayload ¶ added in v0.4.0
type RunPayload struct {
Initial State `json:"initial,omitempty"`
Resume bool `json:"resume,omitempty"`
}
RunPayload is the durable envelope carried by a queued graph run. It is stored as the queue.Run payload so a worker on any node can reconstruct the execution without shared in-process state. When Resume is true the executor continues from the session's latest checkpoint instead of starting fresh; this is how a human-in-the-loop run, once parked and later signaled, advances past its interrupt rather than restarting.
type RunState ¶
type RunState struct {
RunID string `json:"run_id"`
SessionID string `json:"session_id"`
GraphID string `json:"graph_id"`
CurrentNode string `json:"current_node"`
Status RunStatus `json:"status"`
State State `json:"state"`
SeqNum int64 `json:"seq_num"`
StartedAt time.Time `json:"started_at"`
UpdatedAt time.Time `json:"updated_at"`
// Rich output (Agno-inspired)
Messages []Message `json:"messages,omitempty"`
ToolCalls []ToolCallRecord `json:"tool_calls,omitempty"`
TotalUsage UsageStats `json:"total_usage"`
}
RunState captures the full runtime state for a single graph execution.
type Runner ¶
type Runner struct {
// contains filtered or unexported fields
}
Runner executes a CompiledGraph with durable checkpointing.
A Runner is single-use: each Run/Resume/Replay/Fork call must be made on a freshly constructed Runner. Reusing a Runner returns an error rather than panicking on a closed channel.
func NewRunner ¶
func NewRunner(g *CompiledGraph, store storage.Storage) *Runner
NewRunner creates a runner for the given compiled graph.
func (*Runner) ForkFrom ¶ added in v0.3.0
func (r *Runner) ForkFrom(ctx context.Context, checkpointID string, stateUpdate map[string]any) (*RunState, error)
ForkFrom creates a new execution branch from a specific checkpoint with modified state. The original checkpoint history is preserved; the fork continues independently.
func (*Runner) ReplayFrom ¶ added in v0.3.0
ReplayFrom loads a checkpoint and re-executes the graph from the checkpoint's node. All nodes before the checkpoint node are skipped (treated as cached). Re-execution starts at the checkpoint's node and continues to END.
func (*Runner) Resume ¶
Resume continues execution from the latest checkpoint for the given session.
The latest checkpoint records the *next* node to execute, so Resume never re-runs an already-completed node. When that node is an interrupt node, Resume advances past it exactly once so an approved workflow proceeds instead of re-pausing forever.
func (*Runner) ResumeFromCheckpoint ¶
ResumeFromCheckpoint resumes from a specific checkpoint (time-travel).
func (*Runner) Stream ¶
func (r *Runner) Stream() <-chan StreamEvent
Stream returns a channel of execution events for real-time observability.
func (*Runner) WithBroker ¶
WithBroker attaches an SSE Broker so the runner publishes events to SSE subscribers.
func (*Runner) WithMaxSteps ¶ added in v0.4.0
WithMaxSteps overrides the maximum number of node executions for a single run. A value <= 0 restores the default (DefaultMaxSteps).
func (*Runner) WithNodeTimeout ¶ added in v0.4.0
WithNodeTimeout bounds how long a single node may execute. Zero (the default) disables the per-node timeout.
func (*Runner) WithTracer ¶
WithTracer attaches a Tracer for span-based execution tracing.
type StateGraph ¶
type StateGraph struct {
// contains filtered or unexported fields
}
StateGraph is a builder for defining directed graphs with durable execution.
func (*StateGraph) AddConditionalEdge ¶
func (g *StateGraph) AddConditionalEdge(from string, condition EdgeCondition) *StateGraph
AddConditionalEdge adds a dynamic edge that routes based on state.
func (*StateGraph) AddEdge ¶
func (g *StateGraph) AddEdge(from, to string) *StateGraph
AddEdge adds a static edge from one node to another.
func (*StateGraph) AddInterruptNode ¶
func (g *StateGraph) AddInterruptNode(id string, fn NodeFunc) *StateGraph
AddInterruptNode registers a node that will pause execution for human approval.
func (*StateGraph) AddNode ¶
func (g *StateGraph) AddNode(id string, fn NodeFunc) *StateGraph
AddNode registers a node with the given ID and handler function.
func (*StateGraph) AddSubgraph ¶ added in v0.3.0
func (g *StateGraph) AddSubgraph(id string, sub *CompiledGraph) *StateGraph
AddSubgraph registers a compiled graph as a node within this graph.
func (*StateGraph) Compile ¶
func (g *StateGraph) Compile() (*CompiledGraph, error)
Compile validates the graph and returns a CompiledGraph.
func (*StateGraph) SetEntryPoint ¶
func (g *StateGraph) SetEntryPoint(nodeID string) *StateGraph
SetEntryPoint sets the starting node of the graph.
func (*StateGraph) SetFinishPoint ¶
func (g *StateGraph) SetFinishPoint(nodeID string) *StateGraph
SetFinishPoint sets the ending node of the graph.
type StateSchema ¶ added in v0.3.0
StateSchema maps state keys to their reducers. Keys not in the schema use the default ReplaceReducer behavior.
func (StateSchema) ApplyUpdate ¶ added in v0.3.0
func (s StateSchema) ApplyUpdate(existing, update State) State
ApplyUpdate merges an update into the existing state using the schema's reducers.
type StreamEvent ¶
type StreamEvent struct {
Type string `json:"type"` // node_start, node_end, edge_transition, checkpoint, interrupt, error
NodeID string `json:"node_id,omitempty"`
State State `json:"state,omitempty"`
Error string `json:"error,omitempty"`
Timestamp time.Time `json:"timestamp"`
}
StreamEvent is emitted during graph execution for real-time observability.
type ToolCallRecord ¶
type ToolCallRecord struct {
Name string `json:"name"`
Args map[string]any `json:"args"`
Result any `json:"result"`
Error string `json:"error,omitempty"`
}
ToolCallRecord records a tool invocation during the run.
type Tracer ¶ added in v0.4.0
type Tracer interface {
StartSpan(ctx context.Context, sessionID, name, kind string) (*storage.Trace, error)
EndSpan(ctx context.Context, t *storage.Trace, output any, errMsg string) error
}
Tracer records execution spans. It is defined here (rather than importing the os/trace control-plane package) so the engine layer never depends upward on os/; the ChronosOS *trace.Collector satisfies it. Both methods use storage.Trace, which the engine already depends on.
type UsageStats ¶
type UsageStats struct {
PromptTokens int `json:"prompt_tokens"`
CompletionTokens int `json:"completion_tokens"`
TotalTokens int `json:"total_tokens"`
}
UsageStats tracks cumulative token usage across a run.