feat: Added explicit guardrail handling for pending agents
This commit is contained in:
@@ -93,6 +93,36 @@ pub(in crate::config) const DEFAULT_SPAWN_INSTRUCTIONS: &str = indoc! {"
|
||||
agent__collect --id agent_explore_e5f6g7h8
|
||||
```
|
||||
|
||||
### CRITICAL: Never end your turn with pending agents
|
||||
|
||||
Spawned agents do NOT report back on their own. They run in the background until you
|
||||
actively reclaim them with `agent__collect` (to get their output) or `agent__cancel`
|
||||
(to discard them). If you spawn agents and then emit a final message without reclaiming
|
||||
them, the system will detect the unreclaimed agents and reject the turn-end, injecting
|
||||
a reminder forcing you to handle them. After several such reminders, the system will
|
||||
auto-cancel them and warn you that work was lost.
|
||||
|
||||
The correct flow when you have nothing else to do:
|
||||
|
||||
```
|
||||
# WRONG - do NOT do this:
|
||||
agent__spawn --agent explore --prompt \"...\"
|
||||
agent__spawn --agent explore --prompt \"...\"
|
||||
# ... emit text like \"I will synthesize once they report back.\" and stop
|
||||
# ^ The agents will be abandoned. Their output will be lost.
|
||||
|
||||
# RIGHT - always do this:
|
||||
agent__spawn --agent explore --prompt \"...\"
|
||||
agent__spawn --agent explore --prompt \"...\"
|
||||
agent__collect --id <first_id> # blocks until done
|
||||
agent__collect --id <second_id> # blocks until done
|
||||
# ... NOW you can synthesize and end your turn
|
||||
```
|
||||
|
||||
`agent__collect` is a **blocking wait**: it pauses your execution until the agent
|
||||
completes, then returns the output as a tool result. Use it freely — it is the
|
||||
correct primitive for \"I'm done with my own work and just need the agents' results\".
|
||||
|
||||
### Parallel Spawning (DEFAULT for multi-agent work)
|
||||
|
||||
When a task needs multiple agents, **spawn them all at once**, then collect:
|
||||
|
||||
@@ -120,6 +120,7 @@ pub struct RequestContext {
|
||||
pub escalation_queue: Option<Arc<EscalationQueue>>,
|
||||
pub current_depth: usize,
|
||||
pub auto_continue_count: usize,
|
||||
pub pending_agents_guardrail_count: u32,
|
||||
pub todo_list: TodoList,
|
||||
pub skill_registry: SkillRegistry,
|
||||
pub last_continuation_response: Option<String>,
|
||||
@@ -149,6 +150,7 @@ impl RequestContext {
|
||||
escalation_queue: None,
|
||||
current_depth: 0,
|
||||
auto_continue_count: 0,
|
||||
pending_agents_guardrail_count: 0,
|
||||
todo_list: TodoList::default(),
|
||||
skill_registry: SkillRegistry::default(),
|
||||
last_continuation_response: None,
|
||||
@@ -204,6 +206,7 @@ impl RequestContext {
|
||||
escalation_queue: None,
|
||||
current_depth: 0,
|
||||
auto_continue_count: 0,
|
||||
pending_agents_guardrail_count: 0,
|
||||
todo_list: TodoList::default(),
|
||||
skill_registry: SkillRegistry::default(),
|
||||
last_continuation_response: None,
|
||||
@@ -246,6 +249,7 @@ impl RequestContext {
|
||||
escalation_queue: self.escalation_queue.clone(),
|
||||
current_depth: self.current_depth,
|
||||
auto_continue_count: 0,
|
||||
pending_agents_guardrail_count: 0,
|
||||
todo_list: self.todo_list.clone(),
|
||||
skill_registry: self.skill_registry.clone(),
|
||||
last_continuation_response: None,
|
||||
@@ -286,6 +290,7 @@ impl RequestContext {
|
||||
escalation_queue: parent.escalation_queue.clone(),
|
||||
current_depth,
|
||||
auto_continue_count: 0,
|
||||
pending_agents_guardrail_count: 0,
|
||||
todo_list: TodoList::default(),
|
||||
skill_registry: SkillRegistry::default(),
|
||||
last_continuation_response: None,
|
||||
@@ -2787,7 +2792,7 @@ impl RequestContext {
|
||||
|
||||
if self.agent.take().is_some() {
|
||||
if let Some(supervisor) = self.supervisor.clone() {
|
||||
supervisor.read().cancel_all();
|
||||
supervisor.read().cancel_recursive();
|
||||
}
|
||||
self.supervisor = None;
|
||||
self.parent_supervisor = None;
|
||||
@@ -2796,6 +2801,7 @@ impl RequestContext {
|
||||
self.escalation_queue = None;
|
||||
self.current_depth = 0;
|
||||
self.auto_continue_count = 0;
|
||||
self.pending_agents_guardrail_count = 0;
|
||||
self.todo_list = TodoList::default();
|
||||
self.rag.take();
|
||||
self.discontinuous_last_message();
|
||||
|
||||
Reference in New Issue
Block a user