# Changement d’outils pendant une session

Une application peut remplacer les outils qu’elle fournit à une session en direct sans la recréer. Par exemple, une page web peut offrir différents outils à mesure que l’utilisateur navigue, ou un client qui prend le contrôle d’une session peut apporter ses propres outils. Chaque KIT SDK remplace l’ensemble complet d’outils du client et les gestionnaires associés dans un seul appel.

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

> **Expérimental.** Le remplacement de l’outil encapsule le RPC expérimental `session.tools.set` et nécessite un runtime qui le prend en charge.

## Remplacer les outils de ce client

Réussit avec l’ensemble complet d’outils que ce client doit fournir. Il remplace les outils fournis par le client lors de la création ou de la reprise de la session, ou dans un remplacement antérieur. Les outils intégrés, MCP et plug-in et les outils que d’autres clients connectés à la même session fournissent ne sont pas affectés. Passez une liste vide pour supprimer tous les outils de ce client.

Les outils sont définis exactement comme ils le sont pour la création d’une session, et un outil sans gestionnaire se comporte de la même façon dans ce cas également.

<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` déclenche le diagnostic expérimental `GHCP001`, que vous supprimez avec `#pragma warning disable GHCP001` ou avec une option `<NoWarn>GHCP001</NoWarn>` au niveau du projet.

</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` est `@CopilotExperimental`, donc la classe ou la méthode consommatrice doit activer explicitement avec `@AllowCopilotExperimental`. Consultez [Utilisation d’API expérimentales](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>

## Lorsque les nouveaux outils entrent en vigueur

- **Requêtes de modèle.** Le runtime offre les nouveaux outils provenant de la prochaine requête au modèle de l’agent. Cette demande peut faire partie d’un tour de parole qui est déjà en cours.
- **Gestionnaires.** Dès que le runtime accepte le remplacement, chaque appel d’outil que la session envoie utilise les nouveaux gestionnaires. Les appels en cours d’exécution se terminent sur les gestionnaires d’événements qui les ont démarrés.
- **Rejet.** Si le runtime rejette le remplacement, l’appel échoue et les outils et gestionnaires précédents restent en place. Le runtime rejette les noms d’outils comportant des caractères non valides et les noms qu’un autre client connecté fournit déjà.
- **Commande.** Les remplacements simultanés sur la même session sont appliqués un par un, dans l’ordre dans lequel ils sont effectués.
- **Annulation.** Dans les kits sdk qui vous permettent d’annuler l’appel, l’annulation de l’appel alors qu’un remplacement antérieur est toujours en cours, cela n’envoie rien. Une fois la requête envoyée, l’annulation arrête uniquement l’attente : si le runtime accepte le remplacement, les nouveaux gestionnaires prennent toujours effet.

## Remplacement d’outils lors d’un tour

Une requête du modèle déjà en cours d’exécution a été effectuée avec les outils précédents, de sorte que l’agent peut toujours appeler un outil que vous venez de supprimer. La session ne répond pas à cet appel, car un autre client connecté peut fournir un outil portant le même nom. L’appel peut donc rester en attente jusqu’à ce que le turn soit abandonné.

Si une itération en cours d’exécution peut toujours appeler un outil que vous supprimez, remplacez les outils pendant que la session est inactive, par exemple après l’événement `session.idle`, ou abandonnez d’abord l’itération. Le remplacement du gestionnaire d’un outil sous le même nom peut se faire en toute sécurité pendant un tour : les appels acheminés une fois que l’environnement d’exécution a accepté le remplacement utilisent le nouveau gestionnaire.

## Informations de référence sur le SDK

| SDK | Méthode |
|---|---|
| TypeScript | `session.setTools(tools)` |
| Python | `await session.set_tools(tools)` |
| Go | `session.SetTools(ctx, tools)` |
| .NET | `await session.SetToolsAsync(tools, cancellationToken)` |
| Java | 
`session.setTools(tools)`, qui retourne un `CompletableFuture<Void>` |
| Rust | `session.set_tools(tools).await` |