-
Notifications
You must be signed in to change notification settings - Fork 5.1k
Added: Ability to hide subagents from primary agents system prompt. #4773
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 21 commits
765812c
9de0068
b582b53
515e859
3c7b3e5
eab8fc8
0d2a06c
1bbb7d0
29cdde3
a7924bd
1e5c116
d51e467
aaea27e
f3b40d7
a52acd1
58f8dce
cbf549f
f353f08
c42bd93
3d290b8
50fd411
7bf9f16
3120e07
b761290
16aec20
74175bd
3cba3a9
bc82564
e004cdc
fe55ee1
cc79bd7
270ff9c
fbcb276
cac9b3a
5023b0c
fb5cc53
7ae8567
42d66de
59c67a1
45b4078
51c0d37
3eb358f
54614c0
f9da342
2798b2f
da0e1dd
6176b51
c831237
932b457
1063b13
e354ac9
dff1c6d
966171c
7a46f44
2c670a6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -9,6 +9,14 @@ import { Agent } from "../agent/agent" | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { SessionPrompt } from "../session/prompt" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { iife } from "@/util/iife" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { defer } from "@/util/defer" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { Wildcard } from "@/util/wildcard" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { Permission } from "../permission" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| export { DESCRIPTION as TASK_DESCRIPTION } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| export function filterSubagents(agents: Agent.Info[], permissions: Record<string, Config.Permission>) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return agents.filter((a) => Wildcard.all(a.name, permissions) !== "deny") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { Config } from "../config/config" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| export const TaskTool = Tool.define("task", async () => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -30,6 +38,31 @@ export const TaskTool = Tool.define("task", async () => { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| async execute(params, ctx) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const agent = await Agent.get(params.subagent_type) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (!agent) throw new Error(`Unknown agent type: ${params.subagent_type} is not a valid agent type`) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const calling = await Agent.get(ctx.agent) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (calling) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const userInvokedAgents = (ctx.extra?.userInvokedAgents ?? []) as string[] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Skip permission check if user explicitly invoked this agent via @ autocomplete | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (!userInvokedAgents.includes(params.subagent_type)) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const perm = Wildcard.all(params.subagent_type, calling.permission.task ?? {}) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (perm === "deny") { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| throw new Error(`Agent '${params.subagent_type}' is not available to ${ctx.agent}`) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (perm === "ask") { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| await Permission.ask({ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| type: "task", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| title: `Invoke subagent: ${params.subagent_type}`, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pattern: params.subagent_type, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| callID: ctx.callID, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| sessionID: ctx.sessionID, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| messageID: ctx.messageID, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| metadata: { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| subagent: params.subagent_type, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| description: params.description, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | |
| const calling = await Agent.get(ctx.agent) | |
| if (!calling) { | |
| // continue with existing flow | |
| } | |
| const userInvokedAgents = (ctx.extra?.userInvokedAgents ?? []) as string[] | |
| // Skip permission check if user explicitly invoked this agent via @ autocomplete | |
| if (userInvokedAgents.includes(params.subagent_type)) { | |
| // User explicitly invoked, skip permission check | |
| } | |
| const perm = Wildcard.all(params.subagent_type, calling.permission.task ?? {}) | |
| if (perm === "deny") { | |
| throw new Error(`Agent '${params.subagent_type}' is not available to ${ctx.agent}`) | |
| } | |
| if (perm === "ask") { | |
| await Permission.ask({ | |
| type: "task", | |
| title: `Invoke subagent: ${params.subagent_type}`, | |
| pattern: params.subagent_type, | |
| callID: ctx.callID, | |
| sessionID: ctx.sessionID, | |
| messageID: ctx.messageID, | |
| metadata: { | |
| subagent: params.subagent_type, | |
| description: params.description, | |
| }, | |
| }) | |
| } |
Alternatively, the entire permission check block could be extracted into a separate function to reduce complexity. This is just a suggestion - the current code works correctly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
btw don't apply these diffs, typically the agent sucks at diffs but has decent feedback, ill tweak prompt for diffs
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor style suggestion: The style guide prefers avoiding
letstatements. This could be refactored using a conditional expression or IIFE pattern, similar to the existingmergedBashhandling above. However, since this follows the exact same pattern as the existing code, keeping it consistent is also valid. Just a thought for potential cleanup - feel free to ignore if you prefer keeping it consistent with the existingmergedBashpattern.