fix: Forgot to automatically add the bidirectional communication back up to parent agents from sub-agents (i.e. need to be able to check inbox and send messages)
This commit is contained in:
+7
-1
@@ -6,6 +6,9 @@ use crate::{
|
||||
function::{Functions, run_llm_function},
|
||||
};
|
||||
|
||||
use crate::config::prompts::{
|
||||
DEFAULT_SPAWN_INSTRUCTIONS, DEFAULT_TEAMMATE_INSTRUCTIONS, DEFAULT_TODO_INSTRUCTIONS,
|
||||
};
|
||||
use crate::vault::SECRET_RE;
|
||||
use anyhow::{Context, Result};
|
||||
use fancy_regex::Captures;
|
||||
@@ -13,7 +16,6 @@ use inquire::{Text, validator::Validation};
|
||||
use rust_embed::Embed;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::{ffi::OsStr, path::Path};
|
||||
use crate::config::prompts::{DEFAULT_SPAWN_INSTRUCTIONS, DEFAULT_TODO_INSTRUCTIONS};
|
||||
|
||||
const DEFAULT_AGENT_NAME: &str = "rag";
|
||||
|
||||
@@ -200,6 +202,8 @@ impl Agent {
|
||||
functions.append_supervisor_functions();
|
||||
}
|
||||
|
||||
functions.append_teammate_functions();
|
||||
|
||||
agent_config.replace_tools_placeholder(&functions);
|
||||
|
||||
Ok(Self {
|
||||
@@ -340,6 +344,8 @@ impl Agent {
|
||||
output.push_str(DEFAULT_SPAWN_INSTRUCTIONS);
|
||||
}
|
||||
|
||||
output.push_str(DEFAULT_TEAMMATE_INSTRUCTIONS);
|
||||
|
||||
self.interpolate_text(&output)
|
||||
}
|
||||
|
||||
|
||||
+13
-10
@@ -29,8 +29,6 @@ pub(in crate::config) const DEFAULT_SPAWN_INSTRUCTIONS: &str = indoc! {"
|
||||
| `agent__collect` | Blocking wait: wait for an agent to finish, return its output. |
|
||||
| `agent__list` | List all spawned agents and their status. |
|
||||
| `agent__cancel` | Cancel a running agent by ID. |
|
||||
| `agent__send_message` | Send a text message to a sibling or child agent's inbox. |
|
||||
| `agent__check_inbox` | Check your own inbox for messages from other agents. |
|
||||
| `agent__task_create` | Create a task in the dependency-aware task queue. |
|
||||
| `agent__task_list` | List all tasks and their status/dependencies. |
|
||||
| `agent__task_complete` | Mark a task done; returns any newly unblocked tasks. Auto-dispatches agents for tasks with a designated agent. |
|
||||
@@ -69,14 +67,6 @@ pub(in crate::config) const DEFAULT_SPAWN_INSTRUCTIONS: &str = indoc! {"
|
||||
|
||||
**NEVER spawn sequentially when tasks are independent.** Parallel is always better.
|
||||
|
||||
### Teammate Messaging
|
||||
|
||||
Sibling agents (spawned by the same parent) can communicate directly:
|
||||
- `agent__send_message --to <agent_id> --content \"your message\"`: Send to a running sibling
|
||||
- `agent__check_inbox`: Check for messages from siblings or parent
|
||||
|
||||
Use teammate messaging when agents need to coordinate or share intermediate findings.
|
||||
|
||||
### Task Queue (for complex dependency chains)
|
||||
|
||||
When tasks have ordering requirements, use the task queue:
|
||||
@@ -95,3 +85,16 @@ pub(in crate::config) const DEFAULT_SPAWN_INSTRUCTIONS: &str = indoc! {"
|
||||
agent__task_complete --task_id task_1
|
||||
```
|
||||
"};
|
||||
|
||||
pub(in crate::config) const DEFAULT_TEAMMATE_INSTRUCTIONS: &str = indoc! {"
|
||||
## Teammate Messaging
|
||||
|
||||
You have tools to communicate with other agents running alongside you:
|
||||
- `agent__send_message --id <agent_id> --message \"...\"`: Send a message to a sibling or parent agent.
|
||||
- `agent__check_inbox`: Check for messages sent to you by other agents.
|
||||
|
||||
If you are working alongside other agents (e.g. reviewing different files, exploring different areas):
|
||||
- **Check your inbox** before finalizing your work to incorporate any cross-cutting findings from teammates.
|
||||
- **Send messages** to teammates when you discover something that affects their work.
|
||||
- Messages are delivered to the agent's inbox and read on their next `check_inbox` call."
|
||||
};
|
||||
|
||||
@@ -276,6 +276,11 @@ impl Functions {
|
||||
.extend(supervisor::supervisor_function_declarations());
|
||||
}
|
||||
|
||||
pub fn append_teammate_functions(&mut self) {
|
||||
self.declarations
|
||||
.extend(supervisor::teammate_function_declarations());
|
||||
}
|
||||
|
||||
pub fn clear_mcp_meta_functions(&mut self) {
|
||||
self.declarations.retain(|d| {
|
||||
!d.name.starts_with(MCP_INVOKE_META_FUNCTION_NAME_PREFIX)
|
||||
|
||||
+42
-37
@@ -118,43 +118,6 @@ pub fn supervisor_function_declarations() -> Vec<FunctionDeclaration> {
|
||||
},
|
||||
agent: false,
|
||||
},
|
||||
FunctionDeclaration {
|
||||
name: format!("{SUPERVISOR_FUNCTION_PREFIX}send_message"),
|
||||
description: "Send a text message to a running subagent's inbox.".to_string(),
|
||||
parameters: JsonSchema {
|
||||
type_value: Some("object".to_string()),
|
||||
properties: Some(IndexMap::from([
|
||||
(
|
||||
"id".to_string(),
|
||||
JsonSchema {
|
||||
type_value: Some("string".to_string()),
|
||||
description: Some("The target agent ID".into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"message".to_string(),
|
||||
JsonSchema {
|
||||
type_value: Some("string".to_string()),
|
||||
description: Some("The message text to send".into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
])),
|
||||
required: Some(vec!["id".to_string(), "message".to_string()]),
|
||||
..Default::default()
|
||||
},
|
||||
agent: false,
|
||||
},
|
||||
FunctionDeclaration {
|
||||
name: format!("{SUPERVISOR_FUNCTION_PREFIX}check_inbox"),
|
||||
description: "Check for and drain all pending messages in your inbox.".to_string(),
|
||||
parameters: JsonSchema {
|
||||
type_value: Some("object".to_string()),
|
||||
..Default::default()
|
||||
},
|
||||
agent: false,
|
||||
},
|
||||
FunctionDeclaration {
|
||||
name: format!("{SUPERVISOR_FUNCTION_PREFIX}task_create"),
|
||||
description: "Create a task in the task queue. Returns the task ID.".to_string(),
|
||||
@@ -241,6 +204,48 @@ pub fn supervisor_function_declarations() -> Vec<FunctionDeclaration> {
|
||||
]
|
||||
}
|
||||
|
||||
pub fn teammate_function_declarations() -> Vec<FunctionDeclaration> {
|
||||
vec![
|
||||
FunctionDeclaration {
|
||||
name: format!("{SUPERVISOR_FUNCTION_PREFIX}send_message"),
|
||||
description: "Send a text message to a sibling or child agent's inbox. Use to share cross-cutting findings or coordinate with teammates.".to_string(),
|
||||
parameters: JsonSchema {
|
||||
type_value: Some("object".to_string()),
|
||||
properties: Some(IndexMap::from([
|
||||
(
|
||||
"id".to_string(),
|
||||
JsonSchema {
|
||||
type_value: Some("string".to_string()),
|
||||
description: Some("The target agent ID".into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
(
|
||||
"message".to_string(),
|
||||
JsonSchema {
|
||||
type_value: Some("string".to_string()),
|
||||
description: Some("The message text to send".into()),
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
])),
|
||||
required: Some(vec!["id".to_string(), "message".to_string()]),
|
||||
..Default::default()
|
||||
},
|
||||
agent: false,
|
||||
},
|
||||
FunctionDeclaration {
|
||||
name: format!("{SUPERVISOR_FUNCTION_PREFIX}check_inbox"),
|
||||
description: "Check for and drain all pending messages in your inbox from sibling agents or your parent.".to_string(),
|
||||
parameters: JsonSchema {
|
||||
type_value: Some("object".to_string()),
|
||||
..Default::default()
|
||||
},
|
||||
agent: false,
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
pub async fn handle_supervisor_tool(
|
||||
config: &GlobalConfig,
|
||||
cmd_name: &str,
|
||||
|
||||
Reference in New Issue
Block a user