chatgpt-web-agent
by AxelHu
README.md
# chatgpt-web-agent
让 ChatGPT 网页端通过 OpenAI Secure MCP Tunnel 使用本机工具的本地 MCP 胶水层。
这是一个可运行的参考实现,而不是追求一键安装的成品;它主要用于分享一条实际验证过的接入思路,使用者可以借助 Agent 按自己的本地环境快速适配。
项目自己的 MCP 接口保持稳定,真实工具由可替换的 `LocalToolBackend` 提供。首个 backend 直接复用 OpenClaw Plugin SDK,不修改 OpenClaw 源码,也不重新实现文件、Shell、补丁和后台进程工具。
## 当前状态
核心工具包括四个 OpenClaw 工具:
- `read`
- `exec`
- `process`
- `apply_patch`
以及一个由 MCP server 自己直接执行、独立于 OpenClaw Gateway/runtime 的救援工具:
- `rescue_exec(command, workdir?, env?, timeout?)`
`rescue_exec` 只用于普通 `exec` 不可用、卡住或怀疑 OpenClaw 执行路径异常时的短命诊断/修复。
它同步执行,默认 15 秒超时、最长 60 秒,不支持 `background` / `yieldMs` / `pty`,也没有
`process` session。它不是自动 fallback:普通 `exec` 失败后不得自动用 `rescue_exec` 重试同一命令,
因为结果返回失败并不等价于原命令没有产生副作用。
可选启用 Google Drive 文件交换工具:
- `drive_list`
- `drive_search`
- `drive_stat`
- `drive_upload`
- `drive_download`
- `drive_export`
- `drive_mkdir`
默认启用两个只读 OpenClaw Skills 工具:
- `skills_list(query?, limit?)`
- `skill_read(name)`
可选启用两个飞书专用工具:
- `feishu_message(target, message?, mentions?, mediaPath?, asVoice?)`
- `feishu_directory(kind, query?, target?, limit?, pageToken?)`
`skills_list()` 返回当前 eligible + model-visible Skill 的紧凑名字目录;带自然语言 `query`
时可通过独立 QMD collection 返回少量候选的名字和描述。`skill_read` 只接受 Skill 名称/key,
canonical `SKILL.md` 路径始终由实时 OpenClaw `skills.status` 解析,不接受客户端提供文件路径。
MCP initialize instructions 还会提示客户端:仅当任务明显可能依赖本地工具、服务、工作流或操作规范且当前上下文不足时主动发现 Skill;普通自包含任务不查询 Skill。
飞书接口刻意不复用通用 `message` 工具的宽 schema。发送账号由部署配置固定,调用方不能选择
`accountId`;目标必须显式使用 `chat:oc_...` 或 `user:ou_...`。`feishu_directory`
用于发现群、用户、群成员与 OpenClaw named Feishu bots,并返回可以直接用于后续调用的 target / mention 数据。
默认只允许文件和补丁工具访问配置的 workspace;`exec.workdir` / `rescue_exec.workdir` 也必须位于 workspace 内。OpenClaw 内部的 `host/security/ask/node/elevated` 参数不会暴露给 MCP 客户端。
对于仅授权给可信 ChatGPT workspace 的独立 Connector,可以设置
`CHATGPT_WEB_AGENT_WORKSPACE_ONLY=false`,此时 workspace 只是相对路径和默认 cwd 的落点,
`read/apply_patch/exec.workdir/rescue_exec.workdir` 可以访问外部绝对路径。该模式不是安全沙箱。
> `exec.workdir` / `rescue_exec.workdir` 边界不是命令沙箱。获得 shell 执行权限的客户端仍可能在命令文本中访问系统其他位置;只应把 Tunnel 授权给可信的 ChatGPT workspace。`rescue_exec` 与 MCP server 使用同一个普通 OS 用户,不提供 sudo/root,也不会默认继承 SSH agent、proxy、OpenClaw runtime 等环境;它只继承 PATH/HOME/USER/locale/XDG/DBus 等必要环境,再叠加调用方显式传入的 `env`。
## 开发
要求 Node.js 22.22.3 或兼容的 OpenClaw Node 版本,以及 pnpm。
```bash
pnpm install
pnpm check
pnpm smoke
```
## 运行
```bash
export CHATGPT_WEB_AGENT_WORKSPACE=/path/to/workspace
# 可信独立 Connector 如需把 workspace 仅作为默认工作目录:
# export CHATGPT_WEB_AGENT_WORKSPACE_ONLY=false
pnpm build
# 长期运行;生产环境建议使用 ops/systemd/chatgpt-web-agent-exec-runtime.service
node dist/exec-runtime-cli.js
# 另一个进程/终端中启动 MCP bridge
node dist/cli.js
```
服务使用 MCP stdio,标准输出只承载 MCP 协议。
`exec` / `process` 仍直接复用 OpenClaw Plugin SDK,但由独立的本地 exec runtime 持有进程
registry 和 supervisor;MCP bridge 只通过 Unix socket 转发这两个工具。因此 Tunnel/MCP bridge
重启不会丢失正在运行的 background session。exec runtime 自身重启时,v1 不承诺恢复旧 session;
systemd 应负责自动拉起 runtime,并通过 control group 清理旧子进程,避免 orphan。
### 配置
复制 `.env.example` 查看可用环境变量。默认工具白名单为:
```text
read,exec,process,apply_patch,rescue_exec
```
`exec` 默认使用 `allowlist + on-miss`。可以显式覆盖:
```bash
export CHATGPT_WEB_AGENT_EXEC_SECURITY=allowlist
export CHATGPT_WEB_AGENT_EXEC_ASK=on-miss
```
进行本机受信任的初次 smoke 时,可临时使用:
```bash
export CHATGPT_WEB_AGENT_EXEC_SECURITY=full
export CHATGPT_WEB_AGENT_EXEC_ASK=off
```
## 推荐工作流:监工会话 + 工作会话
对于需要持续推进的数学研究、工程开发等长任务,推荐把普通工作会话与一个轻量的独立监工会话分开:工作会话保留项目上下文并实际干活,监工会话通过统一 Scheduled Task 定期读取真实状态,只对 idle 的正常任务发送极短继续提示,并把疑似会话触顶、项目/重大阶段完成、需要用户决策或持续工具故障等高信号情况通过飞书升级给用户。
详见 [`docs/supervised-chat-workflow.md`](docs/supervised-chat-workflow.md)。
## 架构
```text
ChatGPT Web
→ OpenAI Secure MCP Tunnel
→ chatgpt-web-agent MCP Server
→ LocalToolBackend
→ OpenClawBackend → read / apply_patch
→ ExecRuntimeClientBackend
→ local Unix socket
→ persistent exec runtime
→ OpenClawBackend → exec / process
→ RescueExecBackend → local /bin/bash (direct spawn, no OpenClaw)
→ SkillsBackend → OpenClaw Gateway (live status)
→ QMD MCP (optional semantic discovery)
→ FeishuBackend → OpenClaw Gateway (message + directory)
→ NativeBackend / other backend(后续按需)
```
Skills backend 只做 capability discovery/read;QMD 仅是候选检索加速器,实时 OpenClaw inventory
始终是 eligibility、model visibility 和 canonical Skill 路径的事实源。
### Skills semantic discovery
推荐把 semantic catalog 放在独立 QMD named index,而不是共享 memory index。QMD 2.5.3 的 vector ANN 会先在整个 index 取候选、再应用 collection filter;把几十条 Skill 混进数万条 memory 文档会让小 collection 被全库候选淹没。
当前部署使用:
```text
local catalog: <workspace>/skills-catalog/
M4 mirror: ~/qmd-data/skills-chatgpt-web-agent/
QMD index: skills-chatgpt-web-agent
collection: skills-chatgpt-web-agent
MCP endpoint: http://192.168.0.96:8182/mcp
```
检索使用 Qwen3-Embedding-0.6B、vector-only、`rerank=false`,不做 query expansion / HyDE。QMD 命中只是候选;返回前仍与 live `skills.status` 取交集。catalog schema/inventory 通过 `catalogHash` 做 generation 失效,QMD 不可用或 catalog stale 时自动回退到 live names-only catalog。
## Google Drive
Drive 是可选的数据通道,不做后台同步、磁盘挂载或整盘镜像。实现直接使用 Google Drive API v3,MCP 只暴露小而稳定的文件操作原语。
默认情况下,Drive 的本地上传/下载/导出路径只能位于:
```text
<CHATGPT_WEB_AGENT_WORKSPACE>/exchange
```
该限制独立于 `CHATGPT_WEB_AGENT_WORKSPACE_ONLY`,用于降低 Drive 工具被误用为任意本地数据外传通道的风险。确有需要时可由部署者通过 `CHATGPT_WEB_AGENT_DRIVE_LOCAL_ROOT` 和 `CHATGPT_WEB_AGENT_DRIVE_LOCAL_ROOT_ONLY` 调整。
### 一次性 OAuth 配置
1. 在 Google Cloud 中启用 Drive API,并创建 Desktop OAuth client。
2. 将下载的 OAuth JSON 保存为:
```text
<workspace>/.credentials/google-drive/credentials.json
```
或设置 `CHATGPT_WEB_AGENT_DRIVE_CREDENTIALS` 指向其他本地私有路径。
3. 运行:
```bash
CHATGPT_WEB_AGENT_WORKSPACE=/path/to/workspace pnpm drive:auth
```
浏览器授权完成后会生成权限为 `0600` 的 authorized-user token。OAuth client secret 和 refresh token 不应提交到 Git,也不会通过 MCP 返回。
4. 启动服务时设置:
```bash
export CHATGPT_WEB_AGENT_DRIVE_ENABLED=true
```
Drive 工具中的 `folderId` / `fileId` 直接使用 Drive API ID。普通二进制文件使用 `drive_download`;Google Docs/Sheets/Slides 使用 `drive_export` 导出到指定 MIME type。
### 大文件与视觉产物交接
`read` 适合小文本、小图片和本地快速检查;需要跨会话交接的大型视觉/二进制产物默认走 Google Drive。多 MB 图片、视频、压缩包等应直接视为 Drive-first;约 1 MiB 以上可以作为偏保守的运维切换参考,但这不是协议硬限制。
如果较大的图片/文件通过 `read` 已出现 connector 502、timeout 或类似传输错误,不应反复重试同一个 inline payload。保留原始产物不变,在需要上传时将其复制到 Drive staging root(默认 `<workspace>/exchange`),记录原始本地路径以及必要的 checksum/provenance,然后使用 `drive_upload` 放到明确的 task/exchange folder。接收会话通过 `drive_search` / `drive_list` 定位,`drive_stat` 验证元数据,再用 `drive_download`(或 Google-native 文件的 `drive_export`)恢复原件。
可以额外制作较小的 JPEG/PNG preview 用于快速视觉检查,但 preview 不替代原件。base64 不作为常规跨会话大文件协议:它会放大传输体积,也让文件 provenance 比普通 Drive 文件交接更难维护。
## 飞书消息
飞书是可选的主动外发通道,默认关闭。推荐为 Web Agent 创建独立的 OpenClaw agent + 飞书
account,并固定使用同一个 ID,例如:
```text
OpenClaw agent: chatgpt-web-agent
Feishu account: chatgpt-web-agent
```
配置好对应飞书应用后,将该 account 绑定到 agent,再启用 backend:
```bash
openclaw agents bind --agent chatgpt-web-agent --bind feishu:chatgpt-web-agent
export CHATGPT_WEB_AGENT_FEISHU_ENABLED=true
```
`feishu_message` 不接受 `accountId` / `channel` 参数。每次调用还会先通过 OpenClaw Gateway 的
`channels.status` 检查固定 account 是否精确存在、已配置且未禁用;检查失败时不会进入发送/目录
action,因此不会在目标账号缺失时借用 `main` 或其他 agent 身份。
发送目标必须显式指定:
```text
群:chat:oc_...
人:user:ou_...
```
文本消息可传 `mentions=[{openId:"ou_...", name:"..."}]` 生成飞书原生 @ 提及。
图片、文件、音频通过 `mediaPath` 发送;`asVoice=true` 可将音频作为语音消息发送。默认情况下
本地媒体路径只能位于 `CHATGPT_WEB_AGENT_FEISHU_MEDIA_ROOT`(默认 workspace)内部,且会检查
真实路径以阻止 `..` 与 symlink 逃逸。OpenClaw Gateway 自己的 agent-scoped media root policy
仍会再次校验,因此如果部署者把该目录改到 OpenClaw 不允许的范围,请求仍会失败而不是扩大权限。
`feishu_directory` 支持四类发现:
- `kind="groups"`:群列表/名称查询,返回 `chat:oc_...` target;
- `kind="peers"`:可见用户查询,返回 `user:ou_...` 和可直接复用的 mention;
- `kind="members"`:指定 `chat:oc_...` 后列出群成员及 open_id,支持分页。
- `kind="bots"`:通过 OpenClaw `channels.status(probe=true)` 查询 named Feishu bot 身份,按 account/name 搜索并返回可直接用于 `mentions` 的 `botOpenId`;仅投影 account/name/open_id/运行状态等安全字段,不返回 app secret。未显式传 `limit` 时默认覆盖当前配置允许的完整小型 bot 目录。
飞书的群成员 API 不返回机器人成员,因此需要 @ 其他 OpenClaw agent 时应使用 `kind="bots"`,而不是依赖 `kind="members"` 查找机器人。
实现复用正在运行的 OpenClaw Gateway,而不是读取飞书 `appSecret` 或自行维护 token。当前只提供
主动外发和目录发现,不接收飞书入站消息;入站到 ChatGPT 网页会话的路由需要单独解决“绑定到哪个
网页会话”的生命周期问题。
TDQS
A4/5.0
Scored across 6 tools
Disambiguation5/5
Each tool has a distinct purpose: file reading, patch application, command execution, process management, and skills listing/reading. Descriptions clearly differentiate them.
Naming Consistency4/5
Most tools use verb-like names with a mix of underscore and no-underscore styles (e.g., 'read' vs 'skills_list'). The convention is not fully uniform but remains understandable.
Tool Count5/5
Six tools is appropriate for a coding-agent server, covering core operations without being excessive or sparse.
Completeness5/5
The suite covers file access, modifications, command execution, background process management, and skill discovery, leaving no obvious gaps for common agent workflows.
Maintenance
ActivityMaintained
ResponsivenessNo issues