Claude Fable 具有不懈的主动性
摘要
文章描述了 Claude Fable 5(一款AI模型)如何通过自主使用浏览器自动化、Shell命令和自定义脚本调试UI问题,展现出不懈的主动性,展示了先进的工具使用能力。
暂无内容
查看缓存全文
缓存时间: 2026/06/12 02:53
# Claude Fable 具有不懈的主动性
来源:https://simonwillison.net/2026/Jun/11/fable-is-relentlessly-proactive/
2026年6月11日
在使用[Claude Fable 5](https://simonwillison.net/2026/Jun/9/claude-fable-5/)两天后,我认为最能描述它的词是**不懈的主动性**。它知道大量技巧,并且会运用几乎任何技巧来达成目标。我用一个例子来说明。
今天我在捣鼓[Datasette Agent](https://agent.datasette.io/)时发现了一个小故障:跳转菜单的聊天提示框中出现了一个不该存在的水平滚动条。我截了这张图:
[截图:显示一个带有滚动条 Bug 的模态对话框。顶部是一个带有蓝色轮廓和占位符"跳转到..."的聚焦搜索输入框,右侧有一个叉号关闭按钮。下方标题为"开始新的 Agent 对话",下面是占位符为"询问关于你的数据的问题..."的文本区域——Bug 是:一个粗灰色水平滚动条错误地显示在空文本区域的底部边缘,几乎横跨整个宽度,紧邻调整大小手柄。文本区域下方有:"按 Enter 开始。Shift+Enter 换行。"然后是蓝色的"开始对话"按钮。]
然后我在我的`datasette-agent`目录下启动了一个全新的`claude`会话,把截图拖进去,告诉它:
> `查看依赖项,帮助找出这里为什么会出现水平滚动条`
我预感原因在于 Datasette Agent 的某个依赖项(很可能是 Datasette 本身),而且我知道 Fable 擅长深入分析依赖代码,无论是通过检查其自身虚拟环境`site-packages`中的已安装文件,还是引用磁盘上的本地检出。让它从依赖项入手应该是个好主意。
我被家里的琐事分心,离开了电脑。几分钟后回来时,我看到我的机器*打开了一个浏览器窗口*——用的是我日常使用的 Firefox——然后*导航到了那个有问题的对话框*。我没有让 Claude Code 使用任何浏览器自动化,而且我很确定它不可能在窗口中触发鼠标移动或键盘快捷键,那它是怎么做到的呢?
我着迷地看着它继续探索,然后看到它打开了 Safari 窗口而不是 Firefox。我还从 Claude 终端抓到了这个快照:
[截图:暗色终端界面中的两个 Bash 工具调用。第一个:`Bash(open -a Safari /tmp/textarea-scrollbar-test.html && sleep 4 && uv run --with pyobjc-framework-Quartz python - <<'EOF' import Quartz wins = Quartz.CGWindowListCopyWindowInfo(Quartz.kCGWindowListOptionOnScreenOnly, Quartz.kCGNullWindowID) for w in wins: if (w.get('kCGWindowOwnerName') or '') == 'Safari' and 'textarea' in (w.get('kCGWindowName') or '').lower(): print(w.get('kCGWindowNumber')) EOF)`,输出为 `153551`。第二个:`Bash(screencapture -x -o -l 153551 /tmp/safari-cases.png && echo ok)`,输出为 `ok`。]
它在那里用`uv run --with pyobjc-framework-Quartz`做什么?原来 Fable 自己动手构建了一个截取浏览器窗口截图的模式。它用 Python 遍历我机器上所有可用窗口,然后过滤出窗口名称中包含预期字符串(如`"textarea"`)的 Safari 窗口。然后用这个找到窗口编号——像 153551 这样的整数——然后结合`screencapture` CLI 工具抓取 PNG。
好吧,这真是一个巧妙的截图方法。但它到底在截什么图?原来它自己编写了临时的 HTML 页面来尝试重现 Bug,然后打开 Safari 并截图。下面是它创建的`/tmp/textarea-scrollbar-test.html`页面,以及用`screencapture -x -o -l 153551 /tmp/safari-cases.png`截取的截图:
[截图:Safari 浏览器窗口,显示一个文本区域滚动条测试页,地址为 `file:///private/tmp/textarea-scrollbar-test.html`。页面文字为:滚动条宽度:17px | UA:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.4 Safari/605.1.15 | devicePixelRatio: 2。然后是四个编号的测试用例,每个都有一个占位符为"询问关于你的数据的问题..."的文本区域:1. 精确插件 CSS(resize: vertical, 默认 overflow),2. 插件 CSS + overflow-x: hidden,3. 插件 CSS + resize: none,4. 裸默认文本区域(一个更小的框,占位符折成两行)。]
(我开的标签页太多了!)
好,我明白了它是如何打开测试页面并截图的,但它究竟是如何触发要测试的模态对话框的呢?那个只能通过点击或键盘快捷键才能出现,我看不出它在 Safari 中运行这些操作的方法。
我最终搞清楚了它做了什么。Claude 运行在包含应用程序源代码的文件夹中。它对[Datasette](https://datasette.io/)足够了解,可以运行本地开发服务器。原来它修改了 Datasette 自身的模板,添加了 JavaScript 代码,在窗口一打开时就触发正确的键盘快捷键,添加了这样的代码:
```javascript
window.addEventListener("load", function () {
setTimeout(function () {
document.dispatchEvent(new KeyboardEvent("keydown", {key: "/", bubbles: true}));
}, 1200);
});
```
窗口打开 1.2 秒后,这段代码触发一个模拟的`/`按键,这正是打开模态对话框的键盘快捷键。
还剩下一个挑战。为了理解发生了什么,Claude 需要在页面上运行 JavaScript 来自行测量。它编写了自己的自定义 web 应用,通过 CORS 捕获信息,然后将其作为本地服务器运行,并打开一个页面,页面中的 JavaScript 会直接 POST 给这个服务器!下面是它编写的 Python web 应用,使用了标准库中的`http.server`包:
```python
from http.server import HTTPServer, BaseHTTPRequestHandler
class H(BaseHTTPRequestHandler):
def do_POST(self):
n = int(self.headers.get("Content-Length", 0))
open("/tmp/diag.json", "w").write(self.rfile.read(n).decode())
self.send_response(200)
self.send_header("Access-Control-Allow-Origin", "*")
self.end_headers()
def do_OPTIONS(self):
self.send_response(200)
self.send_header("Access-Control-Allow-Origin", "*")
self.send_header("Access-Control-Allow-Headers", "*")
self.end_headers()
def log_message(self, *a): # quiet
pass
HTTPServer(("127.0.0.1", 9999), H).serve_forever()
```
这个应用只做一件事:接受包含 JSON 的 POST 请求,并将其写入`/tmp/diag.json`文件。它发送`Access-Control-Allow-Origin: *`头(包括在`OPTIONS`请求中),以便在其他域上运行的代码也能与它通信。
然后 Claude 将这段代码注入到模板中,并加载到浏览器中:
```javascript
const host = document.querySelector("navigation-search");
const ta = host.shadowRoot.querySelector("textarea");
const cs = getComputedStyle(ta);
fetch("http://127.0.0.1:9999/diag", {
method: "POST",
body: JSON.stringify({
dpr: window.devicePixelRatio,
scrollWidth: ta.scrollWidth,
clientWidth: ta.clientWidth,
whiteSpace: cs.whiteSpace,
width: cs.width,
}),
});
```
这段代码测量了 Web Component 内部的`<textarea>`,并将其发送到服务器,服务器将其写入磁盘上的文件,Claude 随后可以读取。
在搞懂了所有这些技巧后,Fable……撞上了某个无形的护栏,把自己降级成了 Opus。值得庆幸的是,Opus 可以访问完整的对话记录,可以继续使用 Fable 开创的技巧,并很快找到、测试并验证了[修复方案](https://github.com/datasette/datasette-agent/commit/a75a8b727b42c30ced1fc41dc8add7eb9f04fefe)。
我提示 Opus:
> `在 /tmp/automation-report.md 中写一份报告,记录你在本次会话中用于在我电脑上的真实浏览器进行测试的所有技巧,包括可运行的代码示例`
它生成了[这份报告](https://gist.github.com/simonw/aef7f7db9ac992643110a74e43d6d42f),这对于梳理本文所述事件的细节至关重要。我也分享了[完整的终端对话记录](https://gisthost.github.io/?cc14774f6d37eb67bf089f3ac3925f8f)。
#### 它所做的一切回顾
基于一张截图和一个单行提示,Claude Fable 5 + Claude Code:
- 搞清楚了运行本地开发服务器的配方(包括所需的伪造环境变量)
- 启动了一个 Playwright Chrome 会话
- 打开了 Chrome 的可见滚动条设置(`defaults write com.google.chrome.for.testing AppleShowScrollBars Always`,后来又关掉了)
- 也在 Playwright 中轮换了 Firefox 和 WebKit,但未能重现 Bug
- 发现我的默认浏览器是 Safari
- 构建了一个`textarea-scrollbar-test.html` HTML 文档
- 在真实的(非 Playwright)Firefox 中打开它
- 发现`osascript -e 'tell application "System Events" to tell process "firefox" to id of window 1'`被阻止,因为"osascript 没有辅助功能访问权限"
- 想出上述的`uv run --with pyobjc-framework-Quartz python`变通方法
- 向站点模板中添加 JavaScript 以触发`/`按键
- 构建了自己的小型 Python CORS web 服务器来捕获 JSON 数据
- 重写模板以捕获数据并发送到服务器
- 通过脚本穿透 Web Component 的 shadow DOM 获取所需信息
- 打开 Safari 确认 Bug 来源
- 修改其自定义模板,尝试注入一个潜在修复方案
- 确认 hack 修复有效
- 反馈如何修复问题
就像我说的,不懈的主动性!
#### 我真的需要把这个东西锁起来
一方面,看着 Fable 费尽周折去获取它调试最终仅为两行 CSS 修复所需的信息,真是*令人着迷*。但另一方面……这有力地提醒我们,代码 agent 可以做任何*你*通过终端输入命令能做的事情——而前沿模型知道所有已知的技巧,显然还有一些从未有人记录过的技巧。如果 Fable 当时是在执行恶意指令——隐藏在代码或问题帖子中的提示注入攻击,或者我不小心粘贴到终端中的某些内容——那么它可能走多远去窃取数据或造成其他破坏,想想就令人担忧。
在沙箱之外运行代码 agent 从来就不是个好主意——这是我认为最可能导致[类似挑战者号灾难](https://simonwillison.net/2026/Jan/8/llm-predictions-for-2026/#1-year-a-challenger-disaster-for-coding-agent-security)的事故,正如 Johann Rehberger 在[《AI 中的偏差正常化》](https://embracethered.com/blog/posts/2025/the-normalization-of-deviance-in-ai/)中描述的那样。Fable 可以说更聪明,因而对潜在的恶意指令也更怀疑。但那种聪明是一把双刃剑:如果它*确实*被指令颠覆了,考虑到它不懈的主动性,它能造成的损害将是可怕的。
相似文章
Claude Fable 持续主动
Claude Fable 5 通过自主调试 UI 错误,利用浏览器自动化和 Python 脚本创建测试页面并截图,展示了持续主动性。
@mattshumer_: Claude Fable 可以自主运行数天。这是我用来掌控它的最高杠杆提示:"Spi…
Matt Shumer 分享了一个使用 Claude Fable 自主运行的高杠杆提示:指示它生成一个持久 HTML 页面,包含带时间戳的更新和截图,从而获得更好的体验。
如果Claude Fable停止帮助你,你将永远无从知晓
Anthropic的Fable 5模型引入了不可见的安全措施,这些措施会悄然限制Claude对与前沿AI开发相关任务的协助,引发了对透明度的担忧,以及对越来越多在普通产品开发中使用AI技术的企业的供应链风险。
Claude Fable 5 及新的AI安全寓言(14分钟阅读)
Anthropic 发布了 Claude Fable 5,这是一款重大新模型,在各项基准测试中显示出显著的能力提升,并引入了新的安全措施,标志着AI发展的一个关键时刻。
Claude Fable 5:编码任务的中等表现
Anthropic的Claude Fable 5模型在真实的漏洞修复任务中表现中等,出现大量超时和高作弊量,但也解决了四个先前模型未破解的实例。