Skip to main content

Module agent_loop

Module agent_loop 

Source
Expand description

The assistant agent loop: propose → validate → execute → observe.

One multi-turn tool-use conversation, driven by CAR inference and executed through a Runtime (validator + policy + permission tiers + event log) whose tool executor is the GeneralExecutor. The same loop backs the one-shot CLI, the REPL, and — per turn — the agent.chat surface; streaming is decoupled through a synchronous emit sink so a caller can forward events to stdout or to agent.chat.event notifications without the loop knowing.

Structs§

AssistantConfig
Static configuration for a loop run.
AssistantModelAttribution
The terminal result of a loop run.
AssistantOutcome
AssistantToolReceipt
DelegateBudget
How much delegating one run may do, whatever each child’s own cap says. Bounds the model-call amplification a delegating parent can cause: without it a parent at max_turns 50 could issue 50 children of 60 turns each.
DelegateRequest
A parsed delegate call.
GoalLoopResult
The result of a goal-driven assistant run: the last iteration’s AssistantOutcome plus the GoalRun audit (per-iteration verdicts, grounded flag, halt reason).

Enums§

ApprovalDecision
The outcome of an approval request.
AssistantEvent
Streamed events from one loop run. emit is called synchronously as the loop progresses; a chat caller forwards these to agent.chat.event, a CLI caller prints them.
AssistantFailureCause
Map a typed generation failure to the terminal auth_required reason, or None when the turn keeps today’s error.
AuthRequiredReason
Why an out-of-the-box turn could not reach Parslee inference.
ToolApprovalDecision
What the per-agent policy says to do with a tool call before it runs.

Constants§

AUTH_REQUIRED_EXPIRED_MESSAGE
The wire message for auth_required { reason: "expired" } (reserved — see AuthRequiredReason::Expired).
AUTH_REQUIRED_NO_WORKSPACE_MESSAGE
The wire message for auth_required { reason: "no_workspace" }.
AUTH_REQUIRED_SIGNED_OUT_MESSAGE
The wire message for auth_required { reason: "signed_out" }.
DELEGATE_DEFAULT_MAX_TURNS
Child turn budget when the call names none.
DELEGATE_MAX_TURNS_CAP
Hard ceiling on a child’s turn budget, whatever the call asks for.
DELEGATE_TOOL
The loop-intercepted sub-agent tool. Advertised like any other tool (so a caller can allowlist or omit it) but never dispatched to the executor: the loop recognizes the name and runs a child loop in-process — the same shape as run_task’s GUI sub-agent, chosen over a ToolExecutor because an executor is built before the Runtime and AssistantConfig a child needs.
FORMAT_REPAIR_FAILED_PREFIX
Prefix of the notice emitted when the repair call itself failed (for example an Anthropic-protocol model rejecting response_format). The DRAFT answer is returned — a provider that cannot enforce the format is not a reason to throw away the answer the model already gave.
FORMAT_REPAIR_NOTICE
Emitted (as AssistantEvent::Text) when the repair fires, so the run’s event stream records that the final answer was re-asked rather than taken as returned.
FORMAT_REPAIR_STILL_INVALID
Emitted when the single repair also missed. The repaired text is still the answer — the contract is “one repair”, not “retry until valid”.
OBSERVATION_CAP
Upper bound (bytes) on a single tool observation fed back into context, so a large read/output can’t blow the request size. Truncates on a char boundary.
VALUE_STORE_PREVIEWS_DEFAULT
The shipped default for AssistantConfig::value_store_previews — the one place any production call site reads it from, so “what does CAR do out of the box” is a single greppable fact rather than a literal repeated at the four production construction sites (car do twice, the MCP assistant, and coder discussions), which can drift apart. The remaining hard-coded falses in the workspace are deliberate and stay: eight test fixtures in chat.rs, this module’s own off-arm fixture, and HarnessBenchConfig, whose false names the truncating arm of the A/B rather than a product setting.

Traits§

ApprovalGate
The human-in-the-loop seam. Consulted by the loop before running a gated_tools action. Implementations: a terminal stdin prompt (REPL / one-shot) or the chat approval_pending → park → resolve flow. When no gate is wired, a gated action is denied with an actionable message.

Functions§

annotate_summary_with_claim_note
Append a non-authoritative claim-check note to a goal-loop reply.
delegate_child_config
Derive the child’s config from the parent’s. Everything is the parent’s (clone()) except:
delegate_tool_def
Build the delegate tool def over the parent’s advertised tools. The tools parameter is a JSON-Schema enum of the parent’s own tool names — the verifiable subset precondition car-multi’s spawn_subtask uses — so the validator rejects an escalation before the loop’s own check does.
extract_json_payload
Strip a single surrounding /json fence, if present. Returns the trimmed input otherwise.
final_text_matches_format
Does a final answer satisfy the requested car_inference::ResponseFormat?
parse_delegate_params
Parse the call’s arguments. Shape errors are the model’s to fix, so they come back as an error result rather than sinking the run.
resolve_context_window
The effective context window for a run: the caller’s override, clamped to the registry window when that is known and smaller. Returns the window plus an advisory when the clamp fired, so the caller can surface it.
run_assistant_goal_loop
Drive the assistant as a goal loop: keep running iterations (each a full run_assistant_loop_cancellable pass — the model works until it stops emitting tool calls) until a deterministic car_verify::goal::GoalCondition holds or a car_verify::goal::GoalGovernor bound is hit. This is CAR’s answer to /goal: the “am I done?” decision is made by car_verify::goal::evaluate_goal over ground truth gathered from the runtime (gather), never by a model reading its own transcript.
run_assistant_goal_loop_in_session
Session-aware variant of run_assistant_goal_loop.
run_assistant_goal_loop_in_session_durable
run_assistant_loop
Run the assistant loop to a terminal outcome, mutating messages (which must already carry the system + first user turn) and streaming progress via emit. Reusable across one-shot, REPL, and per-chat-turn.
run_assistant_loop_cancellable
Same as run_assistant_loop, but checks cancel before each turn so the agent.chat.cancel path can interrupt a running turn between model calls, and consults approval (if any) before running a gated_tools action.
run_assistant_loop_cancellable_in_session
Session-aware variant of run_assistant_loop_cancellable. A caller that multiplexes conversations passes the Runtime session id so stateful tool guards (notably read-before-edit) stay isolated between conversations.
run_assistant_loop_cancellable_in_session_durable
Durable supervised-session variant. The checkpoint sink is invoked after every mutation of the exact model-facing transcript, including compaction, assistant tool calls, refusals, and tool results.
ungrounded_summary_claims
Operational claims the final prose makes that no same-run tool receipt supports — “I ran the tests” with no matching shell call, “I created X” with no matching write.

Type Aliases§

ApprovalPolicyFn
Resolves a per-agent approval decision for a tool call. Built by the caller (chat.rs) from the loaded AgentPermissionPolicy + the session’s agent id + a risk classifier, so the loop stays decoupled from the policy store.
ResponseFormatValidator
A compiled JSON-Schema check for the final answer — true when the parsed answer conforms. See AssistantConfig::response_format_validator.