HippoBuddy:从"框架驱动"到"能力驱动"
AI 时代的 Agent 框架:从"框架驱动"到"能力驱动"
缘起
以安装量、Pull Requests 数量和 Stack Overflow 讨论热度来看,当前市场上 AI Agent 框架绝大多数以 Python 为主(LangChain、CrewAI、AutoGPT 等),背后原因有历史的惯性,也有生态的路径依赖:
- LLM SDK 优先支持 Python — OpenAI、Anthropic、HuggingFace 的 SDK 首发都是 Python
- 学术界的传承 — 深度学习/CV/NLP 的研究几乎全用 Python,研究者进入工业界自然延续
- Jupyter 文化 — Agent 开发本质是实验驱动,Python 的 REPL + Jupyter 迭代极快
但HippoBuddy 选择了 Java 21。这不是技术上的逆流而行,而是一次有意识的架构判断:Agent 的核心复杂度不在"调用 LLM",而在"构建可靠的自动化系统"——这正是 Java 生态积累数十年的强项。
核心洞察:框架在 AI 时代的角色变化
框架的黄金时代
在 AI 爆发之前,框架的价值无可争议:
你想做一个 Web 项目 →
需要 HTTP、路由、MVC、ORM、事务管理、DI…
自己写?半年没了
→ 用 Spring Boot,一天搞定 ✅
框架的本质是**"将大量重复的基建封装好,让你专注于业务"**。
AI 时代的转折
但 Agent 开发的"基建"发生了根本变化:
你想做一个 Agent →
需要 LLM 调用、Tool Calling 循环、消息管理、Prompt 模板…
自己写?—— 让 AI 帮你写
"帮我写一个 Tool Calling 循环,
LLM 返回 function_call 时解析参数并执行本地工具"
→ 30 秒生成,5 分钟调通 ✅
旧世界:
框架价值 = 节省的工作量 - 学习成本 - 约束成本
≈ 巨大,因为手写太难
AI 时代:
框架价值 = 节省的工作量 - 学习成本 - 约束成本
≈ 变小,因为 AI 能帮你手写大部分基建
框架解决的是"旧问题",不是"新问题"
| 框架 | 擅长的旧问题 | Agent 场景的实际需求 |
|---|---|---|
| Spring | 事务管理、ORM、AOP | Agent 不需要数据库事务 |
| LangChain | Chain、Agent、Memory 抽象 | Prompt 改一下比改框架配置快 10 倍 |
| Hibernate | ORM 映射 | Agent 状态是对话消息,不是关系型数据 |
| MyBatis | SQL 映射 | 同上 |
Agent 真正需要的东西,框架反而帮不上忙:
| 真实需求 | 解决方案 | 需要框架吗? |
|---|---|---|
| 调 LLM API | OkHttp + Jackson 发 HTTP | ❌ 10 行代码搞定 |
| 解析 Tool Call | JSON 反序列化 | ❌ Jackson 一行注解 |
| 执行本地工具 | 接口 + 实现 | ❌ 7 行接口定义 |
| 管理对话历史 | List<Message> | ❌ ArrayList 就够了 |
| SSE 流式响应 | OkHttp SSE | ❌ 一个库依赖搞定 |
Agent 的核心复杂度不在基础设施,而在 prompt 设计和工具编排——这两样框架帮不了你,甚至会限制你。
HippoBuddy 的架构选择
不用框架,用"模式"
HippoBuddy 的 Java 后端没有使用任何重量级框架——没有 Spring、没有 LangChain4j、没有 Guice。取而代之的是一套轻量的、手写的架构模式:
1. 手动 DI,而非自动注入
// CoreModule.java — 按层级手动组装依赖
ServiceLocator.registerSingleton(ToolRegistry.class, toolRegistry);
ServiceLocator.registerSingleton(LlmClient.class, llmClient);
ServiceLocator.registerSingleton(ConcurrentToolExecutor.class, concurrentToolExecutor);
没有 @Autowired、没有 @Bean、没有组件扫描。每个服务的生命周期和依赖关系都显式声明,可追踪、可调试。
2. 接口约定,而非框架注解
// ToolExecutor.java — 7 行接口定义一切
public interface ToolExecutor {
String getName();
String getDescription();
String getParametersSchema(); // JSON Schema 字符串
String execute(JsonNode arguments) throws ToolExecutionException;
}
每个工具就是一个接口实现,没有装饰器、没有基类继承链、不需要理解框架的"正确用法"。
3. 直接使用 JSON Schema,而非框架抽象
// ReadFileTool.java — Java 21 文本块直写 Schema
@Override
public String getParametersSchema() {
return """
{
"type": "object",
"properties": {
"path": { "type": "string", "description": "文件路径" },
"offset": { "type": "integer", "description": "起始行号" },
"limit": { "type": "integer", "description": "读取行数" }
},
"required": ["path"]
}
""";
}
LLM 理解的格式就是 JSON Schema,中间不需要任何框架做"二次翻译"。
为什么不选专属 AI 框架
Java 生态也有专门的 AI 框架——Spring AI 和 LangChain4j。没有选择它们,同样基于对 AI 时代框架角色的判断:
1. AI 编码时代,快速变动的框架反而是负担
如今项目的代码大量由 AI 生成,但 Spring AI、LangChain4j 仍在快速迭代期,API 变动频繁。AI 模型对这些"年轻框架"的知识覆盖有限且容易过时——你问它"Spring AI 怎么调 tool calling",它给出的代码很可能基于旧版本 API,跑起来全是 NoSuchMethodError,最终还得翻官网文档校准。与其让 AI 去学一个它学不准的框架,不如让它直接生成最稳定、最底层的 HTTP + JSON 代码——OpenAI API 规范已经一年没变了,这部分知识 AI 掌握得远比对框架准确。
2. 框架封装的能力,AI 生成更快、更可控
Spring AI 的 ToolCallback、LangChain4j 的 ToolSpecification,本质都是对"调 LLM API → 解析 JSON → 调本地方法"这一流程的封装。但让 AI 直接写这个循环,5 分钟就能得到一段无依赖、可单步调试的代码。框架帮你省的那点工作量,在 AI 编码能力面前可以忽略不计,而换来的是对每一行代码的完全掌控。
3. 复杂功能终究要自己写,框架反而变成天花板
一旦你的 Agent 需要框架没有预设的功能——比如工具级别的缓存、文件锁、并发控制策略、自定义安全拦截链——框架的抽象就会成为障碍。你要么 hack 框架的内部 API(升级兼容噩梦),要么绕开框架自己再套一层(那不如一开始就不用)。Agent 领域的"复杂功能"正在被快速定义,绑定一个框架相当于默认接受了它对"什么算复杂"的假设。
这些选择带来的自由度
因为去掉了框架的约束,HippoBuddy 可以自由地实现很多 Python Agent 框架里难以做到的事情:
| 能力 | 实现方式 | 框架下的难度 |
|---|---|---|
| 文件缓存 | ReadFileTool 内置 LRU 缓存,避免重复读盘 | LangChain 的 Tool 是 stateless 的,得自己套一层 |
| 安全拦截链 | BlockerChain 在工具执行前做权限/安全检查 | AgentExecutor 没有这个 hook 点 |
| 事件监控 | EventBus 发布工具执行事件,用于监控和统计 | 需要继承框架的 callback 机制 |
| 并发工具调用 | 虚拟线程 + ConcurrentToolExecutor,同步写法跑并发 | asyncio 会传染整个调用链 |
| 文件锁 | requiresFileLock() 控制工具间文件互斥 | Python Agent 基本没人做 |
| 精细错误处理 | LlmApiException / LlmConnectionException / LlmTimeoutException 分层异常 | 通常一个 APIError 全兜了 |
JSON Schema 定义工具
每个工具通过 getParametersSchema() 返回 JSON Schema 字符串定义参数结构,ToolRegistry 统一注册,Jackson 统一序列化,构建 tools 参数列表并传给 LLM 进行 function calling。
工具执行流程:
LLM 返回 tool_call (JSON)
→ ToolRegistry.execute(name, arguments)
→ BlockerChain 安全检查
→ ToolExecutor.execute(JsonNode)
→ 返回结果字符串
→ 结果追加到消息列表
→ 继续下一轮 LLM 调用
与 Python Agent 的对比
Python Agent 的常见问题
# Python + LangChain 的典型痛苦
from langchain.agents import AgentExecutor
# 想自定义工具执行逻辑?
# → 得继承 BaseTool,实现 _run + _arun
# → 想改 agent prompt?得重写整个 agent 类
# → 想并发执行?AgentExecutor 不支持
# → 想加中间件?没有 hook 点
HippoBuddy 的对应解法
// 实现接口,仅此而已
public class CustomTool implements ToolExecutor {
@Override
public String execute(JsonNode arguments) {
// 完全自由——想加缓存、加锁、加日志、加监控都可以
// 不需要遵循任何框架的"正确姿势"
}
}
对比总结
| 维度 | Python Agent (LangChain) | HippoBuddy (Java) |
|---|---|---|
| 上手速度 | 快,pip install 即用 | 慢一点,但有 AI 辅助编码 |
| 灵活度 | 框架约束多,定制困难 | 无约束,完全自由 |
| 类型安全 | 运行时才能发现类型错误 | 编译期捕获大部分错误 |
| 并发模型 | asyncio 传染,心智负担重 | 虚拟线程,同步写法 |
| 桌面端 | 需额外套 Electron/PyQt | 原生集成 Electron |
| 企业集成 | 需额外桥接 Java 技术栈 | 天然融入 Java 生态 |
| 生产部署 | 环境管理复杂(pip env) | Maven shade 单 JAR 搞定 |
| 框架版本升级 | LangChain 破坏性变更频繁 | 无框架,永远不需要升级 |
对 AI 时代软件工程的思考
框架的定位正在变化
以前:框架 = 你能做出来的上限
现在:框架 = 你能做出来的下限(而且可能是瓶颈)
什么时候该用框架?
框架依然有价值,但要重新评估:
| 场景 | 建议 | 理由 |
|---|---|---|
| 团队有成熟技术栈 | 沿用现有框架 | 降低团队切换成本 |
| 核心业务无关 | 使用框架 | 日志、配置、监控等,没必要自己写 |
| Agent 核心逻辑 | 自己写 | 这是你的核心差异化,框架帮不了你 |
| 实验性项目 | 框架快速验证 | 验证可行后再考虑去框架化 |
为什么"自己写"在 AI 时代可行了?
因为在传统开发中,写一个 Tool Calling 循环你需要:
- 理解 HTTP 请求和 SSE 流式响应
- 掌握 JSON 序列化/反序列化
- 设计状态管理(消息列表)
- 处理错误和重试
- 设计工具注册和发现机制
这每一项都需要查阅大量文档和代码示例。
而在 AI 时代,你只需要对 LLM 说:
"帮我写一个 Java 方法,接收 LLM 的 chat completion 响应, 解析其中的 tool_calls,根据 tool name 找到对应的执行器, 传入参数执行,把结果包装成 tool message 返回。"
30 秒后,你就有了一份可运行的代码。 剩下的就是根据你的具体需求做调整——而这正是框架最限制你的地方。
结语
HippoBuddy 的架构选择背后的核心哲学是:
AI 时代,最好的"框架"就是没有框架。
不是因为框架不好,而是因为框架解决的是"已知问题", 而 Agent 领域还在快速演化,每天都有"未知问题"出现。
用灵活的架构 + AI 的编码能力,比绑定任何一个框架都更能应对变化。
这也解释了 HippoBuddy 技术栈选择背后的逻辑:
| 问题 | 回答 |
|---|---|
| 为什么用 Java? | 类型安全 + 虚拟线程 + 企业级生态,Agent 是系统不是脚本 |
| 为什么不用 Spring? | Agent 不需要 ORM/事务/AOP,手写 DI 更可控 |
| 为什么不用 LangChain4j? | Tool Calling 的核心就是一个循环,自己写比学框架快 |
| 为什么用 Electron? | 桌面端是最好的 Agent 交互形态,Electron 是 Java 后端最自然的搭档 |
| 为什么能自己写? | 因为 AI 让手写基建的成本从"数月"降到了"数分钟" |
这就是 HippoBuddy 的架构哲学:不追随框架潮流,而是用最适合的方式构建真正可用的 AI Agent。