# セッション中のツールの変更

アプリケーションは、ライブ セッションを再作成せずに、そのセッションに提供するツールを置き換えることができます。 たとえば、ユーザーが操作する中で Web ページでさまざまなツールを提供したり、セッションを引き継ぐクライアントが独自のツールを持ち込んだりすることができます。 各 SDK は、1 回の呼び出しで、クライアントの完全なツール セットとそれを提供するハンドラーを置き換えます。

<!-- markdownlint-disable GHD046 GHD005 -->
<!-- Suppressed: GHD046 (outdated release terminology), GHD005 (hardcoded data variable) -->

> **試験段階。** ツールの置換では、実験用 `session.tools.set` RPC をラップし、それをサポートするランタイムが必要です。

## このクライアントアプリのツールを置き換える

このクライアントが提供する必要があるツールの完全なセットを渡してください。 それは、セッションの作成時または再開時、あるいは以前の置き換え時にクライアントが指定したツールを置き換えます。 組み込み、MCP、プラグイン ツール、および同じセッションに接続している他のクライアントが提供するツールは影響を受けません。 このクライアントのすべてのツールを削除するには、空のリストを渡します。

ツールはセッションを作成する場合とまったく同じように定義され、ハンドラーのないツールはそこで行うのと同じように動作します。

<div class="ghd-codetabs">
<div class="ghd-codetab" data-lang="typescript" data-label="TypeScript"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">TypeScript</div>

```typescript
import { defineTool } from "@github/copilot-sdk";
import { z } from "zod";

const searchIssues = defineTool("search_issues", {
    description: "Search the issues shown on the current page",
    parameters: z.object({ query: z.string().describe("Search text") }),
    handler: async ({ query }) => findIssues(query),
});

// Supply only the tools the current page provides.
await session.setTools([searchIssues]);

// Remove all of this client's tools.
await session.setTools([]);
```

</div>

<div class="ghd-codetab" data-lang="python" data-label="Python"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">Python</div>

```python
from pydantic import BaseModel, Field
from copilot.tools import define_tool

class SearchIssuesParams(BaseModel):
    query: str = Field(description="Search text")

@define_tool(description="Search the issues shown on the current page")
async def search_issues(params: SearchIssuesParams) -> str:
    return await find_issues(params.query)

# Supply only the tools the current page provides.
await session.set_tools([search_issues])

# Remove all of this client's tools.
await session.set_tools([])
```

</div>

<div class="ghd-codetab" data-lang="go" data-label="Go"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">Go</div>

```golang
type SearchIssuesParams struct {
    Query string `json:"query" jsonschema:"Search text"`
}

searchIssues := copilot.DefineTool(
    "search_issues",
    "Search the issues shown on the current page",
    func(params SearchIssuesParams, inv copilot.ToolInvocation) (string, error) {
        return findIssues(params.Query)
    },
)

// Supply only the tools the current page provides.
if err := session.SetTools(ctx, []copilot.Tool{searchIssues}); err != nil {
    log.Fatal(err)
}

// Remove all of this client's tools.
if err := session.SetTools(ctx, nil); err != nil {
    log.Fatal(err)
}
```

</div>

<div class="ghd-codetab" data-lang="dotnet" data-label=".NET"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">.NET</div>

```csharp
var searchIssues = CopilotTool.DefineTool(
    ([Description("Search text")] string query) => FindIssues(query),
    factoryOptions: new AIFunctionFactoryOptions
    {
        Name = "search_issues",
        Description = "Search the issues shown on the current page",
    });

// Supply only the tools the current page provides.
await session.SetToolsAsync([searchIssues]);

// Remove all of this client's tools.
await session.SetToolsAsync([]);
```

`SetToolsAsync` では、`#pragma warning disable GHCP001` によって試験的な診断が発生します。これは、`<NoWarn>GHCP001</NoWarn>` またはプロジェクト レベルの `GHCP001` で抑制します。

</div>

<div class="ghd-codetab" data-lang="java" data-label="Java"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">Java</div>

```java
var searchIssues = ToolDefinition.create(
    "search_issues",
    "Search the issues shown on the current page",
    Map.of(
        "type", "object",
        "properties", Map.of("query", Map.of("type", "string", "description", "Search text")),
        "required", List.of("query")),
    invocation -> CompletableFuture.completedFuture(
        findIssues((String) invocation.getArguments().get("query"))));

// Supply only the tools the current page provides.
session.setTools(List.of(searchIssues)).get();

// Remove all of this client's tools.
session.setTools(List.of()).get();
```

`setTools` は `@CopilotExperimental`であるため、使用するクラスまたはメソッドは `@AllowCopilotExperimental`を使用してオプトインする必要があります。 
[実験用 API の使用を](https://github.com/github/copilot-sdk/tree/main/java/README.md#using-experimental-apis)参照してください。

</div>

<div class="ghd-codetab" data-lang="rust" data-label="Rust"><div class="ghd-codetab-fallback-label" role="heading" aria-level="3">Rust</div>

<!-- docs-validate: skip -->

```rust
#[derive(Deserialize, JsonSchema)]
struct SearchIssuesParams {
    /// Search text
    query: String,
}

let search_issues = define_tool(
    "search_issues",
    "Search the issues shown on the current page",
    |_inv, params: SearchIssuesParams| async move {
        Ok(ToolResult::Text(find_issues(&params.query).await))
    },
);

// Supply only the tools the current page provides.
session.set_tools(vec![search_issues]).await?;

// Remove all of this client's tools.
session.set_tools(Vec::new()).await?;
```

</div>

</div>

## 新しいツールが有効になったとき

- **モデル リクエスト。** ランタイムは、エージェントの次のモデル リクエストで利用可能な新しいツールを提供します。 その要求は、既に進行中のやり取りの一部にすることができます。
- **ハンドラー。** ランタイムが置換を受け入れるとすぐに、セッションがディスパッチするすべてのツール呼び出しは新しいハンドラーを使用します。 既に実行されている呼び出し処理は、それらを開始したハンドラーで終了します。
- **拒否。** ランタイムが置換を拒否した場合、呼び出しは失敗し、以前のツールとハンドラーはそのまま残ります。 ランタイムは、無効な文字を含むツール名、および接続されている別のクライアントが既に提供しているツール名を拒否します。
- **並べ替え。** 同じセッションでの同時置換は、行われた順序で一度に 1 つずつ適用されます。
- **取り消し。** 呼び出しを取り消せる SDK では、以前の置き換え要求がまだ実行中の間に呼び出しを取り消しても何も送信されません。 要求が送信されると、キャンセルは待機のみを停止します。ランタイムが置換を受け入れた場合、新しいハンドラーは引き続き適用されます。

## ターン中のツールの交換

既に実行中のモデル要求は以前のツールで行われたため、エージェントはたった今削除したツールを引き続き呼び出すことができます。 別の接続されたクライアントが同じ名前のツールを提供する可能性があるため、セッションはその呼び出しに応答しないため、ターンが中止されるまで呼び出しは保留状態を維持できます。

実行中のターンで削除しようとしているツールが引き続き呼び出される可能性がある場合は、セッションがアイドル状態の間 (たとえば、`session.idle` イベントの後) にツールを置き換えるか、最初にターンを中止します。 ツールのハンドラーを同じ名前で置き換えることは、ターン中に安全です。ランタイムが置換を受け入れた後にディスパッチされた呼び出しは、新しいハンドラーを使用します。

## SDK リファレンス

| SDK | メソッド |
|---|---|
| TypeScript | `session.setTools(tools)` |
| Python | `await session.set_tools(tools)` |
| Go | `session.SetTools(ctx, tools)` |
| .NET | `await session.SetToolsAsync(tools, cancellationToken)` |
| Java | 
`CompletableFuture<Void>` を返す `session.setTools(tools)` |
| Rust | `session.set_tools(tools).await` |