# OpenClaw ACP 集成 Cursor-Agent:解决 session/load 兼...
# OpenClaw ACP 集成 Cursor-Agent:解决 session/load 兼容性问题
> 环境:OpenClaw + acpx + cursor-agent(Trae IDE 内置)
## 问题背景
OpenClaw 通过 acpx 运行时与各类 Coding Agent(Codex、Claude Code、Cursor-Agent 等)集成。当尝试集成 cursor-agent(Trae IDE 内置的编码助手)时,遇到了一个兼容性问题:
**现象:** acpx 的 `sessions ensure` 流程执行后立即失败,cursor-agent 返回 “Session not found”,acpx 以 exit code 1 退出。
## 根因分析
### acpx 的正常流程
acpx sessions ensure
↓
1. 启动 agent 进程
↓
2. 发送 initialize (JSON-RPC)
↓
3. 发送 session/load(传入 acpx 自己的 record ID 作为 sessionId)
↓
4. 开始工作...
### 问题出在第 3 步
acpx 会传入**自己管理的 session ID**,期望 agent 能加载这个 session。但 cursor-agent 的 `session/load` 只接受**自己创建的** session ID,不接受外部指定的 ID。
虽然 cursor-agent 声明支持 `loadSession`(`agentCapabilities.loadSession: true`),但它只支持加载自己创建的 session,不支持外部指定 ID 加载。
acpx: "请加载 session abc-123"
cursor-agent: "Session not found"(因为 abc-123 不是我创建的)
## 解决方案:JSON-RPC 代理
核心思路:在 acpx 和 cursor-agent 之间插入一个代理层,拦截并转换 `session/load` 请求。
### 设计原理
acpx → proxy → cursor-agent
proxy 拦截 session/load:
- 首次调用:转为 session/new,让 cursor-agent 创建新 session,建立 ID 映射
- 后续调用:用映射后的真实 session ID 发送真正的 session/load
### 核心实现
// cursor-agent-proxy.mjs - JSON-RPC 代理核心逻辑
import { spawn } from '\'child_process'\';
import fs from '\'fs'\';
import path from '\'path'\';
const MAP_DIR = '\'/tmp/acpx-cursor-session-map'\';
// 启动真正的 cursor-agent 进程
const agent = spawn('\'cursor-agent'\', ['\'--stdio'\'], { stdio: ['\'pipe'\', '\'pipe'\', '\'pipe'\'] });
// ID 映射管理
function loadMapping(acpxId) {
const file = path.join(MAP_DIR, `${acpxId}.json`);
if (fs.existsSync(file)) return JSON.parse(fs.readFileSync(file));
return null;
}
function saveMapping(acpxId, realId) {
fs.mkdirSync(MAP_DIR, { recursive: true });
fs.writeFileSync(path.join(MAP_DIR, `${acpxId}.json`), JSON.stringify({ realSessionId: realId }));
}
// 拦截并转发 JSON-RPC 消息
function handleMessage(request) {
if (request.method === '\'session/load'\') {
const acpxSessionId = request.params.sessionId;
const mapping = loadMapping(acpxSessionId);
if (mapping) {
// 已有映射:替换为真实 ID 后转发
request.params.sessionId = mapping.realSessionId;
return forwardToAgent(request);
} else {
// 首次:转为 session/new 创建新 session
const newRequest = { ...request, method: '\'session/new'\', params: {} };
const response = await sendToAgent(newRequest);
if (response.result?.sessionId) {
saveMapping(acpxSessionId, response.result.sessionId);
}
return response;
}
}
return forwardToAgent(request);
}
### 配置方式
在 acpx 配置中,将 cursor-agent 的启动命令指向代理脚本:
{
"agents": {
"cursor-agent": {
"command": "node /path/to/cursor-agent-proxy.mjs",
"args": []
}
}
}
OpenClaw 的 `openclaw.json` 中也需要将 cursor-agent 加入 `acp.allowedAgents`:
{
"acp": {
"enabled": true,
"backend": "acpx",
"allowedAgents": ["codex", "claude", "gemini", "cursor-agent"]
}
}
## Session 映射机制
映射存储在本地文件系统中:
/tmp/acpx-cursor-session-map/
├── abc-123-def.json # acpx session ID → cursor-agent 真实 session ID
├── xyz-456-uvw.json
└── ...
每个映射文件格式:
{
"realSessionId": "cursor-agent-generated-session-id"
}
这种设计确保:
– **重启安全**:映射持久化在磁盘上,进程重启不丢失
– **并发安全**:每个 session 独立文件,无锁竞争
– **调试友好**:直接查看 JSON 文件即可排查问题
## 支持的模型
从 cursor-agent 的 `initialize` 响应中获取到的模型列表:
| 模型 | 提供商 |
|——|——–|
| composer-2, composer-1.5 | Cursor 自研 |
| gpt-5.3-codex, gpt-5.4, gpt-5.4-mini, gpt-5.4-nano, gpt-5.2 | OpenAI |
| claude-sonnet-4-6, claude-opus-4-6, claude-opus-4-5, claude-haiku-4-5 | Anthropic |
| gemini-3.1-pro | Google |
| grok-4-20 | xAI |
| kimi-k2.5 | Moonshot |
## 当前状态与已知问题
| 测试项 | 结果 |
|——–|——|
| JSON-RPC 直接测试 proxy | ✅ 成功 |
| acpx sessions ensure 通过 proxy | ⚠️ 超时(排查中) |
| OpenClaw sessions_spawn | ⏳ 待完成 |
### 已知问题
1. **acpx sessions ensure 超时**:可能是代理的 stdin 关闭时机不对,或 ensure 流程中 prompt 子命令的交互问题。需要进一步排查代理与 acpx 的交互协议。
2. **替代方案**:直接修改 acpx 源码,在检测到 cursor-agent 时自动将 `session/load` 转为 `session/new`(侵入性更大,但更可靠)。
## 总结
| 要点 | 说明 |
|——|——|
| 问题本质 | acpx 与 cursor-agent 对 session/load 的 ID 来源理解不一致 |
| 解决思路 | 插入 JSON-RPC 代理层,做 session ID 映射 |
| 映射机制 | 本地文件系统存储,重启安全、并发安全 |
| 当前状态 | 基础代理已验证,acpx 集成待完善 |
| 适用场景 | 任何声明支持 loadSession 但不接受外部 ID 的 ACP Agent |





