graph

package
v0.3.17 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 17, 2026 License: MIT Imports: 8 Imported by: 0

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

View Source
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.

View Source
const END = "__end__"

END is a sentinel node ID that marks the end of execution.

View Source
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

func FormatWarnings(ws []Warning) string

FormatWarnings returns a human-readable string of all warnings.

func GetTyped

func GetTyped[T any](b *Board, key string) (T, bool)

GetTyped retrieves a typed value from the Board's vars.

func IsCompatible

func IsCompatible(output, input PortType) bool

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

type Board = engine.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 NewBoard

func NewBoard() *Board

NewBoard creates an empty execution 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

type Cloneable = engine.Cloneable

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.

func (*CompiledCondition) Evaluate

func (c *CompiledCondition) Evaluate(board *Board) (bool, error)

Evaluate runs the compiled condition against the given Board variables.

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

type Configurable interface {
	SetConfig(config map[string]any)
	Config() map[string]any
}

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

func NewGraph(raw *RawGraph, meta GraphMeta) *Graph

NewGraph constructs an immutable Graph. Intended to be called by the Assemble step (graph/runner), not by end users directly.

func (*Graph) AllEdges

func (g *Graph) AllEdges() []Edge

func (*Graph) Edges

func (g *Graph) Edges(from string) []Edge

func (*Graph) Entry

func (g *Graph) Entry() string

func (*Graph) Meta

func (g *Graph) Meta() GraphMeta

func (*Graph) Name

func (g *Graph) Name() string

func (*Graph) Node

func (g *Graph) Node(id string) (Node, bool)

func (*Graph) Reverse

func (g *Graph) Reverse(to string) []string

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

func NewPassthroughNode(id, typ string) Node

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

type PortDeclarable interface {
	InputPorts() []Port
	OutputPorts() []Port
}

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

type StreamPublisherFunc func(eventType string, payload any)

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

func CheckPortCompatibility(g *RawGraph) []Warning

CheckPortCompatibility checks if connected nodes have compatible port types.

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.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL