# JavaClaw **Repository Path**: itjee/java-claw ## Basic Information - **Project Name**: JavaClaw - **Description**: 使用Java开发的ai agent. - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 1 - **Created**: 2026-05-13 - **Last Updated**: 2026-05-13 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # javaClaw 参照 [openClaw](https://github.com/openClaw) 原理使用 **Java** 重写的超轻量个人 AI 助手 原作者地址链接:[JavaClaw](https://github.com/laixiaoxing2026/javaClaw)在此基础上进行二次开发,使用SpringBoot进行重构并且新增和完善了相关功能。 *** ## 特性 - **多渠道**:**当前已实现对接的为 QQ 机器人**(WebSocket 网关 + 单聊发消息);钉钉(DingTalk)为预留,未与钉钉平台真正对接。通过消息总线与 Agent 解耦,便于扩展新渠道 - **LLM**:HTTP 调用任意 OpenAI 兼容 API(如 OpenAI、DeepSeek、Azure 等),由 `LLMProvider` 抽象 - **Agent + 工具**:多轮对话、记忆与技能、内置工具(消息发送、文件读写、Shell、MCP 等),LLM 通过 tool\_calls 与 MessageTool 等与渠道间接通信 - **轻量**:Java 17,Picocli CLI + YAML 配置,数据与工作区统一在 `~/.javaclawbot` - **安全**:API密钥保护机制,避免敏感信息泄露 - **用户友好**:终端输出优化,避免乱码,清晰展示AI回复与系统信息分离 *** ## 技术栈 | 类别 | 选型 | | --- | ------------------------------------------------------------ | | 语言 | Java 17+ | | CLI | Picocli | | 配置 | YAML + POJO(Spring Boot Configuration),路径统一为 **javaclawbot** | | LLM | HTTP 调用 OpenAI 兼容 API(`LLMProvider` 抽象) | | 渠道 | QQ(已对接,WebSocket 网关);钉钉(预留) | *** ## 示例 ### 网关模式,通过app来交互 通过 QQ 可以让其远程查看主机信息、执行文件操作等。 | !\[截图1]\(img/img.png null) | !\[截图2]\(img/img\_1.png null) | !\[截图3]\(img/img\_2.png null) | | :------------------------: | :---------------------------: | :---------------------------: | |
|
|
| ### agent模式 通过命令行交互 !\[img\_4.png]\(img/img\_4.png null) !\[img\_5.png]\(img/img\_5.png null) !\[img\_6.png]\(img/img\_6.png null) ### debug模式 手动调试 这样就可以本地调试 !\[img\_7.png]\(img/img\_7.png null) !\[img\_8.png]\(img/img\_8.png null) ### QQ机器人申请以及配置 qq渠道是最容易最简单的,三步即可,无任何卡点 第一步 登陆qq开放平台 第二步 创建机器人 !\[img\_9.png]\(img/img\_9.png null) 第三步 机器人配置 选择开发、沙箱配置,在消息列表配置 添加自己的QQ号,然后点击箭头指向的地方会弹出二维码 扫码关注即进入聊天,不需要发布到线上 !\[img\_10.png]\(img/img\_10.png null) 点击开发管理 就可以拿到机器人的app token等,然后配置到application.yml !\[img\_11.png]\(img/img\_11.png null) ### 配置说明 参考这里 ## [06-config.json 填写说明](docs/06-config.json%20填写说明.md) ## 模块设计介绍 | Java 包/模块 | 职责简述 | 对应 Python | | ----------------------------- | ---------------------------------------------------------------------------------------------------------------------- | ------------------------- | | **`agent`** | 核心 Agent:循环、上下文、记忆、技能、子 Agent、工具 | `nanobot/agent/` | | **`agent.AgentLoop`** | Agent 主循环:取消息 → 建会话/上下文 → 调 LLM → 执行 tool\_call → 写回复/会话 | `agent/loop.py` | | **`agent.ContextBuilder`** | 组装 system prompt、多轮 messages(含 tool 结果、assistant 消息) | `agent/context.py` | | **`agent.MemoryStore`** | 持久记忆:`MEMORY.md`(长期事实)+ `HISTORY.md`(可 grep 的日志) | `agent/memory.py` | | **`agent.SkillsLoader`** | 技能加载:workspace 与内置 skills 目录下的 `SKILL.md`,按需/常驻加载 | `agent/skills.py` | | **`agent.tools`** | 工具抽象与实现:文件读写/列表、shell、**message**(通过 bus 回发到当前会话)、MCP 等;执行时 params 由框架注入 channel、chatId、metadata | `agent/tools/` | | **`bus`** | 消息总线:`InboundMessage` / `OutboundMessage`,`MessageBus`(队列 + 出站分发) | `nanobot/bus/` | | **`channels`** | **QQ 已对接**,钉钉预留:`BaseChannel` 抽象 + `QQChannel`(完整实现)、`DingTalkChannel`(预留);收消息时 `handleMessage` → `bus.publishInbound` | `nanobot/channels/` | | **`channels.ChannelManager`** | 按配置初始化钉钉(预留)/QQ channel、启动 outbound 分发循环(`dispatchOutbound`) | `channels/manager.py` | | **`providers`** | LLM:`LLMProvider` 接口、实现类(如 `OpenAICompatibleProvider`)、Registry 按 model 选 provider | `nanobot/providers/` | | **`config`** | 配置 Schema(POJO):agents、channels.dingtalk、channels.qq、providers、gateway、tools 等;Loader 读 YAML 配置文件 | `nanobot/config/` | | **`session`** | 会话:按 `channel:chatId` 的 sessionKey 管理多轮对话历史与持久化 | `nanobot/session/` | | **`cron`** | 定时任务:Cron 配置与存储,到期通过 Agent 执行 | `nanobot/cron/` | | **`heartbeat`** | 心跳/主动唤醒(如定时拉活) | `nanobot/heartbeat/` | | **`cli`** | CLI:`javaClaw gateway`、`agent`、`onboard`、`status`、`cron` 等子命令 | `nanobot/cli/commands.py` | | **`skills`(资源)** | 内置技能 `SKILL.md` 文件,与 Python 版共用或复制一份 | `nanobot/skills/` | *** ## 架构与调用链 渠道与 Agent 通过 **MessageBus(消息总线)** 解耦:**QQChannel 不调用 MessageTool,MessageTool 也不调用 QQChannel**,二者都只与 MessageBus 打交道。 ### 1. QQChannel 与 MessageTool 的职责 | 组件 | 职责 | | --------------- | -------------------------------------------------------------------------------------- | | **QQChannel** | ① **收**:把 QQ 平台事件转成 `InboundMessage` 并投到总线② **发**:从总线拿到 `OutboundMessage`,调 QQ 接口真正发出去 | | **MessageTool** | Agent 的一个工具:当 LLM 要「给用户发一条消息」时被调用,只负责构造 `OutboundMessage` 并投到总线,**不直接调任何渠道 API** | 因此:MessageTool 不调用 QQChannel,两者都只和 MessageBus 交互。 ### 2. 一条完整调用链(执行顺序) 整体是「**QQ 进 → 总线 → Agent(可能用 MessageTool)→ 总线 → QQ 出**」: ``` 用户发消息到 QQ ↓ ① QQChannel(收) WebSocket 收到事件 → dispatchEvent() → handleMessage() → bus.publishInbound(InboundMessage) // 入队 ↓ ② AgentLoop bus.consumeInbound() 取到消息 → processMessage() → runAgentLoop() → 可能调用 LLM → LLM 返回 tool_calls,其中可能有 "message" → 执行 MessageTool.execute(params) ↓ ③ MessageTool 用 params 里的 channel、chatId、content、metadata 构造 OutboundMessage → bus.publishOutbound(OutboundMessage) // 入队 ↓ ④ ChannelManager.dispatchOutbound() bus.consumeOutbound() 取到 OutboundMessage → 根据 msg.getChannel() 找到 "qq" 对应的渠道 → QQChannel.send(msg) ↓ ⑤ QQChannel(发) send() 里调 QQ 开放接口 POST /v2/users/{openid}/messages → 用户端收到回复 ``` **先后顺序简述**: 1. **先执行**:QQChannel 的「收」逻辑(①),把 QQ 消息变成入站消息。 2. **中间**:AgentLoop + 可能用到的 MessageTool(②③),只和总线交互。 3. **后执行**:ChannelManager 从总线取到出站消息,再调用 QQChannel 的「发」逻辑(④⑤)。 ### 3. 设计原因 - **渠道与 Agent 解耦**:Agent(含 MessageTool)只认识「channel + chatId + content」,不关心具体渠道。发消息统一用 `bus.publishOutbound(msg)`,由 ChannelManager 根据 `msg.getChannel()` 决定交给哪个渠道的 `send()`。**当前已实现与平台对接的仅有 QQ 渠道**(钉钉为预留),加新渠道不用改 Agent / MessageTool。 - **MessageTool 只负责“要发什么”**:只把「发给谁、发什么」写成一条 `OutboundMessage` 丢进总线,不负责 HTTP/WebSocket 等具体发送。真正发 QQ 的是 `QQChannel.send()`,「业务决策(发什么)」与「渠道实现(怎么发)」分离。 - **一条总线串起收发**:入站 `QQChannel → publishInbound → AgentLoop consumeInbound`;出站 `MessageTool(或别的逻辑)→ publishOutbound → ChannelManager consumeOutbound → QQChannel.send()`。所有渠道和 Agent 都通过 MessageBus 通信,便于扩展和测试。 **一句话**:QQChannel 先收用户消息并写入总线,Agent 和 MessageTool 在中间消费、可能再往总线里写回复,最后由 ChannelManager 从总线取出回复并交给 `QQChannel.send()` 真正发到 QQ;两者通过 MessageBus 间接配合,而不是直接调用。 *** ## 构建与运行 ### 环境要求 - JDK 17+ - Maven 3.x ### 配置准备 1. **配置文件模板**:项目提供了 `src/main/resources/application.yml.template` 作为配置模板 2. **创建配置文件**:复制模板并命名为 `src/main/resources/application.yml` 3. **填写配置**:编辑 `application.yml` 文件,设置以下关键信息: - LLM API 密钥(如 DeepSeek、OpenAI 等) - QQ 机器人配置(如已对接) - 工作区路径等 ### 命令示例 ```bash # 编译 mvn compile # 打包可执行 JAR(含依赖) mvn package # 单条消息(CLI 模式) java -jar target/javaclaw.jar agent -m "你好" # 交互模式 java -jar target/javaclaw.jar agent # 启动 Gateway(钉钉/QQ 渠道 + Agent + 出站分发) java -jar target/javaclaw.jar gateway ``` *** ## 子命令 | 命令 | 说明 | | --------- | ------------------------------------------- | | `gateway` | 启动 Gateway(已配置的渠道 + Agent 循环 + outbound 分发) | | `agent` | CLI 运行 Agent(`-m` 单条或交互) | | `status` | 查看配置与工作区状态 | | `cron` | 定时任务管理(占位) | *** ## 配置 - **配置文件**:`src/main/resources/application.yml`(开发环境),`~/.javaclawbot/application.yml`(生产环境) - **数据目录**:`~/.javaclawbot` - **工作区**:`~/.javaclawbot/workspace` - **会话**:`~/.javaclawbot/sessions/` 配置项说明(agents、providers、channels.dingtalk / channels.qq、gateway、tools 等)见文档。 **注意**:`src/main/resources/application.yml` 包含敏感信息(如API密钥),已添加到 `.gitignore` 中。请使用 `application.yml.template` 作为模板创建配置文件。 *** ## 文档 | 文档 | 说明 | | ---------------------------------------------------- | ---------------------------------- | | [01-项目梳理-Java版](docs/01-项目梳理-Java版.md) | 架构、目录、流程与设计特点 | | [02-调用链-Java版](docs/02-调用链-Java版.md) | 程序入口、Gateway 启动、单条消息处理、直接调用、记忆合并 | | [03-接口文档-Java版](docs/03-接口文档-Java版.md) | 消息总线、渠道、LLM、工具、Agent、会话、技能、配置等接口 | | [05-最终技术方案-Java版](docs/05-最终技术方案-Java版.md) | 技术栈、路径约定、模块职责与扩展约定 | | [06-config.json 填写说明](docs/06-config.json%20填写说明.md) | 配置文件各节点与常见场景(注意:当前已使用 YAML 格式配置文件) | *** ## 关注作者 特别感谢原作者的开源,附上其联系方式 !\[qrCode.jpg]\(img/qrCode.jpg null) ## License 请以项目根目录或仓库标注为准。