AIエージェントを組んでいると、ある時点で必ず「重いタスクを別コンテキストウィンドウで動かしたい」という要件にぶつかります。会話履歴が肥大化してLLMの精度が落ちる、観点ごとに専門家を分けたい、並列で複数の観点を走らせたい。理由はだいたいこのあたりです。
このとき検討対象になるサブエージェント機構として、本稿では3つを扱います。
どれを選んでも「親と分離した別コンテキストで子を起動する」という効果は同じです。違いは 定義ファイルの場所と書き方、そしてランタイムごとの可搬性 に出ます。実装イメージを伴って整理します。
別コンテキストを作るのは指示書ではなくランタイムのツール
最初に押さえたい原則です。
AGENTS.md / CLAUDE.md などの指示書 = 何をすべきか書いてあるだけ
ランタイムが提供するツール = 実際にコンテキストを切るエンジン 両方が揃って初めて別コンテキストが生まれます。指示書に「サブを呼べ」と書いただけではコンテキストは分離しません。実際にプロセスやsessionを切るのは、ランタイムが内蔵しているツール の仕事です。
| ランタイム | 別コンテキストを作るツール |
|---|---|
| Claude Code | Taskツール(別名Agentツール) |
| Codex CLI | spawn_agentツール |
| OpenClaw | sessions_spawnツール |
そして重要なのが、これらのランタイムは同居しません。あるプロセス内で動いているのはどれか1つだけで、他のランタイムのツールはそこから呼べません。OpenClawの中でClaude CodeのTaskツールが使えたりはしないということです。
各機構の定義方法
ここからが本題です。同じ「戦略コンサル観点のサブ」を作るとして、それぞれの流儀でどう書くかを並べます。
Claude Code Task: マークダウン1ファイル
.claude/agents/consultant-strategy.md ---
name: consultant-strategy
description: 戦略・競争・ポートフォリオ観点の経営レビューを行う
tools: Read, Grep, WebSearch
---
あなたは戦略コンサルタント専門のサブエージェントです。
Porter / Christensen / Lean Startupの知見を使い…
出力フォーマット: JSON {verdict, reasons[], next_actions[]} これだけで完結します。フロントマターにname / description / 使えるツール一覧を書き、本文がシステムプロンプトになります。1ファイル置くだけ でTaskツールから呼び出せるようになる。これがClaude Code方式の最大の魅力です。
Codex spawn_agent: TOMLファイル1個
.codex/agents/consultant-strategy.toml name = "consultant-strategy"
description = "戦略・競争観点の経営レビューを行う"
model = "claude-opus-4-7"
sandbox_mode = "read-only"
developer_instructions = """
あなたは戦略コンサルタント専門のサブエージェントです。
Porter / Christensen / Lean Startupの知見を使い…
""" こちらも1ファイルで完結します。MarkdownではなくTOML形式で、本文はdeveloper_instructions = """..."""の文字列内に書きます。Claude Codeとの拡張子・構文の違いはありますが、「1ファイル = 1サブ」という設計思想は共通です。
OpenClaw sessions_spawn: ワークスペースフォルダ単位
ここが本稿で一番強調したい点です。
OpenClawのsessions_spawnは、Claude CodeやCodexのように「サブ専用の単一ファイル」という概念を持ちません。サブ自身も親と完全に同じ流儀の「正規エージェント」として登録します。つまり、サブを増やすたびに ワークスペースフォルダごと作る ことになります。
ワークスペースフォルダを作る
サブ(子セッション)には AGENTS.mdとTOOLS.mdだけが自動注入され、SOUL.md / MEMORY.md / USER.md / IDENTITY.md / HEARTBEAT.md / BOOTSTRAP.mdは注入されません。子の人格・口調・出力フォーマット・ルールはすべてAGENTS.mdに集約するのが正解です。
workspace-consultant-strategy/
├── AGENTS.md ← 戦略専門の人格・出力JSON仕様・口調をここに集約
├── TOOLS.md ← 子が使えるツール仕様
└── memory/ ← 必要なら(親と分離) 「子は分業特化なのでロール定義1ファイルで十分」というOpenClawの設計思想に沿った構成です。親と同じファイル構成を子にも作る必要はありません。
openclaw.jsonに登録する
{
"agents": {
"list": [
{
"id": "management-consultant",
"workspace": "${SHARED_REPO}/workspace-management-consultant",
"heartbeat": {
"every": "30m",
"activeHours": { "start": "09:00", "end": "22:00", "timezone": "Asia/Tokyo" }
},
"subagents": { "allowAgents": ["consultant-*"] }
},
{
"id": "consultant-strategy",
"workspace": "${SHARED_REPO}/workspace-consultant-strategy"
}
]
}
} サブも親もここに並列で登録します。「親 → 子」という階層関係はopenclaw.jsonには現れず、どちらも同格の登録エントリとして書く点が独特です。親が子を呼ぶ関係は、AGENTS.md / HEARTBEAT.mdの中に「サブをsessions_spawnで呼べ」と書くことで成立します。
heartbeat設定はトップレベルではなくagents.list[].heartbeatに書く のがポイントです。子エージェントにはheartbeatフィールドを書かないことで「子はheartbeat起動しない」が表現されます。仕様上、いずれかのエージェントにheartbeatブロックがあれば、heartbeatブロックを持つエージェントだけが定期起動対象になります。
つまり
OpenClaw sessions_spawnでは、サブエージェントを「親の小道具」として作るのではなく、「親と同格の独立エージェント」として作る。
これが、Claude CodeやCodexの「1ファイルで完結」スタイルとの一番の違いです。
私が勘違いしていたポイント
検討中に最大のつまずきになったのがここでした。
サブエージェントの定義は、Claude CodeやCodexの感覚で「1ファイル書けば1サブ」と思っていたのですが、OpenClaw sessions_spawnの流儀に乗る場合は 「親も子もワークスペースフォルダを持つ正規エージェント」 であり、サブを増やすたびにworkspace-<name>/を増設し、openclaw.jsonのagents.listに並べる、という発想になります。
これは欠点ではなく、設計思想の違いです。サブが独自のMEMORY.mdを持って学習を積み重ねたり、独自のSOUL.mdで人格を持ったりする選択肢が開けます。Claude Code Taskはサブが基本ステートレス(毎回プロンプト本文だけで動く)なので「使い捨て」想定。OpenClaw sessions_spawnは「恒常的に存在し続ける専門家」想定だと考えると腑に落ちます。
ハートビート / Slackトリガーとの組み合わせ
実運用では、サブを直接呼ぶことはほぼありません。HeartbeatやSlackで起動された親が、必要に応じてサブを呼ぶ という二段構造になります。
[OS の launchd / systemd]
│ 30 分ごと
▼
[OpenClaw Gateway デーモン]
│ heartbeat 設定で "management-consultant" 起動
▼
[親セッション] ← コンテキスト window A
├─ workspace-management-consultant/ を読み込み
├─ HEARTBEAT.md の指示に従って観点判定
└─ sessions_spawn(agentId=..., task=...) を呼ぶ
│
│ 即座に tool_result が返る(中身は accepted /
│ childSessionKey / runId のみ。実作業結果は
│ まだ入っていない)
▼
親は sessions_yield で待機状態に入る
│
▼
[Gateway がサブの新セッション生成]
│
▼
[サブセッション] ← コンテキスト window B(完全分離)
├─ AGENTS.md + TOOLS.md だけが自動注入される
└─ 戦略レビューを実行 → 完了
│
▼
Gateway が「子の作業結果」を OPENCLAW_INTERNAL_CONTEXT
ブロックに包んだ user_message として親 session に push
│
▼
親が次のターンで wake → user_message を受け取る
│
▼
親セッションが結果を memory/ に追記し最終応答を組み立てる ここで重要な挙動が 「親→子→親」が単一ターンでは完結せず、マルチターンで進行する 点です。sessions_spawnは呼び出し直後に「受付完了」だけを返し、実作業の結果は子の完了後にannounceとしてuser_message経由で親に届きます。OpenClawがyield/wakeを自動でハンドリングしてくれるので親側のコードは書き足さなくて良いですが、「子の結果を直後の同一ターンで連続加工する」モデルではないことは押さえておきましょう。
Slackの場合も入口が違うだけで、Gatewayの先 は同じ流れです。Slackチャンネルから受信したメッセージをmanagement-consultantに渡し、必要ならsessions_spawnでサブに委譲する、という形になります。
この構造の良いところは、HeartbeatとSlackで 親エージェント以下の構造を完全に共有できる 点です。サブを増やしても、入口(Heartbeat / Slack)に手を入れる必要はありません。
HEARTBEAT.mdに書く中身(例)
## 30 分ごとの手順
1. `memory/` の最終更新日を確認
2. 戦略観点が必要なら以下を呼ぶ:
sessions_spawn(
agentId="consultant-strategy",
task="""
直近1週間の経営スナップショット: {内容}
依頼: 撤退/拡大判断を XYZ 形式で返せ
"""
)
3. 子の announce が user_message で戻ってきたら `memory/YYYY-MM-DD.md` に追記
4. 集約ロジックを走らせる sessions_spawnのパラメータ名はtaskです(messageではない点に注意)。ほかにもlabel / model / thinkingなどのオプションが指定できます。
3機構の比較
| Claude Code Task | Codex spawn_agent | OpenClaw sessions_spawn | |
|---|---|---|---|
| 定義形式 | Markdown + YAML | TOML | Markdown群 + JSON5登録 |
| サブ1個あたりのファイル数 | 1 | 1 | 最小1(フルだと5〜7) |
| 登録作業 | 不要 | 不要 | openclaw.jsonに追記 |
| サブ独自メモリ | 擬似的に可(Readで読む) | 同左 | ネイティブに可(MEMORY.md) |
| サブ独自人格 | フロントマター本文 | developer_instructions | SOUL.mdで本格定義可 |
| 並列起動 | ◎(複数Taskを1メッセージで) | ○ | ○ |
| Heartbeat統合 | 自前実装が必要 | 自前実装が必要 | ネイティブ対応 |
| Slack統合 | 自前実装が必要 | 自前実装が必要 | ネイティブ対応(@slack/bolt内蔵) |
判断軸はシンプルです。
- HeartbeatやSlackを入口に使うならOpenClaw sessions_spawnが有力。Claude CodeやCodexに乗せ替えると入口を自前で作り直す羽目になります
- 使い捨てサブで十分ならClaude Code Taskが最軽量。1ファイルで完結する手軽さは大きい
- 独自記憶や人格を持つ恒常サブが欲しいならOpenClaw sessions_spawn。ワークスペースを使い分けて人格・記憶ごと分離できる
結論: OpenClaw sessions_spawnで行く
私のケースでは、HeartbeatとSlackを入口にする要件があり、観点別コンサルのように「サブが独自の判断履歴を持って学習し続ける」運用も視野に入っているため、OpenClaw sessions_spawn で行くことに決めました。
最初は「Claude Codeに載せ替えればTaskツールで楽にサブを書けるかも」と思っていましたが、
- Heartbeat / Slackの入口を自前で作り直すコストが大きい
- サブの最小構成(AGENTS.md 1ファイル)ならClaude Codeと書く量はあまり変わらない
- サブが独自メモリを持てる選択肢が将来効いてくる可能性がある
の3点で、OpenClaw内で完結させる方針が筋が通りました。
サブを増やすたびにworkspace-<name>/フォルダとopenclaw.jsonのエントリが増えていく、というスタイルに慣れる必要はありますが、「サブも親と同格の正規エージェント」という思想に乗ればむしろシンプル だと感じています。

