# Alterando ferramentas durante uma sessão

Um aplicativo pode substituir as ferramentas fornecidas para uma sessão ativa sem recriá-la. Por exemplo, uma página da Web pode oferecer ferramentas diferentes à medida que o usuário navega ou um cliente que assume uma sessão pode trazer suas próprias ferramentas. Cada SDK substitui o conjunto de ferramentas completo do cliente e os handlers que o atendem em uma chamada.

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

> **Experimental.** A substituição da ferramenta encapsula o RPC experimental `session.tools.set` e requer um runtime compatível com ele.

## Substituir as ferramentas desse cliente

Informe o conjunto completo de ferramentas que este cliente deve fornecer. Ele substitui as ferramentas fornecidas pelo cliente quando a sessão foi criada ou retomada ou em uma substituição anterior. Ferramentas internas, MCP e plug-ins, e ferramentas fornecidas por outros clientes conectados à mesma sessão não são afetadas. Passe uma lista vazia para remover todas as ferramentas desse cliente.

As ferramentas são definidas exatamente da mesma forma que para criar uma sessão, e uma ferramenta sem um manipulador se comporta da mesma forma como acontece ali.

<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` gera o diagnóstico experimental `GHCP001`, que você pode suprimir com `#pragma warning disable GHCP001` ou um `<NoWarn>GHCP001</NoWarn>` em nível de projeto.

</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`, portanto, a classe ou método consumidor deve optar explicitamente por meio de `@AllowCopilotExperimental`. Consulte [Usando APIs experimentais](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>

## Quando as novas ferramentas entrarem em vigor

- **Solicitações de modelo.** O runtime oferece as novas ferramentas a partir da próxima solicitação de modelo do agente. Essa solicitação pode fazer parte de uma interação que já está em andamento.
- **Tratadores.** Assim que o runtime aceitar a substituição, cada chamada de ferramenta que a sessão despacha usará os novos manipuladores. As chamadas que já estão em execução terminam nos manipuladores que as iniciaram.
- **Rejeição.** Se o runtime rejeitar a substituição, a chamada falhará e as ferramentas e manipuladores anteriores permanecerão em vigor. O runtime rejeita nomes de ferramentas com caracteres inválidos e nomes que outro cliente conectado já fornece.
- **Pedidos.** As substituições simultâneas na mesma sessão são aplicadas uma de cada vez, na ordem em que são feitas.
- **Cancelamento.** Em SDKs que permitem cancelar a chamada, cancelá-la enquanto uma substituição anterior ainda está em andamento não envia nada. Depois que a solicitação é enviada, o cancelamento só interrompe a espera: se o runtime aceitar a substituição, os novos manipuladores ainda entrarão em vigor.

## Substituindo ferramentas durante uma vez

Uma solicitação de modelo que já está em andamento foi feita com as ferramentas anteriores, portanto, o agente ainda pode chamar uma ferramenta que você acabou de remover. A sessão não atende a essa chamada, pois outro cliente conectado pode fornecer uma ferramenta com o mesmo nome, portanto, a chamada pode permanecer pendente até que o turno seja anulado.

Se uma interação em execução ainda puder chamar uma ferramenta que você remove, substitua as ferramentas enquanto a sessão estiver ociosa, por exemplo, após o evento `session.idle`, ou aborte a interação primeiro. Substituir o manipulador de uma ferramenta com o mesmo nome é seguro durante um turno: chamadas enviadas após o runtime aceitar a substituição usam o novo manipulador.

## Referência do SDK

| SDK | Método |
|---|---|
| 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)`, que retorna um `CompletableFuture<Void>` |
| Rust | `session.set_tools(tools).await` |