本文へスキップ
webkida wiki
戻る

【Cursor】サブエージェントとバックグラウンド実行

Cursorのエージェントは、一つの会話の中で調査も実装もテストも進めます。長い一手が終わるまで、別の質問も、別件の依頼も出せないことがあります。

そこでサブエージェントがあります。一塊の仕事を別のエージェントに渡す仕組みです。担当が分かれれば、こちらの会話は空くはずだ、と感じやすいです。

長い調査を子に頼むと、子は動きます。ただ、子が返るまで今の会話は止まったままです。次の依頼を書いても、親は動きません。委譲した瞬間に裏で進む、と思っていたのに、待たされます。

サブエージェントは誰がやるかを分けるだけです。親が待たなくてよくなるのは、バックグラウンドにしたときだけです。以下では、委譲しても止まる理由、委譲の目的、二つの軸の違い、バックグラウンドにする方法を順に整理します。

用語

サブエージェント

今の会話から切り出された、別のエージェントです。調査や実装など、一塊の仕事だけを担当します。今の会話の履歴は共有せず、渡された指示だけを見ます。

Multitask Mode

複数のサブエージェントを、最初からバックグラウンドで同時に出します。入口は /multitask です。

委譲しても、今の会話は止まる

子に仕事を渡すと、子は動きます。親の会話が止まっても、それは担当を分けたせいではありません。1つの会話が一度に一つの仕事しか進めないからです。

【今の会話】

自分:「この調査、子にお願い」

親:「子に渡します」

自分:「返るまでのあいだ、別件もお願い」

親:(動かない。子の結果を待っている)

親の今の一手は、子を起動した時点で終わっていません。子が結果を返すまで、親の返答は出ません。こちらから次の依頼を書いても、親はそれを処理できません。

flowchart LR
  u["自分"] --> p["親"]
  p --> c["子"]
  c --> p
  p --> u

図: 親→子→親が一連の流れ。子が返るまで、親は次の依頼を受け取れない。

待っているあいだ、子の中ではファイルを読んだり、テストを回したりしています。見えているのは親が止まっている状態だけです。モデルが遅いから、というより、会話の一手が子の完了まで閉じているから、待たされます。

サブエージェントは担当を分けます。止まるかどうかは、まだ変わりません。

サブエージェントとは何か

サブエージェントは、今の会話のエージェント(親)が、別のエージェントに一塊の仕事を渡す切り方です。親は方針と、戻ってきた結果の統合を持ちます。子は調査や実装など、切り出した範囲だけをやります。

【親】

「該当箇所の調査だけ、そちらでやって。直すかどうかは、結果を見てこちらで決める」

【子】

「調査だけ受けました。親のこれまでのやり取りは見ていません。渡された指示だけを見ます」

子は親の会話履歴を共有しません。渡した指示が、子が知るすべてです。前提や制約を書かないと、親が当然だと思っている条件が子に届きません。

ここまでが委譲です。担当は分かれます。デフォルトのままだと今の会話は止まったままで、子が返るまで次の依頼は出せません。

図: 仕事は渡しても、今の会話は子が返るまで止まる。

サブエージェントに頼む主な目的

委譲する理由は、待たないことだけではありません。待たせないのは、バックグラウンドにしたときの話です。

文脈を分ける。 長い調査やログは、親の会話を圧迫します。子の中間出力は子に閉じ、結果だけ親に戻します。広い探索を親の履歴に残したくないとき向きです。

一塊に責任を閉じる。 調査だけ、検証だけ、と範囲を切ると、親は方針に集中できます。子は渡された指示だけを見ます。実装の判断を親に残したまま、探索だけ渡す、といった切り方です。

同じ型の仕事を再利用する。 カスタムサブエージェントに、役割と制約を書いておけます。毎回同じ説明を親の会話に書かなくて済みます。

並列に進めたい。 独立した2件を同時に進める、調査と別件の修正を並べる、といった目的もあります。同時に動かすにはバックグラウンドが必要です。委譲しただけでは、子は一人ずつ、親を止めたまま終わります。

委譲とバックグラウンドは別物

軸はふたつです。誰がやるかと、親が待つかです。

誰がやる今の会話は待つか
一本の会話今の会話待つ
サブエージェント(デフォルト)待つ
サブエージェント(バックグラウンド)待たない

【委譲だけ】

親:「調査をお願い」

子:「調べます」

親は止まります。調査が終わるまで、次の依頼は実行できません。担当は分かれていますが、待ちは残っています。

【委譲とバックグラウンド】

親:「調査をお願い。バックグラウンドで」

子:「調べます」

親は次の判断を続けられます。子の完了は、あとから受け取ります。

flowchart TB
  subgraph fg ["委譲だけ(今の会話が待つ)"]
    direction LR
    p1["親"] --> c1["子"]
    c1 --> p1
  end

  subgraph bg ["委譲 + バックグラウンド"]
    direction LR
    p2["親"] --> c2["子"]
    p2 --> next["親の次の判断"]
  end

図: 委譲は担当を分ける。バックグラウンドは親の待ちを外す。両方そろったときだけ、次の依頼を同時に進められる。

次の一手が子の返答に依存するなら、今の会話で待つ選択もあります。待たずに次を出したいときだけ、バックグラウンドにします。

バックグラウンドにする方法

デフォルトでは今の会話が止まります。待たないようにするには、次のいずれかで明示します。

設定で is_background: true

カスタムサブエージェントの frontmatter に書いておけます。呼ぶと親を止めずに走ります。

---
name: explorer
description: コードベースを調査する。長い探索に使う。
is_background: true
---

常に裏で走ってよい役割向けです。結果を見てから次を決めたい子には向きません。

呼び出し時にバックグラウンド指定

設定がデフォルトのままでも、その回だけ裏に出せます。会話で「バックグラウンドで走らせて」と書くか、Task を run_in_background: true で渡します。

一度きりの調査、今だけ待たれたくない依頼向きです。設定を変える必要はありません。

Multitask Mode

バックグラウンドは、1本の依頼について親が待たない実行です。Multitask Mode は、その上で複数本を同時に回します。

/multitask は、複数のサブエージェントを最初からバックグラウンドで出します。キューを直列に消化する代わりに、独立した塊を同時に走らせます。1本だけ裏に出すなら、ここまで使う必要はありません。

親は会話に残り、子の完了を待たずに次を続けられます。同時に出してよいのは、独立した仕事だけです。依存があるものは、先に一つ出してから次へ回します。

flowchart LR
  parent["親"]
  childA["子: 調査"]
  childB["子: 別件"]
  parent --> childA
  parent --> childB

図: Multitask Mode は、バックグラウンドの子を複数同時に出す進め方。

図: 親は会話を続け、独立した子が裏で同時に進む。

Cursor の Subagents ドキュメント では、is_background の初期値は false とされています。

使い分け

先に「誰がやるか」を決め、そのあと「親が待つか」を決めます。二つを一度に混ぜると、委譲しただけで待たなくなる、と錯覚しやすいです。

文脈を分けたい、一塊に閉じたい、同じ型を再利用したい、ならサブエージェントです。ここで決まるのは担当だけです。親を止めるかどうかは、まだ決めていません。

次が子の返答に依存するなら待ちます。調査のあとで直す、検証結果を見てから出す、といった流れです。依存がなければバックグラウンドです。

バックグラウンドにする経路は、役割の寿命で選びます。

状況経路
いつも裏でよい役割設定で is_background: true
その回だけ待たれたくない呼び出し時に指定
独立した複数件を同時にMultitask Mode

調査と実装を分けるなら、調査を子に出し、実装は結果を見てから今の会話で入ります。独立した2件なら、Multitask Mode か、呼び出し時のバックグラウンドで並べます。

小さな一事は切りません。切り出しの指示を書くコストの方が大きいです。同じファイルを触る仕事も並べません。片方の結果をもう片方は知りません。

flowchart TB
  q1{"文脈や担当を分けたいか"}
  q2{"次が子の返答に依存するか"}
  q3{"独立した複数件か"}
  stay["親が自分でやる"]
  wait["サブエージェント<br/>今の会話が待つ"]
  one["呼び出し時か設定で<br/>バックグラウンド"]
  many["Multitask Mode"]
  q1 -->|いいえ| stay
  q1 -->|はい| q2
  q2 -->|はい| wait
  q2 -->|いいえ| q3
  q3 -->|はい| many
  q3 -->|いいえ| one

図: 担当を分けるか、親が待つか、同時に何本出すか、の順で選ぶ。

切り出しで壊れやすい点

いちばん多いのは、委譲しただけで待たなくなる、と思い込むことです。子は動いています。親は止まっています。次の依頼は、まだ実行できません。

指示が薄いと、子はずれます。親の会話履歴は届かないので、前提、触ってよい範囲、やってはいけないことを、渡す文に書きます。

依存する作業を同時に走らせると、同じファイルを踏みます。調査の結果を見て直すなら、調査が先です。並べるのは独立した仕事だけです。

バックグラウンドに出したあと、完了を見ずに次へ進むと、失敗に気づきません。親が手が空くことと、結果を統合しなくてよいことは別です。子が返したら、親が見て次を決めます。

まとめ

サブエージェントへの委譲は、バックグラウンド実行ではありません。委譲は誰がやるかを分けます。バックグラウンドは親が待つかを分けます。

委譲しただけでは、親は子の完了まで止まり、次の依頼を実行できません。待たずに進めるなら、is_background: true、呼び出し時の指定、Multitask Mode のいずれかで明示します。

子へ渡すのは有効です。文脈を分ける、一塊に閉じる、再利用する、といった目的向きです。返答を待つ必要があるなら、今の会話で待ってかまいません。切る対象と、待つかどうかを別々に選びます。


この記事をシェア:

前の記事
【GitHub】SSH認証の仕組みと複数アカウント
次の記事
【GitHub Actions】OIDCでクラウドに認証する