feat: support auto continuation in subagents and prevent them from calling todo__pause
This commit is contained in:
8 files changed
+305
-3
No files matched your search
@@ -648,6 +648,11 @@ impl Agent {
|
||||
enabled_tools: None,
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub fn functions_mut(&mut self) -> &mut Functions {
|
||||
&mut self.functions
|
||||
}
|
||||
}
|
||||
|
||||
impl RoleLike for Agent {
|
||||
|
||||
@@ -74,6 +74,7 @@ pub async fn macro_execute(
|
||||
macro_ctx.current_depth = ctx.current_depth;
|
||||
macro_ctx.auto_continue_count = ctx.auto_continue_count;
|
||||
macro_ctx.todo_list = ctx.todo_list.clone();
|
||||
macro_ctx.auto_continue_paused = ctx.auto_continue_paused.clone();
|
||||
macro_ctx.tool_scope.tool_tracker = ctx.tool_scope.tool_tracker.clone();
|
||||
macro_ctx.discontinuous_last_message();
|
||||
|
||||
|
||||
@@ -63,11 +63,14 @@ pub(in crate::config) const DEFAULT_TODO_INSTRUCTIONS: &str = indoc! {"
|
||||
- `todo__done`: Mark a task done by id. Call this immediately after completing each step.
|
||||
- `todo__list`: Show the current todo list.
|
||||
- `todo__clear`: Clear the entire todo list and reset the goal. Use when the user cancels or changes direction.
|
||||
- `todo__pause`: Pause auto-continue and yield the turn to the user, keeping incomplete todos intact. Use when you are blocked on user input or a user-side action. Auto-continue resumes on the user's next message.
|
||||
|
||||
RULES:
|
||||
- Always create a todo list before starting work.
|
||||
- Mark each task done as soon as you finish it; do not batch.
|
||||
- If the user cancels the current task or changes direction, call `todo__clear` immediately.
|
||||
- If you need user input (or the user must do something on their end) before you can continue, call `todo__pause` with the reason, ask the user, and end your turn. NEVER mark unfinished todos done just to stop the auto-continue prompts.
|
||||
- `todo__pause` is for top-level sessions only. Subagents are driven to completion autonomously and cannot pause. If you are a subagent and need input, use a `user__*` tool (it escalates to the root agent mid-turn and blocks until answered, so you keep working without ending your turn).
|
||||
- If you stop with incomplete tasks, the system will automatically prompt you to continue."
|
||||
};
|
||||
|
||||
|
||||
@@ -336,6 +336,7 @@ pub struct RequestContext {
|
||||
pub todo_list: TodoList,
|
||||
pub skill_registry: SkillRegistry,
|
||||
pub last_continuation_response: Option<String>,
|
||||
pub auto_continue_paused: Option<String>,
|
||||
pub pending_prefill: Option<String>,
|
||||
|
||||
pub session_abort: Option<AbortSignal>,
|
||||
@@ -376,6 +377,7 @@ impl RequestContext {
|
||||
todo_list: TodoList::default(),
|
||||
skill_registry: SkillRegistry::default(),
|
||||
last_continuation_response: None,
|
||||
auto_continue_paused: None,
|
||||
pending_prefill: None,
|
||||
session_abort: None,
|
||||
render_mode: RenderMode::default(),
|
||||
@@ -441,6 +443,7 @@ impl RequestContext {
|
||||
todo_list: TodoList::default(),
|
||||
skill_registry: SkillRegistry::default(),
|
||||
last_continuation_response: None,
|
||||
auto_continue_paused: None,
|
||||
pending_prefill: None,
|
||||
session_abort: None,
|
||||
render_mode: RenderMode::default(),
|
||||
@@ -495,6 +498,7 @@ impl RequestContext {
|
||||
todo_list: self.todo_list.clone(),
|
||||
skill_registry: self.skill_registry.clone(),
|
||||
last_continuation_response: None,
|
||||
auto_continue_paused: self.auto_continue_paused.clone(),
|
||||
pending_prefill: None,
|
||||
session_abort: self.session_abort.clone(),
|
||||
render_mode: self.render_mode,
|
||||
@@ -545,6 +549,7 @@ impl RequestContext {
|
||||
todo_list: TodoList::default(),
|
||||
skill_registry: SkillRegistry::default(),
|
||||
last_continuation_response: None,
|
||||
auto_continue_paused: None,
|
||||
pending_prefill: None,
|
||||
session_abort: None,
|
||||
render_mode: parent.render_mode,
|
||||
@@ -582,6 +587,7 @@ impl RequestContext {
|
||||
|
||||
pub fn init_todo_list(&mut self, goal: &str) {
|
||||
self.todo_list = TodoList::new(goal);
|
||||
self.auto_continue_paused = None;
|
||||
}
|
||||
|
||||
pub fn add_todo(&mut self, task: &str) -> usize {
|
||||
@@ -595,12 +601,21 @@ impl RequestContext {
|
||||
pub fn clear_todo_list(&mut self) {
|
||||
self.todo_list.clear();
|
||||
self.auto_continue_count = 0;
|
||||
self.auto_continue_paused = None;
|
||||
}
|
||||
|
||||
pub fn increment_auto_continue_count(&mut self) {
|
||||
self.auto_continue_count += 1;
|
||||
}
|
||||
|
||||
pub fn pause_auto_continue(&mut self, reason: &str) {
|
||||
self.auto_continue_paused = Some(reason.to_string());
|
||||
}
|
||||
|
||||
pub fn resume_auto_continue(&mut self) {
|
||||
self.auto_continue_paused = None;
|
||||
}
|
||||
|
||||
pub fn reset_continuation_count(&mut self) {
|
||||
self.auto_continue_count = 0;
|
||||
self.last_continuation_response = None;
|
||||
@@ -4676,6 +4691,7 @@ impl RequestContext {
|
||||
self.current_depth = 0;
|
||||
self.auto_continue_count = 0;
|
||||
self.todo_list = TodoList::default();
|
||||
self.auto_continue_paused = None;
|
||||
|
||||
if let Some(session_name) = session_name.as_deref() {
|
||||
self.use_session(app, Some(session_name), abort_signal)
|
||||
@@ -4719,6 +4735,7 @@ impl RequestContext {
|
||||
self.auto_continue_count = 0;
|
||||
self.pending_tasks_guardrail_count = 0;
|
||||
self.todo_list = TodoList::default();
|
||||
self.auto_continue_paused = None;
|
||||
self.rag.take();
|
||||
// Cleared alongside `rag` so the pair never disagrees: an agent RAG is
|
||||
// cached under `RagKey::Agent(<agent name>)`, and leaving that key behind
|
||||
|
||||
Reference in new issue
Block a user