Skip to content

AI 智能体请求生命周期 ​

本页解释一次聊天请求如何从 HTTP/外部渠道进入 Agent 运行时,如何经过队列和 session 执行器,最后以消息、SSE、轨迹和运行状态四种形式落地。阅读顺序建议结合请求链路与时序和智能体执行引擎。

1. 入口模式 ​

AiChatbotAgentController 的 /v1/chatbot/{agentId}/sessions/{sessionId}/chat 有三种行为:

请求组合服务端行为客户端下一步
stream=true&sse=sync当前请求直接获得 SseEmitter,边执行边推送持续消费 SSE,等待完成/错误
stream=true&sse=async用户消息先入队,返回 messageId先建立 /sse/connect,再消费流
stream=false同步等待 handleNormalChat 返回读取 R<T>,仍需判断业务终态

sessionId=new 时 Controller 先创建会话;已有 session 则验证 Agent、用户和租户归属。创建会话时可能同时绑定 FileRoom/Sandbox workspace,这个绑定会在后续 load_config 转换为 AgentConfig.sandboxRoomId,不能由每一轮请求随意替换。

2. 接受消息与持久化 ​

AgentChatServiceImpl 接受消息后生成或补齐以下标识:

标识生命周期用途
clientMessageId客户端请求级pause/resume/cancel 和用户消息去重
messageId队列消息级SSE、错误和队列日志关联
turnId用户一轮输入JSONL 聊天历史和分支投影
runId一次 Agent 执行checkpoint、轨迹、取消和计费关联
runVersionsession 当前运行版本CAS 更新,拒绝旧运行迟到事件
traceId可观测性上下文节点、LLM、工具、RAG 日志关联

启用 JSONL 持久化时,接受用户输入会先写入 session 事件账本,再提交队列;这样即使 worker 尚未启动,也能从 durable inbox 恢复。AgentMessage 会同时保留原始 content 和可供模型使用的 modelContent,附件链接、联网搜索模式、Bearer Token 和 billing 预冻结号也随消息传播。

3. 调度器分发 ​

CentralizedAgentMessageDispatcher 由一个 dispatcher 线程从 AgentMessageQueue.poll() 取消息,再按 sessionId 获取独占的单线程虚拟线程执行器:

调度不变量:

  • 同一 sessionId 的用户输入、resume、cancel 和子 Agent 回调 FIFO 串行。
  • 不同 session 可以并行,线程是虚拟线程,但底层模型/工具仍受各自连接池和限流约束。
  • submitLocal 用于回复目标保存在当前节点内存的外部 IM;直接放入共享队列可能导致消费节点找不到回调对象。
  • 队列实现可为 Memory、Redis 或 RocketMQ;切换实现不能改变 AgentMessage 字段语义。
  • 队列满、worker 拒绝和响应通道超时都必须写失败终态,不能只打印日志。

4. 智能体类型路由 ​

dispatcher 从数据库读取 AgentType 后选择执行器:

AgentType执行器说明
CHATBOTAiChatbotAgentFactory 创建的 Agent当前实现继承自主规划外壳
GENERATIONGenerationAgent内容生成型调用
TOOL_CALLToolCallAgent工具调用型调用
DOMAIN_EXPERTAutoPlanningAgent主动规划和 Agentic Loop
WORKFLOW当前抛出不支持异常不能假定已有工作流执行器

Agent 类型不存在或解析失败时当前代码会降级 AutoPlanningAgent;新增类型时必须同时更新 dispatcher、管理 API、前端选择项和恢复时的 graph 版本策略。

5. 单次智能体执行 ​

worker 进入 Agent 前会:

  1. 从 ChatSessionManager 读取活动 session,检查过期、状态和最大轮数。
  2. 从 AgentResponseChannelRegistry 等待可用响应通道,等待超时则失败并写 pending error。
  3. 绑定 McpSessionContext,让 @Tool、Feign/MCP 和 Sandbox 下游取得 session、Agent、user 上下文。
  4. 启动 ConversationContext 和 TraceLifecycle,记录原始用户输入、流式模式和 runId。
  5. 调用 Agent 的 processMessage,在 finally 中刷新响应快照、释放运行时和 active worker。

自主规划路径进入 AutoPlanningAgent 主图:

text
load_config -> intent_recognition -> web_search_prefetch -> planning
                 -> agentic_loop(init/reasoning/acting/refining/checkpoint)
                 -> task_end

主图、子图、路由信号和状态桥接详见智能体执行引擎。

6. 终态顺序 ​

一个运行可能出现 QUEUED、RUNNING、PAUSE_REQUESTED、PAUSED、COMPLETED、FAILED、CANCELLED 或 RECOVERY_BLOCKED。终态处理需要遵循以下顺序:

text
刷新 token buffer
  -> 写 assistant response snapshot
  -> 写最终轨迹/聊天历史
  -> 更新 run-control 和数据库运行状态
  -> 发送 complete/error/cancel 事件
  -> 释放 channel、LoopRuntime、active worker

客户端断线只代表传输通道不可用,不代表 Agent 取消。取消必须调用 /cancel;暂停必须等待 refining -> checkpoint 安全点。普通聊天 SSE 通过 pending event 和回答快照恢复,轨迹 SSE 通过 Last-Event-ID/sequence 恢复。

7. 失败与重试边界 ​

位置当前策略不应做的事
配置加载记录 error,跳过后续规划或直接进入 task end带空配置调用模型
LLM 调用按节点重试/记录 finish reason无限重试
工具调用工具节点最多三次外层尝试,并有超时兜底;Agentic Loop 另有 journal失败后无记录重跑副作用
RAG返回结果或错误字符串,由循环决定后续动作把空检索当成事实
channel等待有限时间,失败写 pending error阻塞 worker 永不退出
恢复版本、配置、surface digest 不一致时 RECOVERY_BLOCKED清空状态重新执行

排障时先按 runId -> messageId -> traceId -> sessionId 关联日志,再查看最后一个 graph node、工具 journal 和响应通道。不要只看 Controller 的 HTTP 200。