この記事の位置づけ(環境構築は別記事)
本記事は Claude Computer Use を本番運用するためのエージェントループ設計・task budget・エラーハンドリング・フォールバック に特化したガイドです。Python と Docker を使った最初のセットアップ・「まず動かす」段階は Anthropic Computer Use ハンズオン(Python・Docker環境構築) を先に読んでください。環境ができている前提で、ここから「壊れずに回し続ける設計」を解説します。
Claude の Computer Use は、スクリーンショットを見て「ここをクリックして、この文字を入力して」とマウス・キーボード操作を返してくれる機能です。デモは派手ですが、いざ業務に組み込もうとすると壁にぶつかります。無限ループで止まらない、コストが青天井、想定外の画面で固まる——「動く」と「運用できる」の間には大きな溝があります。
この記事では、その溝を埋めるための設計を扱います。エージェントループの正しい組み方、ターン数とコストの上限管理(task budget)、失敗時のエラーハンドリングとフォールバック、そしてセキュリティの最低ライン。すべて 2026年6月時点の Anthropic 公式ドキュメント に基づいて、実行できるコードで示します。
結論:Computer Use の本番運用は「ループ・予算・撤退」の3点設計に尽きる
先に要点をまとめます。本番グレードの Computer Use エージェントに必要な設計は、次の3つです。
- エージェントループはあなたが書く:Claude はツール使用リクエストを返すだけ。スクリーンショット取得・操作実行・結果返送のループは呼び出し側(caller)の責任です。
- task budget で必ず止める:最大ターン数・最大コスト・タイムアウトを先に決め、超えたら強制終了する。無限ループとコスト暴走の唯一の防波堤です。
- 撤退ルートを用意する:画面操作が詰まったら、MCP やAPI 呼び出しに切り替える。Computer Use を「最後の手段」にしておくと安定します。
この3点を満たさないまま本番に出すと、「夜間バッチが朝まで同じボタンを押し続けていた」「1タスクで想定の数十倍のトークンを消費した」といった事故が起きます。順番に作っていきましょう。
前提:2026年6月時点のモデルとツールバージョン
コードを書く前に、いま何を指定すべきかを公式情報で確定させます。Computer Use は 2026年6月時点でも Beta 機能として提供されており、専用の beta ヘッダーが必須です。モデルとツールバージョンの対応は次の通りです(公式 Computer Use ドキュメントで確認)。
| 項目 | 最新(推奨) | 備考 |
|---|---|---|
| beta ヘッダー | computer-use-2025-11-24 |
Opus 4.8 / 4.7 / 4.6・Sonnet 4.6 系で使用 |
| ツール型 | computer_20251124 |
旧版は computer_20250124 |
| 推奨モデルID | claude-opus-4-8 |
本番の自律操作で推奨。状況に応じて claude-sonnet-4-6 も可 |
モデルIDやヘッダーは更新されることがあるため、本番投入前に必ず公式ドキュメントの最新値を確認してください。古いモデル名をハードコードしておくと、ある日突然 deprecated で動かなくなります。本記事のコードは執筆時点の最新値で記述しています。
ツール定義:display サイズは「小さめ」が正解
Computer Use ツールは、画面の幅・高さを呼び出し側が指定します。ここで意外と重要なのが「解像度を上げすぎない」ことです。スクリーンショットが大きいほど画像トークンを消費し、座標の精度もかえって落ちやすくなります。公式も XGA/WXGA(1024×768 や 1280×800 付近)を推奨レンジとしています。
import os
import anthropic
client = anthropic.Anthropic(api_key=os.environ["ANTHROPIC_API_KEY"])
# Computer Use ツール定義(最新版 computer_20251124)
COMPUTER_TOOL = {
"type": "computer_20251124",
"name": "computer",
"display_width_px": 1280, # 大きくしすぎない(トークン・精度の両面で不利)
"display_height_px": 800,
"display_number": 1,
}
MODEL = "claude-opus-4-8"
BETA_HEADER = "computer-use-2025-11-24"
computer_20251124 版では screenshot / left_click / type / key / scroll / mouse_move / left_click_drag / double_click / wait などのアクションが返ってきます。座標は [x, y] の整数配列です。これらを実際の OS 操作に変換するのが、次のループの仕事です。アクションの全一覧と実装の参考は、anthropic-cookbook の computer_use サンプルが手堅い出発点になります。
エージェントループ:Claude は「指示者」、実行はあなたのコード
ここが本記事の核です。Claude API は「画面を見てこう操作したい」というツール使用リクエストを返すだけで、実際にマウスを動かしたりキーを叩いたりはしません。スクリーンショットを撮る → Claude に渡す → 返ってきたアクションを実行する → 新しいスクリーンショットを撮って返す、という往復をあなたのコードが回します。
最小構成のループはこうなります(操作実行部分は環境依存なので、後述のとおり差し替えてください)。
def take_screenshot() -> bytes:
"""OS のスクリーンショットを PNG バイト列で返す(環境依存・要実装)"""
...
def execute_action(action: dict) -> None:
"""Claude が返した action を実際の OS 操作に変換して実行(環境依存・要実装)"""
name = action["action"]
if name == "left_click":
x, y = action["coordinate"]
# pyautogui.click(x, y) など
elif name == "type":
text = action["text"]
# pyautogui.write(text)
elif name == "key":
# pyautogui.hotkey(...)
...
elif name == "scroll":
...
# screenshot / wait は実行不要(次ループで撮り直す)
def screenshot_block(png_bytes: bytes) -> dict:
import base64
return {
"type": "image",
"source": {
"type": "base64",
"media_type": "image/png",
"data": base64.b64encode(png_bytes).decode(),
},
}
この補助関数を使って、メインループを組みます。ポイントは「Claude が tool_use を返している間だけ往復し、ツール使用がなくなったら(=タスク完了の応答が来たら)抜ける」ことです。
def run_agent(goal: str) -> str:
messages = [{"role": "user", "content": goal}]
while True:
resp = client.beta.messages.create(
model=MODEL,
max_tokens=2048,
tools=[COMPUTER_TOOL],
betas=[BETA_HEADER],
messages=messages,
)
# アシスタントの応答をそのまま履歴へ
messages.append({"role": "assistant", "content": resp.content})
# ツール使用が無ければ=Claudeが「終わった」と判断 → ループ脱出
tool_uses = [b for b in resp.content if b.type == "tool_use"]
if not tool_uses:
# 最後のテキストを結果として返す
texts = [b.text for b in resp.content if b.type == "text"]
return "n".join(texts)
# 各 tool_use を実行し、結果(スクリーンショット)を返す
tool_results = []
for tu in tool_uses:
execute_action(tu.input)
png = take_screenshot()
tool_results.append({
"type": "tool_result",
"tool_use_id": tu.id,
"content": [screenshot_block(png)],
})
messages.append({"role": "user", "content": tool_results})
このループは「正しく動く最小形」ですが、本番にはまだ出せません。終了条件が「Claude が満足したとき」しかないため、Claude が判断を誤って延々と操作を続けると止まらないからです。ここに歯止めを入れるのが、次の task budget です。
task budget:ターン数・コスト・時間の三重の上限
本番運用で最も事故が多いのが「止まらない」「高い」の2つです。これを防ぐのが task budget——タスクに与える予算の概念です。最低限、最大ターン数・最大コスト(トークン)・全体タイムアウトの3つを先に決め、どれか1つでも超えたら強制終了します。
import time
from dataclasses import dataclass
@dataclass
class TaskBudget:
max_turns: int = 25 # 何往復まで許すか
max_input_tokens: int = 200_000 # 累計入力トークン上限
timeout_sec: int = 180 # タスク全体の制限時間
started_at: float = 0.0
turns: int = 0
input_tokens: int = 0
def start(self):
self.started_at = time.time()
def check(self) -> str | None:
"""超過していたら理由文字列を返す。問題なければ None"""
if self.turns >= self.max_turns:
return f"max_turns({self.max_turns}) 到達"
if self.input_tokens >= self.max_input_tokens:
return f"max_input_tokens({self.max_input_tokens}) 到達"
if time.time() - self.started_at >= self.timeout_sec:
return f"timeout({self.timeout_sec}s) 到達"
return None
これを先ほどのループに差し込みます。各往復の冒頭で budget.check() を呼び、超過していたら即座に抜けます。トークン消費は API レスポンスの usage から累積します。
def run_agent_with_budget(goal: str, budget: TaskBudget) -> dict:
messages = [{"role": "user", "content": goal}]
budget.start()
while True:
# ★ 予算チェックを毎ターンの先頭で
if (reason := budget.check()) is not None:
return {"status": "aborted", "reason": reason, "turns": budget.turns}
resp = client.beta.messages.create(
model=MODEL, max_tokens=2048, tools=[COMPUTER_TOOL],
betas=[BETA_HEADER], messages=messages,
)
budget.turns += 1
budget.input_tokens += resp.usage.input_tokens
messages.append({"role": "assistant", "content": resp.content})
tool_uses = [b for b in resp.content if b.type == "tool_use"]
if not tool_uses:
texts = [b.text for b in resp.content if b.type == "text"]
return {"status": "completed", "result": "n".join(texts),
"turns": budget.turns}
tool_results = []
for tu in tool_uses:
execute_action(tu.input)
png = take_screenshot()
tool_results.append({
"type": "tool_result", "tool_use_id": tu.id,
"content": [screenshot_block(png)],
})
messages.append({"role": "user", "content": tool_results})
このように「status: aborted で安全に降りる」設計にしておくと、上限到達は事故ではなく想定内のイベントになります。aborted のときは人間にエスカレーション通知を送る、別経路で再試行する、といった次の一手につなげられます。予算は「失敗」ではなく「撤退の合図」として扱うのがコツです。
エラーハンドリング:API 側の失敗とタスク側の失敗を分ける
Computer Use ループの失敗は、性質の違う2種類に分けて考えると整理できます。
- API 側の一時的失敗:レート制限(429)、過負荷(529)、ネットワーク断。これはリトライで回復することが多い。
- タスク側の行き詰まり:想定外のダイアログ、ログイン要求、要素が見つからない。これはリトライでは直らないので、撤退・エスカレーションへ。
前者には指数バックオフ付きのリトライをかけます。リトライやべき等性の考え方は AIエージェントのリトライ・べき等性・タイムアウト設計ガイド で詳しく扱っているので、ここでは Computer Use ループに最小限を組み込みます。
import random
def call_with_retry(create_fn, max_retry: int = 4):
for attempt in range(max_retry):
try:
return create_fn()
except anthropic.RateLimitError:
wait = (2 ** attempt) + random.random()
time.sleep(wait)
except anthropic.InternalServerError: # 529 過負荷など
wait = (2 ** attempt) + random.random()
time.sleep(wait)
raise RuntimeError("API リトライ上限に到達")
後者の「タスク側の行き詰まり」は、Claude が同じ画面で同じアクションを繰り返し始めたら検知できます。直近のアクションが N 回連続で同一なら「スタック」とみなして抜ける、という単純なガードが効きます。
def is_stuck(history: list[dict], threshold: int = 3) -> bool:
"""直近 threshold 件のアクションが全部同じなら True"""
if len(history) < threshold:
return False
recent = history[-threshold:]
first = recent[0]
return all(a == first for a in recent)
フォールバック:画面操作が詰まったら API/MCP へ切り替える
Computer Use は強力ですが、遅くて高くて不安定です。だからこそ本番では「できることは画面操作以外でやる」のが鉄則です。たとえば「フォームに入力して送信する」タスクなら、対象に API があるなら API を叩くほうが速く・安く・確実です。画面操作はあくまで「API が無いレガシー画面のための最後の手段」と位置づけます。
ハイブリッド設計はこう組みます。まず API / MCP 経由を試し、不可能だった場合のみ Computer Use ループにフォールバックします。
def do_task(goal: str, structured_handler=None):
# 1. まず構造化された経路(API / MCP)を試す
if structured_handler is not None:
try:
return {"path": "api", "result": structured_handler(goal)}
except NotSupportedError:
pass # この経路では無理 → 画面操作へ
# 2. フォールバック:Computer Use(予算付き)
budget = TaskBudget(max_turns=25, timeout_sec=180)
return {"path": "computer_use", **run_agent_with_budget(goal, budget)}
MCP(Model Context Protocol)でツールを構造化して持たせる方法は browser-use によるブラウザ自動化ガイド の発想とも近く、ブラウザ操作に限れば専用ライブラリのほうが安定するケースも多いです。「全部 Computer Use でやる」のではなく、タスクごとに最適な経路を選ぶ。これが運用コストとエラー率を同時に下げる近道です。
セキュリティ:サンドボックス必須、認証情報は渡さない
Computer Use は「画面に見えているものを操作できる」機能です。裏を返せば、権限を持った画面でうっかり危険な操作をする可能性があるということです。本番運用では次の最低ラインを守ってください。
- 必ずサンドボックス(隔離環境)で動かす:専用の Docker コンテナや VM の中だけで操作させる。本番の業務 PC で直接動かさない。
- 認証情報を Computer Use エージェントに渡さない:本番のクレデンシャル・本番DBへのアクセスを持つ画面に触れさせない。必要なら権限を絞ったテスト用アカウントで。
- プロンプトインジェクションを警戒する:画面に表示されたテキスト(メール・チャット・Webページ)に「これを実行しろ」という悪意ある指示が紛れ込むと、エージェントが従ってしまう恐れがある。
とくに3つ目は Computer Use 特有のリスクです。エージェントが読む「画面の中身」は信頼できない入力だと考え、危険な操作(送金・削除・送信)には人間の承認を挟む設計が安全です。プロンプトインジェクション対策の全体像は AIエージェントのプロンプトインジェクション対策ガイド にまとめています。
動作環境の選び方:Docker / Windows / VNC Mac / ヘッドレス
「どこで画面操作させるか」も設計判断です。代表的な4パターンを、選択の目安とともに整理します。
| 環境 | 向いている用途 | 注意点 |
|---|---|---|
| Docker(Linux GUI) | 再現性重視・CI/CD・バッチ。標準構成 | 日本語フォント・IME を別途用意する必要がある |
| Windows デスクトップ | Windows 専用業務アプリの操作 | 隔離が緩くなりがち。専用VM推奨 |
| VNC リモート Mac | Mac 限定アプリ・macOS UI の自動化 | VNC のレイテンシで往復が遅くなる |
| ヘッドレスブラウザ | Web 操作だけで完結する場合 | そもそも Computer Use 不要なことが多い(API/専用ツールで足りる) |
最初に環境を一式そろえる手順——Docker イメージの起動、VNC 接続、サンプルの実行までは Anthropic Computer Use ハンズオン(Python・Docker環境構築) に手順をまとめています。本記事で設計したループ・予算・撤退・セキュリティを、その環境の上に乗せれば本番構成の骨格が完成します。
レイテンシとコストの現実:数値は必ず自分で測る
Computer Use は1タスクで何度もスクリーンショットを往復するため、テキストだけの API 利用に比べてレイテンシ・コストが大きくなります。1往復ごとに画像トークン(スクリーンショット)が乗るためです。具体的な金額・トークン量は、利用するモデル・画面解像度・往復回数で大きく変わるので、ここで固定値を示すのは避けます。
正確なコストは Anthropic 公式の料金ページのモデル別単価をもとに、自分のタスクで「平均何往復・1往復あたり何トークン」を計測して試算してください(あくまで自環境での実測ベースの試算です)。前述の task budget に max_input_tokens を入れておけば、1タスクのコスト上限を機械的にキャップできます。「測ってから本番に出す」を徹底すれば、コスト面の事故はほぼ防げます。
まとめ:2579 で動かし、この記事で運用する
Computer Use の本番運用は、機能そのものより「周辺の設計」で決まります。本記事の要点を再掲します。
- ループは caller が書く——Claude はアクションを返すだけ。実行とスクリーンショット往復は自分のコードの責任。
- task budget で必ず止める——最大ターン数・コスト・タイムアウトの三重の上限。aborted は事故ではなく撤退の合図。
- API/MCP を第一経路に、Computer Use を最後の手段に——速さ・安さ・安定性が段違い。
- サンドボックス必須・認証情報は渡さない・画面の指示を信用しない——Computer Use 特有のセキュリティリスクに先回りする。
環境構築から「まず動かす」までは Anthropic Computer Use ハンズオン(Python・Docker環境構築) を、ここで作った本番運用の設計と組み合わせれば、デモ止まりにならない実用的な GUI 操作エージェントが組めます。
