Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
95 changes: 95 additions & 0 deletions docs/jp/steering.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
# ステアリングとキューイング

エージェントが処理中にメッセージを送る方法として、**ステアリング**と**キューイング**の2つのパターンがあります。

## 概要

`send()` / `sendAndWait()` / `sendAndStream()` / `Copilot::run()` のすべてに `$mode` パラメータがあります。

| モード | 動作 |
|--------|------|
| `"enqueue"`(デフォルト) | 現在のターンが完了した後にキューとして処理される |
| `"immediate"`(ステアリング) | 現在処理中のターンに割り込んで即座に注入される |

## ステアリング(`"immediate"`)

エージェントが処理中のターンに直接メッセージを注入します。エージェントはリアルタイムでメッセージを受け取り、応答を調整します。進行中の作業を中断せずに方向修正したい場合に使います。

```php
use Revolution\Copilot\Facades\Copilot;
use Revolution\Copilot\Contracts\CopilotSession;

Copilot::start(function (CopilotSession $session) {
// 長時間かかるタスクを開始
$messageId = $session->send(prompt: 'Refactor the authentication module to use sessions');

// エージェントが処理中に方向修正
$session->send(
prompt: 'Actually, use JWT tokens instead of sessions',
mode: 'immediate',
);

// アイドル状態になるまで待機
$response = $session->sendAndWait(prompt: 'Summarize what you did');
});
```

> **注意:** ステアリングはベストエフォートです。エージェントがすでにツール呼び出しをコミットしていた場合、そのツール呼び出し完了後に適用されますが、同一ターン内で処理されます。ターンが完了した後にステアリングメッセージが届いた場合は自動的にキューに移動されます。

## キューイング(`"enqueue"`)

メッセージをキューに追加し、現在のターンが完了してから順次処理します。各キューされたメッセージは独立したターンとして実行されます。`$mode` を省略した場合のデフォルト動作です。

```php
Copilot::start(function (CopilotSession $session) {
// 最初のタスクを開始
$session->send(prompt: 'Set up the project structure');

// エージェントが処理中に後続タスクをキューへ追加
$session->send(prompt: 'Add unit tests for the auth module', mode: 'enqueue');
$session->send(prompt: 'Update the README with setup instructions', mode: 'enqueue');

// キューが空になるまで待つ
});
```

## Laravelでの実用的な考え方

Laravelでは `Copilot::run()` や `sendAndWait()` を使う同期的なパターンが中心です。これらはメッセージを送ってアイドル状態になるまで待機するため、**エージェントが処理中に割り込む機会がなく、`$mode` は実質的に意味をもちません**。

```php
// Copilot::run() は内部的に sendAndWait() を呼び出すため
// mode を指定しても意味がない

$response = Copilot::run(prompt: 'Tell me something about Laravel.');

// セッション内でも sendAndWait() を順番に呼ぶだけなら不要
Copilot::start(function (CopilotSession $session) {
$r1 = $session->sendAndWait(prompt: 'First task');
$r2 = $session->sendAndWait(prompt: 'Second task');
});
```

ステアリング(`"immediate"`)が活きるのは、`send()` で非同期的にメッセージを送りつつ、並行して別のメッセージで進行中のターンに介入できる場合です。Laravelの同期的な処理フローでは、その機会を作るのが難しいため、**基本的には `$mode` を指定せずデフォルトのままにしておくのが適切です**。

## どちらを使うべきか

| 場面 | パターン |
|------|----------|
| エージェントが間違った方向に進んでいる | ステアリング(`"immediate"`) |
| 次にやることを思いついた | キューイング(`"enqueue"`) |
| 複数タスクを順番に実行したい | キューイング(`"enqueue"`) |
| 通常のLaravelアプリ | デフォルト(`$mode` 不要) |

## ベストプラクティス

- **デフォルトはキューイング** — `$mode` を省略(または `"enqueue"` を指定)するのがほとんどのケースで適切です。予測可能な動作をします。
- **ステアリングは修正用に** — `"immediate"` はエージェントが明らかに間違ったことをしている場合に限定して使います。
- **ステアリングメッセージは簡潔に** — 現在のコンテキストで理解できる短いメッセージにします。長く複雑なステアリングメッセージはかえって混乱を招きます。
- **連続ステアリングは避ける** — 短時間に複数のステアリングを送るとターンの品質が低下する可能性があります。大幅な方向転換が必要な場合はターンを中断して最初からやり直す方が適切なこともあります。

## 参考

- [基本的な使い方](./basic-usage.md)
- [Streaming](./streaming.md)
- [send-on](./send-on.md)
2 changes: 1 addition & 1 deletion src/Contracts/Factory.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ interface Factory
*
* @param string $prompt The prompt/message to send
* @param array<array{type: string, path: string, displayName?: string}>|null $attachments File or directory attachments. type: "file" | "directory"
* @param ?string $mode Message delivery mode. "enqueue": Add to queue (default), "immediate": Send immediately
* @param ?string $mode Message delivery mode. "enqueue": Queue for processing after current turn (default). "immediate": Inject into current turn (steering). Omit for normal use.
*/
public function run(string $prompt, ?array $attachments = null, ?string $mode = null, SessionConfig|array $config = []): ?SessionEvent;

Expand Down
2 changes: 1 addition & 1 deletion src/CopilotManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ public function __construct(
*
* @param string $prompt The prompt/message to send
* @param array<array{type: string, path: string, displayName?: string}>|null $attachments File or directory attachments. type: "file" | "directory"
* @param ?string $mode Message delivery mode. "enqueue": Add to queue (default), "immediate": Send immediately
* @param ?string $mode Message delivery mode. "enqueue": Queue for processing after current turn (default). "immediate": Inject into current turn (steering). Omit for normal use.
*/
public function run(string $prompt, ?array $attachments = null, ?string $mode = null, SessionConfig|array $config = []): ?SessionEvent
{
Expand Down
6 changes: 3 additions & 3 deletions src/Session.php
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ public function rpc(): SessionRpc
*
* @param string $prompt The prompt/message to send
* @param array<array{type: string, path: string, displayName?: string}>|null $attachments File or directory attachments. type: "file" | "directory"
* @param ?string $mode Message delivery mode. "enqueue": Add to queue (default), "immediate": Send immediately
* @param ?string $mode Message delivery mode. "enqueue": Queue for processing after current turn (default). "immediate": Inject into current turn (steering). Omit for normal use.
*
* @throws JsonRpcException
*/
Expand All @@ -160,7 +160,7 @@ public function send(string $prompt, ?array $attachments = null, ?string $mode =
*
* @param string $prompt The prompt/message to send
* @param array<array{type: string, path: string, displayName?: string}>|null $attachments File or directory attachments. type: "file" | "directory"
* @param ?string $mode Message delivery mode. "enqueue": Add to queue (default), "immediate": Send immediately
* @param ?string $mode Message delivery mode. "enqueue": Queue for processing after current turn (default). "immediate": Inject into current turn (steering). Omit for normal use.
* @param float $timeout Maximum time to wait for idle state, in seconds
*/
public function sendAndWait(string $prompt, ?array $attachments = null, ?string $mode = null, ?float $timeout = null): ?SessionEvent
Expand Down Expand Up @@ -367,7 +367,7 @@ public function off(Closure $handler): void
*
* @param string $prompt The prompt/message to send
* @param array<array{type: string, path: string, displayName?: string}>|null $attachments File or directory attachments
* @param ?string $mode Message delivery mode
* @param ?string $mode Message delivery mode. "enqueue": Queue for processing after current turn (default). "immediate": Inject into current turn (steering). Omit for normal use.
* @param float|null $timeout Maximum time to wait for idle state, in seconds
* @return iterable<SessionEvent>
*/
Expand Down