agentloop

package
v0.1.20 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: 15 Imported by: 0

Documentation

Overview

Package agentloop runs a single autonomous agent mission to completion: one model, a jailed toolset, a quality gate that must pass before the run can succeed, budgets that bound it, and a structured result that reports what happened. It is the building block for headless agent pipelines (eval_loop, archie workflows); orchestration across missions lives with the caller.

Index

Constants

View Source
const (
	StopFinished        = "finished"
	StopBudgetExhausted = "budget_exhausted"
	StopTimedOut        = "timed_out"
	StopLoopBreak       = "loop_break"
	StopGateParked      = "gate_parked"
	StopGateFailedFinal = "gate_failed_final"
	StopModelBlocked    = "model_blocked"
	StopIdle            = "idle"
	// StopEndedWithoutFinish: the model stopped producing tool calls
	// after making changes but never called finish — the mission state
	// is unknown, so the run parks for review.
	StopEndedWithoutFinish = "ended_without_finish"
)

Stop reasons reported in Result.StopReason.

View Source
const DefaultSystemTemplate = `` /* 808-byte string literal not displayed */

DefaultSystemTemplate is used when Config.SystemTmpl is empty. Callers with an opinionated role prompt (eval_loop's quality pass, archie's planner/builder) supply their own template.

Variables

This section is empty.

Functions

func TokenBudgetIs

func TokenBudgetIs(maxTokens int) core.StopCondition

TokenBudgetIs returns a stop condition that halts once cumulative token usage across steps reaches maxTokens. Zero or negative disables it. Like all stop conditions it is evaluated between steps, so a run can overshoot by at most one model call.

Types

type Budget

type Budget struct {
	MaxSteps  int
	MaxTokens int
	WallClock time.Duration
}

Budget bounds a run. Zero values disable the corresponding limit.

type Config

type Config struct {
	// Runtime + ModelRef select the model ("provider/model"). Provider,
	// when non-nil, bypasses the runtime (tests, custom providers) and
	// Model names the model to request from it.
	Runtime  *runtime.Runtime
	ModelRef string
	Provider chat.Provider
	Model    string

	// WorkDir is the directory the toolset is jailed to and gate
	// commands run in.
	WorkDir string

	// SystemTmpl is a text/template rendered with PromptData. Empty
	// selects DefaultSystemTemplate.
	SystemTmpl string
	// Mission is the task statement, injected into the first user message.
	Mission string
	// ExtraRules is free-form guidance appended to the rendered prompt.
	ExtraRules string

	// PreloadFiles are read from WorkDir and included in the initial
	// context (the eval_loop "preload everything" strategy). Missing
	// files are skipped with a log line.
	PreloadFiles []string

	// Notes, when non-nil, is loaded into the initial context and
	// exposed to the model via a write_note tool.
	Notes NotesStore

	// Gate is the quality gate. An empty command list disables gating.
	Gate GateConfig
	// Preflight commands run before the loop; their output is injected
	// as ground truth (toolchain versions, go fix -diff, ...).
	Preflight []GateCommand

	Budget Budget

	// ReadOnly registers only read/grep/find (planner/analysis missions).
	ReadOnly bool
	// ProtectPaths, when non-nil, blocks write/edit on matching paths
	// (relative, as the model supplies them) with an in-band refusal —
	// an environmental constraint where a prompt rule would be advisory
	// (e.g. a TDD fix stage protecting the committed repro tests).
	ProtectPaths func(path string) bool
	// Extra tools are merged into the toolset after the built-ins.
	Extra core.ToolSet

	Logger *slog.Logger
}

Config configures a single run.

type FileNotesStore

type FileNotesStore struct{ Path string }

FileNotesStore is a NotesStore backed by a single file (eval_loop's AGENT_NOTES.md pattern).

func (FileNotesStore) Append

func (f FileNotesStore) Append(_ context.Context, entry string) error

func (FileNotesStore) Load

type GateCommand

type GateCommand struct {
	Name          string
	Argv          []string
	ExpectFailure bool
}

GateCommand is one command in the quality gate, run in the work directory. ExpectFailure inverts success: the command must exit nonzero (a TDD repro stage requires the new tests to FAIL before the fix is written).

type GateConfig

type GateConfig struct {
	Commands []GateCommand
	// MaxConsecutiveFailures parks the run after N failing gate cycles
	// in a row. Zero means the default of 5.
	MaxConsecutiveFailures int
}

GateConfig is the quality gate for a run: the command list that must pass after mutations, and how many consecutive failing cycles are tolerated before the run parks instead of flailing.

type NotesStore

type NotesStore interface {
	Load(ctx context.Context) (string, error)
	Append(ctx context.Context, entry string) error
}

NotesStore is caller-side persistent memory across runs. Entries follow the eval_loop convention: every note must cite how it was verified (verified_by), and stores live outside the work tree so they neither pollute diffs nor vanish with the worktree.

type PromptData

type PromptData struct {
	WorkDir      string
	GateCommands []string // human-readable command lines, in gate order
	ExtraRules   string
	ReadOnly     bool
}

PromptData is what SystemTmpl is rendered with.

type Result

type Result struct {
	Status     Status   `json:"status"`
	StopReason string   `json:"stop_reason"`
	Changes    []string `json:"changes,omitempty"` // files written/edited, in first-touch order
	Iterations int      `json:"iterations"`
	TokensUsed int      `json:"tokens_used"`
	Summary    string   `json:"summary,omitempty"` // from the finish tool
	Detail     string   `json:"detail,omitempty"`  // last gate failure / park explanation
}

Result is the structured outcome of a run. It is the caller's PR body, state-machine transition, and notes write-back in one place.

func Run

func Run(ctx context.Context, cfg Config) (Result, error)

Run executes the mission to completion and reports what happened. The returned error is reserved for infrastructure failures (provider resolution, provider errors); mission-level failures are expressed in Result.Status.

type Status

type Status string

Status is the overall outcome of a run.

const (
	// StatusPassed means the mission finished and the gate passed.
	StatusPassed Status = "passed"
	// StatusParked means the run stopped without a clean finish: gate
	// failures hit the cap, a budget ran out, the loop breaker fired, or
	// the model reported itself blocked. Parked runs carry the reason.
	StatusParked Status = "parked"
	// StatusIdle means the model ended the conversation without calling
	// finish and without changing anything.
	StatusIdle Status = "idle"
)

Jump to

Keyboard shortcuts

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