compose

package
v0.1.1 Latest Latest
Warning

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

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

Documentation

Overview

Package compose wires a workload bundle plus its specialist specs into a runnable root agent. It is the shared core behind the two entry points that construct dispatch shapes: cmd/mast (flag-driven) and the top-level mast convenience package (programmatic). Both MUST go through BuildRoot so the dispatch semantics — planner override, graph vs. coordinator, per-mode toolset offering — cannot drift between the binary and the library.

This is runtime glue, not public API (docs/library-api-design.md marks internal/ packages churnable); library consumers reach it via the root mast package or compose the pkg/ subsystems directly.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func BuildClassRoot

func BuildClassRoot(class string, llm model.LLM) (adkagent.Agent, error)

BuildClassRoot constructs the runnable root agent for one public task class — the shape behind cmd/mast's one-shot path (`mast --task=<class> "<prompt>"`). The class → mode mapping is pkg/taskclass's (docs/orchestration-design.md "Public task classes"):

  • chat → a Chat-mode coordinator (pkg/agent.NewCoordinator).
  • debug / implement / research / review → a Task-mode agent, wrapped in a one-node workflow root because ADK v2.1.0's runner only accepts Chat-mode LlmAgent roots directly (same idiom as pkg/planner.NewRoot).
  • orchestrate → the planner-enabled root (pkg/planner.NewRoot) with an empty specialist roster — the planner scaffold runs and reports honestly that no specialists are declared; a roster needs a workload bundle, which is serve-mode territory in v0.1.

Instruction precedence (pkg/taskclass modes.go): the class profile's per-class default is passed explicitly, so it beats the generic per-mode fallback; classes without per-class text (chat) fall through to pkg/agent's mode default via the constructor's own empty-Instruction rule.

func BuildModel

func BuildModel(ctx context.Context, provider, name string) (model.LLM, error)

BuildModel constructs the model.LLM for the given provider alias and model name. The provider alias is only consulted where the model id alone is ambiguous (claude-* serves against api.anthropic.com or Vertex); everything else dispatches on the name.

  • "echo": fake in-process echo model (no credentials required).
  • "scripted": JSONL recorded-turn replay via pkg/providers/mock; the recording path comes from MAST_SCRIPT, and MAST_SCRIPT_STRICT=1 enables strict Contents matching.
  • "gemini-*": ADK's Gemini model wrapped in pkg/providers/gemini's builtin-tool layer (GoogleSearch + URLContext on — core-agent's defaults; Vertex vs API key is genai's env-driven selection).
  • "claude-*": pkg/providers/anthropic; see anthropicProvider for backend selection.

func BuildRoot

func BuildRoot(cfg RootConfig) (adkagent.Agent, error)

BuildRoot builds the roster and assembles the dispatch shape:

  • bundle.Planner.Enabled → the supervisor-body planner root (pkg/planner); Dispatch is ignored.
  • DispatchGraph → the workflow graph (pkg/graph); errors without a SingleTurn classifier.
  • DispatchCoordinator → the SubAgents coordinator (pkg/router).
  • DispatchAuto/empty → graph when the roster has both a SingleTurn classifier and a graph.FallbackName specialist, else coordinator.

func RatePer1K

func RatePer1K(modelName string) float64

RatePer1K derives pkg/budget's flat USD-per-1K-total-tokens rate for a model name (budget.Limits.RatePer1K — API unchanged).

Gemini and Claude rates come from pkg/pricing's builtin catalog (longest-prefix lookup, so dated/suffixed IDs land). The catalog prices input and output tokens separately, but the budget meter only sees UsageMetadata.TotalTokenCount, so the flat rate is the plain average of the two per-MTok rates scaled to per-1K — a deliberate v0.1 approximation that overcharges input-heavy sessions and undercharges output-heavy ones rather than complicating the budget API. Gemini IDs the catalog doesn't know keep the old flat spike rate so cost metering never silently drops to zero.

The echo fake keeps its inflated rate: offline smoke tests (scripts/demo-spike2.sh scenario 3) trip small caps with it. The scripted replay shares it — both are offline test doubles.

Types

type Dispatch

type Dispatch string

Dispatch selects the root shape BuildRoot assembles.

const (
	// DispatchCoordinator is the spike-1 SubAgents pattern: a
	// Chat-mode coordinator with the roster as SubAgents (pkg/router).
	DispatchCoordinator Dispatch = "coordinator"

	// DispatchGraph is the spike-2 workflow-graph LLM-as-router shape
	// (pkg/graph). Requires a SingleTurn classifier in the roster.
	DispatchGraph Dispatch = "graph"

	// DispatchAuto picks the shape from the roster: graph when a
	// SingleTurn classifier and a graph.FallbackName Task specialist
	// are both present (the pair graph dispatch needs), coordinator
	// otherwise. This is the library default — programmatic callers
	// declare a roster, not a flag.
	DispatchAuto Dispatch = "auto"
)

type RootConfig

type RootConfig struct {
	// Bundle is the workload definition (naming, roster order,
	// planner/HITL policy).
	Bundle workload.Bundle

	// Specs is the loaded specialist roster. Specs with an empty Mode
	// build as Task-mode (the same default pkg/specialists applies).
	Specs []specialists.Spec

	// Model drives every built specialist (specs with a model override
	// already bound it upstream — the spike binds one model per
	// process).
	Model model.LLM

	// Toolsets are offered to Task-mode specialists (and filtered
	// through each spec's allowlist by specialists.Build). SingleTurn
	// classifiers never receive toolsets — they run one shot with no
	// tool loop.
	Toolsets []tool.Toolset

	// Dispatch selects the root shape. Empty means DispatchAuto.
	Dispatch Dispatch

	// Logger, when non-nil, receives the same construction-time notes
	// cmd/mast has always logged (e.g. planner overriding dispatch).
	Logger *slog.Logger
}

RootConfig carries everything BuildRoot needs to turn a loaded bundle + specs into a root agent. Bundle and Specs use the existing pkg/workload and pkg/specialists vocabulary — file-loaded and programmatic values are indistinguishable here by design (docs/library-api-design.md, "Embeddable config vs. file-loaded config").

Jump to

Keyboard shortcuts

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