Goal Extension
The Goal extension adds a session-scoped objective contract to an LLMAgent.
It is useful when a user wants the agent to keep working until a larger
objective is either complete or blocked.
This is an Agent extension, not a Runner mode:
- install it with
llmagent.WithExtensions(goal.New()); - the model gets
get_goal,create_goal, andupdate_goal; - goal state is stored in session state;
- streaming progress output can still be emitted, while premature final model responses are blocked inside the same model loop;
- the outer
Runner.Runstill ends with onerunner.completion.
Usage
Applications may provide their own command layer. For example, a CLI can parse
/goal <objective> and create the session goal before calling Runner.Run:
The framework does not parse slash commands.
Semantics
When a goal is active, a final model response is not enough. The model must
either continue working or call update_goal with:
complete: the objective has actually been achieved;blocked: the same blocking condition has repeated across goal attempts, and the agent cannot make meaningful progress without user input or an external state change.
If the model repeatedly emits premature final responses, the extension retries
up to WithMaxRetries. After the retry budget is exhausted, the response passes
through unchanged so the run cannot loop forever.
WithMaxRetries only bounds the premature-final-response -> reminder ->
continuation cycle. Applications can also configure WithMaxLLMCalls and
WithMaxToolIterations on the same LLMAgent to impose hard limits on model
calls and tool-call iterations in that agent's invocation. When Goal is installed
on the Runner's primary LLMAgent, this usually bounds one Runner.Run.
Reaching either limit stops the run, but does not automatically mark the session
goal complete or blocked; a later invocation receives a new budget. These
limits are therefore invocation-level circuit breakers, not goal terminal-state
decisions.
Goal does not change streaming configuration. Streaming remains controlled by
the LLMAgent generation config or run options such as agent.WithStream(...).
Callers may see intermediate assistant output before the agent continues; that
output does not mean the goal has completed. The run is still terminal only when
runner.completion is emitted.
Goal tools need serial semantics. Do not enable llmagent.WithEnableParallelTools(true)
on the same LLMAgent that owns the Goal extension. A model response should not
call create_goal and update_goal in the same parallel tool batch, because
parallel execution uses isolated invocation/session views for each tool call.
If an application needs parallel business tools, keep Goal on a serial owner
agent or use a separate agent for the parallel work.
Boundaries
- The extension is installed on one
LLMAgent; sub-agents do not inherit it. - Multiple agents can share the same session goal by using the same state key, but the usual recommendation is to install it on the agent that owns the completion decision.
token_budgetis not part of this extension. Budgeting is a separate runtime policy.- Concurrency control is still the caller's responsibility. If the same session
is run concurrently, session state writes follow the behavior of the selected
session.Service.
See examples/goal for a runnable example.