子 Agent 委派工具构建器(对标 beamai_agent_delegate)
提供三类入口:
delegate-tool:spawn→await→drop,同步拿结果。fanout-tool:tasks 列表,并发启动多个子 agent,汇总。management-tools:spawn/list/result/kill/restart,供 LLM 跨轮自管。每个函数返回内联工具 map(含 :handler),可直接放入 :tools 列表。
三类入口的 config 都认一个可选的 :observer——协议无关的观察挂点,
原样透进 manager/spawn! 的 spec(契约见 manager 的 ns docstring)。
AG-UI 那侧用它把委派期间的 token / 工具调用归属到一条 lane
(docs/subagent-event-attribution-design.md);不传就是今天的行为,逐字不变。
使用示例: (def research-tool (delegate-tool {:name "deep_research" :subagent-fn (fn [_ _] {:provider p :model "gpt-4o"}) :timeout 120000})) (create-agent {:tools [#'my-tool research-tool] ...})
子 Agent 委派工具构建器(对标 beamai_agent_delegate)
提供三类入口:
1. **同步单委派** `delegate-tool`:spawn→await→drop,同步拿结果。
2. **同步并发 fan-out** `fanout-tool`:tasks 列表,并发启动多个子 agent,汇总。
3. **异步管理工具集** `management-tools`:spawn/list/result/kill/restart,供 LLM 跨轮自管。
每个函数返回**内联工具 map**(含 :handler),可直接放入 :tools 列表。
三类入口的 config 都认一个可选的 `:observer`——**协议无关的观察挂点**,
原样透进 `manager/spawn!` 的 spec(契约见 `manager` 的 ns docstring)。
AG-UI 那侧用它把委派期间的 token / 工具调用归属到一条 lane
(docs/subagent-event-attribution-design.md);不传就是今天的行为,逐字不变。
使用示例:
(def research-tool
(delegate-tool {:name "deep_research"
:subagent-fn (fn [_ _] {:provider p :model "gpt-4o"})
:timeout 120000}))
(create-agent {:tools [#'my-tool research-tool] ...})子 Agent 管理器 — 受管异步注册表(对标 beamai_subagent_manager)
维护一个全局 atom 注册表,每个子 agent 在虚拟线程上运行 (j.u.c.Future 语义,kill! 走 future-cancel 中断)。
状态机::running → :done | :failed | :killed
使用模式:
同步委派(spawn→await→drop): (let [{:ok id} (spawn! spec)] (await! id 60000) (drop! id))
异步管理(LLM 跨轮自管): (let [{:ok id} (spawn! spec)] ;; 稍后查询 (result id) ;; 或 kill (kill! id))
spec 格式: {:subagent-config map — 传给 client/create-agent 的配置 :prompt string — 子 agent 的用户输入 :result-fn fn? — (fn [chat-result] -> string),默认取 :text :owner any? — 归属标识,用于 list-agents 过滤 :observer fn? — 观察者工厂,见下 :subagent-name string — 给观察者看的标签(缺省 "subagent") :task string — 同上,缺省取 :prompt :parent-tool-call-id string — 同上,发起本次委派的 tool-call id}
观察者(:observer)——协议无关的观察挂点
(fn [{:keys [id name task owner attempt parent-tool-call-id]}] -> {:decorate :chat-opts :start! :settle!})
| 键 | 类型 | 说明 |
|---|---|---|
:decorate | (fn [agent] agent') | 给子 agent 挂采集(如事件发射)。抛异常 → 用原 agent |
:chat-opts | map | 并进子 agent 的 chat opts(如 :on-token) |
:start! | (fn []) | 建 agent 之前 |
:settle! | (fn [outcome]) | 在 finally 里,故 kill / 超时 / 崩溃三条路径都覆盖得到 |
三条契约:
restart! 算新的一次,
:attempt 递增)——fan-out N 路 = N 个观察者实例,各自独立;agui.subagent)负责把这四个钩子
翻译成事件——client 模块不依赖 agui,反向依赖也不存在。子 Agent 管理器 — 受管异步注册表(对标 beamai_subagent_manager)
维护一个全局 atom 注册表,每个子 agent 在虚拟线程上运行
(j.u.c.Future 语义,kill! 走 future-cancel 中断)。
状态机::running → :done | :failed | :killed
使用模式:
1. 同步委派(spawn→await→drop):
(let [{:ok id} (spawn! spec)]
(await! id 60000)
(drop! id))
2. 异步管理(LLM 跨轮自管):
(let [{:ok id} (spawn! spec)]
;; 稍后查询
(result id)
;; 或 kill
(kill! id))
spec 格式:
{:subagent-config map — 传给 client/create-agent 的配置
:prompt string — 子 agent 的用户输入
:result-fn fn? — (fn [chat-result] -> string),默认取 :text
:owner any? — 归属标识,用于 list-agents 过滤
:observer fn? — 观察者工厂,见下
:subagent-name string — 给观察者看的标签(缺省 "subagent")
:task string — 同上,缺省取 :prompt
:parent-tool-call-id string — 同上,发起本次委派的 tool-call id}
**观察者(`:observer`)——协议无关的观察挂点**
`(fn [{:keys [id name task owner attempt parent-tool-call-id]}]
-> {:decorate :chat-opts :start! :settle!})`
| 键 | 类型 | 说明 |
|---|---|---|
| `:decorate` | `(fn [agent] agent')` | 给子 agent 挂采集(如事件发射)。抛异常 → 用原 agent |
| `:chat-opts` | map | 并进子 agent 的 `chat` opts(如 `:on-token`) |
| `:start!` | `(fn [])` | 建 agent 之前 |
| `:settle!` | `(fn [outcome])` | **在 `finally` 里**,故 kill / 超时 / 崩溃三条路径都覆盖得到 |
三条契约:
1. **工厂在 worker 线程上调用,每次 spawn 一次**(`restart!` 算新的一次,
`:attempt` 递增)——fan-out N 路 = N 个观察者实例,各自独立;
2. **四个钩子全可选、各自吞异常**:观察者永远不许改变被观察者的行为;
3. 本 ns **不认识任何协议**。AG-UI 那侧(`agui.subagent`)负责把这四个钩子
翻译成事件——client 模块不依赖 agui,反向依赖也不存在。子代理异步工具组(designs/runtime-borrow.md §14;借 Keelson Subagent/SubagentTools.cs)。
delegate/management-tools 有 spawn/list/result/kill/restart,但缺三样:
wait(阻塞等一组子 agent,带超时——不然模型只能空转轮询 subagent_result)、
send(给已完成的子 agent 续一句话,带着它自己的历史接着干)、上限
(同时运行的数量、嵌套深度——不然一个模型能把 fan-out 套成指数)。
五个内联工具:spawn_agent / send_agent / wait_agent / list_agents /
interrupt_agent,基于 subagent/manager。
:tool-context 种子 :subagent/depth 显式传递(设计原则 §3:
跨 ChatClient 边界只走显式通道);子代理异步工具组(designs/runtime-borrow.md §14;借 Keelson `Subagent/SubagentTools.cs`)。 `delegate/management-tools` 有 spawn/list/result/kill/restart,但缺三样: **wait**(阻塞等一组子 agent,带超时——不然模型只能空转轮询 `subagent_result`)、 **send**(给已完成的子 agent 续一句话,带着它自己的历史接着干)、**上限** (同时运行的数量、嵌套深度——不然一个模型能把 fan-out 套成指数)。 五个内联工具:`spawn_agent` / `send_agent` / `wait_agent` / `list_agents` / `interrupt_agent`,基于 `subagent/manager`。 - 深度经子 agent 的 `:tool-context` 种子 `:subagent/depth` **显式**传递(设计原则 §3: 跨 ChatClient 边界只走显式通道); - send = 同一 conversation-id + 同一 memory store 再起一次运行,历史自然续上; - 对模型暴露的 id 稳定不变(send 之后内部 spawn id 换了,表里记着映射)。
cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |