docs(agent): clarify lifecycle and security caveats in react agent guide

Add notes on framework integration prerequisites, event listener
threading, build-time capability methods, session reuse semantics,
built-in tool risks, and two new troubleshooting entries.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
everywhere.z
2026-05-14 19:13:31 +08:00
parent 828a2d9099
commit d72d04475b

View File

@@ -46,7 +46,7 @@
</dependency>
```
如果一个应用里要同时使用多个模型平台,可以同时引入多个平台模块。
业务应用仍需引入 LiteFlow 对应的运行集成,例如 `liteflow-spring-boot-starter``liteflow-spring-boot4-starter` 或其他已有 LiteFlow starter模型平台模块只提供 ReAct Agent 能力和平台 SDK 入口。如果一个应用里要同时使用多个模型平台,可以同时引入多个平台模块。
### 2.2 配置 LiteFlow 与 Agent
@@ -232,6 +232,8 @@ if (response.isSuccess()) {
没有注册 `eventListener` 时,`ReActAgentComponent` 会继续走原来的阻塞调用路径,不会产生额外事件开销;注册 listener 后,组件会使用 AgentScope 的 `agent.stream(...)` 执行,并在流结束后照常调用 `handleReply(reply)`、保存 memory、返回 `LiteflowResponse`
`eventListener` 在 chain 执行线程中同步回调。生产环境转发到 SSE、WebSocket 或消息队列时,建议在 listener 中只做轻量入队或缓冲,不要执行耗时 I/Olistener 抛出的异常会向上传播,并可能导致本次链路失败。
---
## 3. ReActAgentComponent 扩展点
@@ -268,6 +270,8 @@ if (response.isSuccess()) {
注意:`systemPrompt()` 只在同一 `(conversationId, agentKey)` 下首次构建 Agent 时调用;后续调用会复用同一个 Agent 实例和 memory。动态输入应放在 `userPrompt()` 中,并通过 `ctx()``getSlot()` 读取当次 invocation 的数据。
同理,`tools()``hooks()``skills()``enableSkills()``enableReActLogging()``buildModel()` 都属于 Agent 构建期能力声明,通常只在同一 `(conversationId, agentKey)` 首次构建缓存 Agent 时生效。不要让这些方法依赖单次请求数据;如果确实需要按请求隔离模型、工具或 hook请把请求维度体现在 `agentKey()``conversationId` 中,让框架构建新的 AgentSession。
---
## 4. ModelSpec 与模型入口
@@ -573,6 +577,8 @@ protected String agentKey() {
当 Session 数量超过 `max-sessions` 时,会按 `lastActive` 淘汰最旧的 JVM 内缓存。这个淘汰只移除热 Agent 实例,不删除 workspace也不删除 Redis、MySQL 或文件中的持久化记忆。
注意:`AgentSessionManager` 在首次执行 Agent 组件时按当前 `liteflow.agent.*` 配置懒创建,已有热 Session 中的 Agent 也会被复用。运行中修改 memory、skills、模型、工具或 hook 配置后,已有 `(conversationId, agentKey)` 不一定立即体现新配置;通常需要使用新的 conversation / agentKey或重启应用。
### 5.5 memory 持久化模式
`liteflow.agent.session.memory.*` 控制 Agent memory 保存在哪里。它和热 Session 缓存是两件事:热缓存决定当前 JVM 里保留多久memory 持久化决定重启或重新加载后能否恢复对话历史。
@@ -668,6 +674,8 @@ LiteFlow 不创建 JDBC 连接池,`DataSource` 也需要由业务应用提供
所有路径都必须是相对路径。绝对路径或 `..` 越界路径会被拒绝。
当前文件工具面向文本内容:`read_file``max-file-bytes` 截断读取,`write_file` 是覆盖写入并自动创建父目录。业务如果允许 Agent 写入大文件或二进制文件,建议关闭内置文件工具,改用自定义工具做大小、类型和审计控制。
关闭方式:
```java
@@ -699,6 +707,8 @@ liteflow.agent.shell.mode=disabled
确实需要 Shell 时,优先使用 `WHITELIST`,并把白名单收窄到业务需要的命令。
默认白名单包含 `curl``wget``python3``node` 等能力较强的命令。即使当前实现不经过系统 shell、不支持管道和重定向这些命令仍可能带来网络访问或脚本执行风险生产环境不要直接沿用默认白名单。
### 6.5 ReAct 事件日志
框架内置 `ReActLoggingHook`,把 agent 的 `reason` / `act` / `error` 事件写入 SLF4J便于在终端直接观察 ReAct 推理过程。日志中的方括号 ID 为 `conversationId:agentKey`
@@ -1053,6 +1063,8 @@ liteflow.agent.anthropic-compatible.gateway.base-url=https://anthropic-gateway.e
| `references unknown tool class` | `SKILL.md``tools` 字段声明了 classpath 上找不到的 Java 工具类 | 确认工具类全限定名正确、依赖已打包、类有无参构造器 |
| `usedSkills()` 为空 | 本轮 Agent 没有成功调用 `load_skill_through_path`,或读取时已离开 `process()` 生命周期 | 在 `handleReply()` 或工具回调中读取;确认模型确实加载了对应 skill |
| 没有收到流式事件 | 本次调用没有使用 `ExecuteOption.eventListener(...)`,或链路中没有 ReAct Agent 节点 | 注册 listener确认事件类型是否为 `agent.reasoning``agent.tool_result``agent.summary``agent.result` |
| `ctx() must be called during process()` | 在构造器、Bean 初始化、异步线程或 `process()` 结束后的生命周期中调用了 `ctx()` | 只在 `userPrompt()`、工具回调、Hook 回调和 `handleReply()``process()` 触发的调用链内读取;跨 invocation 缓存的对象不要保存 `ReActAgentContext` |
| 注册 listener 后链路失败 | `eventListener` 回调中抛出了异常,或执行了阻塞 I/O 导致上游超时 | listener 内只做轻量处理并自行捕获异常;重型转发逻辑放到外部队列或线程池 |
| `WHEN` 中多个 Agent 看起来没有并行 | 多个组件解析到了相同 `(conversationId, agentKey)`,共用了同一把锁;或下游等待最慢分支 | 确保需要并行的 Agent 使用不同 `agentKey()`;如还要隔离文件,则使用不同 conversation 或子目录 |
---