这篇解决什么困惑

刚开始学 Agent 时,我最容易产生的错觉是:是不是要先把 Java 放下,改学 Python、向量数据库和一整套新框架?真正做完一个证据型 Agent 的前几个里程碑后,我的答案变成了:语言不是第一道门槛,控制不确定性的能力才是。

Java 后端经验并没有失效。接口契约、数据库事务、认证、异常分类、测试、容器和发布链路,仍然构成服务的骨架。变化在于,普通后端通常执行明确分支,而 Agent 把一部分“下一步做什么”交给模型。模型输出有概率性,会遗漏字段、引用不存在的对象,甚至把外部文本里的指令当真。于是工程重点从“业务代码能跑”扩展为“即使模型不可靠,系统也必须可控”。

关键结论

我的迁移路线不是从 Java 跳到 Python,而是从确定性服务逐步进入概率性系统:

  1. 保留 Java 的控制面:认证、状态、预算、工具、持久化和最终校验由程序掌握。
  2. 把模型放进严格边界:输入有上限,输出有 Schema,引用只能来自已观察集合。
  3. 用固定样本和真实失败推进设计,而不是先堆框架。
  4. 只有当 Python 能提供已测量的质量或交付优势时,才引入第二运行时。

从整体到局部

这个项目按“来源 → 信号 → 主张 → 证据 → 判断”展开。M0 先证明 Java 服务、数据库、模型网关和部署链路成立;M1 增加来源抓取、去重和失败隔离;M2 才做主张抽取、证据定位、相关性、检索和带引用回答;M3 再把这些能力放进受限 Agent Loop。

这个顺序对我很重要。若一开始就搭 Agent Loop,我很难判断失败来自模型、抓取、检索、状态管理还是部署。拆成里程碑后,每一层都有自己的契约和测试,Agent 只是组合这些可靠能力,而不是用一个大提示词掩盖所有问题。

可以把技术栈变化理解成三层:

  • 不变的后端基础:Java、Spring、PostgreSQL、迁移脚本、HTTP、认证、CI 和容器。
  • 新增的模型边界:模型网关、结构化输出、提示词版本、供应商错误映射和用量元数据。
  • 新增的 Agent Harness:Loop、工具协议、预算、Completion Verifier、Trace 与恢复策略。

对应代码与测试证据

公开讨论只使用逻辑模块名。服务骨架由 bootstrap 和数据库迁移承担;采集链路位于 ingestion;证据的抽取、检索、相关性和合成位于 evidence;M3 的执行控制位于 agent/loop,模型决策适配位于 agent/runtime

证据不是“代码看起来合理”,而是多层测试:模型网关有契约测试,数据库有集成测试,采集有端到端和失败隔离测试,证据链路有固定集与真实模型可选评测,Loop 有步数、deadline、重复决策、伪造引用和恢复测试。真实模型测试默认不进入无密钥 CI,这也避免把外部服务稳定性伪装成代码稳定性。

我真正踩过的坑

第一个坑是把“接通 LLM”误认为“已经有 Agent”。Smoke Test 只证明 API Key、网络和模型配置可用,不包含上下文管理、工具执行或循环。

第二个坑是相信结构化输出会天然正确。真实模型曾返回错误 offset、空集合和非法状态。后来由 Harness 在唯一原文匹配时确定性修正 offset,其余情况拒绝;状态则通过严格枚举约束。这里的原则不是尽量猜对,而是无法证明时失败关闭。

第三个坑是过早争论 Java 还是 Python。实验显示,一次一进程的 Python Worker 增加了明显的进程边界成本,却没有改善当时的确定性决策质量。问题在策略,不在语言。

适用边界

这条路线适合已有后端经验、想做可部署 Agent 服务的人。它不会让人最快做出炫目的 Demo,却能更快发现哪些能力真的存在。若目标只是一次性数据分析或快速验证 Python 专属库,直接使用 Python 可能更省时间;若已有 Java 服务和数据资产,先保留控制面通常更稳。

当前与未来

当前 M0—M2 已完成,M3 正在进行。系统已有受限的 Search → Resolve → Decide → Verify → Stop 链路,但还不是 production-ready:持久化 checkpoint、生产级步骤与模型用量 trace、真实 Token/费用扣减、通用工具异常恢复以及对外 Agent API 仍未完成。M4 的人工审批与隔离实验执行也尚未开始。

我的下一阶段重点不是换语言,而是补齐这些 Harness 能力,并继续用固定回归集检验每次变化。若未来出现 Java 难以承载、而 Python 已证明有明显价值的能力,再通过窄协议把 Worker 接入,而不是迁移整个控制面。

更新时间:2026-08-18