|
28 | 28 | activity))))) |
29 | 29 |
|
30 | 30 | (defn ^:private all-agents |
31 | | - [config] |
32 | | - (->> (:agent config) |
| 31 | + [config parent-agent-name] |
| 32 | + (->> (config/available-subagents config parent-agent-name) |
33 | 33 | (keep (fn [[agent-name agent-config]] |
34 | | - (when (and (contains? (config/agent-modes agent-config) "subagent") |
35 | | - (:description agent-config)) |
| 34 | + (when (:description agent-config) |
36 | 35 | {:name agent-name |
37 | 36 | :description (:description agent-config) |
38 | 37 | :model (:defaultModel agent-config) |
|
42 | 41 | vec)) |
43 | 42 |
|
44 | 43 | (defn ^:private get-agent |
45 | | - [agent-name config] |
46 | | - (first (filter #(= agent-name (:name %)) (all-agents config)))) |
| 44 | + [agent-name config parent-agent-name] |
| 45 | + (first (filter #(= agent-name (:name %)) (all-agents config parent-agent-name)))) |
47 | 46 |
|
48 | 47 | (defn ^:private max-steps [subagent] |
49 | 48 | (:max-steps subagent)) |
|
125 | 124 | (defn ^:private spawn-agent |
126 | 125 | "Handler for the spawn_agent tool. |
127 | 126 | Spawns a subagent to perform a focused task and returns the result." |
128 | | - [arguments {:keys [db* config messenger metrics chat-id tool-call-id call-state-fn trust]}] |
| 127 | + [arguments {:keys [db* config messenger metrics chat-id tool-call-id call-state-fn trust agent]}] |
129 | 128 | (let [arguments (normalize-arguments arguments) |
130 | 129 | agent-name (get arguments "agent") |
131 | 130 | task (get arguments "task") |
132 | 131 | activity (get arguments "activity") |
| 132 | + parent-agent-name agent |
133 | 133 | db @db* |
134 | 134 |
|
135 | 135 | ;; Check for nesting - prevent subagents from spawning other subagents |
|
138 | 138 | {:agent-name agent-name |
139 | 139 | :parent-chat-id chat-id}))) |
140 | 140 |
|
141 | | - subagent (get-agent agent-name config) |
| 141 | + subagent (get-agent agent-name config parent-agent-name) |
142 | 142 | _ (when-not subagent |
143 | | - (let [available (all-agents config)] |
144 | | - (throw (ex-info (format "Agent '%s' not found. Available agents: %s" |
145 | | - agent-name |
| 143 | + (let [available (all-agents config parent-agent-name)] |
| 144 | + (throw (ex-info (format "Agent not found or not available. Available agents: %s" |
146 | 145 | (if (seq available) |
147 | 146 | (str/join ", " (map :name available)) |
148 | 147 | "none")) |
|
269 | 268 |
|
270 | 269 | (defn ^:private build-description |
271 | 270 | "Build tool description with available agents and models listed." |
272 | | - [config] |
| 271 | + [config parent-agent-name] |
273 | 272 | (let [base-description (tools.util/read-tool-description "spawn_agent") |
274 | | - agents (all-agents config) |
| 273 | + agents (all-agents config parent-agent-name) |
275 | 274 | agents-section (str "\n\nAvailable agents:\n" |
276 | 275 | (->> agents |
277 | 276 | (map (fn [{:keys [name description]}] |
|
280 | 279 | (str base-description agents-section))) |
281 | 280 |
|
282 | 281 | (defn definitions |
283 | | - [config _db] |
284 | | - {"spawn_agent" |
285 | | - {:description (build-description config) |
286 | | - :parameters {:type "object" |
287 | | - :properties {"agent" {:type "string" |
288 | | - :description "Name of the agent to spawn"} |
289 | | - "task" {:type "string" |
290 | | - :description "The detailed instructions for the agent"} |
291 | | - "activity" {:type "string" |
292 | | - :description "Concise label (max 3-4 words) shown in the UI while the agent runs, e.g. \"exploring codebase\", \"reviewing changes\", \"analyzing tests\"."} |
293 | | - "model" {:type "string" |
294 | | - :description "Optional sub-agent model override. Reserved for explicit user override only. Omit unless the user explicitly named a model."} |
295 | | - "variant" {:type "string" |
296 | | - :description "Optional sub-agent model variant override. Reserved for explicit user override only. Omit unless the user explicitly named a variant."}} |
297 | | - :required ["agent" "task"]} |
298 | | - :handler #'spawn-agent |
299 | | - :summary-fn (fn [{:keys [args]}] |
300 | | - (if-let [agent-name (get args "agent")] |
301 | | - (if-let [activity (get (normalize-arguments args) "activity")] |
302 | | - (format "%s: %s" agent-name activity) |
303 | | - agent-name) |
304 | | - "Spawning agent"))}}) |
| 282 | + ([config db] |
| 283 | + (definitions config db nil)) |
| 284 | + ([config _db parent-agent-name] |
| 285 | + {"spawn_agent" |
| 286 | + {:description (build-description config parent-agent-name) |
| 287 | + :parameters {:type "object" |
| 288 | + :properties {"agent" {:type "string" |
| 289 | + :description "Name of the agent to spawn"} |
| 290 | + "task" {:type "string" |
| 291 | + :description "The detailed instructions for the agent"} |
| 292 | + "activity" {:type "string" |
| 293 | + :description "Concise label (max 3-4 words) shown in the UI while the agent runs, e.g. \"exploring codebase\", \"reviewing changes\", \"analyzing tests\"."} |
| 294 | + "model" {:type "string" |
| 295 | + :description "Optional sub-agent model override. Reserved for explicit user override only. Omit unless the user explicitly named a model."} |
| 296 | + "variant" {:type "string" |
| 297 | + :description "Optional sub-agent model variant override. Reserved for explicit user override only. Omit unless the user explicitly named a variant."}} |
| 298 | + :required ["agent" "task"]} |
| 299 | + :handler #'spawn-agent |
| 300 | + :summary-fn (fn [{:keys [args]}] |
| 301 | + (if-let [agent-name (get args "agent")] |
| 302 | + (if-let [activity (get (normalize-arguments args) "activity")] |
| 303 | + (format "%s: %s" agent-name activity) |
| 304 | + agent-name) |
| 305 | + "Spawning agent"))}})) |
305 | 306 |
|
306 | 307 | (defmethod tools.util/tool-call-details-before-invocation :spawn_agent |
307 | 308 | [_name arguments _server {:keys [db config chat-id tool-call-id]}] |
308 | 309 | (let [agent-name (get arguments "agent") |
309 | 310 | user-model (get arguments "model") |
310 | 311 | user-variant (get arguments "variant") |
| 312 | + parent-agent-name (get-in db [:chats chat-id :agent]) |
311 | 313 | subagent (when agent-name |
312 | | - (get-agent agent-name config)) |
| 314 | + (get-agent agent-name config parent-agent-name)) |
313 | 315 | parent-model (get-in db [:chats chat-id :model]) |
314 | 316 | subagent-model (or user-model (:model subagent) parent-model) |
315 | 317 | subagent-chat-id (when tool-call-id |
|
0 commit comments