# 세션 중 도구 변경

애플리케이션은 라이브 세션을 다시 만들지 않고 라이브 세션에 제공하는 도구를 대체할 수 있습니다. 예를 들어 웹 페이지는 사용자가 탐색할 때 다른 도구를 제공하거나 세션을 이어받는 클라이언트가 자체 도구를 가져올 수 있습니다. 각 SDK는 클라이언트의 전체 도구 집합과 해당 도구 집합을 한 번의 호출로 제공하는 처리기를 대체합니다.

<!-- 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`은 `GHCP001` 실험적 진단을 발생시키며, 이 진단은 `<NoWarn>GHCP001</NoWarn>` 또는 프로젝트 수준의 `#pragma warning disable 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>

## 새 도구가 효력을 발휘할 때

- **모델 요청 목록.** 런타임은 에이전트의 다음 모델 요청에서 새 도구를 사용할 수 있습니다. 해당 요청은 이미 진행 중인 턴의 일부일 수 있습니다.
- **처리기.** 런타임에서 교체를 수락하는 즉시 세션이 디스패치하는 모든 도구 호출은 새 처리기를 사용합니다. 이미 실행 중인 호출은 시작한 처리기에서 완료됩니다.
- **거부.** 런타임에서 교체를 거부하는 경우 호출이 실패하고 이전 도구 및 처리기가 그대로 유지됩니다. 런타임은 잘못된 문자가 포함된 도구 이름이나 다른 연결된 클라이언트가 이미 제공한 이름을 거부합니다.
- **정렬.** 동일한 세션의 동시 교체는 순서대로 한 번에 하나씩 적용됩니다.
- **취소.** 호출을 취소할 수 있는 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)` |
| 러스트 | `session.set_tools(tools).await` |