面向物理世界闭环的Agent

前言

年初 OpenClaw 爆火时,我希望 OpenClaw 能面向物理世界做交互,于是将OpenClaw 接入了 RDK X5 开发板,接入了负责输出的舵机和扬声器、以及提供系统输入的麦克风和摄像头,现成闭环,让 OpenClaw 机器与物理世界能进行简单的“伪 VLA”交互,制作了 RDK 550 机器人: 【AI Native】一行代码没写!OpenClaw帮我实现了《流浪地球》中的MOSS - 项目与案例 / 新手上路 - 地瓜机器人论坛


但…目前(2026年6月),已经没什么人提 OpenClaw 了,因为他的 BUG 实在太多了…tools 报错、上下文压缩完丢失、飞书通道的长链接失效…种种 BUG 让 OpenClaw 逐渐没落。

现在更加火爆的是 Codex、Claude Code、Cursor Gemini CLI 等“海外模型三巨头”推出的 AI Native 工具,他们具有十分强大的功能,但使用这些工具,他们只是让我们的开发、攥写、分析等工作更加便捷了,并没有催生出更加智能的实体机器人。


那么如果想将 Agent 应用于实体机器人,应该怎么做?用 OpenClaw 那一套系统吗?—— 既然是机器人开发,我觉得可以用 ROS2,ROS2 具有天然的去耦合通信优势,只要保证 Agent 循环不掉,环境输入、动作反馈等节点哪怕出问题,也可以及时被 Agent 捕捉到并修复。


一、架构设计

1.1. Agent 架构

和大部分 Agent 一样,Agent 采用 ReAct 架构,使用多轮思考,最终输出。

但与其他 Agent 不一样的是,这个架构会循环思考,架构禁止 Agent 返回 reply 消息,与用户交互的方式不再是简单地:

注入 role=user 消息 -> ReAct -> 返回 role=assistant

而是:

LoopAct -> input 子系统注入消息(包括接收用户消息) -> LoopAct -> output 子系统输出(包括向用户发送消息) -> LoopAct -> ...

另外再结合上下文压缩、记忆管理机制,就可以实现基本的 Agent 协作了。

其中, input 子系统和 output 子系统是一套热插拔的 Agent 输入输出系统,input 子系统用于搜索符合架构规定的 ROS2 话题与服务,例如视觉图像信息、声觉输入信息、系统状态信息、用户指令文本等,并将其注入 Agent Loop,output 子系统同样搜索符合架构规定的 ROS2 话题和服务,例如移动、跳跃、命令执行器、消息发送器等,将它们的使用方法转化为 LLM API 的 tools 字段(具体可以去看各模型厂商的 API 文档了解)。

  • ReAct 架构的 Agent 工作模式为一问一答,用户说“帮我…”,大模型思考、调用工具、循环几轮之后完成工作,向用户反馈结构,然后一轮工作结束;

  • 但是本架构下,Agent 一直在思考,用户说“帮我…”,Agent 会说“收到,马上去弄…”,工作过程遇到问题,或者需要建议,也会询问用户,工作完成后,再次通知用户。


1.2. Input 子系统

input_mgmt_node节点规范管理了所有输入的“传感器”,一个传感器节点需实现2个话题:

  • /<agent_name>/input/<name>/info:使用指定格式介绍“传感器”的基本信息,兼为输入“传感器”的心跳;

  • /<agent_name>/input/<name>:“传感器”的具体数据内容,为自由文本格式;

输入管理节点会持续检测/<agent_name>/input/<src>/info心跳,将活跃的 Input 节点信息注入大模型对话。

输入源有两种缓存模式:

  • accumulate:提供上次注入后的完整信息,适用于用户指令、偶发事件等一次性提醒;

  • lastest:提供上次注入后的最新消息,适用于实时图像、IMU数据、坐标等高频实时数据。

Input 子系统会根据输入源的缓存模式,拼接所有输入源为“快照”,以 user 的方式注入对话。


1.3. Output 子系统

output_mgmt_node 节点统一管理所有输出"工具",一个工具节点需实现:

  • /<agent_name>/output/<name>/info:OpenAI function-calling 格式的 JSON 工具描述,兼为节点心跳;

  • /<agent_name>/output/<name>ExecuteTool 类型的 action,接收 input_json(对应 LLM 的 tool_call.arguments)和 timeout_sec,返回 output_json + exit_code

输出管理节点持续检测/<agent_name>/output/*/info 心跳,自动发现活跃工具并注入大模型对话的工具列表。

工具调用流程:

  1. LLM 输出 tool_callsagent_loop_node 解析

  2. → 构造 {name, arguments} 发送到 /{agent}/output action

  3. output_mgmt_nodename 路由到对应工具节点

  4. → 工具执行完毕,结果透传回 LLM

输入管理节点有以下特性:

  • 自动发现:扫描 /<agent_name>/output/*/info,发现新工具自动注册

  • 心跳管理:info 超时 3s 未更新则移除,工具节点崩溃自动检测

  • JSON 自修复:LLM 输出的 tool_call 参数若有尾逗号/括号不全,自动修复

  • 并发控制:同一工具同时只允许一个 Goal 执行,防止竞态

  • 超时控制:支持 timeout_sec 超时,超时后主动 Cancel 子工具

  • 结果透传exit_code=0 透传为成功,exit_code≠0 透传为失败

在开发新工具时,只需实现 info 话题 + ExecuteTool action 即可,output_mgmt_node 将会自动发现。


1.4. 记忆管理节点

本架构的记忆管理方法也采用了一种巧妙的方法,底层是存储于 Git 仓库。主要有三个部分:

  • 规则文件:RULE.md、MASTER.md、METHOD.md、WORLD.md。这些是持久记忆,每次启动都会读到上下文里。

  • 日记diaries/YYYYMMDD.md,每天一个文件。每条日记带机器码前缀,知道是哪台机器上写的。

  • 对话快照data/diary/UTC时间-adam.json,每轮完整上下文存一份。写完 → git push,云端同步。

所有写操作都是原子化的:先写临时文件 → fsync → rename → git 提交推送,多终端同时推送时也能合法处理冲突。

这样一来,只要在不同的终端指定同一个 SSH 可达的 Github 记忆仓库,就实现了同一个 Agent 记忆在不同实体中运行。


二、项目实现

目前项目已经可以基本稳定测试,所有源码开源到了 Github 中,链接附上(欢迎star):

hachi-leaf/Cloud-Soul: 基于 ROS2 的 Agent 工具

机器人应用基本是 Ubuntu 系统,本项目依赖 Ubuntu-22.04 + ROS2 Humble;

通过 4 个功能包组织 Agent 系统:

  • cs_core:核心包,负责大模型循环、记忆管理等;

  • cs_input:输入管理节点与自带的输入“传感器”节点;

  • cs_output:输出管理节点与自带的输出工具节点;

  • cs_interfaces:公共消息类型。

截止目前,开发了 2 个输入源:

  • system_status:检测并提供设备的机器码、CPU、内存、GPU、温度等基本信息;

  • message_receive:接收用户的终端聊天信息和网页聊天信息。

以及 3 个输出工具:

  • shell_exec:终端命令执行器;

  • file_rdwt:文件读写一体化工具;

  • message_send:可通过邮箱、网页或终端话题向用户发送消息,支持自定义其他通道。


三、快速体验

  1. 克隆仓库后,需要按照以下依赖:
sudo apt install ros-humble-desktop libgit2-dev libcurl4-openssl-dev \
  nlohmann-json3-dev libxml2-dev s-nail python3-yaml
  1. 在仓库根目录下编译项目并安装:
source /opt/ros/*/setup.bash
colcon build

source ./install/setup.bash
  1. 通过配置工具来初始化或修改大模型 API 、工作区和节点参数等配置
./config

  1. 一键启动 Agent
./start [config_path]

  1. 开 web 端对话

默认 web 端口为 8080,启动后,在浏览器导航栏输入 localhost:8080 即可链接到 Agent 的 Web 对话端了,目前支持文件上传功能。

四、应用案例

以下为一例机械臂应用案例,使用 RDK 开发板连接 USB-CAN 机械臂设备和 USB 摄像头。

算法通路为:

摄像头目标检测物体位置(Input) -> Agent 分析思考 -> 调用机械臂搬运(Output)

运行效果如下(经过 Input/Output 封装和调优):


五、结语

Cloud-Soul 的核心思路很简单:Agent 不是对话框,Agent 是一个持续运行的进程。

传统的 AI Agent 是你问一句、它答一句。Cloud-Soul 的 Agent 一直在后台思考,有消息就处理,没事就等着,发现问题主动找你,干完活主动汇报。这在物理机器人上尤其重要——你不能指望机械臂搬东西搬到一半等你去点"继续"。

ROS2 天然适合这个场景。节点挂了自动发现、话题松耦合、Action 有反馈,正好匹配 Agent 需要的高容错、可扩展的输入输出系统。把传感器和工具都做成 ROS2 节点,Agent 不需要知道具体实现,只需要发现和调用。

目前项目还在 Beta 阶段,但核心循环已经跑通——可以在笔记本上开发,推到开发板上运行,同一个 Git 记忆仓库让两边共享同一套记忆和规则。接下来会继续丰富输入源和工具,让 Agent 能接入更多物理设备。

如果各位也在做机器人 + AI 的项目,欢迎来提 PR 或者 issue,一起把这个架构做扎实。

1 个赞