子 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,反向依赖也不存在。(await! id timeout-ms)同步等待子 agent 完成(便利方法)。timeout-ms 到则返回 {:error :timeout}(不 kill)。
返回:{:ok result-str} | {:error reason}
同步等待子 agent 完成(便利方法)。timeout-ms 到则返回 {:error :timeout}(不 kill)。
返回:{:ok result-str} | {:error reason}(clear-all!)清空整个注册表(kill 所有 running 的子 agent)。测试/重置用。
清空整个注册表(kill 所有 running 的子 agent)。测试/重置用。
(drop! id)从注册表移除(running 时先 kill)。
⚠️ 挂起的条目不能这么摘——它存着等人答复的那个 agent 实例,摘了就没法
resume 了。委派工具的 finally 因此要先看状态(见 delegate/run-sync)。
从注册表移除(running 时先 kill)。 ⚠️ **挂起的条目不能这么摘**——它存着等人答复的那个 agent 实例,摘了就没法 resume 了。委派工具的 `finally` 因此要先看状态(见 `delegate/run-sync`)。
(kill! id)Kill 指定子 agent(cancel future + deliver error)。
:result 同步写入 {:error :killed}——kill 后 await!/result 返回明确错误而非 nil; 被中断的 worker 随后的 finish! 因状态已终结而 no-op,不会把 :killed 覆盖成 :failed。
Kill 指定子 agent(cancel future + deliver error)。
:result 同步写入 {:error :killed}——kill 后 await!/result 返回明确错误而非 nil;
被中断的 worker 随后的 finish! 因状态已终结而 no-op,不会把 :killed 覆盖成 :failed。(list-agents)(list-agents owner)列出所有(或指定 owner 的)子 agent 信息。
列出所有(或指定 owner 的)子 agent 信息。
(restart! id)用原 spec 重启子 agent(同 id,状态回 :running)。
用原 spec 重启子 agent(同 id,状态回 :running)。
(result id)非阻塞查询结果。running 时返回 {:error :not-ready}。
非阻塞查询结果。running 时返回 {:error :not-ready}。
(resume! id decision payload & [observer])恢复一个挂起的子 agent,返回与 await! 同形的 outcome
({:ok s} / {:error r} / {:suspended …}——可以再次挂起:一轮里连着
两个敏感工具是正常的)。
decision / payload 直通 simple-agent/resume(:approved / :rejected
/ :reply)。恢复的是挂起时那一个 agent 实例(run-result 带出来的),
不是重新 create 一个——后者不认得这次暂停。
observer 可选:resume 发生在新的一条 run 里,事件要发进新那条流,所以
观察者得现给(lane id 仍由 spawn id 决定,故 subagentRunId 跨 resume 不变
——AG-UI 说的「通过相同的 subagentRunId 恢复执行」正是这个意思)。
恢复一个挂起的子 agent,返回与 `await!` 同形的 outcome
(`{:ok s}` / `{:error r}` / `{:suspended …}`——**可以再次挂起**:一轮里连着
两个敏感工具是正常的)。
`decision` / `payload` 直通 `simple-agent/resume`(`:approved` / `:rejected`
/ `:reply`)。恢复的是**挂起时那一个 agent 实例**(`run-result` 带出来的),
不是重新 create 一个——后者不认得这次暂停。
`observer` 可选:resume 发生在**新的一条 run** 里,事件要发进新那条流,所以
观察者得现给(lane id 仍由 spawn id 决定,故 `subagentRunId` 跨 resume 不变
——AG-UI 说的「通过相同的 subagentRunId 恢复执行」正是这个意思)。(spawn! spec)异步启动一个子 agent,立即返回 {:ok id}。
spec 键::subagent-config :prompt :result-fn :owner
异步启动一个子 agent,立即返回 {:ok id}。
spec 键::subagent-config :prompt :result-fn :owner(suspended? id)该子 agent 是否挂起在等人(:paused 的那种,不是失败)。
该子 agent 是否挂起在等人(`:paused` 的那种,不是失败)。
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 |