Documentation
¶
Overview ¶
Package graph implements the core graph engine for FlowCraft.
A Graph is a compiled, immutable directed graph of Nodes connected by Edges. Nodes operate on a shared Board and pass control to successor node(s). Edges may carry compiled conditions (evaluated by expr-lang/expr) for dynamic routing.
File layout in this package:
core.go engine sentinels, Node interface family, ExecutionContext, Graph definition.go declarative GraphDefinition / RawGraph / GraphMeta port.go typed input/output ports + runtime validation board.go blackboard alias to engine.Board condition.go compiled boolean expressions for edge / skip conditions stream.go StreamPublisher abstraction handed to nodes vars.go well-known board variable keys
Index ¶
- Constants
- func FormatWarnings(ws []Warning) string
- func GetTyped[T any](b *Board, key string) (T, bool)
- func IsCompatible(output, input PortType) bool
- func ValidateInputs(b *Board, node PortDeclarable) error
- func ValidateInputsWithConfig(b *Board, node PortDeclarable, config map[string]any) error
- func ValidateOutputs(b *Board, node PortDeclarable) error
- type Board
- type BoardSnapshot
- type Cloneable
- type CompiledCondition
- type CompiledGraph
- type Configurable
- type Describable
- type Edge
- type EdgeDefinition
- type ExecutionContext
- type Graph
- func (g *Graph) AllEdges() []Edge
- func (g *Graph) Edges(from string) []Edge
- func (g *Graph) Entry() string
- func (g *Graph) Meta() GraphMeta
- func (g *Graph) Name() string
- func (g *Graph) Node(id string) (Node, bool)
- func (g *Graph) Reverse(to string) []string
- func (g *Graph) SkipCondition(id string) (*CompiledCondition, bool)
- type GraphDefinition
- type GraphMeta
- type Node
- type NodeDefinition
- type Port
- type PortDeclarable
- type PortType
- type RawGraph
- type StreamPublisher
- type StreamPublisherFunc
- type Warning
Constants ¶
const ( // VarInterruptedNode records the ID of the node that returned an // engine.Interrupted error, written by the executor before propagating // the interrupt to the caller. Used by resume flows to know where to // restart. VarInterruptedNode = "__interrupted_node" // VarToolCalls is the engine-managed slice that mirrors tool_call / // tool_result stream events into board state, so resume / inspection // flows can see the in-flight tool loop without replaying the stream. VarToolCalls = "__tool_calls" )
Board variable keys owned by the graph layer.
Only engine-produced keys live here — names written by the executor itself as a side effect of running a graph. Node-type-specific keys (e.g. summarisation index, previous-message count, the LLM transcript channel name) belong in the owning node sub-package.
const END = "__end__"
END is a sentinel node ID that marks the end of execution.
const MainChannel = engine.MainChannel
MainChannel is the default message channel key (empty string). Re-exported from engine so nodes can reference graph.MainChannel without importing the engine package directly.
Variables ¶
This section is empty.
Functions ¶
func FormatWarnings ¶ added in v0.2.3
FormatWarnings returns a human-readable string of all warnings.
func IsCompatible ¶
IsCompatible checks if an output port type can feed into an input port type.
func ValidateInputs ¶
func ValidateInputs(b *Board, node PortDeclarable) error
ValidateInputs checks that all required input ports have corresponding Board variables.
func ValidateInputsWithConfig ¶
func ValidateInputsWithConfig(b *Board, node PortDeclarable, config map[string]any) error
ValidateInputsWithConfig checks that all required input ports are satisfied, either by a board variable, a non-empty main channel (for message ports), or a value supplied directly via the node's resolved config map.
func ValidateOutputs ¶
func ValidateOutputs(b *Board, node PortDeclarable) error
ValidateOutputs checks that all required output ports have been written to the Board.
Symmetric with ValidateInputsWithConfig: PortTypeMessages outputs may be satisfied either by a board variable or by a non-empty channel of the same name. Without this fallback, nodes that follow the v0.3 channels- only messages contract (e.g. llmnode.writeResults' board.SetChannel) would fail validation despite writing the data the port describes.
Types ¶
type Board ¶
Board is the graph execution blackboard (vars + message channels).
Implementation lives in the engine package; graph aliases it so nodes, the executor and the validator share a single Board type with the rest of the runtime. Kanban card coordination lives in kanban.Board.
func RestoreBoard ¶
func RestoreBoard(snap *BoardSnapshot) *Board
RestoreBoard reconstructs a Board from a snapshot.
type BoardSnapshot ¶
type BoardSnapshot = engine.BoardSnapshot
BoardSnapshot is serialisable execution state (vars + channels only).
type Cloneable ¶ added in v0.2.3
Cloneable may be implemented by values stored in Board vars to provide a type-safe deep copy instead of the reflection fallback used by Snapshot and RestoreBoard.
type CompiledCondition ¶
type CompiledCondition struct {
Raw string
// contains filtered or unexported fields
}
CompiledCondition holds a pre-compiled expr-lang program for edge/skip conditions.
func CompileCondition ¶
func CompileCondition(raw string) (*CompiledCondition, error)
CompileCondition compiles a raw expression string into a reusable program.
type CompiledGraph ¶ added in v0.2.3
type CompiledGraph struct {
Graph *RawGraph
NodeDefs []NodeDefinition
EdgeDefs []EdgeDefinition
Warnings []Warning
Metadata GraphMeta
}
CompiledGraph is the result of compilation, containing the raw graph structure and analysis metadata. Nodes in RawGraph are passthrough placeholders; actual node construction is deferred to downstream Assemble + NodeFactory.
func Compile ¶ added in v0.2.3
func Compile(def *GraphDefinition) (*CompiledGraph, error)
Compile transforms a GraphDefinition into a CompiledGraph. All nodes are represented as passthrough placeholders; the original definitions are preserved in NodeDefs/EdgeDefs for downstream NodeFactory construction. The returned CompiledGraph is safe to cache and reuse across many runner.New calls — compilation has no side effects.
Compile is a pure static analysis pass: it constructs no node instances and performs no I/O. Errors are validation failures (errdefs.Validation); non-fatal issues surface as Warnings on the result.
type Configurable ¶
Configurable is an optional interface for nodes whose config can be dynamically resolved (e.g. variable reference expansion).
type Describable ¶
type Describable interface {
Description() string
}
Describable is an optional interface for nodes that provide a description.
type Edge ¶
type Edge struct {
From string
To string
Condition *CompiledCondition
}
Edge represents a directed connection between two nodes. A nil Condition means the edge is unconditional; otherwise the executor evaluates it against the current Board to decide whether to follow the edge.
type EdgeDefinition ¶
type EdgeDefinition struct {
From string `json:"from" yaml:"from"`
To string `json:"to" yaml:"to"`
Condition string `json:"condition,omitempty" yaml:"condition,omitempty"`
}
EdgeDefinition describes a single edge in a GraphDefinition.
type ExecutionContext ¶
type ExecutionContext struct {
Context context.Context
Host engine.Host
Publisher StreamPublisher
RunID string
Deps *engine.Dependencies
Attributes map[string]string
}
ExecutionContext wraps a standard context.Context with graph execution metadata.
Host is the engine.Host the executor was started with; nodes use it for cooperative interrupts (Host.Interrupts()), user prompts (Host.AskUser), usage reporting and checkpointing. The executor guarantees Host is non-nil (it falls back to engine.NoopHost{}) so nodes never need a nil check.
Publisher is a thin wrapper around Host.Publish kept for backwards compatibility and ergonomic event emission with (type, payload) pairs; new code MAY call Host.Publish directly with a fully formed envelope.
Deps is the typed dependency container the upstream agent.Run handed to the engine via engine.Run.Deps. The graph runner propagates it verbatim so nodes can recover host-supplied dependencies (LLM clients, tool registries, retrievers, …) via engine.GetDep instead of closure-binding them at builder time. May be nil when the engine was invoked directly without engine.Run.Deps; nodes that need a dep MUST handle the nil case (engine.GetDep does).
Attributes is the read-only string-keyed bag that the upstream agent.Run promoted from [agent.Request] / [agent.RunInfo]. Canonical keys live under github.com/GizClaw/flowcraft/sdk/telemetry (e.g. AttrAgentID / AttrTaskID / AttrContextID) so nodes that need agent-scoped identity (scriptnode RunInfoBridge, telemetry hooks, envelope agent_id) can read them without inventing a parallel transport. May be nil when the engine was invoked without attributes.
type Graph ¶
type Graph struct {
// contains filtered or unexported fields
}
Graph is an immutable, executable directed graph of nodes.
It can only be created via NewGraph (called by Assemble) and provides read-only accessors. The executor is the sole consumer.
func NewGraph ¶
NewGraph constructs an immutable Graph. Intended to be called by the Assemble step (graph/runner), not by end users directly.
func (*Graph) SkipCondition ¶
func (g *Graph) SkipCondition(id string) (*CompiledCondition, bool)
type GraphDefinition ¶
type GraphDefinition struct {
Name string `json:"name" yaml:"name"`
Entry string `json:"entry" yaml:"entry"`
Nodes []NodeDefinition `json:"nodes" yaml:"nodes"`
Edges []EdgeDefinition `json:"edges" yaml:"edges"`
}
GraphDefinition is the declarative definition of a graph (YAML/JSON).
func (*GraphDefinition) Validate ¶
func (d *GraphDefinition) Validate() error
Validate checks that the definition is structurally valid.
type GraphMeta ¶
type GraphMeta struct {
NodeCount int `json:"node_count"`
EdgeCount int `json:"edge_count"`
HasCycles bool `json:"has_cycles"`
HasParallel bool `json:"has_parallel"`
MaxDepth int `json:"max_depth"`
}
GraphMeta contains structural analysis results produced by the compiler.
type Node ¶
type Node interface {
ID() string
Type() string
ExecuteBoard(ctx ExecutionContext, board *Board) error
}
Node is the interface that all graph nodes must implement.
func NewPassthroughNode ¶
NewPassthroughNode creates a no-op node with the given ID and type.
type NodeDefinition ¶
type NodeDefinition struct {
ID string `json:"id" yaml:"id"`
Type string `json:"type" yaml:"type"`
Config map[string]any `json:"config,omitempty" yaml:"config,omitempty"`
SkipCondition string `json:"skip_condition,omitempty" yaml:"skip_condition,omitempty"`
}
NodeDefinition describes a single node in a GraphDefinition.
type Port ¶
type Port struct {
Name string `json:"name"`
Type PortType `json:"type"`
Required bool `json:"required"`
Desc string `json:"desc,omitempty"`
}
Port declares a typed input or output slot on a node.
type PortDeclarable ¶
PortDeclarable is an optional interface for nodes that declare typed input/output ports for compile-time and runtime validation.
type PortType ¶
type PortType string
PortType identifies the data type of a node port.
const ( PortTypeString PortType = "string" PortTypeInteger PortType = "integer" PortTypeFloat PortType = "float" PortTypeBool PortType = "bool" PortTypeArray PortType = "array" PortTypeObject PortType = "object" PortTypeMessages PortType = "messages" PortTypeUsage PortType = "usage" PortTypeAny PortType = "any" )
type RawGraph ¶
type RawGraph struct {
Name string
Entry string
Nodes map[string]Node
Edges map[string][]Edge
Reverse map[string][]string
SkipConditions map[string]*CompiledCondition
}
RawGraph is the intermediate graph structure produced by the compiler.
All fields are exported for static analysis during compilation. It is NOT intended for direct execution — use Assemble (graph/runner) to produce an immutable *Graph for the executor.
type StreamPublisher ¶ added in v0.2.3
type StreamPublisher interface {
// Emit pushes one streaming event. Type is a short tag like "token",
// "tool_call", "tool_result", "delta". Payload SHOULD be a map[string]any
// so downstream filters can introspect fields without reflection.
Emit(eventType string, payload any)
}
StreamPublisher emits in-flight node events (token / tool_call / tool_result / ...).
Nodes obtain a publisher from ExecutionContext.Publisher and call Emit to push deltas. The executor decides where the events ultimately go (typically engine.Host.Publish via the run's host) so nodes never see that concern.
Emit is fire-and-forget: implementations must not block the caller and must not return errors. Implementations are expected to be safe for concurrent use because tool execution may emit from goroutines spawned by the LLM round.
func NoopPublisher ¶ added in v0.2.3
func NoopPublisher() StreamPublisher
NoopPublisher returns a publisher that discards every event. Safe to assign to ExecutionContext.Publisher when no observer is registered.
type StreamPublisherFunc ¶ added in v0.2.3
StreamPublisherFunc adapts a plain function into a StreamPublisher. Useful for tests and for ad-hoc wrapping.
func (StreamPublisherFunc) Emit ¶ added in v0.2.3
func (f StreamPublisherFunc) Emit(eventType string, payload any)
Emit implements StreamPublisher.
type Warning ¶ added in v0.2.3
type Warning struct {
Code string `json:"code"`
Message string `json:"message"`
NodeIDs []string `json:"node_ids,omitempty"`
}
Warning represents a non-fatal issue found during compilation.
func CheckPortCompatibility ¶ added in v0.2.3
CheckPortCompatibility checks if connected nodes have compatible port types.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Package node hosts the runtime-side primitives shared by every concrete graph node implementation: the per-type Builder registry (Factory) and the port declarations consumed by jsnode.
|
Package node hosts the runtime-side primitives shared by every concrete graph node implementation: the per-type Builder registry (Factory) and the port declarations consumed by jsnode. |
|
knowledgenode
Package knowledgenode implements the "knowledge" graph node and exposes a Register helper for binding it into a node.Factory.
|
Package knowledgenode implements the "knowledge" graph node and exposes a Register helper for binding it into a node.Factory. |
|
llmnode
Package llmnode implements the Go-native "llm" graph node and exposes a Register helper for binding it into a node.Factory.
|
Package llmnode implements the Go-native "llm" graph node and exposes a Register helper for binding it into a node.Factory. |
|
scripts
Package scripts embeds all built-in JS node scripts via embed.FS.
|
Package scripts embeds all built-in JS node scripts via embed.FS. |
|
Package runner is the assembly + lifecycle layer on top of graph/executor.
|
Package runner is the assembly + lifecycle layer on top of graph/executor. |
|
internal/executor
Package executor provides the graph execution engine.
|
Package executor provides the graph execution engine. |
|
Package variable provides a typed variable system for the graph engine.
|
Package variable provides a typed variable system for the graph engine. |