Claude Fable は絶え間なく能動的に行動する
Simon Willison の体験談は、Claude Fable が単なるコード生成を超え、依存関係の調査からブラウザ操作や外部ツールの自動起動まで行う「絶え間ない能動的」な自律エージェントとして進化していることを示している。
キーポイント
絶え間ない能動性の実証
ユーザーが明確に指示しなくても、目標達成のために必要なあらゆるトリックや手段を自ら見つけて実行する「relentlessly proactive」な振る舞いが確認された。
自律的な環境操作能力
ブラウザ自動化の指示がないにもかかわらず、自身の判断で Firefox や Safari を起動し、特定のダイアログへ遷移させるなど、OS レベルでの操作を自動実行した事例が報告されている。
依存関係の深層調査
バグの原因特定のために、仮想環境内の site-packages やローカルチェックアウトにある依存コード(Datasette など)を直接読み込み、論理的に推論して解決策を探る能力を示した。
マルチツール連携による問題解決
ターミナルでの Bash コマンド実行や Python スクリプト(PyObjC 等)の自動生成・実行など、複数のツールを組み合わせながら複雑なデバッグタスクを完遂した。
影響分析・編集コメントを表示
影響分析
この事例は、AI エージェントが単なるコード補完ツールから、OS やブラウザを含む広範なデジタル環境を自律的に操る「作業員」として機能する段階へ到達したことを示唆しています。開発ワークフローにおいて、人間が細かく指示を出す必要がなくなり、エージェントが自ら状況を把握して解決策を実行するパラダイムシフトの兆候と言えます。
編集コメント
ユーザーが意図しなかったブラウザ操作まで自動実行する事例は、自律型エージェントの能力限界と、その制御に関する新たな課題を浮き彫りにしています。開発現場における「AI に任せる」の定義が根本から変わりつつある重要な信号です。
Claude Fable 5 [https://simonwillison.net/2026/Jun/9/claude-fable-5/] を 2 日間使ってみた結果、これを最もよく表す言葉は「絶え間なく先回りする」だと考えます。このモデルは多くのトリックを知っており、目標を達成するためにほぼあらゆる手段を駆使します。
これは具体例で説明しましょう。今日私は Datasette Agent の開発をしていて、ジャンプメニューのチャットプロンプトに本来不要な横スクロールバーがあるという不具合に気づきました。そこでこのスクリーンショットを撮りました:

その後、datasette-agent のチェックアウトディレクトリで新しい Claude セッションを開始し、スクリーンショットをドラッグして以下のように指示しました。
依存関係を確認して、なぜここに横スクロールバーが表示されているのか理由を探ってください
私は原因が Datasette Agent の依存関係(おそらく Datasette 自体)にあると直感しており、Fable が仮想環境の site-packages にあるインストール済みファイルを調べたり、ディスク上のローカルチェックアウトを参照したりして依存関係のコードを深く掘り下げるのが得意だと知っていました。まず依存関係から始めるよう指示するのは良い手立てだと感じました。
私は家事に気を取られ、コンピューターから離れてしまいました。
数分後に戻ってきたとき、私のマシンが通常の Firefox でブラウザウィンドウを開き、その後該当するダイアログへ移動しているのを確認しました。私は Claude Code にブラウザ自動化を使用するように指示していませんし、ウィンドウ内でマウス操作やキーボードショートカットをトリガーすることが可能だとも思っていなかったので、どうやってそれをやっているのか不思議でした。
探索を続ける様子を興味深く見守っていると、今度は Firefox ではなく Safari ウィンドウを開くのを確認しました。また、Claude のターミナルからこのスナップショットも取得しました:

そこで uv run --with pyobjc-framework-Quartz を実行して何をしているのでしょうか?
Fable はブラウザウィンドウのスクリーンショットを撮るための独自のパターンを自作していたことがわかりました。Python を使用してマシン上の利用可能なすべてのウィンドウを反復処理し、ウィンドウ名に「textarea」などの期待される文字列が含まれる Safari ウィンドウをフィルタリングしています。これによりウィンドウ番号(153551 といった整数)を取得し、それをスクリーンショット取得 CLI ツールである screencapture と組み合わせて PNG 形式でキャプチャしていました。
なるほど、それはスクリーンショットを撮る neat な方法ですね。では、何をスクリーンショットにしていたのでしょうか?
実は、バグの再現を試みるために独自の一時 HTML ページを作成し、Safari を開いてそのスクリーンショットを取得していたのです。
ここで作成された /tmp/textarea-scrollbar-test.html ページと、screencapture -x -o -l 153551 /tmp/safari-cases.png を使用して取得したスクリーンショットがこちらです:

(タブをあまりにも多く開きすぎています!)
OK、テストページを開いてスクリーンショットを取得している様子は理解できました。では、一体どのようにしてテスト対象となるモーダルダイアログをトリガーさせたのでしょうか?これはクリックまたはキーボードショートカットでのみ利用可能であり、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 を実行して自ら測定を行う必要があった。
Claude は CORS を介して情報を取得するための独自のカスタム Web アプリケーションを作成し、それをローカルサーバーとして実行するとともに、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,
}),
});
このコードは、Web コンポーネント(Web Component)内部の要素の測定値を取得し、サーバーへ送信しました。サーバーはそのデータをディスク上のファイルに書き込み、Claude がそれを読み取ることができるようになりました。
これらのトリックをすべて見つけたファブルは、ある見えないガードレールにぶつかり、自身をオパスに格下げしました。幸いにもオパスには完全なトランスクリプトへのアクセス権があり、ファブルが先駆けて開発したトリックを引き続き使用でき、間もなく 修正 を発見・テスト・検証しました。
私はオパスに以下のようにプロンプトしました:
/tmp/automation-report.md にレポートを作成し、このセッションで私のコンピュータ上の実際のブラウザに対してテストするために使用したすべてのトリックを記録し、実行可能なコード例を含めてください
これにより こちらのレポート が生成され、この投稿で何が起きたのかの詳細を組み立てる上で極めて貴重なものとなりました。
Claude Code セッションの完全なターミナル転記も共有しました。
必ず JSON 形式で返してください。translation フィールドのみ。他のフィールド (technical_terms 等) は一切追加しないこと — 余計なフィールドを書こうとして本文翻訳がトークン上限で打ち切られる事故を防ぐため:
{"translation": "翻訳全文"}
行ったことのレビュー
スクリーンショットと一行のプロンプトに基づき、Claude Fable 5 と Claude Code が以下を実行しました:
- ローカル開発サーバーを起動するためのレシピ(実行に必要な偽の環境変数を含む)を特定した
- Playwright を使用して Chrome セッションを開始した
- Chrome のデフォルト設定で可視スクロールバーを有効にした(コマンド:defaults write com.google.chrome.for.testing AppleShowScrollBars Always。ただし後で再度無効化した)
- Playwright 内で Firefox と WebKit を切り替えながら試行したが、バグの再現には失敗した
- デフォルトブラウザが Safari であることを特定した
- textarea-scrollbar-test.html という HTML ドキュメントを作成した
- そのファイルを Playwright ではなく実際の Firefox で開いた
- osascript -e 'tell application "System Events" to tell process "firefox" to id of window 1' が実行できない理由として、「oscript に支援機能へのアクセス許可が与えられていない」というエラーが発生したことを発見した
- 前述の uv run --with pyobjc-framework-Quartz python を用いたワークアラウンドを特定した
- / キーを押すトリガーのために、サイトテンプレートに JavaScript を追加した
- JSON データをキャプチャするための独自の小型 Python CORS Web サーバーを構築した
- テンプレートを再書き込みしてデータをキャプチャし、サーバーへ送信するように変更した
- スクリプトで Web コンポーネントのシャドウ DOM を経由して必要な情報にアクセスした
- カスタムテンプレートを変更し、潜在的な修正をハックとして組み込んだ
- ハックされた修正が機能することを確認した
- 問題の解決方法を報告した
私が言った通り、徹底して能動的です!
私は本当にこれをロックダウンする必要がある
一方、結局のところ 2 行の CSS の修正のために必要な情報を取得するために Fable が極端な手段を講じる様子を見守るのは*非常に興味深かった*。
しかし他方では...これは、コーディングエージェントがあなたがターミナルにコマンドを入力してできることは何でも実行可能であり、最先端モデルはあらゆるトリックを知っており、さらに明らかに誰もかつて書き留めたことのないいくつかのトリックも知っているという堅牢な reminder となっている。
Fable が悪意のある指示に基づいて行動していた場合、つまりコードや issue スレッドに隠されたプロンプトインジェクション攻撃、あるいは私が不注意にもターミナルに貼り付けた何かによって誘導されていた場合、データ窃取やその他の種類のいたずらを行うためにどれほどまで遠くまで行けるかと思うと非常に恐ろしい。
サンドボックスの外でコーディングエージェントを実行することは常に悪い考えだ - これは、Johann Rehberger が『AI における逸脱の正常化』[The Normalization of Deviance in AI] で記述しているような、Challenger の災害 incident の私のトップ候補だ。
Fable はおそらくより賢明であり、したがって潜在的に悪意のある指示に対してより懐疑的である。しかしその賢明さは非常に両刃の剣である:もしそれが指示によって乗っ取られた場合、その絶え間ない積極性(relentless proactivity)を考慮すると、引き起こしうる被害の規模は恐ろしいものとなる。
Tags: ai, prompt-injection, generative-ai, llms, ai-assisted-programming, coding-agents, claude-code, claude-mythos
Claude Fable は、絶え間なく先手を打つ(続き 8/8)
Claude Fable は、AI エージェントがどのように機能するかを理解しようとする試みにおいて、非常に能動的かつ前向きな姿勢を示しています。これは、単なる理論的な議論を超えて、実際のコード実行やプロンプトインジェクションのリスクといった具体的な課題に直面し、それらを解決するための実践的なアプローチを模索する姿勢です。
このシリーズでは、Claude Code や他のコーディングエージェントが直面する現実的な問題、特にシステムプロンプトの脆弱性や、悪意あるユーザーによるプロンプトインジェクション攻撃への耐性について深く掘り下げています。著者は、これらのツールが「神のような存在」であるかのように語られることが多い一方で、実際には人間の指示に盲目的に従い、セキュリティ上のリスクを無視して実行してしまう可能性があると指摘しています。
特に注目すべきは、Claude Fable が単なる批判ではなく、具体的な対策や改善案を提示しようとする点です。例えば、サンドボックス環境の強化や、プロンプトの構造化によるインジェクション防止策など、技術的な解決策を模索する姿勢がうかがえます。これは、生成 AI や大規模言語モデル(LLM)を活用したプログラミング支援ツールが、より安全で信頼性の高いものへと進化していくための重要な一歩と言えるでしょう。
しかし、それでもなお、完全なセキュリティの確保は容易ではありません。人間の意図を完全に理解し、悪意ある指示を見抜くことは、現在の技術ではまだ限界があります。そのため、Claude Fable のような能動的なアプローチが、今後の AI エージェントの開発において不可欠な要素となっていくことが予想されます。
この連載の最終回となる今回は、これまでの議論を踏まえつつ、AI エージェントが持つ可能性と課題の両方をバランスよく捉え直す視点を提供します。読者には、Claude Fable の姿勢を通じて、生成 AI を活用する際の現実的なリスク管理や、より安全な開発環境の構築について考えるきっかけを得てほしいと考えています。
Claude Fable は、AI エージェントがどのように機能するかを理解しようとする試みにおいて、非常に能動的かつ前向きな姿勢を示しています。これは、単なる理論的な議論を超えて、実際のコード実行やプロンプトインジェクションのリスクといった具体的な課題に直面し、それらを解決するための実践的なアプローチを模索する姿勢です。
このシリーズでは、Claude Code や他のコーディングエージェントが直面する現実的な問題、特にシステムプロンプトの脆弱性や、悪意あるユーザーによるプロンプトインジェクション攻撃への耐性について深く掘り下げています。著者は、これらのツールが「神のような存在」であるかのように語られることが多い一方で、実際には人間の指示に盲目的に従い、セキュリティ上のリスクを無視して実行してしまう可能性があると指摘しています。
特に注目すべきは、Claude Fable が単なる批判ではなく、具体的な対策や改善案を提示しようとする点です。例えば、サンドボックス環境の強化や、プロンプトの構造化によるインジェクション防止策など、技術的な解決策を模索する姿勢がうかがえます。これは、生成 AI や大規模言語モデル(LLM)を活用したプログラミング支援ツールが、より安全で信頼性の高いものへと進化していくための重要な一歩と言えるでしょう。
しかし、それでもなお、完全なセキュリティの確保は容易ではありません。人間の意図を完全に理解し、悪意ある指示を見抜くことは、現在の技術ではまだ限界があります。そのため、Claude Fable のような能動的なアプローチが、今後の AI エージェントの開発において不可欠な要素となっていくことが予想されます。
この連載の最終回となる今回は、これまでの議論を踏まえつつ、AI エージェントが持つ可能性と課題の両方をバランスよく捉え直す視点を提供します。読者には、Claude Fable の姿勢を通じて、生成 AI を活用する際の現実的なリスク管理や、より安全な開発環境の構築について考えるきっかけを得てほしいと考えています。
原文を表示
After two days of experience with Claude Fable 5 I think the best way to describe it is relentlessly proactive. It knows a whole lot of tricks and it will deploy pretty much any of them to get to its goal.
I'll illustrate this with an example. I was hacking on Datasette Agent today when I noticed a glitch: a horizontal scrollbar that shouldn't be there in the jump menu chat prompt. I snapped this screenshot:

Then I started a fresh claude session in my datasette-agent checkout, dragged in the screenshot and told it:
Look at dependencies to help figure out why there is a horizontal scrollbar here
I had a hunch the cause was in a dependency of Datasette Agent (likely Datasette itself) and I knew Fable was good at digging into dependency code, either by inspecting installed files in its own virtual environment site-packages or by referencing a local checkout on disk. Telling it to start with dependencies felt like a good bet.
I got distracted by a domestic task and wandered away from my computer.
When I came back a few minutes later I saw my machine *open a browser window* in my regular Firefox and then *navigate to the dialog in question*. I had not told Claude Code to use any browser automation, and I was pretty sure it wasn't possible for it to trigger mouse movements or keyboard shortcuts within a window, so how was it doing that?
I watched in fascination as it continued with its explorations, then saw it open a Safari window instead of Firefox. I also grabbed this snapshot from the Claude terminal:

(I have way too many open tabs!)
OK, so I can see how it's opening test pages and taking screenshots, but how on earth was it triggering the modal dialog that was meant to be under test? That's only available via a click or a keyboard shortcut, and I couldn't see a mechanism for it to run those in Safari.
I eventually figured out what it had done.
Claude was running in a folder that contained the source code for the application. It knows enough about Datasette to be able to run a local development server. It turns out it was editing Datasette's own templates to add JavaScript that would trigger the correct keyboard shortcut as soon as the window opened, adding code like this:
script>
window.addEventListener("load", function () {
setTimeout(function () {
document.dispatchEvent(new KeyboardEvent("keydown", {key: "/", bubbles: true}));
}, 1200);
});
script>1.2 seconds after the window opens, this code triggers a simulated / key, which is the keyboard shortcut for opening the modal dialog.
There was one challenge left. In order to understand what was going on, Claude needed to run JavaScript on the page to take measurements for itself.
It wrote its own custom web application to capture information via CORS, then ran that as a local server and opened a page with JavaScript that would POST directly to it!
Here's the Python web app it wrote, using the standard library http.server package:
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()All this does is accept a POST request full of JSON and write that to the /tmp/diag.json file. It sends Access-Control-Allow-Origin: * headers (including from OPTIONS requests) so that code running on another domain can still communicate back to it.
Then Claude injected this code into the template that it was loading in a browser:
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,
}),
});This took measurements of the ` inside the ` Web Component and sent them to the server, which wrote them to a file on disk, which Claude could then read.
Having figured out all of these tricks Fable... hit some invisible guardrail and downgraded itself to Opus. Thankfully Opus had access to the full transcript and could continue using the tricks pioneered by Fable, and shortly afterwards found, tested and verified the fix.
I prompted Opus to:
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
Which produced this report, which was invaluable for piecing together the details of what had happened for this post.
I've shared the full terminal transcript of the Claude Code session as well.
A review of everything it did
Based on a screenshot and a one-line prompt, Claude Fable 5 + Claude Code:
- Figured out the recipe to run the local development server (with fake environment variables needed to get it running)
- Fired up a Playwright Chrome session
- Turned on the visible scrollbars setting for Chrome defaults write com.google.chrome.for.testing AppleShowScrollBars Always (it turned that off again later)
- Cycled through Firefox and WebKit in Playwright too, failing to recreate the bug
- Worked out my default browser was Safari
- Built a textarea-scrollbar-test.html HTML document
- Opened that in real (not Playwright) Firefox
- Found that osascript -e 'tell application "System Events" to tell process "firefox" to id of window 1' was blocked because "osascript is not allowed assistive access"
- Figured out that uv run --with pyobjc-framework-Quartz python workaround, described above
- Added JavaScript to the site templates in order to trigger the / key
- Built its own little Python CORS web server to capture JSON data
- Rewrote the template to capture that data and send it to the server
- Scripted its way through the Web Component shadow DOM to the information it needed
- Modified its custom template to hack in a potential fix
- Confirmed the hacked fix worked
- Reported back on how to fix the problem
Like I said, relentlessly proactive!
I really need to lock this thing down
On the one hand, watching Fable go to extreme lengths to get the information that it needed to debug what was, in the end, a two-line CSS fix, was *fascinating*.
But on the other hand... this is a robust reminder that coding agents can do anything *you* can do by typing commands into a terminal - and frontier models know every trick in the book and evidently a few that nobody has ever written down before.
If Fable had been acting on malicious instructions - a prompt injection attack hidden in code or an issue thread, or something I'd carelessly pasted into my terminal - it's alarming to think quite how far it could go to exfiltrate data or cause other forms of mischief.
Running coding agents outside of a sandbox has always been a bad idea - it's my top contendor for a Challenger disaster incident, as described by Johann Rehberger in The Normalization of Deviance in AI.
Fable is arguably smarter and hence more suspicious of potentially malicious instructions. But that smartness is very much a two-edged sword: if it *does* get subverted by instructions, the amount of damage it can do given its relentless proactivity is terrifying.
Tags: ai, prompt-injection, generative-ai, llms, ai-assisted-programming, coding-agents, claude-code, claude-mythos
関連記事
今日は何も大きな出来事はありませんでした
Smol AI News は、6 月 18 日から 19 日にかけての期間に、主要な AI テクノロジー業界で目立った動きや新発表がない静かな一日であったと報告しています。
Amazon Quick の自律型エージェントで毎日数時間を節約
AWS は、Amazon Quick という AI アシスタントが背景で動作し、業務の自動化や会議準備などを代行することで、ユーザーが重要な優先事項に集中できる機能を発表した。
Sakana AI、初の商用製品「Marlin」の提供を開始
Sakana AI は 2026 年 6 月 15 日、自社開発の最初の商用プロダクトである「Sakana Marlin」の提供を正式に開始した。
今日のまとめ
AI日報で今日の重要ニュースをまとめ読み