Documentation
¶
Overview ¶
Package reactree implements the ReAcTree (Reasoning-Acting Tree) execution engine for Genie's multi-step agent workflows.
It solves the problem of running complex tasks as a behavior tree: the orchestrator builds a graph of nodes (sequence, selector, agent nodes), and the tree is ticked until completion. Each agent node runs an Expert (LLM + tools); control flow (retry, fallback, parallel stages) is expressed as tree structure rather than ad-hoc code. Without this package, multi-step flows would be hard-coded and harder to extend or reason about.
Index ¶
- Constants
- func BuildFallback(sg *graph.StateGraph, nodeIDs []string) *graph.StateGraph
- func BuildParallel(sg *graph.StateGraph, nodeIDs []string, aggregatorID string) *graph.StateGraph
- func BuildSequence(sg *graph.StateGraph, nodeIDs []string) *graph.StateGraph
- func BuildSequenceWithEarlyExit(sg *graph.StateGraph, nodeIDs []string) *graph.StateGraph
- func NewAgentNodeFunc(cfg AgentNodeConfig) graph.NodeFunc
- func NewCreateAgentTool(modelProvider modelprovider.ModelProvider, expert expert.Expert, ...) *createAgentTool
- func NewReAcTreeSchema() *graph.StateSchema
- func WrapNodeForParallel(nodeID string, original graph.NodeFunc) graph.NodeFunc
- func WrapToolsForDryRun(tools []tool.Tool) ([]tool.Tool, func() []string)
- func WrapWithValidator(t tool.Tool, validator ActionValidator) tool.Tool
- type ActionReflector
- type ActionValidator
- type AgentNodeConfig
- type AuditHook
- func (h *AuditHook) OnDryRun(ctx context.Context, event hooks.DryRunEvent)
- func (h *AuditHook) OnIterationEnd(ctx context.Context, event hooks.IterationEndEvent)
- func (h *AuditHook) OnIterationStart(ctx context.Context, event hooks.IterationStartEvent)
- func (h *AuditHook) OnPlanExecution(ctx context.Context, event hooks.PlanExecutionEvent)
- func (h *AuditHook) OnReflection(ctx context.Context, event hooks.ReflectionEvent)
- func (h *AuditHook) OnToolValidation(ctx context.Context, event hooks.ToolValidationEvent)
- type ControlFlowType
- type CreateAgentRequest
- type CreateAgentResponse
- type DeterministicValidator
- type DryRunResult
- type DryRunToolWrapper
- type ExpertReflector
- type NoOpReflector
- type NodeResult
- type NodeStatus
- type OrchestratorConfig
- type OrchestratorResult
- type Plan
- type PlanStep
- type ReflectionRequest
- type ReflectionResult
- type StageConfig
- type Toggles
- type TreeConfig
- type TreeExecutor
- type TreeRequest
- type TreeResult
- type ValidatingToolWrapper
Constants ¶
const ( AuditEventIterationStart audit.EventType = "reactree_iteration_start" AuditEventIterationEnd audit.EventType = "reactree_iteration_end" AuditEventCriticRejection audit.EventType = "reactree_critic_rejection" AuditEventReflection audit.EventType = "reactree_reflection" AuditEventDryRun audit.EventType = "reactree_dry_run" AuditEventPlanExecution audit.EventType = "reactree_plan_execution" )
AuditEventType constants for ReAcTree-specific audit events.
const ( // StateKeyGoal is the current task goal for agent nodes to work on. StateKeyGoal = "reactree_goal" // StateKeyNodeStatus stores the NodeStatus result from the last node. StateKeyNodeStatus = "reactree_node_status" // StateKeyOutput stores the text output from the last node. StateKeyOutput = "reactree_output" // StateKeyWorkingMemory stores shared observations across nodes. StateKeyWorkingMemory = "reactree_working_memory" // StateKeyTaskCompleted indicates the agent finished without making any // tool calls. When true, the task was fully answered in this stage and // subsequent stages can be skipped to save cost and latency. StateKeyTaskCompleted = "reactree_task_completed" // StateKeyPreviousStageOutput carries the output from the previous stage // so subsequent stages can see what was already accomplished and avoid // redundant work (e.g. repeating the same web search). StateKeyPreviousStageOutput = "reactree_previous_stage_output" // StateKeyIterationContext carries the accumulated output from all prior // iterations in the adaptive loop. This replaces staged previousStageOutput // with a rolling context window. StateKeyIterationContext = "reactree_iteration_context" // StateKeyIterationCount tracks the current iteration number in the // adaptive loop (0-indexed). StateKeyIterationCount = "reactree_iteration_count" // StateKeyToolCallCounts reports per-tool call counts (name→count) from // a single agent node execution. The adaptive loop accumulates these // across iterations to enforce ToolBudgets. StateKeyToolCallCounts = "reactree_tool_call_counts" )
State keys used by the ReAcTree graph nodes to share data.
const (
CreateAgentToolName = "create_agent"
)
Variables ¶
This section is empty.
Functions ¶
func BuildFallback ¶
func BuildFallback( sg *graph.StateGraph, nodeIDs []string, ) *graph.StateGraph
BuildFallback wires nodes into a fallback on the given StateGraph. Nodes are connected so that if the current one succeeds the graph ends, otherwise the next node is tried. If all nodes fail, the graph ends with failure. This models Behavior Tree Fallback (OR) semantics.
func BuildParallel ¶
func BuildParallel( sg *graph.StateGraph, nodeIDs []string, aggregatorID string, ) *graph.StateGraph
BuildParallel wires nodes for parallel execution with majority voting. Callers are responsible for connecting the entry point (e.g., graph.Start) to each child in nodeIDs to create the fan-out. This function only wires the fan-in via AddJoinEdge to an aggregator node that performs majority voting.
Each child node's original function is wrapped so that its NodeStatus is also stored under a per-node key (StateKeyNodeStatus:<nodeID>). This lets the aggregator read individual results without them being overwritten by sibling nodes that share the same StateKeyNodeStatus key.
func BuildSequence ¶
func BuildSequence( sg *graph.StateGraph, nodeIDs []string, ) *graph.StateGraph
BuildSequence wires nodes into a sequence on the given StateGraph. Nodes are connected with AddEdge in order. After each node, a conditional edge checks NodeStatus: if Failure, the graph ends immediately. This models Behavior Tree Sequence (AND) semantics.
func BuildSequenceWithEarlyExit ¶
func BuildSequenceWithEarlyExit( sg *graph.StateGraph, nodeIDs []string, ) *graph.StateGraph
BuildSequenceWithEarlyExit wires nodes into a sequence that supports early termination when a stage completes the task without tool calls. Like BuildSequence, it short-circuits on Failure. Additionally, if a stage sets StateKeyTaskCompleted=true (zero tool calls), remaining stages are skipped — preventing redundant cost and latency.
func NewAgentNodeFunc ¶
func NewAgentNodeFunc(cfg AgentNodeConfig) graph.NodeFunc
NewAgentNodeFunc creates a graph.NodeFunc that wraps an expert.Expert call. The returned function reads the goal from state, enriches the prompt with working memory and episodic memory, calls the expert, and writes the result back to state. This is the bridge between the ReAcTree concept of an "agent node" and trpc-agent-go's graph execution model.
func NewCreateAgentTool ¶
func NewCreateAgentTool( modelProvider modelprovider.ModelProvider, expert expert.Expert, summarizer agentutils.Summarizer, toolRegistry *tools.Registry, workingMemory *memory.WorkingMemory, episodic memory.EpisodicMemory, toolWrapSvc *toolwrap.Service, ) *createAgentTool
NewCreateAgentTool creates a tool that spawns sub-agents with dynamic tool subsets. The llmModel is the LLM to use for sub-agents. The toolRegistry is a name→tool map of all available tools the sub-agent can choose from. The optional toolWrapSvc, when provided, wraps sub-agent tools with HITL approval gating, audit logging, and file-read caching — ensuring sub-agents cannot execute write tools without human approval.
func NewReAcTreeSchema ¶
func NewReAcTreeSchema() *graph.StateSchema
NewReAcTreeSchema creates a graph.StateSchema with the fields used by ReAcTree nodes. This schema defines the shared state that flows between nodes in the compiled graph.
func WrapNodeForParallel ¶
WrapNodeForParallel wraps a node function so that, in addition to returning its normal state, the NodeStatus is also stored under a per-node key (StateKeyNodeStatus:<nodeID>). This allows the majority-vote aggregator to read each node's result independently.
Usage: when building a parallel graph, wrap each child node before adding it:
sg.AddNode("a", WrapNodeForParallel("a", myNodeFunc))
sg.AddNode("b", WrapNodeForParallel("b", otherNodeFunc))
BuildParallel(sg, []string{"a", "b"}, "aggregator")
func WrapToolsForDryRun ¶
WrapToolsForDryRun wraps all tools with DryRunToolWrapper for simulation. Returns the wrapped tools and a collector function to gather all invocations.
func WrapWithValidator ¶
func WrapWithValidator(t tool.Tool, validator ActionValidator) tool.Tool
WrapWithValidator wraps the provided tool with the given validator. If validator is nil, it returns the tool unmodified.
Types ¶
type ActionReflector ¶
type ActionReflector interface {
// Reflect takes a proposed goal and the output from the most recent agent
// node execution, and produces a reflection text. If the reflection
// determines the action is unsafe or illogical, it returns an error.
Reflect(ctx context.Context, req ReflectionRequest) (ReflectionResult, error)
}
ActionReflector performs a Reasoning-Action-Reflection (RAR) loop before external actions. When enabled, the agent is prompted to justify why it is about to take an action, producing an "internal monologue" that is recorded for auditability and prevents hallucinated side-effectful calls.
type ActionValidator ¶
type ActionValidator interface {
// Validate checks if the tool call with its JSON arguments is permitted.
// Returns an error if the action is rejected/pruned.
Validate(ctx context.Context, toolName string, jsonArgs []byte) error
}
ActionValidator defines the middleware interface for deterministic or LLM-based branch pruning.
type AgentNodeConfig ¶
type AgentNodeConfig struct {
Goal string
Expert expert.Expert
WorkingMemory *memory.WorkingMemory
Episodic memory.EpisodicMemory
MaxDecisions int
Tools []tool.Tool
// TaskType selects the model for this node via ModelProvider.GetModel().
// If empty, defaults to TaskPlanning.
TaskType modelprovider.TaskType
// Attachments are file/media attachments from the incoming message.
// Image attachments are passed as multimodal content to the LLM.
Attachments []messenger.Attachment
// BudgetExhaustedTools lists tool names whose budget has been reached.
// The adaptive loop sets this when tools in ToolBudgets have hit their
// limits. A prompt hint is injected telling the LLM these tools are
// unavailable; the tools themselves are also stripped from the list.
BudgetExhaustedTools []string
// SystemInstruction, when set, makes this node use a lightweight
// llmagent instead of the full Expert. This prevents plan-step
// sub-agents from inheriting the main agent's persona (which
// contains orchestration patterns and causes tool hallucination).
SystemInstruction string
// ModelProvider is used to resolve the model when SystemInstruction
// is set (lightweight mode). Ignored when using Expert.
ModelProvider modelprovider.ModelProvider
}
AgentNodeConfig holds configuration for creating an agent node function.
type AuditHook ¶
type AuditHook struct {
hooks.NoOpHook // embed no-op defaults
// contains filtered or unexported fields
}
AuditHook implements hooks.ExecutionHook by writing structured events to an audit.Auditor. This is the bridge between the generic hook system and the existing audit infrastructure.
func NewAuditHook ¶
NewAuditHook creates an ExecutionHook that writes to the given auditor. Returns nil if auditor is nil.
func (*AuditHook) OnDryRun ¶
func (h *AuditHook) OnDryRun(ctx context.Context, event hooks.DryRunEvent)
func (*AuditHook) OnIterationEnd ¶
func (h *AuditHook) OnIterationEnd(ctx context.Context, event hooks.IterationEndEvent)
func (*AuditHook) OnIterationStart ¶
func (h *AuditHook) OnIterationStart(ctx context.Context, event hooks.IterationStartEvent)
func (*AuditHook) OnPlanExecution ¶
func (h *AuditHook) OnPlanExecution(ctx context.Context, event hooks.PlanExecutionEvent)
func (*AuditHook) OnReflection ¶
func (h *AuditHook) OnReflection(ctx context.Context, event hooks.ReflectionEvent)
func (*AuditHook) OnToolValidation ¶
func (h *AuditHook) OnToolValidation(ctx context.Context, event hooks.ToolValidationEvent)
type ControlFlowType ¶
type ControlFlowType string
ControlFlowType identifies the behavior of a control flow pattern.
const ( // ControlFlowSequence executes children in order. // Returns Success only if ALL children succeed (AND logic). ControlFlowSequence ControlFlowType = "sequence" // ControlFlowFallback tries children in order. // Returns Success on the FIRST child success (OR logic). ControlFlowFallback ControlFlowType = "fallback" // ControlFlowParallel executes all children. // Returns Success if a majority succeed (majority vote). ControlFlowParallel ControlFlowType = "parallel" )
type CreateAgentRequest ¶
type CreateAgentRequest struct {
AgentName string `json:"agent_name" jsonschema:"description=Name of the sub-agent,required"`
Goal string `json:"goal" jsonschema:"description=The goal or task for the sub-agent to accomplish,required"`
ToolNames []string `json:"tool_names,omitempty" jsonschema:"description=Names of tools to give the sub-agent. If empty all tools are provided."`
TaskType modelprovider.TaskType `` /* 378-byte string literal not displayed */
MaxToolIterations int `` /* 193-byte string literal not displayed */
MaxLLMCalls int `` /* 181-byte string literal not displayed */
TimeoutSeconds float64 `` /* 210-byte string literal not displayed */
// SummarizeOutput controls whether large sub-agent output is summarized
// before returning to the parent agent. When false (default), the raw
// output is returned as-is, preserving all detail. Set to true only when
// the output is expected to be very large and a condensed version suffices.
SummarizeOutput bool `` /* 245-byte string literal not displayed */
// Steps enables multi-step plan execution. When provided, the tool builds
// a graph from these steps using the specified Flow type, instead of
// running a single sub-agent. Each step becomes an agent node.
Steps []PlanStep `` /* 185-byte string literal not displayed */
// Flow selects how Steps are coordinated:
// sequence — steps run in order (fail-fast)
// parallel — steps run concurrently (majority vote)
// fallback — steps tried in order (first success wins)
// Defaults to sequence if not specified.
Flow string `` /* 156-byte string literal not displayed */
}
CreateAgentRequest is the input for the create_agent tool.
type CreateAgentResponse ¶
CreateAgentResponse is the output for the create_agent tool.
type DeterministicValidator ¶
type DeterministicValidator struct {
BlockedTools []string
}
DeterministicValidator implements ActionValidator by checking against safe policies.
func NewDeterministicValidator ¶
func NewDeterministicValidator(blockedTools []string) *DeterministicValidator
NewDeterministicValidator creates a validator that rejects tools in the BlockedTools list
type DryRunResult ¶
type DryRunResult struct {
// PlannedSteps is the number of graph nodes that would execute.
PlannedSteps int
// ToolsUsed lists the tool names that would be invoked.
ToolsUsed []string
// EstimatedCost is a heuristic cost label (low/medium/high).
EstimatedCost string
// Summary is a human-readable description of the simulated plan.
Summary string
}
DryRunResult holds the simulated execution plan summary.
func BuildDryRunSummary ¶
func BuildDryRunSummary(toolsUsed []string, iterationCount int) DryRunResult
BuildDryRunSummary creates a human-readable dry run report.
type DryRunToolWrapper ¶
DryRunToolWrapper wraps a tool.Tool so that Call() records the invocation without executing any real side effects. It returns a mock response.
func NewDryRunToolWrapper ¶
func NewDryRunToolWrapper(t tool.Tool) *DryRunToolWrapper
NewDryRunToolWrapper creates a wrapper that intercepts calls for simulation.
func (*DryRunToolWrapper) Call ¶
Call records the tool invocation and returns a mock success response without executing the underlying tool.
func (*DryRunToolWrapper) Invocations ¶
func (d *DryRunToolWrapper) Invocations() []string
Invocations returns a copy of the tool names that were "called" during simulation.
func (*DryRunToolWrapper) StreamableCall ¶
func (d *DryRunToolWrapper) StreamableCall(ctx context.Context, jsonArgs []byte) (*tool.StreamReader, error)
StreamableCall records the tool invocation and returns nil (no stream in dry run).
type ExpertReflector ¶
type ExpertReflector struct {
// contains filtered or unexported fields
}
ExpertReflector uses a lightweight LLM call to produce reflections. It uses the front-desk/efficiency model to keep costs low.
func NewExpertReflector ¶
func NewExpertReflector(exp expert.Expert) *ExpertReflector
NewExpertReflector creates a reflector that uses the given expert for reflection prompts. The expert should be configured with a cheap/fast model (e.g. TaskEfficiency).
func (*ExpertReflector) Reflect ¶
func (r *ExpertReflector) Reflect(ctx context.Context, req ReflectionRequest) (ReflectionResult, error)
Reflect generates an internal monologue evaluating whether the proposed action is aligned with the goal. This is the "R" in the RAR loop.
type NoOpReflector ¶
type NoOpReflector struct{}
NoOpReflector is a no-op implementation that always proceeds. Used when action reflection is disabled.
func (*NoOpReflector) Reflect ¶
func (n *NoOpReflector) Reflect(_ context.Context, _ ReflectionRequest) (ReflectionResult, error)
Reflect always returns a proceed result with no monologue.
type NodeResult ¶
type NodeResult struct {
Status NodeStatus
Output string
Err error
}
NodeResult carries the outcome of a node's execution, including any output text produced and any error encountered.
type NodeStatus ¶
type NodeStatus int
NodeStatus represents the outcome of a node execution in the ReAcTree. This enum follows the standard Behavior Tree convention: Running, Success, or Failure.
const ( // Running indicates the node is still executing and needs more ticks. Running NodeStatus = iota // Success indicates the node completed its goal successfully. Success // Failure indicates the node failed to complete its goal. Failure )
func (NodeStatus) String ¶
func (s NodeStatus) String() string
String returns a human-readable representation of the NodeStatus.
type OrchestratorConfig ¶
type OrchestratorConfig struct {
// Expert provides the LLM policy p_LLM(·) used by each agent node
// to sample actions. All nodes in the plan share this expert.
// Thread safety: Expert.Do() creates independent runners per call,
// so concurrent use from parallel nodes is safe.
Expert expert.Expert
// WorkingMemory is the shared blackboard (Section 4.2) that stores
// environment-specific observations across all agent nodes in the tree.
// Enables steps to share results without re-exploration.
WorkingMemory *memory.WorkingMemory
// Episodic is the experience store (Section 4.2) that records
// subgoal-level trajectories. Successful step results are stored
// as episodes for future in-context retrieval.
Episodic memory.EpisodicMemory
// MaxDecisions caps the number of LLM calls per agent node (D_max
// in Algorithm 1, line 11). Prevents runaway iteration.
MaxDecisions int
ToolRegistry *tools.Registry
// ToolWrapSvc wraps plan step tools with HITL approval, audit logging,
// and caching — same as single sub-agent tools. Without this, plan step
// agents would bypass human approval for write tools.
ToolWrapSvc *toolwrap.Service
// WrapRequest carries per-request fields (ThreadID, RunID)
// needed for HITL wrapping to propagate approval events to the UI.
WrapRequest toolwrap.WrapRequest
// Timeout is the wall-clock deadline for the entire plan execution.
// Prevents stuck plan steps from hanging the parent agent indefinitely.
// Defaults to 3 minutes if zero.
Timeout time.Duration
// Toggles holds opt-in configurations for predictability.
Toggles Toggles
// ModelProvider resolves models for lightweight plan-step agents.
// When set (along with ToolRegistry), plan-step agents use a minimal
// sub-agent instruction instead of the full Expert persona.
ModelProvider modelprovider.ModelProvider
}
OrchestratorConfig holds the dependencies for executing a Plan. This is the Go implementation of the inputs to Algorithm 2 (ExecCtrlFlowNode).
Reference: ReAcTree (arXiv:2511.02424), Section 4.1, Algorithm 2
type OrchestratorResult ¶
type OrchestratorResult struct {
Status NodeStatus
Outputs map[string]string // step name → output
}
OrchestratorResult captures the outcome of a planned execution. Status maps to the success/failure return of Algorithm 2. Outputs maps each step name to its text result.
func ExecutePlan ¶
func ExecutePlan(ctx context.Context, plan Plan, cfg OrchestratorConfig) (OrchestratorResult, error)
ExecutePlan runs a Plan by building a graph with the appropriate control flow and agent nodes. This is the Go implementation of Algorithm 2 (ExecCtrlFlowNode).
For "sequence" flow: steps run in order, sharing state. Each step's output becomes the previous stage output for the next step.
For "parallel" flow: steps run concurrently via graph.AddJoinEdge. Results are aggregated by majority vote.
For "fallback" flow: steps are tried in order. First success returns.
type Plan ¶
type Plan struct {
// Flow corresponds to f^n in the paper — the control flow type that
// governs how child agent nodes are coordinated.
//
// Paper (Section 4.1, "Control Flow Nodes"):
// sequence (→) — returns success only if ALL children succeed
// fallback (?) — returns success on the FIRST child success
// parallel (⇒) — aggregates outcomes via majority voting
Flow ControlFlowType `json:"flow"`
// Steps correspond to the subgoals [g_1^n, ..., g_K^n] in the paper.
// Each step becomes an independent agent node n_i with its own goal,
// tool set, and local context.
Steps []PlanStep `json:"steps"`
}
Plan represents a decomposed task with subgoals and a control flow strategy.
This implements the paper's "Expand" action (Algorithm 1, lines 20-28):
a_t^n = (f^n, [g_1^n, ..., g_K^n])
where f^n is the control flow type (Flow) and each g_i^n is a natural language subgoal (Steps). A control flow node n_f with type f^n is attached as a child of the expanding agent node, and agent nodes n_i with subgoals g_i^n are added as children of n_f.
Reference: ReAcTree (arXiv:2511.02424), Section 4.1, "Agent Nodes > Expanding"
type PlanStep ¶
type PlanStep struct {
// Name uniquely identifies this step (used as graph node ID).
Name string `json:"name"`
// Goal is g_i^n — the natural language subgoal for this agent node.
// The paper emphasizes that isolating subgoals reduces hallucination
// and logical errors by keeping each agent focused on its local context.
Goal string `json:"goal"`
// Tools define the executable skill set A_t^n available to this node.
// send_message is always stripped (framework invariant).
Tools []string `json:"tools,omitempty"`
// TaskType selects the LLM model for this step.
TaskType modelprovider.TaskType `json:"task_type,omitempty"`
}
PlanStep is a single subgoal in a Plan, corresponding to one agent node n_i in the paper's tree. Each agent node operates as an LLM-based task planner with its own subgoal g_i^n, context c_t^n, and action space A_t^n.
Reference: ReAcTree (arXiv:2511.02424), Section 4.1, "Agent Nodes"
type ReflectionRequest ¶
type ReflectionRequest struct {
// Goal is the current task goal.
Goal string
// ProposedOutput is the output the agent is about to produce.
ProposedOutput string
// ToolCallsMade lists the tool names that were invoked in this turn.
ToolCallsMade []string
// IterationCount is the current iteration number.
IterationCount int
}
ReflectionRequest contains the inputs for a reflection step.
type ReflectionResult ¶
type ReflectionResult struct {
// Monologue is the internal justification produced by the reflector.
Monologue string
// ShouldProceed indicates whether the action should continue.
ShouldProceed bool
}
ReflectionResult captures the outcome of a reflection step.
type StageConfig ¶
type StageConfig struct {
// Name is the display name shown in the TUI progress bar (e.g., "Understanding").
Name string
// Instruction is appended to the goal for this stage (optional).
// Example: "Read relevant files and gather context before acting."
Instruction string
// TaskType selects the LLM model for this stage via ModelProvider.GetModel().
// If empty, the expert's default (TaskPlanning) is used.
// Example: modelprovider.TaskToolCalling for execution-heavy stages.
TaskType modelprovider.TaskType
}
StageConfig defines a named stage in a multi-stage ReAcTree. Each stage becomes an agent node in a sequence graph. The stage instruction is appended to the goal to guide the LLM's focus for that stage.
type Toggles ¶
type Toggles struct {
EnableCriticMiddleware bool `mapstructure:"enable_critic_middleware"`
EnableActionReflection bool `mapstructure:"enable_action_reflection"`
EnableDryRunSimulation bool `mapstructure:"enable_dry_run_simulation"`
EnableMCPServerAccess bool `mapstructure:"enable_mcp_server_access"`
EnableAuditDashboard bool `mapstructure:"enable_audit_dashboard"`
// Reflector is the ActionReflector used for RAR loops.
// Only used when EnableActionReflection is true.
Reflector ActionReflector `json:"-"`
// Hooks are lifecycle callbacks invoked at well-defined points during
// tree execution. Multiple hooks can be composed via hooks.NewChainHook.
// Hooks replace the previous AuditEmitter field — the AuditHook
// implementation provides the same audit-logging behavior.
Hooks hooks.ExecutionHook `json:"-"`
}
Toggles configures optional predictability and bounding mechanisms. All fields default to zero values (disabled). Callers opt in by setting booleans and injecting the corresponding dependency.
type TreeConfig ¶
type TreeConfig struct {
// MaxDepth limits how deep the tree can grow through recursive expansion.
MaxDepth int
// MaxDecisionsPerNode limits how many LLM calls a single agent node can make.
MaxDecisionsPerNode int
// MaxTotalNodes limits the total number of nodes in the tree.
MaxTotalNodes int
// Stages defines the named stages for multi-stage execution.
// If empty, a single root node is built (backward compatible).
// If set, a sequence graph is built with one agent node per stage.
// Deprecated: prefer MaxIterations for adaptive loop execution.
Stages []StageConfig
// MaxIterations sets the maximum number of adaptive-loop iterations.
// When > 0 (and Stages is empty), the executor runs a single agent node
// in a loop that accumulates context and terminates when the LLM produces
// zero tool calls or the iteration cap is reached. This replaces the fixed
// stage pipeline with dynamic, task-driven expansion.
MaxIterations int
// ToolBudgets limits how many times specific tools can be called across
// all iterations of the adaptive loop. When a tool's budget is exhausted,
// it is removed from the tool list so the LLM is forced to proceed
// without it. Example: {"ask_clarifying_question": 1} ensures the agent
// asks at most one clarifying question before using defaults.
ToolBudgets map[string]int
// Toggles holds opt-in configurations for predictability, bounding,
// and enterprise readiness.
Toggles Toggles
// Checkpointer is used to save and restore execution state.
Checkpointer graph.CheckpointSaver `json:"-"`
}
TreeConfig holds configuration for a ReAcTree execution run. These limits prevent runaway tree growth and unbounded LLM calls.
func DefaultTreeConfig ¶
func DefaultTreeConfig() TreeConfig
DefaultTreeConfig returns sensible defaults for tree execution.
type TreeExecutor ¶
type TreeExecutor interface {
// Run executes a ReAcTree for the given goal and returns the result.
Run(ctx context.Context, req TreeRequest) (TreeResult, error)
}
TreeExecutor orchestrates a full ReAcTree run from a top-level goal. It builds a graph.StateGraph, compiles it, creates a graph.Executor, and runs it — delegating all orchestration to trpc-agent-go's graph package.
func NewTreeExecutor ¶
func NewTreeExecutor( exp expert.Expert, workingMem *memory.WorkingMemory, episodic memory.EpisodicMemory, config TreeConfig, ) TreeExecutor
NewTreeExecutor creates a TreeExecutor configured with the given expert and options. The expert is used as the LLM backend for all agent nodes in the tree.
type TreeRequest ¶
type TreeRequest struct {
Goal string
Tools []tool.Tool
TaskType modelprovider.TaskType
// Attachments are file/media attachments from the incoming message.
// Image attachments are passed as multimodal content to the LLM.
Attachments []messenger.Attachment
// WorkingMemory overrides the tree-level working memory for this request.
// When set, enables per-sender memory isolation. If nil, falls back to
// the tree's shared working memory.
WorkingMemory *memory.WorkingMemory
// EpisodicMemory overrides the tree-level episodic memory for this request.
// When set, enables per-sender episode isolation. If nil, falls back to
// the tree's shared episodic memory.
EpisodicMemory memory.EpisodicMemory
}
TreeRequest contains all inputs for a single tree execution.
type TreeResult ¶
type TreeResult struct {
Status NodeStatus
Output string
NodeCount int
}
TreeResult captures the outcome of a complete ReAcTree execution run.
type ValidatingToolWrapper ¶
ValidatingToolWrapper wraps a tool.Tool with an ActionValidator.
func (*ValidatingToolWrapper) Call ¶
Call wraps the tool Call method by running the validator first.
func (*ValidatingToolWrapper) StreamableCall ¶
func (v *ValidatingToolWrapper) StreamableCall(ctx context.Context, jsonArgs []byte) (*tool.StreamReader, error)
StreamableCall wraps the tool StreamableCall method by running the validator first.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
memoryfakes
Code generated by counterfeiter.
|
Code generated by counterfeiter. |
|
Code generated by counterfeiter.
|
Code generated by counterfeiter. |