Documentation
¶
Overview ¶
Package todo contributes a live run plan: a checklist the model writes for itself and that the loop pins into every request.
The plan is deliberately NOT part of the transcript. It lives in a Store the tool writes and a context hook reads, so compaction can never trim it — even after the original task and all early turns are summarized away, the freshly rendered checklist is right there in front of the model. That is the whole point of the capability: it is what keeps a long autonomous run on its original objective.
Tools and request hooks share a run-bound store. Native checkpoints preserve its bounded plan state; forks get a fresh store so child plans cannot replace the parent's checklist.
Index ¶
Constants ¶
const ( StatusPending = "pending" StatusInProgress = "in_progress" StatusCompleted = "completed" StatusBlocked = "blocked" StatusAbandoned = "abandoned" )
Todo status values. A well-formed plan has at most one in_progress item — the single thing the agent is doing right now — mirroring a focused worklist.
const ContextPrefix = "[run plan]"
ContextPrefix marks the injected plan reminder so it is recognizable in a transcript and never confused with model-authored content.
const PatchToolName = "patch_plan"
PatchToolName updates stable item IDs without replacing unrelated phases.
const ToolName = "update_plan"
ToolName is the stable name the model calls, and the name a policy must permit.
Variables ¶
This section is empty.
Functions ¶
func NewTool ¶
NewTool returns the built-in update_plan tool bound to a run's plan store. The model calls it to record and revise its checklist for a multi-step task; the stored plan is then pinned into every later native request by PiContextHook.
func PiContextHook ¶
func PiContextHook(store *Store) agentcore.PiContextHook
PiContextHook pins the bounded plan into Pi's outgoing native view. Raw provider messages pass through untouched, and the reminder never becomes another persisted conversation message on each turn.
Types ¶
type Item ¶
type Item struct {
ID string `json:"id,omitempty"`
Phase string `json:"phase,omitempty"`
Content string `json:"content"`
Status string `json:"status"`
}
Item is one step in the run's plan: a short imperative description and its current status.
type Plugin ¶
type Plugin struct {
// Store holds this run's plan. Required — a plan with nowhere to live is a
// tool that silently forgets, which is worse for the model than no tool at
// all. One Store per run; sharing one across concurrent runs would let two
// agents overwrite each other's checklist.
Store *Store
// CheckCompletion asks the model to resolve pending/in_progress steps before
// accepting a normal finish. Explicitly blocked or abandoned steps may remain.
CheckCompletion bool
// MaxCompletionNudges optionally bounds repair attempts. Nonpositive means
// unlimited. Exhaustion stops as todo_incomplete, never successful completion.
MaxCompletionNudges int
}
Plugin contributes the run plan: the update_plan tool and the context hook that pins the plan into every request.
type Store ¶
type Store struct {
// contains filtered or unexported fields
}
Store holds a single run's live plan. It is the out-of-band state that makes a long run goal-stable: the plan is owned here, not in the transcript, so compaction can never trim it. The loop re-injects a rendering of it before every native provider request (PiContextHook), so the model always sees its own up-to-date checklist regardless of how much history was summarized away.
A Store is safe for concurrent use; the tool writes it while a context hook reads it.
func (*Store) Render ¶
Render formats the plan as a compact checklist for the model. It returns the empty string when there is no plan yet, so the context hook injects nothing until the agent has actually written one.
func (*Store) Set ¶
Set replaces the whole plan. The model always sends the full list (not a delta), so a replace is the correct semantics and keeps the store trivially consistent. Items are copied so a later caller mutation cannot alias the store.
Set also folds: completed steps beyond the most recent few are dropped from the list and added to a running count. This is what keeps a long run's plan from becoming a transcript. It is done HERE rather than only in Render so that what the model reads and what the store holds are the same thing — a model shown a folded list sends the folded list back, and a store that quietly held more would re-expand the render on the next write.