planner

package
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Jul 30, 2026 License: Apache-2.0 Imports: 13 Imported by: 0

Documentation

Overview

Package planner implements the v0.1 scaffold of the supervisor-body planner from docs/orchestration-design.md ("The planner", shape C with light D flavor): a Task-mode LlmAgent whose tool vocabulary is the workload's execution vocabulary. Each planner turn is one tool call; the "graph" is emergent from the sequence of decisions and is recorded to the event log turn by turn; finish_task (auto-installed by ADK for Task mode) is the canonical exit.

v0.1 scaffold scope (orchestration-design phasing, "v0.1" row — "Planner scaffolded — schema for tool vocabulary in place, but run_shape_* tools may not all be implemented yet"):

  • invoke_specialist(name, input) is implemented and dispatches to the bundle's built specialist roster (see dispatch.go for the mechanism and the ADK constraints that shaped it).
  • run_shape_llm_router and run_shape_fan_out_fan_in are declared (their schema is part of the pinned vocabulary contract) but return a structured not_implemented result; the Phase-2 "reference-graph library" item wires them.
  • request_operator_input(message, schema) pauses the planner on a durable long-running-tool interrupt (see dispatch.go for what ADK v2.1.0 does and does not allow from a tool context).

Budget: the planner introduces no budget machinery of its own. Its model calls stream past the runner event consumer like any other agent's, so the workload meter (pkg/budget, wired in cmd/mast) bounds the planner exactly as it bounds specialists. See the "sub-invocation metering" note in dispatch.go for the one known gap.

Index

Constants

View Source
const (
	ToolInvokeSpecialist     = "invoke_specialist"
	ToolRunShapeLLMRouter    = "run_shape_llm_router"
	ToolRunShapeFanOutFanIn  = "run_shape_fan_out_fan_in"
	ToolRequestOperatorInput = "request_operator_input"
)

Tool names of the v0.1 planner vocabulary. Exported so callers and tests can pin the contract without string literals. finish_task is not listed: ADK auto-installs it for Task mode.

View Source
const DefaultInstructionTemplate = `` /* 1624-byte string literal not displayed */

DefaultInstructionTemplate is the planner's default system prompt (docs/orchestration-design.md "The planner": supervisor-body turn loop, plan-first gate as a first-turn prose plan, finish_task exit). Rendered with the roster; Config.Instruction overrides it wholesale.

Variables

View Source
var ErrNotImplemented = fmt.Errorf("planner: tool not implemented in v0.1 scaffold")

ErrNotImplemented mirrors the NotImplemented tool result for Go callers probing the vocabulary programmatically.

Functions

func New

func New(cfg Config) (adkagent.Agent, error)

New constructs the planner as a Task-mode LlmAgent via pkg/agent.NewTaskAgent, with the v0.1 tool vocabulary attached.

The returned agent CANNOT be a runner root directly: ADK v2.1.0's runner requires an LlmAgent root to be Chat-mode (runner.go, "root agent ... must be a chat LlmAgent"). Use NewRoot for the runnable wrapper.

func NewRoot

func NewRoot(cfg Config) (adkagent.Agent, error)

NewRoot constructs the planner and wraps it as a runnable root agent: a single-node workflow (DynamicNode -> RunNode -> AgentNode) around the Task-mode planner, because ADK's runner rejects non-Chat LlmAgent roots. The wrapper:

  • forwards every planner event to the runner's event stream (so the workload meter and event log see planner turns), and
  • propagates a request_operator_input pause as a durable workflow interrupt (WithRaiseOnWait -> ErrNodeInterrupted -> node parks).

The body passes nil node input on every activation: the planner reads the work item from session history (the runner appends the inject turn before dispatch), which keeps fresh runs and post-interrupt resume re-runs identical — on resume the planner simply continues from history, where the operator's FunctionResponse now answers the pending call.

func NotImplemented

func NotImplemented(toolName string) map[string]any

NotImplemented is the structured result every scaffolded-but-unwired vocabulary tool returns in v0.1. It is a tool RESULT rather than a Go error so the planner LLM receives a deterministic, parseable response (a Go error would surface as {"error": ...} and invite retries); ErrNotImplemented is the programmatic counterpart for mast-side callers.

Types

type Config

type Config struct {
	// Name is the workload name; the planner agent is named
	// "<Name>_planner". Required.
	Name string

	// Description is a human-readable summary, surfaced in operator
	// UIs and logs.
	Description string

	// Model is the LLM driving the planner's turn loop. Required.
	Model model.LLM

	// Instruction overrides the default planner instruction template.
	// Empty renders DefaultInstructionTemplate against the roster —
	// the planner-specific frame from orchestration-design's planner
	// section (resolved open question #7: single template with
	// variables; per-workload override as the escape hatch). The
	// generic pkg/agent DefaultTaskInstruction never applies here: a
	// planner is never a generic task agent, so the template embeds
	// the unattended-task discipline itself.
	Instruction string

	// Specialists is the bundle's built roster, indexed by specialist
	// name — the invoke_specialist targets.
	Specialists map[string]adkagent.Agent

	// Order optionally fixes the roster ordering used in the rendered
	// instruction and tool description (bundle declaration order).
	// Names absent from Specialists are ignored; specialists absent
	// from Order are appended in map-iteration-stable sorted order.
	Order []string
}

Config describes how to construct a planner for one workload bundle.

Jump to

Keyboard shortcuts

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