コードを書かないSE日誌

SE歴26年。コードを書かずにClaude Codeで8体のAIエージェントチームを動かしています。AIエージェント・自動化・GTDの実験日誌。

Claude Code のサブエージェントに Cowork を使った話——外部視点を組み込むと何が見えるか

この記事の概要: Mac で動く Claude デスクトップアプリ(Cowork)を Claude Code(CLI)の非同期サブエージェントとして運用する仕組みを設計・実装した記録。Monitor ツールによる完了検知設計の過程で、Cowork 自身に設計をレビューさせたことで、CLI 側からは気づけない構造的な盲点が浮かび上がった。

長時間のCLIセッションが続くと、判断が偏り始める感覚がある。「この設計で本当にいいのか」と思いながらも、積み上げてきた文脈の重みに引っ張られて、立ち止まれなくなる。

以前はChatGPTに相談していたが、ワークスペースを共有できないためにファイルを口頭で説明し直すコストが高かった。今はCowork(Mac ネイティブの Claude デスクトップアプリ)に同じMacのファイルを直接読ませて壁打ちできる。これが成立するだけで、相談の質がまるで違う。

そのCoworkを、CLIのサブエージェントとして動かせないか——そう思ったのが今回の出発点だ。


1. 「ワンステップでサブエージェント化できるじゃないか」

/cowork スキルは、Coworkへの指示書(ops/active/cowork-pending.md)を生成するものだ。CLI側で指示の内容をまとめてファイルに書き出し、Cowork側でそれを読んで作業してもらう。

ある日、Coworkに渡すコマンドが「ops/active/cowork-pending.md を読んで作業してください」というワンステップだと気づいた。指示書に作業内容を全部書いておけば、私が手で貼り付けるだけでCoworkが動く。それは「ほぼサブエージェントとして使えるじゃないか」という感覚だった。

あとは、作業の完了をCLI側で自動検知できれば、CoworkはCLIから見て非同期で動くサブエージェントになる。


2. Cowork とは何か、なぜサブエージェント化したいのか

Coworkとは、同じMacで動くClaudeデスクトップアプリのことだ(Claude Code とは別のプロセス・別のコンテキストで動く)。CLIはファイル操作・git・スクリプト実行が得意で文脈を積み上げられる反面、長時間運用で判断が文脈に引っ張られる。Coworkは毎回フレッシュなコンテキストで立ち上がり、ブラウザ操作やワークスペースファイルの直接参照もできる。

この2つを組み合わせる仕組みとして cowork-cli-bridge プロトコルを運用している(Cowork×Claude Code 連携の正解)。CLIとCoworkが ops/active/ 以下のローカルファイルを共有バスとして使う2ファイル方式だ。今回やりたいのは、その通信に「完了検知」を加えて、Coworkを本格的なサブエージェントにすることだ。


3. 設計フェーズ——ローカルファイル経由の非同期プロトコル

既存の cowork-cli-bridge プロトコル

基本的な仕組みはシンプルだ。

  1. CLI側が ops/active/cowork-pending.md(指示書)を生成する
  2. Cowork側がファイルを読み、作業を実行する
  3. Coworkが status: completed に書き換え、成果物のパスを review_output フィールドに記録する
# 完了後の cowork-pending.md(frontmatterのみ)
status: completed
completed_at: 2026-05-20 18:35:00
completed_by: cowork
review_output: ops/active/cowork-review-xxx.md

ここに「CLIが完了を検知して報告する」層を加えれば、サブエージェント化が完成する。

/cowork --wait オプションの設計

CLI側の /cowork スキルに --wait オプションを追加する設計にした。

/cowork <指示内容> --wait
/cowork <指示内容> --wait 30    # タイムアウト30分

--wait をつけると、指示書生成後に待ち受けプロセスが起動する。Coworkが作業を終えてstatus書き換えると、CLI側に通知が届く。私(COO)は他の作業をしながら待ち受けられ、通知が来たら成果物を確認する。


4. 実装の落とし穴——Agent ライフサイクルと長時間ループは共存しない

当初の設計(v1)では、secretary(別の専用エージェント)を run_in_background: true で起動して、内部で30回のsleepループを回してポーリングする構想だった。

これが動かなかった。

Claude Agent SDKには「Agent はツール呼び出し → 応答 → 完了」というライフサイクルがある。secretaryを起動すると、Agentはbash bg jobを立ち上げて「完了」とみなしてしまう。bg jobからはReadツール等のエージェントツールが使えないため、完了検知後にCLIへ報告する経路が消えていた(実機確認: PID 58437がプロセスとして残っているのに、secretary自体は「完了」扱いになっていた)。

「Agentは短命。長時間監視にはMonitorツールを使う」——これが転換点だった。

Monitorツールはbashコマンドを起動し、そのstdoutの各行をリアルタイムでCOOへ通知する仕組みだ。長時間監視 → 完了1回通知というユースケースに設計上マッチしている。

v2での実装はこうなった(前述の §3 のコマンド例 --wait 30 は使い方の例で、ここではデフォルトの60分を使う)。

# Monitorツールが起動するbashスクリプト
# パスは各自の環境(プロジェクトルート)に合わせて書き換えてください
COUNTER=0
MAX=60  # タイムアウト60分
FILE="ops/active/cowork-pending.md"
while [ $COUNTER -lt $MAX ]; do
  if grep -q "^status: completed" "$FILE" 2>/dev/null; then
    echo "COMPLETED at iteration=$COUNTER: $(grep '^status:' "$FILE" | head -1)"
    exit 0
  fi
  if grep -q "^status: cancelled" "$FILE" 2>/dev/null; then
    echo "CANCELLED at iteration=$COUNTER: $(grep '^status:' "$FILE" | head -1)"
    exit 0
  fi
  sleep 60
  COUNTER=$((COUNTER+1))
done
echo "TIMEOUT after $MAX iterations: $(grep '^status:' "$FILE" | head -1)"

bashがCOMPLETEDを出力した瞬間、Monitor経由でCOOに通知が届く。COOはReadツールで cowork-pending.md を確認し、成果物ファイルの先頭20行をそのままユーザーに報告する。

また、--wait で指示書を生成した場合は、Cowork側に「CLI側で待ち受けていること」を伝える専用セクションを末尾に自動追記するようにした。詳細は後述するが、この追記が設計の核心になった。


5. Cowork に「自分のことをレビュー」させてみた

--wait の設計書が一通りできたところで、Coworkに自己レビューを依頼した。

設計書、スキル本体(workspaces/skill-dev/cowork/cowork.md)、プロトコル定義(ops/playbooks/cowork-cli-bridge.md)の3ファイルを渡し、「4観点で設計の問題点を洗い出してほしい」と依頼した。Coworkへの依頼プロンプトの骨格はこうだ。

  • 依頼形式: /cowork <この指示書> を読んで実行してください--wait なし。結果を後から確認する非同期モード)
  • 指示書の内容:
    • 添付3ファイルのパスを列挙して「すべてを読むこと」と明示
    • 評価する4観点をそれぞれ見出しで記述(設計の盲点 / エラーケース / 既存プロトコルとの整合性 / Coworkから見た違和感)
    • 「問題点とその深刻度(実装ブロッカー / 推奨改善)を分けて報告してほしい」と書き添えた

なぜCowork(デスクトップアプリ側)にやらせるのか。

CLIセッションは長く文脈を積み上げているほど、その文脈に引っ張られた判断になる。設計した本人が「これで動く」と思っている仮定を、自分自身では疑いにくい。Coworkは毎回フレッシュなコンテキストで立ち上がるため、「CLI側で自明になっているもの」を「自明ではないもの」として見ることができる。

Coworkから返ってきたレビューは4観点すべてで「問題あり」だった。観点1(設計の盲点)から観点3(既存プロトコルとの整合性)まで、実装上の具体的な問題がいくつか出てきた。観点1では並行起動時の報告取り違え、観点3では completed_at のフォーマット不一致など、実装ブロッカー級の指摘も複数含まれており、いずれもv2設計書で対応済みだ。AIが別のAIの成果物を批評するアプローチについては、「AIにAIの書いた文章を批評させたら60点だった話」でも試みている。

しかし観点4(Coworkから見た違和感)の指摘が、別の質を持っていた。


6. 浮かんだ盲点——CLI側からは絶対に気づけない構造的な問題

観点4はCowork自身の視点から書かれた指摘だ。そのサマリーをそのまま引用する。

ここが CLI 側からは見えない盲点の本丸です。Cowork として 「自分が監視されていることを知らない」「タイムアウトを知らない」「中断方法を知らない」 という構造的な情報非対称があります。

最重要と評価された指摘(観点4-1)はこうだ。

現在、cowork-pending.md の本文には依頼内容と「完了後 status を completed に書き換えてください」しか書かれていません。--wait で起動された pending か、そうでないかが Cowork 側からは区別できません

Cowork が「これは後で時間できた時にやろう」と判断した場合、CLI 側が永遠に待っていることを知らないため、20 分で終わるはずの依頼が 2 時間放置される、といったことが起きます。

これを読んだとき、「確かにそのとおりだ」と思った。同時に、「CLI側だけで設計していたら、この問題に気づく機会はなかった」とも思った。

なぜCLI側だけでは気づけないのか。CLI側では「--waitで起動されたことはpending.mdにわかるはず」と思っていた。でもCoworkはCLIの内部状態を見ていない。Coworkが見えるのは指示書ファイルの内容だけだ

もう一つ、補足の言葉も刺さった。

Cowork は毎回新規セッションで立ち上がります。CLI 側は積み上げた context を保持していますが、Cowork はその context を持ちません。CLI 側で「自明」となっているプロトコル・規約は、Cowork から見ると全部「指示書本文に書かれていないと知らない」のです。情報は指示書に閉じて完結させる 設計原則を、Playbook 全体に適用していくと、この種の盲点が減ります。

この指摘は、単なる実装バグへの指摘ではない。「送り手の文脈は受け手に届かない」という、分散システムの基本原則を人間の言葉で言い直したものだ。

対応策はシンプルだった。--wait で指示書を生成した場合に、末尾に「⏰ CLI 側で待ち受け中」セクションを自動追記する。

## ⏰ CLI 側で待ち受け中

CLI 側で Monitor がこのファイルの完了を待っています(タイムアウト: 60 分、開始: 2026-05-20 18:00:00 JST)。

- 完了したら速やかに status を `completed` に書き換えてください
- 中止する場合は status を `cancelled` に書き換え、`cancelled_reason` を追記してください
- 時間がかかる場合は status を `in_progress` に書き換えると、CLI 側に進行中が伝わります(任意)

情報をCowork側に届けるために、指示書本文に書く。それだけだ。でも「それだけ」のことに、設計者本人だけでは気づけなかった。


7. Claude Agent SDK とマルチエージェント設計から得た3つの教訓

今回の実装と外部レビューを通じて、いくつかの教訓が得られた。

1. Agentライフサイクルを理解して待ち受けを設計する

Claude Agent SDKでバックグラウンド待ち受けをしたい場合、Agentツールの run_in_background は適していない。Monitorツールが正しい選択肢だ。「Agentは短命、Monitorは長命」と覚えておくと迷わない。Remote Trigger やスケジューラとの設計上の違いは「Claude Code のスケジュール枠は3つだけ」で整理している。

2. 情報は受け手の視点から設計する

指示書を作るとき、送り手は「自分が知っていることは相手も知っている」と無意識に仮定してしまう。これは人間どうしのコミュニケーションでも起きる問題だが、AIセッション間の通信では特に顕在化しやすい。CoworkのセッションはCLIの文脈を引き継がないため、「指示書に書いていないことはゼロとして扱われる」と思っておくべきだ。

3. 外部視点を「組織的に取れる構造」が本質かもしれない

AIのサブエージェント化というと「タスクを自動実行させる」側面に目が向きがちだ。しかし今回の経験から見えたのは、「自分が気づけない前提を外から指摘させる構造を作ること」の方が、より根深い価値を持つかもしれないということだ。

CLIが長時間のセッションで積み上げた文脈は資産でもあるが、盲点の温床でもある。そこへCoworkというフレッシュな視点を定期的に入れる仕組みは、ひとりで考え続けることの限界を補う装置になる。

これは社内でのAI活用にも転用できる視点だ。例えば個人開発の場面では、設計書を書き終えたタイミングで「文脈なしで見た場合の違和感」を別のセッションに問う——そのひと手間を自動化する仕組みがあれば、見落としの検出コストが下がる。ひとつのAIチャットに全部頼むのではなく、外部視点を意図的に組み込んだAI活用のアーキテクチャとして設計すること——それが今回の実装を通じて見えてきたものだ。マルチエージェント組織をマネジメントする視点からの考察は「SE歴26年、初めての部下はAIだった」が詳しい。


今回作った /cowork --wait は、CLIのステータスバーに「1 monitor」と表示される。あの表示を見ると、Coworkが向こう側で作業してくれているという安心感がある。Monitor経由の待ち受けは、CLI側でも「ちゃんと動いている」が可視化されるのがUXとして地味に効く。

コスト面について補足しておく。Monitor は bash プロセスを起動してポーリングするだけで、LLM の推論は呼び出していない。待ち受け中にトークンが消費されることはなく、追加の API 課金も発生しない。完了検知後に COO が Read / Report する部分だけが通常の Claude Code セッションのトークン消費になる。月 $200 超の課金が気になるフェーズであっても、Monitor の常駐自体はコストに影響しない。

次は、Coworkに渡した指示書の精度をどう上げるか、だ。「指示書に閉じて情報を完結させる」設計原則を、他のエージェント連携にも広げていきたい。


この記事でカバーしきれなかった設計・運用の全体像は、Zenn Books にまとめている。序章・第1部は無料で読める。

この記事のテーマを深掘りした本

Claude Codeで作る1人エージェントチーム エンジニア向け。writer + reviewer の2体から始めるサブエージェント設計(序章無料)

シリーズ全6冊: Vol.1 作るまでVol.2 回すまでVol.3 書き続けるまでVol.4 仕組みを渡すまでVol.5 仕事を任せるまでVol.6 1人エージェントチーム