Add goal model tools (3 / 5) (#18075)

Adds the model-facing goal tools on top of the app-server API from PR 2.

## Why

Once goals are persisted and exposed to clients, the model needs a
small, constrained tool surface for goal workflows. The tool contract
should let the model inspect goals, create them only when explicitly
requested, and mark them complete without giving it broad control over
user/runtime-owned state.

## What changed

- Added `get_goal`, `create_goal`, and `update_goal` tool specs behind
the `goals` feature flag.
- Added core goal tool handlers that validate objectives and token
budgets before mutating persisted state.
- Constrained `create_goal` to create only when no goal exists, with
optional `token_budget` only when a budget is explicitly provided.
- Tightened the `create_goal` instructions so the model does not infer
goals from ordinary task requests.
- Constrained `update_goal` to expose only goal completion; pause,
resume, clear, and budget-limited transitions remain user- or
runtime-controlled.
- Registered the goal tools in the tool registry and kept them out of
review contexts where they should not appear.

## Verification

- Added tool-registry coverage for feature gating and tool availability.
- Added core session tests for create/get/update behavior, duplicate
goal rejection, budget validation, and completion-only updates.
This commit is contained in:
Eric Traut authored and GitHub committed 2026-04-24 20:54:40 -07:00
1 parent 6c874f9b34
commit 32ace07ac5
14 files changed
+975

No files matched your search

+8
View File
@@ -101,6 +101,7 @@ pub struct ToolsConfig {
pub code_mode_only_enabled: bool,
pub can_request_original_image_detail: bool,
pub collab_tools: bool,
pub goal_tools: bool,
pub multi_agent_v2: bool,
pub hide_spawn_agent_metadata: bool,
pub spawn_agent_usage_hint: bool,
@@ -140,6 +141,7 @@ impl ToolsConfig {
let include_code_mode = features.enabled(Feature::CodeMode);
let include_code_mode_only = include_code_mode && features.enabled(Feature::CodeModeOnly);
let include_collab_tools = features.enabled(Feature::Collab);
let include_goal_tools = features.enabled(Feature::Goals);
let include_multi_agent_v2 = features.enabled(Feature::MultiAgentV2);
let include_agent_jobs = features.enabled(Feature::SpawnCsv);
let include_default_mode_request_user_input =
@@ -218,6 +220,7 @@ impl ToolsConfig {
code_mode_only_enabled: include_code_mode_only,
can_request_original_image_detail: include_original_image_detail,
collab_tools: include_collab_tools,
goal_tools: include_goal_tools,
multi_agent_v2: include_multi_agent_v2,
hide_spawn_agent_metadata: false,
spawn_agent_usage_hint: true,
@@ -254,6 +257,11 @@ impl ToolsConfig {
self
}
pub fn with_goal_tools_allowed(mut self, allowed: bool) -> Self {
self.goal_tools = self.goal_tools && allowed;
self
}
pub fn with_max_concurrent_threads_per_session(
mut self,
max_concurrent_threads_per_session: Option<usize>,