2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

IBM Bobのサブエージェントの動作を制御する

2
Posted at

本記事の内容はIBM Bob IDE Version 2.0.1時点のものです。

はじめに

IBM Bob IDE Version 2.0.0にてサブエージェント機能が実装されました。

サブエージェントとは、メインタスクとは独立したコンテキストウィンドウを持つエージェントです。一般的には、特定のタスクに特化して動作することが想定されており、並列で複数のサブエージェントを実行させることもできます。

Bobのドキュメントの説明も引用します。

subagentはBobがspawnできる独立したエージェントで、焦点を絞った自己完結型のタスクを処理します。独自の隔離されたcontext windowで実行され、割り当てられた作業を実行し、結果の要約をメインの会話に返します。

他のAIコーディングツールでは、サブエージェントの動作をファイルで定義したり、タスクの内容に応じて最適なサブエージェントに自動委託する機能が提供されています。Bobにはドキュメントを見る限り、このような機能は存在しません。

本記事ではBobのサブエージェントの仕様について確認し、エージェント動作を再現性のある方法で制御できないか検証してみた内容になります。

スキルについては、以下をご参照ください。

環境

Windows 11 (x64)

バージョン: 1.121.0+bob2.0.1
コミット: 1.121.0
日付: 2.0.1
Electron: 7bf9666aa258fbb67422037ee9590f428f0f9807
ElectronBuildId: 2026-07-01T13:18:44+02:00
Chromium: 39.8.8
Node.js: undefined
V8: 142.0.7444.265
OS: 22.22.1

Bobのサブエージェント

前提として、Bobは明示的にサブエージェントを利用するように指示をしないと、積極的にサブエージェントを利用しない設計になっています。

Bobはsubagentsを控えめに使用します。デフォルトは常にsubagentをspawnせずに直接作業を行うことです。subagentが検討されるのは、以下のすべてに当てはまる場合のみです:

  • タスクが明確に自己完結型であり、返送が必要なのは要約のみである。
  • メインのコンテキストに大量の無関係なコンテンツを追加することになる。
  • 1〜2回の直接的なtool呼び出しでは達成できない。

Bobがサブエージェントを生成する場合は、spawn_subagentツールが利用されます。

ツール 目的 使用例
spawn_subagent 独自のコンテキスト・ウィンドウを持つ独立したエージェントを作成します コードベースのセクションを調査し、メイン・コンテキストを汚染せずに情報を収集

Bob自身に確認させたところ、このツールは3つのパラメータを持ちます。
image.png

Bobで生成されるサブエージェントを制御するには、このdescriptionを適切に設定する必要があると言えます。また、fork_contextをtrueにしておけば、メインタスクの会話内容を渡すことができます。

上のnameの説明にある通り、Bobのサブエージェントは2種類提供されています。ドキュメントより引用します。

種類 説明 最適な用途
explore 読み取り専用のコードベース探索・軽量モデルで実行 コードの検索と要約、関連ファイルの検索、構造の理解
general フルtoolアクセス・デフォルトモデルで実行 読み取り、書き込み、またはコマンドを必要とする自己完結型タスク

generalサブエージェントの仕様について (Windows環境 v2.0.1時点)

上の表では、generalのエージェントを利用するとすべてのツールを利用できるとあります。ただ、筆者の環境で検証したところ、メインタスクで利用できるMCP toolやスキル利用tool(use_skills)などが、generalのサブエージェントでは利用できませんでした。
Bobに利用できるツールを確認させたところ、以下のように完全なフルアクセスではないことが分かりました。

(Bob(親)はメインタスクを指します)
image.png

つまり、現時点でのBobのサブエージェントは、自律的にスキルを適用したり、MCPサーバーを利用できないということになります。

サブエージェント定義機能の実装

定義ファイルとスキルを使って、サブエージェント定義を実装してみます。非常に単純ですが、図示すると以下のような流れになります。

.bob/agents配下に置かれた定義ファイルをサブエージェント生成時に読み込み、spawn_subagentの各パラメータに渡すという流れです。

ファイル構造は以下の通りです。後述するコードをコピーしてワークスペース内の./bob配下を配置すれば、同じように動作するかと思います。

.bob/
├── agents/
│   └── xxxx.md        # エージェント定義ファイル
└── skills/
    ├── create-custom-agent/ # エージェント定義の作成スキル
    │   └── SKILL.md
    └── load-custom-agent/   # 定義読込スキル
        ├── SKILL.md
        ├── agent-types.md
        └── conversion-rules.md

同じ定義ファイルを利用すれば、定義読込スキル(load-custom-agent)がspawn_subagentdiscriptionを毎回同じ内容で作成します。これにより動作の再現性をかなり高めることができます。

それぞれの詳細について説明します。

エージェント定義ファイル

サブエージェントの動作定義をするためのファイルを、Markdownで記述するようにします。定義ファイルは、ワークスペースの.bob/agents配下に置かれることを想定しています。

なお、フォーマットはClaude Codeのサブエージェント定義ファイルを参考に作成しました。

サブエージェントのMCPサーバー利用に関しては、今回スコープ外としています。

以下はPythonのコードをレビューするサブエージェントの定義例です。review-pycodeスキルを適用し、コードレビューとレポート作成を行うエージェントを想定しています。また呼び出せるかのテストも兼ねて、あえて本筋と関係のない、LLM知見をで永続保存するauto-memoryスキルも指定しています。

review-pycodeもauto-memoryの筆者の自作スキルですが、本記事の本質とは関係ないので詳細は割愛します。

pycode-reviewer.md
---
name: pycode-reviewer
description: Pythonコードをレビューし、標準化された指摘レポートを生成するエージェント
type: general
fork_context: false
skills:
  - review-pycode
  - auto-memory
---

# pycode-reviewer

Pythonコードをレビューし、`review-pycode` スキルの手順に従って標準フォーマットの指摘レポートを生成するエージェント。

## 役割

- 指定されたPythonファイルを読み込み、コードレビューを実施する
- 規定の出力フォーマットでレポートを生成する

## 制約

- 独自のチェックルールや重大度を追加してはならない
- 出力フォーマットはスキル定義のテンプレートから逸脱してはならない

YAMLフロントマターにエージェント名と簡易的な説明、spawn_subagentに渡すエージェント種類とfork_context値、読み込ませるスキルを書き、その下に具体的な指示を書きます。

YAMLフロントマター内のdescriptionフィールドと、spawn_subagentパラメータに渡すdescriptionは別物です。

スキル

前述した定義ファイルを作成するためのスキルをcreate-custom-agent、サブエージェント生成時に定義ファイルをロードし、spawn_subagentのパラメータに内容を渡すスキルをload-custom-agentとして定義します。

create-custom-agentスキル

.bob/agents配下に定義ファイルを作成します。サブエージェントに利用させる(読み込ませる)スキルに関しては、ワークスペースの.bob/skills配下に存在するものから選択されます。

サブエージェントに利用させるスキルは、ワークスペースの.bob/skills配下にあるものにしか対応していません。

本スキルの利用は必須ではありません。フォーマットさえ守れば手書きしたファイルも同様に機能します。

SKILL.md
---
name: create-custom-agent
description: カスタムサブエージェントを新規作成・編集したいときに使う — .bob/agents/ に配置する定義ファイルのフォーマットと手順を案内する。
---

# create-custom-agent

`load-custom-agent` が読み込む `.bob/agents/.md` を作成する。

---

## Step 1 — 目的・基本情報を確定する

エージェント名(kebab-case)・1行の役割要約(description)・`type` を決める。

**type 選択基準:**

| 種類 | 説明 | 利用可能ツール |
|---|---|---|
| `explore` | 読み取り専用・軽量モデル | read_file / list_files / glob / grep / GetSymbolsOverview / FindSymbol / FindReferencingSymbols / ask_followup_question |
| `general` | 読み書き・コマンド実行・デフォルトモデル | explore のツール + write_file / apply_diff / insert_content / search_and_replace / read_xlsx / execute_command |

> `use_skill` / `spawn_subagent`(ネスト)/ MCP ツール(`mcp__*`)はどの type でも利用不可。

`fork_context` は、タスクが `description` だけで自己完結するなら `false`(デフォルト)。親の会話での決定事項をサブに知らせる必要があるなら `true`。

## Step 2 — 重複確認・スキル選択

`list_files(".bob/agents/")` で同名ファイルがないか確認する(存在する場合は新規作成ではなく更新)。

`list_files(".bob/skills/")` で利用可能なスキルを確認し、`skills:` に含めるものを決める。スキルが不要なら省略する。

> `use_skill` は利用不可。スキルを読ませたい場合は `skills:` に指定する。`load-custom-agent` が `read_file(".bob/skills//SKILL.md")` へ変換して注入する。

## Step 3 — ファイルを作成する

`write_file(".bob/agents/.md")` で以下フォーマットに従い作成する。

**フォーマット:**

```markdown
---
name:        # ファイル名(.md 除く)と完全一致
description: <1行の要約>
type: explore|general
fork_context: false      # 任意。true にすると親の会話履歴を引き継ぐ(デフォルト: false)
skills:                  # 任意
  - skill-name
---

# 

## 役割
...

## 制約
...
```

**frontmatter フィールド一覧:**

| フィールド | 必須 | 注入時の扱い |
|---|---|---|
| `name` | yes | ファイル名と一致させる(注入には使われない) |
| `description` | yes | 1行の役割要約(注入には使われない) |
| `type` | yes | `spawn_subagent` の `name` パラメータ(`explore` / `general`) |
| `fork_context` | no | `spawn_subagent` の `fork_context` パラメータ。未指定時は `false` |
| `skills` | no | 全エントリを `read_file(".bob/skills//SKILL.md")` に1行ずつ変換する |
| 本文 | — | 役割としてそのまま注入される |

作成後に以下を検証する:

```
[ ] name がファイル名(.md 除く)と一致している
[ ] skills: のエントリが実際に .bob/skills/ に存在するスキルと一致している
[ ] プロジェクトのルール・コンテキスト全文を静的コピーしていない
```

load-custom-agentスキル

.bob/agents配下から定義ファイルを探し出して内容をロードし、spawn_subagentのパラメータに引き渡します。具体的には定義ファイルのフォーマットとspawn_subagentパラメータの対応は以下の通りです。

  • YAMLフロントマターのtypename
  • YAMLフロントマターのfork_contextfork_context
  • YAMLフロントマターのskillsread_file命令に変換後)+ 本文 → descriptionの先頭

なお、descriptionの後側にはメインタスクからの指示(具体タスク)が入るようになっています。
スキルに関しては、定義ファイルで渡されたスキル名と同名のファイルを.bob/skills配下から探し、スキル本体であるSKILL.mdを読むように指示を加えています。
前述のとおりサブエージェントではuse_skillツールが使えないため、スキル名はそのまま渡されず read_file(".bob/skills/<name>/SKILL.md") という命令に1対1で変換してからdescriptionに埋め込みます。

サポートファイルが複数あるスキルの場合でも、一般的なスキル設計としてSKILL.md内でサポートファイルを必要に応じて読むように指示が書かれます。そのため、SKILL.mdだけ読ませればスキルとしては十分です。サブエージェントはSKILL.mdの指示に従い、必要時にサポートファイルを読みに行きます。

SKILL.md
---
name: load-custom-agent
description: カスタムサブエージェントを spawn_subagent で起動するときに使う。.bob/agents/ の定義ファイルを読み込み、役割・スキル制約を description へ注入する。spawn_subagent 呼び出し前に必ず使うこと。
---

# load-custom-agent

`.bob/agents/.md` を読み込み、内容を `spawn_subagent` の `description` 先頭に注入することで、
事前設定されたサブエージェントを疑似的に実現する。

サブエージェントの種類・利用可能ツールの一覧は `agent-types.md` を参照。

---

## Step 1 — エージェント定義ファイルを読み込む

`list_files(".bob/agents/")` でエージェント一覧を確認し、`.bob/agents/.md` を `read_file` で読み込む。
frontmatter から `type` / `skills` / `fork_context` を抽出し、本文(役割・制約のセクション)を取り出す。

## Step 2 — skills リストを変換する

`skills:` のエントリを **1対1** で `read_file` 呼び出しに変換する。

変換ルールと正誤例は `conversion-rules.md` を参照。

変換後に以下を自己チェックしてから次へ進む:

```
[ ] skills: のエントリ数(N 個)と read_file 行数(N 行)が一致している
[ ] 各行のパスが .bob/skills//SKILL.md になっている
[ ] skills: にないファイルを自己判断で追加していない
```

## Step 3 — description を組み立てて spawn_subagent を呼び出す

Step 1・Step 2 の結果を下記テンプレートに埋め込み、`spawn_subagent` を呼び出す。

**`spawn_subagent` パラメータ:**

| パラメータ | 値 |
|---|---|
| `name` | frontmatter の `type` 値 |
| `fork_context` | frontmatter の `fork_context` 値(未指定時は `false`) |
| `description` | 下記テンプレートで生成したテキスト |

**description テンプレート:**

```
=== カスタムサブエージェント定義: {name} ===
(.bob/agents/{name}.md をロードして注入したもの。役割・制約として厳守すること。)

## あなたの役割
{Step 1 で抽出した本文}

## 起動時に必ず読み込むスキル
use_skill は使えないため、以下を read_file で直接読み込み手順に従うこと(スキルごとに1行、全て必須):
{Step 2 で生成した read_file 行}
(skills 未指定の場合はこのセクションを省略)

=== 定義ここまで。以下は今回の具体タスク ===
{今回の指示}
```

---

## 注意事項

- 定義 MD にプロジェクトのルール・コンテキスト全文を静的コピーしない。必要なら `fork_context: true` でメインタスクから渡すこと
- `fork_context` の選択基準: `description` が自己完結していれば `false`。親の会話の決定事項・追加制約をサブに知らせる必要がある場合は `true`
- 複数サブエージェントを並列起動するときは役割ごとに個別適用する
agent-types.md
# サブエージェントの種類と利用可能ツール(実測値)

> `use_skill` は利用不可。`read_file(".bob/skills//SKILL.md")` で代替すること。

| 種類 | 説明 |
|---|---|
| `explore` | 読み取り専用・軽量モデル |
| `general` | 読み書き・コマンド実行・デフォルトモデル |

| ツール | explore | general |
|---|---|---|
| read_file / list_files / glob / grep / GetSymbolsOverview / FindSymbol / FindReferencingSymbols | yes | yes |
| ask_followup_question | yes | yes |
| write_file / apply_diff / insert_content / search_and_replace / read_xlsx | no | yes |
| execute_command | no | yes |
| use_skill / spawn_subagent(ネスト) | no | no |
| MCP ツール(mcp__*) | no | no |
conversion-rules.md
# skills 変換ルールと正誤例

## ルール(3つ、全て必須)

| ルール | 内容 |
|---|---|
| **全エントリ変換** | `skills:` のエントリ数と `read_file` 行数が必ず一致すること |
| **SKILL.md のみ** | `read_file(".bob/skills//SKILL.md")` のみ。サポートファイルは列挙しない |
| **追加禁止** | `skills:` に存在しないファイルを自己判断で追加しない |

## 正誤例

エントリが3つある定義ファイルの場合:

```yaml
# .bob/agents/.md の skills:
skills:
  - skill-a    # エントリ 1
  - skill-b    # エントリ 2
  - skill-c    # エントリ 3
```

```text
# 正しい変換(エントリ数 3 = read_file 行数 3)
- read_file(".bob/skills/skill-a/SKILL.md")
- read_file(".bob/skills/skill-b/SKILL.md")
- read_file(".bob/skills/skill-c/SKILL.md")

# 誤り:skill-a が抜けている(エントリ数 3 != read_file 行数 2)
- read_file(".bob/skills/skill-b/SKILL.md")
- read_file(".bob/skills/skill-c/SKILL.md")

# 誤り:サポートファイルを追加している(SKILL.md 以外は禁止)
- read_file(".bob/skills/skill-b/SKILL.md")
- read_file(".bob/skills/skill-b/best-practices.md")          <- 禁止
- read_file(".bob/skills/skill-b/implementation-patterns.md") <- 禁止
- read_file(".bob/skills/skill-c/SKILL.md")
```

具体例

前述した定義ファイルpycode-reviewer.mdを使って、具体例(ステップ)を示します。

Step 1. YAMLフロントマターから以下を抽出

キー 用途
type general spawn_subagent の name
fork_context false spawn_subagent の fork_context
skills [review-pycode, auto-memory] Step 2 で変換
本文 役割・制約テキスト description に埋め込み

Step 2. skills リストを read_file 行に変換

- read_file(".bob/skills/review-pycode/SKILL.md")
- read_file(".bob/skills/auto-memory/SKILL.md")

Step 3.description を組み立てて spawn_subagent を呼出

spawn_subagent のパラメータ:

パラメータ
name "general"
fork_context false
description 下記テンプレートのテキスト

description(組み立て後):

=== カスタムサブエージェント定義: pycode-reviewer ===
(.bob/agents/pycode-reviewer.md をロードして注入したもの。役割・制約として厳守すること。)

## あなたの役割
Pythonコードをレビューし、`review-pycode` スキルの手順に従って標準フォーマットの指摘レポートを生成するエージェント。

### 役割
- 指定されたPythonファイルを読み込み、コードレビューを実施する
- 規定の出力フォーマットでレポートを生成する

### 制約
- 独自のチェックルールや重大度を追加してはならない
- 出力フォーマットはスキル定義のテンプレートから逸脱してはならない

## 起動時に必ず読み込むスキル
use_skill は使えないため、以下を read_file で直接読み込み手順に従うこと(スキルごとに1行、全て必須):
- read_file(".bob/skills/review-pycode/SKILL.md")
- read_file(".bob/skills/auto-memory/SKILL.md")

=== 定義ここまで。以下は今回の具体タスク ===

実際には、メインタスク (Bob)から渡されてくる「具体タスク」が末尾に挿入された状態でspawn_subagentに渡されます。

結果(実行例)

定義ファイルに指定した指示・スキルが確実にサブエージェントへ注入・実行されるかを確認してみます。適当な5つのPythonファイルを用意し、pycode-reviewerエージェントを使って並列レビューさせてみます。

load-custom-agentスキルを有効にして、Bobに以下のプロンプトで指示を出してみます。

test/ 配下にある5つのファイルを、pycode-reviewerサブエージェントで並列評価してください。

定義ファイルが少ないうちは、「python評価サブエージェント」のような指示でも読み込んでくれます。
ただ、定義ファイルが増えてきた場合は、具体的な定義ファイル名を指定したほうが確実です。

結果、load-custom-agentスキルが呼び出され、5つのサブエージェントが生成されました。spawn_subagentに渡されたdescriptionは以下のような構造になっています。(前述した具体例 Step 3と同じです)

=== 定義ここまで ===より上が定義ファイルから注入された内容、下がメインタスクから渡された具体的な指示です。

=== カスタムサブエージェント定義: pycode-reviewer ===
(.bob/agents/pycode-reviewer.md をロードして注入したもの。役割・制約として厳守すること。)

## あなたの役割
Pythonコードをレビューし、`review-pycode` スキルの手順に従って標準フォーマットの指摘レポートを生成するエージェント。

### 役割
- 指定されたPythonファイルを読み込み、コードレビューを実施する
- 規定の出力フォーマットでレポートを生成する

### 制約
- 独自のチェックルールや重大度を追加してはならない
- 出力フォーマットはスキル定義のテンプレートから逸脱してはならない

## 起動時に必ず読み込むスキル
use_skill は使えないため、以下を read_file で直接読み込み手順に従うこと(スキルごとに1行、全て必須):
- read_file(".bob/skills/review-pycode/SKILL.md")
- read_file(".bob/skills/auto-memory/SKILL.md")

=== 定義ここまで。以下は今回の具体タスク ===

`test/test01.py` をレビューし、スキル手順に従って標準フォーマットの指摘レポートを生成してください。
レポートは `reports/test01_review.md` に保存してください。

5つのサブエージェントが並列で起動された様子です。
image.png

次に、サブエージェントが利用したツールを確認します。
https___qiita-image-store.s3.ap-northeast-1.amazonaws.com_0_4199720_3ea7a992-4031-4e23-a7d7-e682cc2e956b.jpg
①が定義ファイルのskills:に指定したスキルのSKILL.mdの読み込みで、スキル本体がサブエージェント内で参照されていることが確認できます。また②は、SKILL.mdの指示に従ってサブエージェントが必要なタイミングで自律的にサポートファイルを読み込んでいることを示しています。

実行結果に関しても、指定した内容を全サブエージェントが行ってくれたのを確認しました。

同じプロンプトで何回か試しましたが、いずれも同じ内容のdescriptionでサブエージェントが生成されました。定義ファイルによる具体的な指示と使用スキルを、サブエージェントに確実に与えて実行できることが確認できました。

補足

load-custom-agentスキルを使わなくとも(無効にしても)、サブエージェント生成時に.bob/agents配下の定義ファイルの内容が自動的に利用される挙動を確認しました。どうやらexploregeneralと同様に、.bob/agents配下の定義がサブエージェントの種類として自動的に認識されているようです。

定義ファイルのYAMLフロントマターのdescriptionが参照され、タスクに適切なサブエージェントが自動選択される動きも見られました。

ただし、スキルの呼び出しについてはuse_skillツールを利用できない制約が残ります。その点で、今回実装したload-custom-agentスキルは、スキル呼出の再現性の担保という意味では有効と考えています。

おわりに

本記事では、spawn_subagentの動作の整理と、再現性のあるサブエージェントの定義方法について検証しました。実際筆者はこの実装をIaCの生成タスクに導入しており、安定して動作していることを確認しています。

サブエージェントの定義が標準機能としてリリースされたら不要になる内容ですが、それまでは使い続けてみようと思います。

以上になります。

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?