Liking cljdoc? Tell your friends :D

im.ttalk.agent.simple-agent

SimpleAgent - 统一 Agent(合并原 kernel-agent / process-agent)

对话历史由 ChatClient 的 ChatMemory store 按 conversation-id 自管(Memory Filter)。 Agent 只持 conversation-id + 轻量控制状态。

Callback 体系(独立于 chat-client filter): 通过 :callbacks map 注册 9 个回调,用于监控和控制 agent 执行过程: :on-turn-start (fn [metadata]) 新 turn 开始 :on-turn-end (fn [metadata]) turn 正常完成 :on-turn-error (fn [error metadata]) turn 出错 :on-llm-call (fn [messages metadata]) 每次 LLM 调用前(在 react 层触发) :on-llm-result (fn [response metadata]) 每次 LLM 返回后(在 react 层触发) :on-tool-call (fn [tool-name args]) tool 调用前;返回 {:interrupt reason} 触发中断 :on-tool-result (fn [tool-name result]) tool 执行后(在 react 层触发) :on-interrupt (fn [interrupt-info metadata]) 进入中断状态时 :on-resume (fn [interrupt-info metadata]) 从中断状态恢复时

pause/resume 为可选能力:配置 callbacks :on-tool-call 即启用。

线程安全:单个 agent 实例不可被多线程并发 chat/resume。每个 agent 应绑定 单一对话线程;并发请按会话各建一个 agent(共享底层持久 store + 各自 :conversation-id 即可隔离)。

使用示例:

;; 简单同步 (def a (create-agent {:provider p :model "glm-4.7" :tools [#'get-weather]})) (chat a "北京天气?") ;; => {:status :completed :text "..." :tool-calls-made [...]}

;; 带 callbacks 的可观测 agent (def a (create-agent {:provider p :tools [#'my-tool] :callbacks {:on-turn-start (fn [m] (println "Turn" (:turn-count m))) :on-tool-result (fn [n r] (println n "=>" r)) :on-tool-call (fn [n a] (when (risky? n) {:interrupt :need-approval}))}}))

;; 工具审批:on-tool-call 返回 {:interrupt reason} 触发暂停 (def a (create-agent {:provider p :tools [#'delete-file] :callbacks {:on-tool-call (fn [n _] (when (= :delete-file n) {:interrupt "需要审批"})) :on-interrupt (fn [info _] (println "等待审批" (:reason info)))}})) (let [r (chat a "删除 /tmp/x")] (when (= :paused (:status r)) (resume a "approved")))

SimpleAgent - 统一 Agent(合并原 kernel-agent / process-agent)

对话历史由 ChatClient 的 ChatMemory store 按 conversation-id 自管(Memory Filter)。
Agent 只持 conversation-id + 轻量控制状态。

**Callback 体系**(独立于 chat-client filter):
通过 :callbacks map 注册 9 个回调,用于监控和控制 agent 执行过程:
  :on-turn-start   (fn [metadata])                  新 turn 开始
  :on-turn-end     (fn [metadata])                  turn 正常完成
  :on-turn-error   (fn [error metadata])            turn 出错
  :on-llm-call     (fn [messages metadata])         每次 LLM 调用前(在 react 层触发)
  :on-llm-result   (fn [response metadata])         每次 LLM 返回后(在 react 层触发)
  :on-tool-call    (fn [tool-name args])             tool 调用前;返回 {:interrupt reason} 触发中断
  :on-tool-result  (fn [tool-name result])          tool 执行后(在 react 层触发)
  :on-interrupt    (fn [interrupt-info metadata])   进入中断状态时
  :on-resume       (fn [interrupt-info metadata])   从中断状态恢复时

pause/resume 为可选能力:**配置 callbacks :on-tool-call 即启用**。

线程安全:单个 agent 实例不可被多线程并发 chat/resume。每个 agent 应绑定
单一对话线程;并发请按会话各建一个 agent(共享底层持久 store + 各自
:conversation-id 即可隔离)。

使用示例:

;; 简单同步
(def a (create-agent {:provider p :model "glm-4.7" :tools [#'get-weather]}))
(chat a "北京天气?")    ;; => {:status :completed :text "..." :tool-calls-made [...]}

;; 带 callbacks 的可观测 agent
(def a (create-agent {:provider p :tools [#'my-tool]
                      :callbacks {:on-turn-start  (fn [m] (println "Turn" (:turn-count m)))
                                  :on-tool-result (fn [n r] (println n "=>" r))
                                  :on-tool-call   (fn [n a] (when (risky? n) {:interrupt :need-approval}))}}))

;; 工具审批:on-tool-call 返回 {:interrupt reason} 触发暂停
(def a (create-agent {:provider p :tools [#'delete-file]
                      :callbacks {:on-tool-call (fn [n _] (when (= :delete-file n) {:interrupt "需要审批"}))
                                  :on-interrupt (fn [info _] (println "等待审批" (:reason info)))}}))
(let [r (chat a "删除 /tmp/x")]
  (when (= :paused (:status r))
    (resume a "approved")))
raw docstring

chatclj

(chat agent message)
(chat agent message opts)

对话。返回 {:status :completed :text ...} 或 {:status :paused ...}

对话。返回 {:status :completed :text ...} 或 {:status :paused ...}
sourceraw docstring

chat-asyncclj

(chat-async agent message)
(chat-async agent message opts)

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

给 Ring / Luminus 异步 handler 用:

(defn handler [request respond raise]
  (-> (agent/chat-async a (get-in request [:body-params :message]))
      (flt/fmap (fn [r] {:status 200 :body {:text (:text r)}}))
      (async/on-complete respond raise)))

返回值形状与 chat 逐字相同(:completed / :paused / :error),只是被 deferred 包了一层:async/join 阻塞取、flt/fmap 组合、async/on-complete 接回调。turn 级回调在工作线程上触发(见 run-loop-async)。

opts 与 chat-stream 同源:传 :on-token 即异步流式,传 :cancel-token 即可从别的线程取消(见 loop-passthrough-keys)。

⚠️ agent 的 state-atom 是单会话状态机:同一个 agent 上不要并发多个 chat-async(start-turn! 会互相踩 run-id / 暂停态)。web 场景下每个会话 一个 agent 实例,或自行串行化。

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

给 Ring / Luminus 异步 handler 用:

```clojure
(defn handler [request respond raise]
  (-> (agent/chat-async a (get-in request [:body-params :message]))
      (flt/fmap (fn [r] {:status 200 :body {:text (:text r)}}))
      (async/on-complete respond raise)))
```

返回值形状与 `chat` 逐字相同(`:completed` / `:paused` / `:error`),只是被
deferred 包了一层:`async/join` 阻塞取、`flt/fmap` 组合、`async/on-complete`
接回调。turn 级回调在工作线程上触发(见 `run-loop-async`)。

**opts 与 `chat-stream` 同源**:传 `:on-token` 即异步流式,传 `:cancel-token`
即可从别的线程取消(见 `loop-passthrough-keys`)。

⚠️ agent 的 state-atom 是单会话状态机:**同一个 agent 上不要并发多个
chat-async**(`start-turn!` 会互相踩 run-id / 暂停态)。web 场景下每个会话
一个 agent 实例,或自行串行化。
sourceraw docstring

chat-streamclj

(chat-stream agent message on-token)
(chat-stream agent message on-token opts)

流式对话。on-token 接收 {:token / :reasoning-token ...}(增量 token,需全文请自行累积)。

返回最终结果(与 chat 同形)。取消:opts 传 :cancel-token。

chat-async 也吃 :on-token(opts 透传,见 loop-passthrough-keys)—— 要「异步 + 流式 + 可取消」用 (chat-async a msg {:on-token f :cancel-token t})。

流式对话。`on-token` 接收 {:token / :reasoning-token ...}(增量 token,需全文请自行累积)。

返回最终结果(与 chat 同形)。取消:opts 传 `:cancel-token`。

**`chat-async` 也吃 `:on-token`**(opts 透传,见 `loop-passthrough-keys`)——
要「异步 + 流式 + 可取消」用 `(chat-async a msg {:on-token f :cancel-token t})`。
sourceraw docstring

create-agentclj

(create-agent opts)

创建 Agent

参数 opts:

  • :chat-client 预构建 ChatClient(提供则跳过构建)
  • :provider ILLMProvider 实例
  • :model 模型名(默认 "glm-4")
  • :max-tokens 最大 token(默认 4096)
  • :temperature 温度
  • :system-prompt 系统提示词
  • :tools tool var / inline-tool map 列表
  • :memory ChatMemory store(可选,默认 in-memory;false → 无记忆)
  • :pause-store PauseStore(可选,见 im.ttalk.agent.pause):暂停快照自动 持久化,进程重启后同 conversation-id + 同 store 重建 agent 即可 resume(跨重启 HITL;对话历史请配 SQLite ChatMemory)
  • :conversation-id 会话 ID(可选)
  • :max-iterations 最大工具循环次数(默认 10)
  • :tool-context 装配期塞进 ToolContext 的种子 map(可选,见返回值注释)
  • :on-pause (fn [{:keys [pending-tool reason]}])(可选):配置即启用 pause/resume——声明 deftool {:sensitive true} 的工具在执行 前自动暂停,等 resume。暂停发生时本回调被触发。
  • :callbacks 回调 map(:on-turn-start/:on-turn-end/:on-turn-error/:on-llm-call/ :on-llm-result/:on-tool-call/:on-tool-result/:on-interrupt/:on-resume; :on-event 收生命周期事件,见 im.ttalk.agent.events)
  • :approval 声明式审批(designs/runtime-borrow.md §5 §6,可选): {:policy 策略(im.ttalk.agent.approval 的 rule-policy / hint-policy …) :cache 会话缓存(缺省每个 agent 一份;false = 不缓存) :timeout-ms 暂停超过这么久再 resume → 按「拒绝:审批超时」处理 :breaker 拒绝熔断参数 {:max-consecutive 3 …}(resume 的拒绝计数)} 配置即启用暂停;与 :on-pause / :on-tool-call 并存时三路取最严

两条 pause 启用路径,可并存(缺省两条都不配 = 永不暂停,chat 只会返回 :completed/:error,无人值守调用方不会收到意外的暂停态):

  • :on-pause —— 声明式,{:sensitive true} 的工具一律暂停;
  • :callbacks :on-tool-call —— 命令式,返回 {:interrupt reason} 即暂停。 两条都配时先问回调;回调放行的,若工具是敏感工具仍暂停——:sensitive 是工具作者立的下限,不该被一个泛泛的回调放行掉。

:chat-client 与 :memory 可独立同时指定,store 解析规则:

  • :memory store → 用它(预构建 chat-client 上的 memory-filter 会被重挂到该 store)
  • :memory false → 无记忆(预构建 chat-client 上的 memory-filter 会被移除)
  • :memory 缺省 → 复用 chat-client memory-filter 的 store;都没有则默认 in-memory

Agent 层不暴露 chat-client filter(传入 :filters 会被忽略并警告); 需要 filter 请用 chat-client/build-chat-client 自建后经 :chat-client 传入。

返回 Agent map

创建 Agent

参数 opts:
- :chat-client        预构建 ChatClient(提供则跳过构建)
- :provider      ILLMProvider 实例
- :model         模型名(默认 "glm-4")
- :max-tokens    最大 token(默认 4096)
- :temperature   温度
- :system-prompt 系统提示词
- :tools         tool var / inline-tool map 列表
- :memory        ChatMemory store(可选,默认 in-memory;false → 无记忆)
- :pause-store   PauseStore(可选,见 im.ttalk.agent.pause):暂停快照自动
                 持久化,进程重启后同 conversation-id + 同 store 重建 agent
                 即可 resume(跨重启 HITL;对话历史请配 SQLite ChatMemory)
- :conversation-id 会话 ID(可选)
- :max-iterations 最大工具循环次数(默认 10)
- :tool-context   装配期塞进 ToolContext 的种子 map(可选,见返回值注释)
- :on-pause      (fn [{:keys [pending-tool reason]}])(可选):**配置即启用
                 pause/resume**——声明 `deftool {:sensitive true}` 的工具在执行
                 前自动暂停,等 `resume`。暂停发生时本回调被触发。
- :callbacks     回调 map(:on-turn-start/:on-turn-end/:on-turn-error/:on-llm-call/
                           :on-llm-result/:on-tool-call/:on-tool-result/:on-interrupt/:on-resume;
                           :on-event 收生命周期事件,见 im.ttalk.agent.events)
- :approval      声明式审批(designs/runtime-borrow.md §5 §6,可选):
                 {:policy     策略(im.ttalk.agent.approval 的 rule-policy / hint-policy …)
                  :cache      会话缓存(缺省每个 agent 一份;false = 不缓存)
                  :timeout-ms 暂停超过这么久再 resume → 按「拒绝:审批超时」处理
                  :breaker    拒绝熔断参数 {:max-consecutive 3 …}(resume 的拒绝计数)}
                 配置即启用暂停;与 :on-pause / :on-tool-call 并存时三路取最严

**两条 pause 启用路径,可并存**(缺省两条都不配 = 永不暂停,`chat` 只会返回
`:completed`/`:error`,无人值守调用方不会收到意外的暂停态):
- `:on-pause` —— 声明式,`{:sensitive true}` 的工具一律暂停;
- `:callbacks :on-tool-call` —— 命令式,返回 `{:interrupt reason}` 即暂停。
两条都配时先问回调;回调放行的,若工具是敏感工具**仍暂停**——`:sensitive`
是工具作者立的下限,不该被一个泛泛的回调放行掉。

:chat-client 与 :memory 可独立同时指定,store 解析规则:
- :memory store   → 用它(预构建 chat-client 上的 memory-filter 会被重挂到该 store)
- :memory false   → 无记忆(预构建 chat-client 上的 memory-filter 会被移除)
- :memory 缺省    → 复用 chat-client memory-filter 的 store;都没有则默认 in-memory

Agent 层不暴露 chat-client filter(传入 :filters 会被忽略并警告);
需要 filter 请用 chat-client/build-chat-client 自建后经 :chat-client 传入。

返回 Agent map
sourceraw docstring

default-max-iterationsclj

工具循环的缺省上限。提成常量是为了装配方能如实上报——/info 的 capabilities.execution.maxIterations 要报这个数,抄一份魔数过去迟早对不上。

工具循环的缺省上限。提成常量是为了**装配方能如实上报**——`/info` 的
`capabilities.execution.maxIterations` 要报这个数,抄一份魔数过去迟早对不上。
sourceraw docstring

get-historyclj

(get-history agent)

获取该会话的完整中立消息历史

获取该会话的完整中立消息历史
sourceraw docstring

get-messagesclj

source

make-cancel-tokenclj

创建取消令牌,传给 chat-stream 的 opts :cancel-token。见 im.ttalk.agent.streaming。

创建取消令牌,传给 chat-stream 的 opts :cancel-token。见 im.ttalk.agent.streaming。
sourceraw docstring

paused?clj

(paused? agent)

是否处于暂停态(本进程 state-atom 或 PauseStore 中的持久化快照)。

是否处于暂停态(本进程 state-atom 或 PauseStore 中的持久化快照)。
sourceraw docstring

request-cancel!clj

请求取消 chat-stream(取消上游 + 停止循环)。见 im.ttalk.agent.streaming。

请求取消 chat-stream(取消上游 + 停止循环)。见 im.ttalk.agent.streaming。
sourceraw docstring

reset!clj

(reset! agent)

清空会话历史、持久化暂停快照并重置控制状态

清空会话历史、持久化暂停快照并重置控制状态
sourceraw docstring

resumeclj

(resume agent decision)
(resume agent decision payload)
(resume agent decision payload opts)

恢复暂停的 Agent(本进程暂停或跨重启的持久化暂停均可)。

审批暂停:

  • "approved"/:approved 批准;payload 可带 {:args 新参数}(编辑后批准, pending 工具以替换后的参数执行)
  • "reply"/:reply 答复即结果(ask-user 语义):payload 必带 {:message 答复}, pending 工具不执行、答复直接作为其结果回模型
  • 其余 → 拒绝;payload 可带 {:message 理由}(结果「已拒绝执行:<理由>」, 模型直接拿到原因,省一轮干猜)

环境类暂停(:env-retry):"retry"/:retry 或 "approved"/:approved 表示 环境已修复、重跑失败工具;其余 → 错误结果交给模型(不支持 :reply)。

resume 的 ToolContext 恢复自暂停快照(各轮 :writes 的累积折叠结果保留)。

4-arity 的 opts 与 chat 侧同义,尤其是 :on-token / :cancel-token: HITL 第二段(审批之后的续跑)往往正是最终答案那段,不给这两个键,前端就只能 干等若干秒再一次性收到整段文字,期间「停止」也按不动。 payload 是用户答复的载荷(:args / :message),传输选项走 opts ——两件事不挤一个槽。

恢复暂停的 Agent(本进程暂停或跨重启的持久化暂停均可)。

审批暂停:
- "approved"/:approved 批准;payload 可带 {:args 新参数}(编辑后批准,
  pending 工具以替换后的参数执行)
- "reply"/:reply 答复即结果(ask-user 语义):payload 必带 {:message 答复},
  pending 工具不执行、答复直接作为其结果回模型
- 其余 → 拒绝;payload 可带 {:message 理由}(结果「已拒绝执行:<理由>」,
  模型直接拿到原因,省一轮干猜)

环境类暂停(:env-retry):"retry"/:retry 或 "approved"/:approved 表示
环境已修复、重跑失败工具;其余 → 错误结果交给模型(不支持 :reply)。

resume 的 ToolContext 恢复自暂停快照(各轮 :writes 的累积折叠结果保留)。

4-arity 的 `opts` 与 `chat` 侧同义,**尤其是 `:on-token` / `:cancel-token`**:
HITL 第二段(审批之后的续跑)往往正是最终答案那段,不给这两个键,前端就只能
干等若干秒再一次性收到整段文字,期间「停止」也按不动。
`payload` 是**用户答复**的载荷(`:args` / `:message`),传输选项走 `opts`
——两件事不挤一个槽。
sourceraw docstring

resume-asyncclj

(resume-async agent decision)
(resume-async agent decision payload)
(resume-async agent decision payload opts)

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

HITL 的第二段(人答复之后接着跑)与第一段一样长——首段用了 chat-async, 这段还阻塞 HTTP 线程就白费了。返回值形状同 resume;4-arity 的 opts 见 resume(:on-token / :cancel-token 在这里同样成立)。

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

HITL 的第二段(人答复之后接着跑)与第一段一样长——首段用了 `chat-async`,
这段还阻塞 HTTP 线程就白费了。返回值形状同 `resume`;4-arity 的 `opts`
见 `resume`(`:on-token` / `:cancel-token` 在这里同样成立)。
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