引言
随着大语言模型(LLM)的爆发,自主 Agent(Autonomous Agent)成为人工智能领域最受关注的方向之一。OpenClaw 作为一个典型的自主 Agent 项目,展示了如何通过多轮工具调用、上下文管理和多渠道接入,完成复杂任务的自动化。本文将基于 Spring AI 框架,从零开始构建一个类似的自主 Agent 系统,涵盖用户接入、会话管理、智能体运行、工具调用以及前端管理后台,完整呈现一个生产级 Agent 的架构设计与实现思路。
Spring AI 作为 Spring 生态系统中的 AI 抽象层,提供了统一的接口对接各大 LLM 提供商(如 OpenAI、Azure、Hugging Face 等),并内置了对函数调用(Function Calling)、提示词模板(Prompt Template)、输出解析等特性的支持,能够极大简化 Agent 的开发工作。
本文将使用 Spring Boot + Spring AI 从零搭建一套类 OpenClaw 的自主 Agent 系统,具有以下核心能力:
- 支持多渠道(Web、钉钉、企业微信、Telegram、WhatsApp 等)
- 会话级长期记忆 + 上下文自动压缩 - 每30分钟主动心跳检查待办事项
- 动态技能加载 + 工具链(文件、Shell、Web、子任务拆分等)
- 前端管理后台(聊天、子任务、技能、日志、模型切换)
一、整体架构与数据流
核心闭环如下(从用户输入到输出形成完整回路):

整个系统分为两大部分:后端闭环 (用户请求处理至最终响应)和前端管理(配置与监控)。后端闭环从多渠道用户请求开始,经过适配器标准化、网关路由、智能体运行、LLM 调用及工具执行,最终返回结果给用户。前端管理则提供对会话、子任务、调度、技能、日志和模型的统一管控。
二、核心模块详解
1. 环境准备
- JDK 21+
- Maven 3.8+
- Node.js 18+
- spring-ai 1.1.2
2. 多渠道适配器
- 为了支持 Web、钉钉、Telegram 等多种用户入口,我们需要设计渠道适配器层。每个渠道对应一个适配器实现,职责包括:
-
- 协议转换:将不同渠道的消息格式(如 HTTP JSON、WebSocket、钉钉回调)统一为内部消息对象。
- 订阅管理:处理渠道特有的订阅/推送机制(如钉钉的订阅消息、Telegram 的 Webhook)。 入站消息格式
arduino
/**
*入站消息
*/
public class InboundMessage {
/** 渠道: dingding, qqbot, web, etc. */
private ChannelType channel;
/** 发送者的唯一标识 */
private String senderId;
/** 渠道的唯一标识 */
private String chatId;
/** 消息内容 */
private String content;
/**
* 生成会话的唯一标识
*
*/
public String getSessionKey() {
return channel + ":" + chatId;
}
}
出站消息格式
arduino
public class OutboundMessage {
/** 渠道 */
private ChannelType channel;
/** 渠道标识 */
private String chatId;
/**消息内容 */
private String content;
/** 回复的userId */
private String replyTo;
}
消息管理
swift
public class MessageBus {
/**进站消息队列管理 */
private final BlockingQueue<InboundMessage> inbound = new LinkedBlockingQueue<>();
/**出站消息队列管理*/
private final BlockingQueue<OutboundMessage> outbound = new LinkedBlockingQueue<>();
/**订阅关系管理*/
private final Map<String, List<Consumer<OutboundMessage>>> outboundSubscribers = new ConcurrentHashMap<>();
/**提供消息分发的能力*/
private void dispatchLoop() {}
}
针对上面的消息,将不同的渠道消息进行转换,以下是常见渠道实现方式对比(2026主流做法):
| 渠道 | 推荐方式 | 难点 |
|---|---|---|
| Telegram | long-polling / Webhook | 文件下载、inline keyboard |
| 钉钉 | 机器人 stream 模式 | accessToken 刷新、卡片消息 |
| Web | WebSocket + STOMP | 心跳、断线重连 |
| 企业微信 | 回调 + 被动回复 | 加密解密 |
3. 网关服务器
网关是整个系统的流量入口,主要承担:
- 会话管理:通过渠道 + 用户 ID 识别唯一会话,维护会话状态(如对话历史、上下文元数据)。当前系统采用的是文件存储的,存储在渠道+用户ID.json文件上。样例如下:
swift
* 样例数据:
* {"_type":"metadata","created_at":"2026-02-25T01:12:43.115946","updated_at":"2026-02-25T01:16:17.610407900","metadata":{},"last_consolidated":0}
* {"role":"user","content":"d盘目录","timestamp":[2026,2,25,1,12,43,183314900]}
* {"role":"assistant","content":"D盘目录结构如下:\n\n**主要目录:**\n1. **,这是你的工作目录。","timestamp":[2026,2,25,1,16,17,610407900]}
*/
- 消息路由分发:根据消息类型(普通聊天、子任务指令、调度请求等)将请求路由到对应的处理器。例如,聊天消息进入智能体运行流程,技能配置请求则进入管理服务。
4. 智能体运行核心
这是 Agent 的大脑,负责与 LLM 交互并驱动任务执行。主要包含以下组件:
-
模型选择器 :根据会话配置或任务类型动态选择 LLM 模型(如 GPT-4、Claude、通义千问等)。Spring AI 的
ChatModel抽象支持切换不同提供商。 -
提示词组装器:动态构建发送给 LLM 的提示词,通常包含:
- 系统提示词:定义 Agent 的角色、行为准则、可用工具描述,通过读取AGENTS.md, SOUL.md, USER.md, TOOLS.md,Identity.md 去实现。
- 历史提示词:从会话上下文管理器获取之前的对话摘要或完整消息。
typescript
// 从会话上获取消息
public List<Map<String, String>> getHistory(int maxMessages) {
int start = Math.max(0, messages.size() - maxMessages);
List<Map<String, String>> result = new ArrayList<>();
for (int i = start; i < messages.size(); i++) {
result.add(messages.get(i).toLlmFormat());
}
return result;
}
dart
// 追加到上下文上面
for (Map<String, String> msg : history) {
Map<String, Object> historyMsg = new LinkedHashMap<>();
historyMsg.put("role", msg.get("role"));
historyMsg.put("content", msg.get("content"));
messages.add(historyMsg);
}
- 技能提示词:当前可用工具的详细描述(名称、参数、返回值)。
go
public String buildSkillsSummary() {
List<SkillInfo> allSkills = listSkills(false);
if (allSkills.isEmpty()) {
return "";
}
StringBuilder xml = new StringBuilder();
xml.append("<skills>\n");
for (SkillInfo skill : allSkills) {
xml.append(" <skill available="").append(skill.isAvailable()).append("">\n");
xml.append(" <name>").append(escapeXml(skill.getName())).append("</name>\n");
xml.append(" <description>").append(escapeXml(skill.getDescription())).append("</description>\n");
xml.append(" <location>").append(skill.getPath()).append("</location>\n");
xml.append(" </skill>\n");
}
xml.append("</skills>");
return xml.toString();
}
-
上下文窗口管理器:当对话历史超过模型 token 限制时,自动进行摘要或截断。
-
心跳查询:每隔 30 分钟(可配置)读取HEARTBEAT.md文件,并且向LLM模型询问是否需要主动执行后台任务(如定时检查邮件、监控数据)。
5. LLM API 调用与工具使用
Spring AI 的 ChatClient 提供了流畅的 API 用于调用 LLM。核心步骤如下:
ini
String finalContent = null;
// 获取所有的工具
var toolCallbacks = toolRegisterManager.getToolCallbacks();
try {
// 调用LLM带工具方式
var response = chatClient.prompt()
.messages(messages)
.toolCallbacks(toolCallbacks)
.call();
String content = response.content();
if (content == null || content.trim().isEmpty()) {
finalContent = "No response from AI.";
} else {
finalContent = content;
}
} catch (Exception e) {
log.error(e);
finalContent = "Error during processing: " + e.getMessage();
}
return finalContent;
- 工具传入 :通过
toolCallbacks方法注册可用的工具函数。这些工具需要实现ToolCallback接口。Spring AI 会自动将工具描述和调用逻辑传递给支持函数调用的模型。在类org.springframework.ai.model.tool.DefaultToolCallingManager#executeToolCall上实现的。
ini
String toolCallResult = ToolCallingObservationDocumentation.TOOL_CALL
.observation(this.observationConvention, DEFAULT_OBSERVATION_CONVENTION, () -> observationContext,
this.observationRegistry)
.observe(() -> {
String toolResult;
try {
toolResult = toolCallback.call(finalToolInputArguments, toolContext);
}
catch (ToolExecutionException ex) {
toolResult = this.toolExecutionExceptionProcessor.process(ex);
}
observationContext.setToolCallResult(toolResult);
return toolResult;
});
toolResponses.add(new ToolResponseMessage.ToolResponse(toolCall.id(), toolName,
toolCallResult != null ? toolCallResult : ""));
-
工具执行:LLM 在响应中可能包含工具调用请求,系统解析后执行对应工具,并将结果作为新的消息再次调用 LLM(智能体循环)。
-
基础工具集:
- 文件/目录管理:创建、读取、写入、删除文件,列出目录。
- 命令执行:在沙箱环境中执行 shell 命令(需严格权限控制)。
- Web 查询:调用搜索 API 或抓取网页内容。
- 子任务生成:将复杂任务拆分为多个子任务,并提交给调度器异步执行。
6. 智能体循环
当 LLM 返回的响应包含工具调用请求时,Agent 不会立即结束,而是进入循环:
- 解析工具调用,执行对应工具。
- 将工具执行结果封装为
ToolResponseMessage。 - 携带历史消息和工具结果再次调用 LLM。
- 重复直到 LLM 返回最终文本响应或达到最大循环次数。 Spring AI 的
ChatClient内置了对工具调用循环的支持,可以通过call()自动处理,开发者只需提供工具实现即可。
7. 前端管理能力
为了方便运维和调试,我们需要一个管理后台,通常采用 Vue/React 实现,通过 REST API 与后端交互。关键功能模块:
- 聊天界面:模拟用户与 Agent 的对话,支持查看完整交互日志(包括工具调用过程),方便测试验证。

-
子任务管理:展示由 Agent 生成的子任务列表,查看执行状态、结果。
-
调度配置:设置定时任务(如心跳间隔、自动清理策略),以及周期性任务的触发规则。

- 技能管理:动态注册、禁用或更新工具函数,无需重启服务。可通过文件存储工具定义,运行时动态加载。

- 日志审计:记录所有请求、工具调用、错误信息,便于问题追踪。

- 模型管理:配置可用的 LLM 模型列表(API Key、端点、参数),切换后需要重启服务。

总结与展望
本文基于 Spring AI 设计并实现了一个类 OpenClaw 的自主 Agent 系统,涵盖了多渠道接入、会话管理、智能体运行、工具调用、心跳机制以及前端管理功能。Spring AI 提供的抽象能力大大简化了与 LLM 的集成,使开发者能够专注于业务逻辑和工具开发。
未来可以进一步优化:
- 引入向量数据库,实现长期记忆和 RAG 增强。
- 更精细的权限控制,防止工具滥用。
- 分布式 Agent 集群,提升任务处理能力。
- 引入MCP的能力 ,丰富其他的接入渠道等。