Goal API¶
The goal loop keeps the agent working toward a completion condition across turns,
judged by a small, fast model. See Goal loop for the
overview and the CLI /goal command.
GoalEvaluator¶
pydantic_deep.goal.GoalEvaluator
dataclass
¶
Judges whether a goal condition is met using a small, fast model.
The evaluator does not call tools; it reasons only over the transcript built
by :func:build_goal_transcript, matching Claude Code's behaviour where the
condition must be demonstrable from what the agent has already surfaced.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
model
|
Model | str
|
pydantic-ai model string or :class: |
DEFAULT_GOAL_MODEL
|
max_context_messages
|
int
|
Recent-message budget for the transcript. |
12
|
max_chars_per_part
|
int
|
Per-part truncation budget for the transcript. |
600
|
evaluate(condition, messages)
async
¶
Evaluate condition against the conversation messages.
The model is constrained to a :class:Verdict via output_type (no
reply-text parsing). On any failure the evaluation defaults to not met
(with an error reason) so a transient evaluator hiccup keeps the agent
working rather than declaring premature success.
GoalState¶
pydantic_deep.goal.GoalState
dataclass
¶
Mutable, session-scoped state for one active goal.
The host owns the wall-clock timer (started_monotonic) and increments
turns / token counters as it drives the loop. max_turns is a hard
safety cap so a poorly-specified condition can never loop forever.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
condition
|
str
|
The completion condition the agent works toward. |
required |
turns
|
int
|
Number of evaluation turns spent so far. |
0
|
achieved
|
bool
|
Set once the evaluator confirms the condition is met. |
False
|
last_reason
|
str
|
The evaluator's most recent reason. |
''
|
max_turns
|
int
|
Hard cap on evaluation turns before the loop stops itself. |
100
|
started_monotonic
|
float | None
|
|
None
|
input_tokens
|
int
|
Cumulative evaluator prompt tokens. |
0
|
output_tokens
|
int
|
Cumulative evaluator completion tokens. |
0
|
GoalEvaluation¶
pydantic_deep.goal.GoalEvaluation
dataclass
¶
Result of a single goal evaluation.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
met
|
bool
|
Whether the evaluator judged the condition satisfied. |
required |
reason
|
str
|
One-sentence explanation, surfaced to the user and fed back to
the agent as guidance for the next turn when |
required |
impossible
|
bool
|
Whether the evaluator judged the condition genuinely
unachievable this session (self-contradictory, needs an unavailable
resource, or the agent exhausted reasonable approaches). Always
implies |
False
|
input_tokens
|
int
|
Prompt tokens spent by the evaluator (0 if unknown). |
0
|
output_tokens
|
int
|
Completion tokens spent by the evaluator (0 if unknown). |
0
|
parse_goal_command¶
pydantic_deep.goal.parse_goal_command(arg)
¶
Interpret the argument to a /goal command.
Returns a (action, condition) pair:
- empty argument →
("status", "") - a clear alias (see :data:
GOAL_CLEAR_ALIASES) →("clear", "") - anything else →
("set", <condition truncated to the char cap>)
build_goal_transcript¶
pydantic_deep.goal.build_goal_transcript(messages, max_recent=12, max_chars=600)
¶
Render a compact transcript for the evaluator to judge against.
Unlike the periodic-reminder transcript, this keeps the content the evaluator needs — assistant text and tool results (truncated) — because the verdict depends on evidence the agent surfaced (test output, build status, file state). The original request is always included as anchoring context.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
messages
|
list[ModelMessage]
|
Full conversation history. |
required |
max_recent
|
int
|
How many of the most recent messages to render in detail. |
12
|
max_chars
|
int
|
Per-part truncation budget. |
600
|
goal_continue_directive¶
pydantic_deep.goal.goal_continue_directive(condition, reason)
¶
Build the synthetic prompt that drives the next goal turn.
format_goal_status¶
pydantic_deep.goal.format_goal_status(state, elapsed_seconds=None)
¶
Render a human-readable status block for /goal with no argument.