通过调试适配协议(DAP)让AI Agent自主控制调试器,而非MCP工具调用,实现真正自主调试。
上个月我做了一个 acpdbg:一个调试器,能把自己的停止状态通过 ACP 交给一个 coding agent,让 agent 查看 crash,甚至驱动 lldb。我很喜欢它。在调试器里玩了一个驻留 agent 之后,下一步显而易见。
我每天大部分时间都开着 Claude Code 或 Copilot。所以:为什么不让调试会话暴露几个 MCP 工具——bt、frame variable、p some_expr、step——然后让我已经打开的那个 agent 直接调用?调试会话变成一个 MCP server;我的聊天 agent 获得了调试超能力。
这很诱人。但我认为,这也把思路做反了。
À l'envers——"方向搞反了"。问题就在这里。在 acpdbg 里,调试器主动联系 agent:调试器是 ACP 客户端,程序停止时唤醒 agent。MCP server 这个思路保持了同样的形态——我坐在一个停止的进程前,把工具推给当前打开的聊天 agent。这是人在循环中,而且是逐 agent 的:我得给 Copilot 配一套 MCP surface,再给 Claude 配一套,然后再给下一个配。
但一个能自主调试的 agent 不想从我这里接收工具。它想自己伸手进调试器——设断点、跑过去、读栈帧——主动出击。箭头翻转了:agent 做客户端,调试器做它驱动的 server。
而我不需要发明协议。协议已经存在了。
Debug Adapter Protocol 是 VS Code 及同类工具用来与任意调试器通信的协议,无需了解调试器内部细节。每个调试器写一个 adapter,每个编辑器写一个 client,大家就能互联互通——这正是我喜欢的 ACP 对编辑器、MCP 对工具的那种 N×M 坍缩效果,只不过这次指向调试器。
如果 agent 讲 DAP,它就不绑在我的打开的会话上,也不绑在某家厂商的工具列表上。每种有 debug adapter 的语言突然都可以 reach——LLDB 调试原生代码、Delve 调 Go、debugpy 调 Python——统统通过同一个接口。调试能力活在 agent 里,不在我给每个聊天工具反复栓上的桥接层里。
这不是假设。oh my pi(omp,omp.sh)是一个终端 coding agent,原生支持 DAP——大约二十七个操作——所以它能附加到真实的调试器上,自主设断点、暂停、检查栈帧、读局部变量、求值表达式、单步执行,对常规目标运行良好。
所以我做了显而易见的事:让它对准一门不寻常的语言。
4D Server 自带 DAP server——只是监听在固定端口(19815),而 omp 喜欢动态选择 DAP 端口。所以整个方案归结为一个小型(大约 120 行)的 TCP bridge:omp-4d-dap。让 omp 指向它选中的端口,把请求转发到 4D 的端口,agent 就在和运行中的 4D 应用进行 DAP 对话了。
而且它真的能用。有了这个 bridge,我实现了对运行中 4D 应用的真实实时调试,由 agent 驱动:设断点、单步跟踪、拉取栈trace、读取状态——在这个平台上本该如此的方式——通过带 context:"watch" 的 evaluate,它同时返回值和 4D 数据类型。

agent 自己的 Debug threads 调用:adapter 4d,session running,真实的线程列表——然后它去拉栈trace。不需要编辑器,不需要我介入。
还不是所有功能都到位,我在 supported-operations 文档里维护了一份持续更新的清单。简短版:scopes/variables 会超时(所以绕道 evaluate/watch)、无法暂停正在运行的 debuggee、4D Server 从不发出干净的终止事件(客户端靠超时判断何时结束)、REPL 运行代码但返回空结果。还要在代码运行前先设好所有断点。实时调试,但有注意事项。
这里有个反转:我"方向搞反"的想法之所以死里逃生,是因为 omp 里面有 DAP。Claude Code 和 Copilot 没有。所以干净、通用的路径目前只对少数内置 DAP client 的 agent 有效。
对其他所有 agent,实用的桥接正是我称之为 à l'envers 的方案——去 agent 已经在的地方找它。现在有两种做法:
文档化的 skills——用文字教 agent 如何调试:命令、工作流、平台怪癖(4D 上:先设断点,通过 evaluate/watch 读状态)。agent 通过它已有的 shell 运行调试器。
MCP debug server——把 set_breakpoint、step、evaluate、backtrace 暴露为 MCP 工具,任何支持 MCP 的 agent 都能 pick them up。没错,这是我最初的想法——只是现在被定位为 DAP-less agent 的 fallback,而不是主角。
所以不是非此即彼。DAP 当 agent 有能力时用,MCP 或 skills 用来桥接没有 DAP 的 agent——理想情况下底层是同一个调试后端。
我对任何自主性任务倾向 DAP:有 DAP 能力的 agent 不该等我把调试器递过去。但我实际用的大多数 agent 还没有 DAP,所以 MCP-tools-and-skills 桥接是让 Claude Code 或 Copilot 今天就能调试的方式。而我也不会扔掉 acpdbg——当我身处 crash 现场时,调试器驱动 agent 的循环仍然感觉是对的。每条路都值得一试。
Bridge 和注意事项:github.com/mesopelagique/omp-4d-dap。告诉我你会怎么构建这个方向。🐛