我是怎么把一个普通 AI 聊天项目改造成工程化 Agent Runtime 的

我是怎么把一个普通 AI 聊天项目改造成工程化 Agent Runtime 的

大二,学 Java 后端,想做点和 AI 有关的项目,然后 fork 了一个现成的面试平台。

结果就一发不可收拾地折腾了好几个月,把它改造成了一个有 Trace、Memory、Approval、Guardrail、多步预算控制的工程化 Agent 系统。

这篇文章就是想聊聊这个过程------我是怎么想的,踩了哪些坑,以及什么设计让我觉得"这才对"。


起点:一个"会调 API 的聊天页"

说实话,一开始 fork 下来的项目,AI 能力就是:把用户消息塞进 Prompt,调一下大模型,把回复展示出来。

这没什么问题,能跑,功能也完整------简历解析、模拟面试、知识库问答都有。

但它有一个根本性的问题:模型输出直通执行,没有任何 Agent 化的治理边界

什么叫"直通执行"?就是模型说什么就是什么,没有工具注册、没有 trace、没有失败收口、没有状态管理。这在 demo 里没问题,但一旦想把它做成可维护、可调试、可演进的东西,就彻底撑不住了。

所以我给自己定了一个目标:把它改成一个清楚知道自己在干嘛的 Agent 系统


第一步:把"聊天"改成"Turn"

最先做的事,是引入 Turn(执行单元) 的概念。

原来的系统没有 Turn,只有 Message。每次用户发消息,就是追加一条记录,完全是流水账。

问题在哪?你不知道这条消息是否被处理过、处理到哪一步了、有没有失败。如果中途出错,你只能看日志猜。

我引入 Turn 之后,每一次 Agent 请求都变成了一个有生命周期的执行单元:

复制代码
STARTED → PROCESSING → SUCCESS / DEGRADED / FAILED

Turn 有租约控制,同一个会话不能并发跑两个 Turn。这一个改动,把"调模型"变成了"执行一次可审计的 Agent 决策"。

感觉是质变,不是量变。


第二步:Trace 让 Agent 行为变得"可看"

Turn 有了之后,下一个问题:Agent 到底在干什么,我怎么知道?

之前的答案是:看日志。问题是日志是流式输出,没有结构,找个问题要翻半天。

所以我做了 Trace 系统。每一步 Agent 行为------输入 guardrail 校验、决策生成、工具调用开始/结束、委派、审批等待------都会落一条 Step Trace,带 statusstartTimedurationMstoolOutput

java 复制代码
// 工具执行前:开始 trace
traceService.startToolStep(turnId, toolName, toolInput);

// 工具执行后:记录结果
traceService.completeToolStep(turnId, toolOutput);

前端有个 Agent Workbench,可以看到每个 Turn 的完整执行链路,哪步花了多久、工具返回了什么、是否触发了 guardrail。

这个东西做完之后,我第一次觉得:"这才是 Agent,不是聊天页。"


第三步:工具调用 + 统一输出归一化

Agent 真正有用,是因为它能调工具。我给系统注册了两个只读工具:

  • read_resume:读取用户简历画像
  • search_knowledge_base:检索知识库(走 pgvector + RAG 链路)

但光有工具还不够,工具的输出格式必须统一,否则 Prompt 组装、Memory 写回和 Trace 记录都要分别处理,维护成本会炸。

我设计了 AgentToolResult 这个统一视图:

java 复制代码
// 每个工具都输出这个结构
AgentToolResult {
    summary,         // 给 Prompt 的一句话摘要
    answerPayload,   // 结构化答案(给 LLM 用的上下文)
    debugPayload,    // 调试信息(不进 Prompt,只给工作台)
    confirmedFacts   // 可信事实(写入 Memory)
}

这个设计的好处是:不管是简历工具还是知识库工具,输出进来之后,Prompt 组装、Memory 更新、Trace 记录走的是同一条路,不需要为每个工具写专属逻辑。

后来 handoff(受控委派)也直接输出 AgentToolResult,workbench 不需要为委派单独发明一套展示协议。这个决定省了很多事。


第四步:Guardrail 和 Approval------让 Agent 有约束

这是我觉得最有意思的一个设计决定。

很多 AI 项目在"安全"上的做法是:事后判断输出是否有问题。但这个思路有个根本问题------工具如果有副作用,你执行完再发现不合适,已经晚了

所以我的 Guardrail 和 Approval 都发生在执行之前:

  • Input Guardrail:用户输入先过一遍校验,不符合的直接拦截,不进入 Agent 决策链路
  • Tool Guardrail :高风险工具调用,resolveDecision() 会标记需要人工审批
  • Approval:真正的工具执行挂起,等待审批通过后才继续

审批通过后的恢复逻辑我设计了三种语义:

恢复路径 场景
EXECUTE_TOOL trace 还在 WAITING_APPROVAL,工具尚未执行,批准后可以安全执行
FINALIZE_FROM_TRACE 工具已执行完毕,直接从 trace 恢复结果,不重跑
BLOCK_REPLAY trace 状态不明,为防止副作用重复,显式阻断并降级

这三条路走下来,审批恢复的正确率 100%,没有出现过"重复执行同一个工具"的情况。


第五步:Memory,真正减少重复劳动的地方

这是做完之后最有成就感的一个模块。

Agent 多轮对话最大的问题不是"记不住",而是重复读取已知信息 。第一轮读了一次简历,第二轮还会再去 read_resume 一次,因为 Prompt 里没有记住"我已经知道这份简历的关键信息了"。

我用结构化 Memory 解决了这个问题:

复制代码
memory {
    phase: INTERVIEWING,
    confirmedFacts: ["候选人熟悉 Spring Boot", "有 Redis 使用经验"],
    nextFocus: "深入追问分布式锁的使用场景",
    usedTools: ["read_resume"]
}

Memory 在每次工具调用后写回,下次 Turn 装配上下文时先读 Memory,usedTools 里有的就不再重复调用。

量化结果:在 9 组固定 Memory 样本测试中,重复工具读取从 3 次降到 0,重复事实确认从 2 次降到 0。

这让 Agent 在多轮任务里的行为开始变得像"有记忆的人",而不是"每次都从零开始的机器"。


第六步:多步执行 + 预算控制

单步 Agent 够用,但有些任务需要多步决策------检索知识库,再基于结果出追问题,再评估答案。

我加了受控多步 loop,但默认不开,需要显式传 runtimeConfig.multiStepEnabled=true 才会进入。

多步执行有三类预算:

  • maxSteps:最多执行几步
  • maxDurationMillis:最多跑多少毫秒
  • maxEstimatedModelTokens:预估 Token 上限

任意一个触发,就进入降级收口,不继续跑。terminalState 统一给 UI 和 metrics 提供语义,不是简单的"成功/失败"。


踩坑集锦

做这个项目让我对"Agent"的理解从"调大模型"变成了"工程化编排",但过程里也踩了不少坑:

坑1:pgvector 向量表不自动创建

initialize-schema: false 时 Spring AI 不创建 vector_store 表,启动就报错。开发环境记得设 true

坑2:JPA ddl-auto 第一次用 create,以后必须换成 update

第一次启动 create 没问题,下次重启就把所有数据库表删掉重建了......把测试数据全搞没了,痛一次就记住了。

坑3:Redis Stream Consumer 不够健壮

简历分析任务失败后,Consumer 没有正确 ACK,导致同一条消息被重复消费了 3 次。后来统一加了重试计数和死信队列逻辑。

坑4:SSE 不能走 axios

知识库问答的流式响应走 SSE,结果发现 axios 的拦截器会等全部数据到了再 resolve,流式输出就没了效果。前端改成直接 fetchReadableStream


写在最后

这个项目做到现在,我觉得最大的收获不是某个具体技术,而是对"Agent 工程化"有了真实感受。

大模型调 API 很容易,但 "让 Agent 行为可解释、可约束、可调试、可演进",才是真正难的地方

Turn、Trace、Memory、Guardrail、Approval------每一个模块单独看都不复杂,但它们组合在一起,才让 Agent 从一个"聊天页"变成了一个有执行状态、有安全边界、可以持续迭代的系统。

如果你也在做 Java 后端方向,想找一个把 Spring AI 用深的实践项目,这个方向真的值得搞。

代码在 GitHub:[Kiyra-gjx/interview-guide](

相关推荐
PythonFun1 小时前
WPS AI隐藏玩法!自定义指令让办公效率起飞
人工智能·wps
weixin_417197051 小时前
王府井来了个新店员:穿机械骨骼,不会请假,还会表演节目
人工智能·机器人
lisw051 小时前
【计算机科学技术/AI领域】名词释义:词元(token)!
人工智能·机器学习·软件工程
qdprobot1 小时前
ESP32S3 AiTall V3 Mixly 图形化编程开发AI小智 MCP AIOT大模型对话开发视频教程Micropython小智AI系统
人工智能·micropython·esp32s3·图形化编程·mcp·mixly小智ai·大模型对话
AIGC安琪1 小时前
Transformer 和 LLM 到底是什么关系?
人工智能·深度学习·ai·语言模型·程序员·大模型·transformer
小e说说1 小时前
解锁孩子学习新姿势:告别厌学,玩学平台来助力!
人工智能
可爱の小公举1 小时前
Redis面试高频考点全解析
人工智能·学习·职场和发展·ai编程
小妖同学学AI1 小时前
告别手动盯盘!开源框架Freqtrade,教你用Python打造“永不下班”的AI交易员
人工智能·python·开源
IT_陈寒1 小时前
JavaScript的this又背刺我,这次真长记性了
前端·人工智能·后端