Align goal extension behavior with core

This commit is contained in:
Eric Traut
2026-06-04 23:10:37 -07:00
parent 6a6a5f925e
commit 919dbbefd1
3 changed files with 19 additions and 19 deletions

View File

@@ -1,8 +1,4 @@
//! Extension crate sketch for the `/goal` feature.
//!
//! This crate is intentionally not wired into the host yet. It contains the
//! goal tool specs, extension registration shape, and the parts of runtime
//! accounting that can be represented with today's extension API.
//! Extension crate for the `/goal` feature.
mod accounting;
mod api;

View File

@@ -281,6 +281,15 @@ impl GoalRuntimeHandle {
return Ok(());
}
let Some(thread_manager) = self.inner.thread_manager.upgrade() else {
tracing::debug!("skipping goal continuation because thread manager is unavailable");
return Ok(());
};
let Ok(thread) = thread_manager.get_thread(self.inner.thread_id).await else {
tracing::debug!("skipping goal continuation because live thread is unavailable");
return Ok(());
};
let Some(goal) = self
.inner
.state_dbs
@@ -296,16 +305,7 @@ impl GoalRuntimeHandle {
self.inner.accounting_state.clear_active_goal();
return Ok(());
}
let item = continuation_steering_item(&protocol_goal_from_state(goal));
let Some(thread_manager) = self.inner.thread_manager.upgrade() else {
tracing::debug!("skipping goal continuation because thread manager is unavailable");
return Ok(());
};
let Ok(thread) = thread_manager.get_thread(self.inner.thread_id).await else {
tracing::debug!("skipping goal continuation because live thread is unavailable");
return Ok(());
};
if let Err(err) = thread.try_start_turn_if_idle(vec![item]).await {
let reason = err.reason();

View File

@@ -34,7 +34,8 @@ pub fn create_create_goal_tool() -> ToolSpec {
(
"token_budget".to_string(),
JsonSchema::integer(Some(
"Optional positive token budget for the new active goal.".to_string(),
"Positive token budget for the new goal. Omit unless explicitly requested."
.to_string(),
)),
),
]);
@@ -62,7 +63,7 @@ pub fn create_update_goal_tool() -> ToolSpec {
JsonSchema::string_enum(
vec![json!("complete"), json!("blocked")],
Some(
"Required. Set to complete only when the objective is achieved and no required work remains. Set to blocked only when the goal cannot currently proceed without a user decision, missing dependency, or external unblock."
"Required. Set to `complete` only when the objective is achieved and no required work remains. Set to `blocked` only after the same blocking condition has recurred for at least three consecutive goal turns and the agent is at an impasse. After a previously blocked goal is resumed, the resumed run starts a fresh blocked audit."
.to_string(),
),
),
@@ -71,11 +72,14 @@ pub fn create_update_goal_tool() -> ToolSpec {
ToolSpec::Function(ResponsesApiTool {
name: UPDATE_GOAL_TOOL_NAME.to_string(),
description: r#"Update the existing goal.
Use this tool only to mark the goal achieved or blocked.
Use this tool only to mark the goal achieved or genuinely blocked.
Set status to `complete` only when the objective has actually been achieved and no required work remains.
Set status to `blocked` only when the goal cannot currently proceed until something external changes.
Set status to `blocked` only when the same blocking condition has repeated for at least three consecutive goal turns, counting the original/user-triggered turn and any automatic continuations, and the agent cannot make meaningful progress without user input or an external-state change.
If the user resumes a goal that was previously marked `blocked`, treat the resumed run as a fresh blocked audit. If the same blocking condition then repeats for at least three consecutive resumed goal turns, set status to `blocked` again.
Once the blocked threshold is satisfied, do not keep reporting that you are still blocked while leaving the goal active; set status to `blocked`.
Do not use `blocked` merely because the work is hard, slow, uncertain, incomplete, or would benefit from clarification.
Do not mark a goal complete merely because its budget is nearly exhausted or because you are stopping work.
You cannot use this tool to pause, resume, or budget-limit a goal; those status changes are controlled by the user or system.
You cannot use this tool to pause, resume, budget-limit, or usage-limit a goal; those status changes are controlled by the user or system.
When marking a budgeted goal achieved with status `complete`, report the final token usage from the tool result to the user."#
.to_string(),
strict: false,