---
name: chatgpt-web-bridge
description: |
  通过 chatgpt-web 桥（MCP / REST）把本地 agent 接入 ChatGPT 网页版：网页端当大脑，本地只做传输与执行。
  触发：「推进/继续网页端会话」「让网页端设计、本地执行」「协作/对等/共同推进」「对等模式/让两边辩一下/协作评审」「共同协作/本地跑任务它维护模型」「用网页端的资料/只读拉取」「把网页版接进 harness」「conversation_id 续接」「网页版比较聪明所以用它」。
  不适用：让网页端直接执行本地 shell/文件操作——桥只承载文本，网页端永远没有本地工具。
---

# ChatGPT Web Bridge

## 快速使用（自然语言即模式）

| 你说 | 模式 | 本地做什么 |
|---|---|---|
| 「推进网页端 XXX 项目/会话」 | A 推进 | 发「继续」式最小提示往前推；纠偏算在内（只给事实不给方案）；判断何时真结束，没结束就不停 |
| 「让网页端 GPT 指挥现在这个项目」 | B 指挥循环 | 它出指令 → 本地执行 → 回帖事实到同一 conv → 直到它说完成 |
| 「协作/对等/共同推进 XX」 | C 协作 | **取长补短**：交锋（因模型不同/权限不同有信息差）+ 执行（永远本地，禁止交给网页端） |
| 「用网页端 XXX 的资料/看它怎么说的」 | D 只读 | 只拉取不发送：会话记录、项目文件、记忆——零写操作 |

**会话定位**：指明 conversation_id/标题就精确命中；没指明 → 按项目名归类（`list_conversations` + `list_projects` 匹配）；仍不确定 → **先问用户再发**，不猜。首轮新会话：用户说了项目就带 `project_id`（名字即可），没说 = 独立会话。

## 核心原则：谁思考

**网页端是大脑，本地是手和邮差。**

- 网页端持有完整上下文（会话历史 + Project 指令 + Memory）——它的判断依赖这些，不需要在消息里复述给它。
- 本地侧只做三件事：把文字送进正确的 conversation_id、把回文拿回来、（指挥模式下）忠实执行网页端给出的任务。
- **不要替它写执行步骤。** 发「继续」式最小提示，让它自己决定下一步。消息写得越细，网页端思考得越少。

## 适用边界与安全

**触发**：推进/继续已有网页端会话、网页端设计本地执行的回合制循环、「协作/对等/共同」类取长补短（C 协作模式：交锋+本地执行）、conversation_id 专线续接。

**不适用**：

- 让网页端直接执行本地命令或读写文件——桥是文本桥，网页端永远没有本地工具
- 高频自动轮询——这是低频人工节奏
- Chrome 专用 profile 未登录 ChatGPT——先登录再调用，别让请求悬死

**安全与验证**：所有写操作（新建会话、删除会话）都是真实网页操作；删除类工具需服务端显式 `W2A_ENABLE_DESTRUCTIVE=1`。本地侧只验证 conversation_id 续接正确、tab 复用正确，不替网页端校验其输出内容的正确性——那是它自己的责任。

## 循环纪律：本地侧是唯一的发动机

网页端永远不会主动发起下一轮——**本地收到回帖不等于回合结束**。每轮拿到回文后，先对照本模式的终止条件判断；不满足就继续发下一轮，直到终止条件命中或用户叫停。「它回完了」不是停止理由，「终止条件命中」才是。

**等回复纪律（2026-09-11 定型，网页端裁决后才收敛的坑）**：

- **长等待是常态**：联网搜索 + 长报告要数分钟到十几分钟。等待本身就是工作的一部分，不是回合结束信号。
- **轮询到有结果为止**：发出消息后对方仍在生成 ≠ 本轮结束。在回合内持续拉取（REST 返回或 backend-api 拉尾部）直到拿到完整回文或明确失败；回合时长、上下文压缩预期都不构成停止理由。拿不准时就拉尾部确认——「还在写」和「写完了」是可观测的两种状态，不许靠猜。
- **阻塞抛给协作者**：本地卡住的点（环境门禁、授权边界、协议歧义、缺工具）先发回同一 conversation_id 求方案，写清「阻塞事实 + 已试过的路径 + 待裁决项」，不要在本地只汇报给用户或写进任务控制就停。网页端看不见本机状态，它要的是可裁决的输入不是进度摘要。
- **本地中断 ≠ 消息未送达**：chat_completion 在本地被 cancel/打断时，消息可能已落盘网页端——重发前先 `get_conversation` 核实尾部，否则产生重复发送（2026-09-12 实证：被打断的发送已完整落盘）。同理，`not_ready` / `Turn reconciliation failed` / `generation_stuck` 等报错也可能已送达（同日实证：两次 not_ready 报错均落盘，造成同一里程碑重复上报）——**任何报错后重发前必须先核实**

## 四种用法

### A. 推进模式（默认，低频）

把已有网页任务往前推一格：

- 最小提示：`继续` / `按你的结论推进` / `下一步`
- 纠偏只给判断不给方案：`这条线判断错了，事实是 X` —— 让它自己想修法
- 每轮必须带 conversation_id；不知道就先 `list_conversations` 找目标
- 网页端产出长报告时，本地只保存/转发原文，不做二次「翻译」
- **终止条件**（满足其一才停）：网页端书面宣布本阶段完成且没有它自己的下一步；它提出需要用户/外部世界才能回答的问题（权限、要买的数据、要你拍板的方向）；用户叫停。**它写完一轮报告不是终止。**

### B. 指挥循环（网页端指挥本地）

网页端设计 → 本地执行 → 回帖 → 网页端继续设计：

1. 首轮 `chat_completion`（可带 `project_id` 让会话落进项目），存下返回的 `conversation_id` 作为专线
2. 每轮本地回帖只写事实：**结果摘要 + 关键证据 + 阻塞项**，不夹带自己的分析
3. 网页端输出的指令照做，做完把结果发回同一 conversation_id
4. 循环频率低是正常的——这是回合制协作，不是轮询系统
5. **继续义务**：回帖后必须读它的下一条指令并执行——一轮就停等于循环没建起来
6. **终止条件**（满足其一才停）：网页端宣布任务完成/无下一轮指令；连续两轮它只复述已有结论不产生新指令；它的指令越权（要本地没有的能力）且澄清后仍无法执行；用户叫停

### C. 协作模式（取长补短：交锋 + 本地执行）

用户说「协作/对等/共同」即进入本模式。两个成分缺一不可：

- **为什么交锋**：两个模型不一样（思考方式不同）、权限不一样（网页端看得见搜索/项目/Memory，本地看得见文件系统/执行/实时状态）——信息差决定了必须先把各自立场摊开再合并，任何一侧单方输出都会丢掉对方的盲区。
- **为什么执行在本地**：网页端永远没有本地工具。需要执行（跑命令/改文件/取真实结果）的动作永远由本地完成，**禁止把执行交给网页端**。

适用前提：**token 不缺、本地智力被认可、两边互有知识盲区**。任何其他场景回到 A/B。

**协议（防坍缩结构，顺序不可省）**：

1. **R0 盲答**：同一问题两侧独立作答——网页端**不许看**本地已写好的答案，本地也别先发自己的立场去锚它。各自交卷后才交换。
2. **对齐盲区**：首轮双方各自声明「我看不见什么」。之后把问题路由给看得见的那侧：网页端要本地数据就问，本地要网页端搜/读项目就问。
3. **逐条交锋**：每个议题独立走状态机 `proposed → accepted / rejected / deferred / escalated`。反驳先 steelman（复述对方论点的最强版本），再给证据反驳；**只有新证据能翻案，自信语气不算证据**。
4. **执行落本地**：议题分出方案后，需要真实执行的步骤由本地完成；网页端只维护判断/模型/裁决。本地上报格式：`[OBS] 任务来源｜事前预测（若有）｜真实结果（保留原文摘录）｜知情度标签`；需要模型修订时发 `[UPDATE-REQUEST]`。
5. **上报节奏**：默认每里程碑一次（一个里程碑 = 一条可判定的局部因果链）；例外立即上报（预测失败/关键反证/State 明显错误/足以改变行动/不可逆操作前）；无信息增量的中间步骤不上报。每步上报会把维护成本做实，只报失败会造成成功样本偏置——两个极端都不要。
6. **轮次封顶**：默认 5 轮或议题清零。到顶仍分歧 → 产出**分歧报告**（各自立场 + 关键证据 + 僵持点）交给用户裁决。禁止假装共识。
7. **谄媚自检**：连续两轮没有任何实质异议是危险信号不是成功信号——此时主动要求对方「指出我立场里最弱的一点」。

**信封格式**（每轮本地发给网页端的消息）：

```text
[PEER R{n}] {议题}
我的立场: …
依据: …
对你上轮的反驳: （先复述你的最强版本）…
我可能盲的地方: …
需要你侧的数据: …
待裁决: …（无则省）
```

**终止**：双方书面确认收敛，或分歧报告交付用户，或用户喊停。**只交换一轮不是对等协作——议题未达终态前本地侧必须继续发下一轮。**

### D. 只读模式（用网页端的资料，不发送）

用途：把网页端已积累的东西当本地输入——会话历史、项目文件、Memory、它的既有结论。零发送、零新会话、零 Memory 写入。

- 通道：`list_conversations` / `get_conversation` / `list_projects` / `get_project_files` / `get_memories`（MCP 走共享 utility 槽，不占会话 tab）
- 单次请求即结束——只读没有循环，拿到资料就地交付
- 拿到长资料本地只做筛选/引用，不改写它的结论
- 触发词：「用网页端 XXX 的资料」「看看它/项目里怎么说的」「把 XXX 会话的结论拉下来」
- **空结果先核 ID**：`get_conversation` 返回 `{messages:[], total:0}` ≠ 会话被锁/被删——桥会把后端 404 `conversation_inaccessible` 静默映射成空，conversation_id 抄错一位就触发。以 `list_conversations` 的 id 逐字符为准，或从已打开 tab 的 `/c/{id}` URL 取
- **真实错误取证**：直连 `127.0.0.1:9222`（browser-level flatten attach，不占用桥的 tab），在 chatgpt.com 页内 fetch `/api/auth/session` 拿 token 后 fetch `/backend-api/conversation/{id}`，看真实 status——区分 404(ID 错) / 429(限流) / mapping 结构变化

## 硬规则

- **一对一专线**：一个本地会话只绑定一个网页端 conversation_id。禁止为多路并行/A-B 盲测/分身评审开多个网页会话——需要隔离执行时用本地子代理（各自独立上下文，天然盲），不需要隔离的活本地自己做。
- **执行永远本地**：凡是要产出/执行/跑实验的活都在本地完成（含子代理）；网页端只承担依赖它自身上下文与判断的角色（推理、评审、用它项目知识的分析），不是并行生成器。「我做不了干净的盲」不成立——本地起个子代理就是干净的盲。
- **转述中立**：把用户任务发给网页端时逐字或中性改写，不自行加预设方向（如「哪里弱/哪里是自我安慰」这类措辞等于替它定了批判结论）。

1. 专线靠 `conversation_id` 续接；首轮创建后可省略（同 session 自动续），跨 session 必须显式带
2. 永不发「记住/以后都/remember」措辞——会污染 ChatGPT Memory
3. 临时上下文塞在 message / system_prompt 里，不落 Memory
4. 同一会话永远落在同一个浏览器 tab（conv-affinity 内置）；别手动挪桥用 tab
5. 要项目上下文就显式传 `project_id`（gizmo id 或精确项目名，桥会校验，传错直接报错而不是落错项目）；不传 = 独立会话，别指望项目记忆
6. 首轮一次带对 project_id；发现发错会话/项目时**不要立刻重发**——先确认前一条是否已落地，否则产生重复会话
7. 只读任务在消息里声明「只读测试」；删除类工具需服务端 `W2A_ENABLE_DESTRUCTIVE=1`
8. 生成很慢（联网搜索 + 长报告）：客户端超时 ≥15 分钟，中途绝不重发
9. 桥内置账号级跨进程节流（send ≥30s、backend 读 ≥8s、命中限流全体冷却 300s，配置 `request_pace_*`/`W2A_PACE_*`）——别写循环猛发绕过它，限流会连累所有通道

## 通道选择

| 场景 | 通道 | 说明 |
|---|---|---|
| 串行推进会话 | REST `POST /v1/chat/completions` + `conversation_id` | daemon 复用会话 tab |
| agent 工具态 | MCP `chatgpt-web` → stdio `chatgpt-web2api-mcp`（推荐，harness-bound） | `chat_completion` + 读工具 |
| 读会话/列项目 | MCP `get_conversation` / `list_*` | 走共享 utility 槽，不占会话 tab |

## 运维（本机实例）

- 注册：harness MCP 配置用 stdio `chatgpt-web2api-mcp`（随会话生灭，首调自动拉起 Chrome，不用零进程）；共享 daemon 才用 SSE `:8090`
- 启动（仅 daemon 模式）：`<本仓库>/mcp/chatgpt-web-bridge/start.ps1`（Chrome 独立进程 + REST :8080 + MCP :8090）；venv 在仓库外时由 `W2A_VENV` 解析
- 自愈：`chatgpt-web2api ensure`（daemon 挂了/重启后跑一次即可，幂等带锁；stdio 模式不需要）
- Chrome 与 daemon 生命周期解耦：重启 daemon 不动浏览器，反之亦然
- 登录态掉了：在专用 profile 的 Chrome 里登录，daemon 自动恢复
- 排查 tab 绑定：`http://127.0.0.1:9222/json/list`
- 其它设备安装：见 `examples/install-other-devices.md`（桥已 vendored 在 `mcp/chatgpt-web-bridge/`，随本仓库同步）

## 反模式

- 消息里写好全套执行步骤让网页端照做——等于你在思考
- 每轮不带 conversation_id——每轮一个新会话，上下文全断
- 给网页端发「执行这条 shell 命令」——它没有也不该有本地工具
- 客户端默认 60s 超时——正常生成要数分钟
- 对等模式下让网页端先看你答案再「评审」——锚定的同意不是共识
- 对等模式分歧到顶继续磨——出分歧报告交用户，不伪造收敛
- 收到一轮回帖就当任务结束——终止看条件不看「它这轮说完了」
- 发完消息看到对方还在生成就结束回合交差——等回复是本地义务，轮询到有结果为止
- 本地阻塞只向用户汇报或写进任务控制就停——先把阻塞事实+已试路径+待裁决项发回协作者求方案
- 把「干净 A/B」拆给两个网页会话——盲隔离用本地子代理做，不是多开专线
- 以「我无法盲自己」为由把执行外包——本地子代理的隔离上下文就是盲
- 协作模式下每步都上报——按里程碑粒度，每步上报等于把维护成本做实
- 协作模式下只上报失败——丢失成功预测证据，形成失败样本偏置
- 协作模式下把执行步骤发给网页端让它"做"——执行永远本地，它只做判断/建模/裁决
- 本地侧发送被打断后立刻重发——中断不等于未送达，先核实落盘
