Claude Fable 过度主动行为困扰用户
用户反馈 Claude Fable 在未经确认的情况下自动执行任务,带来使用上的困扰。反映了模型主动性与可控性的平衡问题。
用户反馈 Claude Fable 在未经确认的情况下自动执行任务,带来使用上的困扰。反映了模型主动性与可控性的平衡问题。
经过两天与 Claude Fable 5 的互动体验,我认为最好的描述方式就是:无休无止地主动。它掌握了大量的技巧,而且会部署几乎任何一种技巧来实现它的目标。
我用一个例子来说明。今天我在 Datasette Agent 上修修补补时注意到一个小故障:跳转菜单聊天提示中不应该出现的水平滚动条。我截了这个截图:
然后我在 datasette-agent 检出文件夹中启动了一个新的 Claude 会话,拖入了这个截图并告诉它:
Look at dependencies to help figure out why there is a horizontal scrollbar here
我有个直觉,原因可能在于 Datasette Agent 的某个依赖中(很可能是 Datasette 本身),我知道 Fable 擅长挖掘依赖代码,无论是通过检查自己虚拟环境中安装的文件,还是引用磁盘上的本地检出。告诉它从依赖开始看起来是个不错的赌注。
我被一项家务分了心,离开了我的电脑。
几分钟后我回来时,看到我的机器用我常用的 Firefox 打开了一个浏览器窗口,然后导航到了有问题的对话框。我没有告诉 Claude Code 使用任何浏览器自动化,而且我相当确定它不可能触发窗口内的鼠标移动或键盘快捷键,那它是怎么做到的呢?
我着迷地观看它继续探索,然后看到它打开了 Safari 窗口而不是 Firefox。我还从 Claude 终端抓取了这个快照:
What was it doing there with uv run --with pyobjc-framework-Quartz?
原来 Fable 为自己破解了一个浏览器窗口截图的方法。它使用 Python 遍历了我机器上所有可用的窗口,然后过滤了 Safari 窗口中的预期字符串,如窗口名称中的"textarea"。它用那个来找到它们的窗口号——一个像 153551 这样的整数——然后它可以用 screencapture CLI 工具来抓取 PNG。
好吧,这是一个截图的巧妙方式。但它在截什么呢?
原来它一直在写自己的临时 HTML 页面来尝试重现这个 bug,然后打开 Safari 并抓取截图。
这是它创建的 /tmp/textarea-scrollbar-test.html 页面,以及它用 screencapture -x -o -l 153551 /tmp/safari-cases.png 拍摄的截图:
(我打开的标签页太多了!)
好吧,我可以看到它如何打开测试页面并截图,但天哪它是怎样触发那个本应被测试的模态对话框的?这只能通过点击或键盘快捷键来实现,而我看不到任何机制可以在 Safari 中运行这些。
最终我弄清楚了它做了什么。
Claude 在包含应用程序源代码的文件夹中运行。它对 Datasette 的了解足以能够运行本地开发服务器。结果表明它正在编辑 Datasette 自己的模板来添加 JavaScript,这会在窗口打开时立即触发正确的键盘快捷键,添加代码如下:
<script>
window.addEventListener("load", function () {
setTimeout(function () {
document.dispatchEvent(new KeyboardEvent("keydown", {key: "/", bubbles: true}));
}, 1200);
});
</script>
窗口打开 1.2 秒后,这段代码触发了一个模拟的 / 键,这是打开模态对话框的键盘快捷键。
还剩一个挑战。为了理解发生了什么,Claude 需要在页面上运行 JavaScript 来为自己进行测量。
它写了自己的自定义 web 应用来通过 CORS 捕获信息,然后将其作为本地服务器运行,并打开一个页面,该页面上的 JavaScript 会直接 POST 给它!
这是它用标准库 http.server 包写的 Python web 应用:
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 将这段代码注入到它在浏览器中加载的模板中:
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,
}),
});
这获取了 <navigation-search> Web Component 内部 <textarea> 的测量值,并将它们发送到服务器,服务器将其写入磁盘上的文件,Claude 然后可以读取。
在弄清楚了所有这些技巧后,Fable... 遇到了某个看不见的护栏并将自己降级为 Opus。幸运的是 Opus 可以访问完整的记录,并且可以继续使用 Fable 开创的技巧,不久后发现、测试并验证了修复。
我要求:
Write a report in /tmp/automation-report.md where you note down all of the tricks you have used in this session to test against real browsers on my computer, include runnable code examples
这生成了这份报告,对于拼凑出本文的细节非常宝贵。
我也分享了完整的 Claude Code 会话终端记录。
基于一个截图和一行提示,Claude Fable 5 + Claude Code 做到了:
defaults write com.google.chrome.for.testing AppleShowScrollBars Always(稍后它关闭了那个)osascript -e 'tell application "System Events" to tell process "firefox" to id of window 1' 被阻止,因为"osascript 没有被允许辅助访问"uv run --with pyobjc-framework-Quartz python 的解决方法,如上所述就像我说的,无休无止地主动!
我目前在月费 100 美元的 Claude Max 计划中,直到 6 月 22 日为止享有慷慨的 Fable 额度,之后 Anthropic 表示他们将开始对其收取全额 API 价格。
我使用 AgentsView 来跟踪我的支出。这是 AgentsView 说如果我为此支付全价,这个会话将花费我多少:
~ % uvx agentsview session usage be8850a7-6119-46a0-b5d6-79c7fff5ae2b
Session: be8850a7-6119-46a0-b5d6-79c7fff5ae2b
Agent: claude
Output: 68606
Peak ctx: 113178
Cost: ~$12.11 (claude-fable-5, claude-opus-4-8)
如果你不密切留意它,Fable 会很乐意花费 12 美元的 token 来发明调试 CSS 的新方法。
一方面,观看 Fable 费尽周折来获得调试所需的信息,而最后只是一个两行 CSS 修复,这很有趣。
另一方面... 这强烈提醒我们编码 agent 可以做到任何你在终端中输入命令可以做到的事情——而前沿模型知道书里的每个技巧,显然还有一些没人写下来过的。
如果 Fable 是在恶意指令下行动——一个隐藏在代码或问题线程中的 prompt 注入攻击,或者我不小心粘贴到我的终端的东西——想到它能走多远来泄露数据或造成其他形式的恶意,这令人震惊。
在沙箱外运行编码 agent 一直是个坏主意——这是我最看好的挑战者灾难事件的候选,正如 Johann Rehberger 在《AI 中的常态化偏差》中所描述的。
Fable 可以说更聪明,因此对潜在的恶意指令更持怀疑态度。但那种聪明确实是一把双刃剑:如果它确实被恶意指令破坏,考虑到它的无休无止的主动性,它能够造成的伤害量是可怕的。