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 ¶
const ( ToolInvokeSpecialist = "invoke_specialist" ToolRunShapeLLMRouter = "run_shape_llm_router" ToolRunShapeFanOutFanIn = "run_shape_fan_out_fan_in" ToolRequestOperatorInput = "request_operator_input" // ToolPauseSession is the v0.2 plane-A self-pause // (docs/durable-execution-design.md, "The v0.2 pause/abort // mechanics"). Registered only when Config.PauseRecorder is set. ToolPauseSession = "pause_session" )
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.
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 ¶
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 ¶
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 ¶
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 ¶
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
// PauseRecorder mints the durable pause record + resume token for
// pause_session (the v0.2 plane-A self-pause). Nil leaves
// pause_session out of the vocabulary — callers without a durable
// store (one-shot in-memory sessions) get a coherent tool set
// rather than a pause that would die with the process.
PauseRecorder PauseRecorder
}
Config describes how to construct a planner for one workload bundle.
type PauseRecorder ¶ added in v0.2.0
type PauseRecorder interface {
PauseInterrupt(ctx context.Context, userID, sessionID, interruptID string, spec transcript.PauseSpec) (transcript.PauseHandle, error)
}
PauseRecorder mints the durable pause record + resume token for a plane-A interrupt pause. *transcript.Store implements it.