Liking cljdoc? Tell your friends :D

im.ttalk.agent.react

工具调用循环(从 chat-client 下沉而来)

chat-client 只提供原语 invoke-chat / invoke-tool;'驱动 LLM↔工具直到文本或暂停' 这套策略(含 max-iterations / gate 暂停 / resume / 悬空 tool_use 自愈)属编排层, 放在 simpleagent。每轮只向 invoke-chat 传 delta,由 chat-client 的 memory filter 按 conversation-id 拼出完整历史。

store 显式传入(chat-client 不再持有 memory):用于 heal 与临时会话清理; 与 chat-client 上挂载的 memory-filter 必须是同一个 store 实例。

callbacks 独立于 chat-client filter::on-llm-call/:on-llm-result/:on-tool-result 在循环关键节点直接触发,不走 filter 链。gate 评估结果缓存,确保每个工具调用 恰好触发一次观察回调(不重复)。

工具调用循环(从 chat-client 下沉而来)

chat-client 只提供原语 invoke-chat / invoke-tool;'驱动 LLM↔工具直到文本或暂停'
这套策略(含 max-iterations / gate 暂停 / resume / 悬空 tool_use 自愈)属编排层,
放在 simpleagent。每轮只向 invoke-chat 传 delta,由 chat-client 的 memory filter
按 conversation-id 拼出完整历史。

store 显式传入(chat-client 不再持有 memory):用于 heal 与临时会话清理;
与 chat-client 上挂载的 memory-filter 必须是同一个 store 实例。

callbacks 独立于 chat-client filter::on-llm-call/:on-llm-result/:on-tool-result
在循环关键节点直接触发,不走 filter 链。gate 评估结果缓存,确保每个工具调用
恰好触发一次观察回调(不重复)。
raw docstring

check-decisions!clj

(check-decisions! loop-state payload)

校验 resume payload 的逐件决定 :decisions(§15):每条 :reply 都带 :message, 且答全、答对——点名了不在待审批里的 id → ex-info :interrupt-unknown; 有待审批的调用没答 → :interrupt-incomplete。没有 :decisions 时什么都不做。 旧暂停态没有 :pending-ids 时以 [:pending-id] 为准。

公开出来,是为了让调用方(simple-agent 的 resume)在动暂停态之前先校验: 答错是调用方的输入错误,不该把暂停快照(连同整批待审批)清掉。

校验 resume payload 的逐件决定 `:decisions`(§15):每条 :reply 都带 :message,
且**答全、答对**——点名了不在待审批里的 id → ex-info `:interrupt-unknown`;
有待审批的调用没答 → `:interrupt-incomplete`。没有 `:decisions` 时什么都不做。
旧暂停态没有 :pending-ids 时以 [:pending-id] 为准。

公开出来,是为了让调用方(simple-agent 的 resume)在**动暂停态之前**先校验:
答错是调用方的输入错误,不该把暂停快照(连同整批待审批)清掉。
sourceraw docstring

emit-event!clj

(emit-event! callbacks type m)

发一个生命周期事件(designs/runtime-borrow.md §11)。callbacks 里没有 :on-event 就什么都不做;出口抛的异常吞掉(观察者不许打断回合)。 事件带 :type :ts,以及回调元数据里的 :conversation-id / :run-id。

发一个生命周期事件(designs/runtime-borrow.md §11)。`callbacks` 里没有
`:on-event` 就什么都不做;出口抛的异常吞掉(观察者不许打断回合)。
事件带 `:type` `:ts`,以及回调元数据里的 `:conversation-id` / `:run-id`。
sourceraw docstring

execute-batchclj

(execute-batch chat-client tool-calls gate tool-context init-records)
(execute-batch chat-client
               tool-calls
               gate
               tool-context
               init-records
               on-tool-result)

MapReduce 执行一批工具调用(设计见 docs/agent-loop-concurrency-design.md §9)。

缺省串行(无 :tool-manager 时走这里):每个调用按序在调用方线程执行。 并发要求同批工具的副作用彼此无序依赖——那是调用方才知道的性质,框架不替它 假定。要并发就注入 virtual-thread-tool-calling-manager(或 thread-pool 版)。

map:每个调用拿同一份轮初 tool-context 快照(同批工具互相看不到对方的写)。 批内任一工具声明 :serial 时,即使选了并发引擎也整批退化为按序执行。 状态语义与引擎无关:三个引擎都是快照 + 屏障折叠。

reduce:屏障收齐后,各工具的 :writes 按 tool-call 原始序经 chat-client :state-slots 的槽级 reducer 折叠进 context(未声明槽默认 last-writer; 同批多工具写同一未声明槽记 warn)。messages/records 按原始序排回。

gate: (fn [tool-call] -> 决策),nil 视为全 :proceed;批前串行预判 (审批可交互,绝不并发)。决策词汇:

  • :proceed 执行
  • :reject 跳过,结果「已拒绝执行」
  • {:reject 理由} 跳过,结果「已拒绝执行:<理由>」(模型直接拿到原因)
  • {:reply 结果} 不执行,载荷即工具结果(ask-user 语义)

on-tool-result: (fn [tool-name result-str]),每个实际执行的工具恰好触发 一次(:reject / {:reply} 不触发);并行下批内触发顺序不确定。

返回: {:messages [...] :records [...] :context 新ctx :errors [{:id :name :class :message :tc :data?} ...]} :errors 为本批失败调用及其故障类别(重试耗尽后仍失败的才出现在此), 供屏障处策略路由(环境类 → 暂停等人,见 run-tool-loop)。

MapReduce 执行一批工具调用(设计见 docs/agent-loop-concurrency-design.md §9)。

**缺省串行**(无 `:tool-manager` 时走这里):每个调用按序在调用方线程执行。
并发要求同批工具的副作用彼此无序依赖——那是调用方才知道的性质,框架不替它
假定。要并发就注入 `virtual-thread-tool-calling-manager`(或 thread-pool 版)。

map:每个调用拿同一份轮初 tool-context 快照(同批工具互相看不到对方的写)。
批内任一工具声明 :serial 时,即使选了并发引擎也整批退化为按序执行。
**状态语义与引擎无关**:三个引擎都是快照 + 屏障折叠。

reduce:屏障收齐后,各工具的 :writes 按 tool-call 原始序经 chat-client
:state-slots 的槽级 reducer 折叠进 context(未声明槽默认 last-writer;
同批多工具写同一未声明槽记 warn)。messages/records 按原始序排回。

gate: (fn [tool-call] -> 决策),nil 视为全 :proceed;批前串行预判
(审批可交互,绝不并发)。决策词汇:
- :proceed          执行
- :reject           跳过,结果「已拒绝执行」
- {:reject 理由}    跳过,结果「已拒绝执行:<理由>」(模型直接拿到原因)
- {:reply 结果}     不执行,载荷即工具结果(ask-user 语义)

on-tool-result: (fn [tool-name result-str]),每个实际执行的工具恰好触发
一次(:reject / {:reply} 不触发);并行下批内触发顺序不确定。

返回: {:messages [...] :records [...] :context 新ctx
       :errors [{:id :name :class :message :tc :data?} ...]}
:errors 为本批失败调用及其故障类别(重试耗尽后仍失败的才出现在此),
供屏障处策略路由(环境类 → 暂停等人,见 run-tool-loop)。
sourceraw docstring

heal-dangling-tool-calls!clj

(heal-dangling-tool-calls! store conv-id)

开新一轮前的自愈:为 conv-id 历史里的悬空 tool_use 补「已取消」中立结果,使会话重新配平。 无悬空则 no-op。store 即挂载于 chat-client 的同一 memory store。 store 为 nil 时(如 :memory false 的子 Agent)直接跳过,无需自愈。

开新一轮前的自愈:为 conv-id 历史里的悬空 tool_use 补「已取消」中立结果,使会话重新配平。
无悬空则 no-op。store 即挂载于 chat-client 的同一 memory store。
store 为 nil 时(如 :memory false 的子 Agent)直接跳过,无需自愈。
sourceraw docstring

invokeclj

(invoke chat-client store messages opts)

工具调用循环主入口(统一循环)。同步:阻塞到出结果。

参数:

  • chat-client: ChatClient 实例(需配置 ChatModel)
  • store: ChatMemory store(与 chat-client 上 memory-filter 同一实例;用于 heal/临时清理)
  • messages: 本轮新消息(中立消息)
  • opts: {:context :system-prompts :max-iterations :tool-choice :tool-gate :tags/:exclude-tags :on-env-error :pause|:proceed(缺省 :proceed——环境类工具失败照常交给模型; :pause 时在屏障处暂停等人,resume :retry/:proceed 续跑) :callbacks 回调 map(:on-llm-call/:on-llm-result/:on-tool-result/:metadata 等)}

返回: {:status :completed :response r :tool-context c :tool-calls-made [...]} {:status :paused :loop-state {...} :pending-tool {...} :tool-context c}

工具调用循环主入口(统一循环)。**同步**:阻塞到出结果。

参数:
- chat-client:   ChatClient 实例(需配置 ChatModel)
- store:    ChatMemory store(与 chat-client 上 memory-filter 同一实例;用于 heal/临时清理)
- messages: 本轮新消息(中立消息)
- opts:     {:context :system-prompts :max-iterations :tool-choice :tool-gate :tags/:exclude-tags
            :on-env-error :pause|:proceed(缺省 :proceed——环境类工具失败照常交给模型;
                           :pause 时在屏障处暂停等人,resume :retry/:proceed 续跑)
            :callbacks  回调 map(:on-llm-call/:on-llm-result/:on-tool-result/:metadata 等)}

返回:
{:status :completed :response r :tool-context c :tool-calls-made [...]}
{:status :paused    :loop-state {...} :pending-tool {...} :tool-context c}
sourceraw docstring

invoke-asyncclj

(invoke-async chat-client store messages opts)

同 invoke,但立刻返回 CompletableFuture,整个 turn 跑在虚拟线程上。

给 Ring / Luminus 异步 handler 用:HTTP 工作线程不被 LLM 往返占住。 取结果用 flt/fmap 组合、async/on-complete 接回调,或 async/join 阻塞。

语义与 invoke 逐字相同(同一份 invoke*):暂停/取消/错误状态、 ephemeral 会话清理、turn filter 的递归重入都照旧;差别只在返回值被 deferred 包了一层。turn filter 在这条路径上会真的拿到 deferred—— 写响应侧时必须走 flt/fmap / flt/fbind,不能 let 出来直接用(§2.6.4)。

全链路 deferred(2026-09-03,P2):循环本体走 run-tool-loop-async—— 每轮 LLM 调用经 chat-client/invoke-chat-async,:chat / :iteration / :turn 三条链都在异步形态下运行。ChatModel 未实现 IAsyncChatModel 时由 chat-model/call-async* 用虚拟线程兜底,行为一致、只是每次 LLM 调用占一根 虚拟线程。:tool 终端仍同步(工具是用户代码,阻塞是常态;批次并行本就在 executor 上),见 docs/async-chat-model-design.md §8。

同 `invoke`,但**立刻返回 `CompletableFuture`**,整个 turn 跑在虚拟线程上。

给 Ring / Luminus 异步 handler 用:HTTP 工作线程不被 LLM 往返占住。
取结果用 `flt/fmap` 组合、`async/on-complete` 接回调,或 `async/join` 阻塞。

语义与 `invoke` **逐字相同**(同一份 `invoke*`):暂停/取消/错误状态、
ephemeral 会话清理、turn filter 的递归重入都照旧;差别只在返回值被
deferred 包了一层。turn filter 在这条路径上会真的拿到 deferred——
写响应侧时必须走 `flt/fmap` / `flt/fbind`,不能 `let` 出来直接用(§2.6.4)。

**全链路 deferred**(2026-09-03,P2):循环本体走 `run-tool-loop-async`——
每轮 LLM 调用经 `chat-client/invoke-chat-async`,`:chat` / `:iteration` /
`:turn` 三条链都在异步形态下运行。ChatModel 未实现 `IAsyncChatModel` 时由
`chat-model/call-async*` 用虚拟线程兜底,行为一致、只是每次 LLM 调用占一根
虚拟线程。`:tool` 终端仍同步(工具是用户代码,阻塞是常态;批次并行本就在
executor 上),见 docs/async-chat-model-design.md §8。
sourceraw docstring

resumeclj

(resume chat-client loop-state decision opts)

从 paused 的 loop-state 继续工具循环。同步:阻塞到出结果。

两种暂停 phase:

  • 审批暂停(缺省,工具未执行):decision :approved(强制全部执行) | :rejected(gate 决定,敏感→拒绝)| :reply(不执行 pending 工具, payload :message 直接作为其结果——ask-user 语义)
  • :env-retry(批已执行、环境类失败):decision :retry(环境已修复,重跑 失败调用)| :proceed(错误结果交给模型)

opts :payload(审批 phase 可选,携带用户答复):

  • :approved + {:args 新参数} → pending 工具以替换后的参数执行(编辑后批准)
  • :rejected + {:message 理由} → 结果「已拒绝执行:<理由>」(模型直接拿到原因)
  • :reply + {:message 答复} → 答复即 pending 工具的结果(必填)

参数:

  • chat-client: ChatClient 实例
  • loop-state: invoke 返回的 :loop-state
  • decision: 见上
  • opts: 同 invoke(须含带 conversation-id 的 :context 以接续历史; 可含 :payload)

turn 链语义:resume 同样经过 :turn 洋葱——首次进入终端执行「暂停 turn 的 延续」(消费 loop-state);turn filter 的递归重入(如校验反馈)走全新 工具循环(新 delta,上下文由 memory 拼接)。TurnRequest 带 :resume? true 标记,请求侧改写类 filter(RAG 注入等)应据此跳过首次改写。

返回: 同 invoke(:completed 或再次 :paused)

从 paused 的 loop-state 继续工具循环。**同步**:阻塞到出结果。

两种暂停 phase:
- 审批暂停(缺省,工具未执行):decision :approved(强制全部执行)
  | :rejected(gate 决定,敏感→拒绝)| :reply(不执行 pending 工具,
  payload :message 直接作为其结果——ask-user 语义)
- :env-retry(批已执行、环境类失败):decision :retry(环境已修复,重跑
  失败调用)| :proceed(错误结果交给模型)

opts :payload(审批 phase 可选,携带用户答复):
- :approved + {:args 新参数}   → pending 工具以替换后的参数执行(编辑后批准)
- :rejected + {:message 理由}  → 结果「已拒绝执行:<理由>」(模型直接拿到原因)
- :reply    + {:message 答复}  → 答复即 pending 工具的结果(必填)

参数:
- chat-client:     ChatClient 实例
- loop-state: invoke 返回的 :loop-state
- decision:   见上
- opts:       同 invoke(须含带 conversation-id 的 :context 以接续历史;
              可含 :payload)

turn 链语义:resume 同样经过 :turn 洋葱——首次进入终端执行「暂停 turn 的
延续」(消费 loop-state);turn filter 的递归重入(如校验反馈)走全新
工具循环(新 delta,上下文由 memory 拼接)。TurnRequest 带 :resume? true
标记,请求侧改写类 filter(RAG 注入等)应据此跳过首次改写。

返回: 同 invoke(:completed 或再次 :paused)
sourceraw docstring

resume-asyncclj

(resume-async chat-client loop-state decision opts)

同 resume,但立刻返回 CompletableFuture,延续跑在虚拟线程上。

HITL 的第二段(人答复之后接着跑)在 web 场景与首段同样长——首段异步了、 这段还阻塞 HTTP 线程就没有意义。语义与 resume 逐字相同(同一份 resume*)。

同 `resume`,但立刻返回 `CompletableFuture`,延续跑在虚拟线程上。

HITL 的第二段(人答复之后接着跑)在 web 场景与首段同样长——首段异步了、
这段还阻塞 HTTP 线程就没有意义。语义与 `resume` 逐字相同(同一份 `resume*`)。
sourceraw docstring

run-toolsclj

(run-tools chat-client tool-calls tool-context)

execute-batch 的无 gate 特例:全部执行。供外部手搓工具循环使用。

恒串行(无视 :tool-manager)——不复用引擎的调度,但吃引擎的 :timeout 缺省(经 invoke-tool → effective-tool-timeout 读 :tool-manager)。 不对称是 v0.3 引入的::timeout 在 invoke-tool 强制,而调度在 react——两者 分属不同层,run-tools 只走前者。要完整引擎行为(含调度)请用 invoke/resume。

execute-batch 的无 gate 特例:全部执行。供外部手搓工具循环使用。

**恒串行**(无视 `:tool-manager`)——不复用引擎的调度,但**吃引擎的 `:timeout`
缺省**(经 invoke-tool → effective-tool-timeout 读 `:tool-manager`)。
不对称是 v0.3 引入的:`:timeout` 在 invoke-tool 强制,而调度在 react——两者
分属不同层,run-tools 只走前者。要完整引擎行为(含调度)请用 invoke/resume。
sourceraw docstring

sequential-tool-calling-managerclj

(sequential-tool-calling-manager)
(sequential-tool-calling-manager {:keys [timeout]})

缺省引擎:每个工具按调用序在调用方线程执行,无并发。

为什么串行是缺省:并发要求同批工具的副作用彼此无序依赖——那是调用方才 知道的性质,框架不该替它假定。串行是那个「无论工具长什么样都成立」的选择: 顺序可预期、可调试、不会因为 LLM 某轮多发一个 tool-call 就把副作用交错起来。 要并发是显式的决定:注入 virtual-thread-tool-calling-manager。 (状态语义两者相同:都是轮初快照 + 屏障折叠。)

线程模型:调用方线程,全程不构造 Future(故不背 ExecutionException 包装 与 Future.get 的中断语义——这是它与「给 VT 引擎塞一个 same-thread executor」 的本质区别)。例外:声明了 :timeout 的工具——超时在 terminal 内由 call-with-timeout 强制(R1),此时起一根 VT 跑工具本体、调用方线程等 deref, 「不构造 Future」承诺在此情形下不成立(R2 诚实降级)。未声明超时的工具(大多数) 照常在调用方线程上直接跑。 隔离边界:不持任何资源,无可争之物。

opts:

  • :timeout 本引擎为没有声明 :timeout 的工具设的缺省超时(毫秒)。 缺省 nil = 不超时。工具自己的声明恒优先。
**缺省引擎**:每个工具按调用序在调用方线程执行,无并发。

**为什么串行是缺省**:并发要求同批工具的副作用彼此无序依赖——那是**调用方才
知道**的性质,框架不该替它假定。串行是那个「无论工具长什么样都成立」的选择:
顺序可预期、可调试、不会因为 LLM 某轮多发一个 tool-call 就把副作用交错起来。
要并发是**显式**的决定:注入 `virtual-thread-tool-calling-manager`。
(状态语义两者相同:都是轮初快照 + 屏障折叠。)

线程模型:调用方线程,**全程不构造 Future**(故不背 ExecutionException 包装
与 Future.get 的中断语义——这是它与「给 VT 引擎塞一个 same-thread executor」
的本质区别)。**例外:声明了 `:timeout` 的工具**——超时在 terminal 内由
`call-with-timeout` 强制(R1),此时起一根 VT 跑工具本体、调用方线程等 deref,
「不构造 Future」承诺在此情形下不成立(R2 诚实降级)。未声明超时的工具(大多数)
照常在调用方线程上直接跑。
隔离边界:不持任何资源,无可争之物。

opts:
- :timeout  本引擎为**没有声明 `:timeout`** 的工具设的缺省超时(毫秒)。
            缺省 nil = 不超时。工具自己的声明恒优先。
sourceraw docstring

shutdown-tool-calling-manager!clj

(shutdown-tool-calling-manager! m)

关停 manager 持有的资源。只有 ThreadPoolToolCallingManager 持有池; VT / Sequential 无资源,调用即 no-op。等价于对 Closeable 实现调 .close。

关停 manager 持有的资源。只有 ThreadPoolToolCallingManager 持有池;
VT / Sequential 无资源,调用即 no-op。等价于对 Closeable 实现调 .close。
sourceraw docstring

thread-pool-tool-calling-managerclj

(thread-pool-tool-calling-manager)
(thread-pool-tool-calling-manager {:keys [pool-size thread-name-prefix timeout]
                                   :or {pool-size (.availableProcessors
                                                    (Runtime/getRuntime))
                                        thread-name-prefix "clj-agent-tool-"}})

有界平台线程池引擎:工具批在本实例自己的池里跑,形成舱壁隔离。

线程模型:固定大小的平台线程池(daemon 线程)。 隔离边界:每个实例一个池——工具执行的并发上限 = pool-size,不与其他 chat-client 相互挤占;池随实例关停(见下)。这是 VT 引擎给不了的:后者用进程全局无界池。

opts:

  • :pool-size 正整数,缺省 (availableProcessors)
  • :thread-name-prefix 线程名前缀,缺省 "clj-agent-tool-"
  • :timeout 为没有声明 :timeout 的工具设的缺省超时(毫秒), 缺省 nil = 不超时;工具自己的声明恒优先。 本引擎尤其值得给一个:没有超时的工具若卡死(如无限 循环、socket 挂死),会永久占住一个池槽(舱壁逐格坏死); 有超时则池线程在 deref 超时后释放(但注意 R2:有超时的工具 实际跑在 VT 上、池线程只等 deref,舱壁退化为信号量)

生命周期由持有者负责——池不会自己关。实现了 java.io.Closeable:

(with-open [m (thread-pool-tool-calling-manager {:pool-size 4})] (let [cc (chat-client/build-chat-client {:chat-model cm :tools [...] :tool-manager m})] ...))

关停后再执行工具批抛 ex-info(:error-class :environment)。

不变量:一个引擎属于一个 chat-client,不跨 delegate 边界。 子 agent 是独立 agent,自有引擎——这本来就是默认:delegate 的 subagent-config 全部来自用户的 :subagent-fn,父 chat-client 的 :tool-manager 没有渠道流进去。

故不要把同一个实例亲手塞进 subagent-config 复用(那是绕过默认去踩): delegate-tool 是 spawn→await→drop,父批的工具会占着池线程阻塞等子 agent 跑完, 而子 agent 的批又要同一个池的线程——互等,永久挂起。子 agent 要限流就给它 自己的实例(各自封顶,互不嵌套);不需要就留默认 VT 引擎。

同理,一个引擎的批不嵌套自己:别在本引擎某个工具的函数体里,再拿同一个 实例去跑一批(同样自锁)。框架不为此设防——不变量本身就是答案。

顺带一提:有界平台池是给真正干活的工具封顶用的。delegate 这类只是阻塞等 网络的工具,占一根平台线程停几秒到几分钟,本就不该走有界池。

有界平台线程池引擎:工具批在**本实例自己的池**里跑,形成舱壁隔离。

线程模型:固定大小的平台线程池(daemon 线程)。
隔离边界:每个实例一个池——工具执行的并发上限 = pool-size,不与其他 chat-client
相互挤占;池随实例关停(见下)。这是 VT 引擎给不了的:后者用进程全局无界池。

opts:
- :pool-size          正整数,缺省 (availableProcessors)
- :thread-name-prefix 线程名前缀,缺省 "clj-agent-tool-"
- :timeout            为**没有声明 `:timeout`** 的工具设的缺省超时(毫秒),
                       缺省 nil = 不超时;工具自己的声明恒优先。
                       **本引擎尤其值得给一个**:没有超时的工具若卡死(如无限
                       循环、socket 挂死),会**永久占住一个池槽**(舱壁逐格坏死);
                       有超时则池线程在 deref 超时后释放(但注意 R2:有超时的工具
                       实际跑在 VT 上、池线程只等 deref,舱壁退化为信号量)

**生命周期由持有者负责**——池不会自己关。实现了 java.io.Closeable:

  (with-open [m (thread-pool-tool-calling-manager {:pool-size 4})]
    (let [cc (chat-client/build-chat-client {:chat-model cm :tools [...] :tool-manager m})]
      ...))

关停后再执行工具批抛 ex-info(:error-class :environment)。

**不变量:一个引擎属于一个 chat-client,不跨 delegate 边界。**
子 agent 是独立 agent,自有引擎——这本来就是默认:delegate 的 subagent-config
全部来自用户的 :subagent-fn,父 chat-client 的 :tool-manager 没有渠道流进去。

故**不要把同一个实例亲手塞进 subagent-config 复用**(那是绕过默认去踩):
delegate-tool 是 spawn→await→drop,父批的工具会占着池线程阻塞等子 agent 跑完,
而子 agent 的批又要同一个池的线程——互等,永久挂起。子 agent 要限流就给它
**自己的**实例(各自封顶,互不嵌套);不需要就留默认 VT 引擎。

同理,**一个引擎的批不嵌套自己**:别在本引擎某个工具的函数体里,再拿同一个
实例去跑一批(同样自锁)。框架不为此设防——不变量本身就是答案。

顺带一提:有界平台池是给**真正干活**的工具封顶用的。delegate 这类只是阻塞等
网络的工具,占一根平台线程停几秒到几分钟,本就不该走有界池。
sourceraw docstring

virtual-thread-tool-calling-managerclj

(virtual-thread-tool-calling-manager)
(virtual-thread-tool-calling-manager {:keys [timeout]})

并发引擎:每调用一根虚拟线程,尊重 :serial 声明。

不是缺省——缺省是串行(见 sequential-tool-calling-manager)。同轮多个 tool-call 并发跑,要求这些工具的副作用彼此无序依赖;那是调用方才知道的事, 故须显式选择。

线程模型:虚拟线程,无界。 隔离边界:无——用的是进程全局共享 executor(见 tool-executor)。 需要舱壁 / 限流 / 可关停边界时改用 thread-pool-tool-calling-manager。

opts:

  • :timeout 本引擎为没有声明 :timeout 的工具设的缺省超时(毫秒)。 缺省 nil = 不超时。工具自己的声明恒优先。
并发引擎:每调用一根虚拟线程,尊重 :serial 声明。

**不是缺省**——缺省是串行(见 `sequential-tool-calling-manager`)。同轮多个
tool-call 并发跑,要求这些工具的副作用彼此无序依赖;那是**调用方才知道**的事,
故须显式选择。

线程模型:虚拟线程,无界。
隔离边界:**无**——用的是进程全局共享 executor(见 tool-executor)。
需要舱壁 / 限流 / 可关停边界时改用 thread-pool-tool-calling-manager。

opts:
- :timeout  本引擎为**没有声明 `:timeout`** 的工具设的缺省超时(毫秒)。
            缺省 nil = 不超时。工具自己的声明恒优先。
sourceraw docstring

cljdoc builds & hosts documentation for Clojure/Script libraries

Keyboard shortcuts
Ctrl+kJump to recent docs
←Move to previous article
→Move to next article
Ctrl+/Jump to the search field
× close