- Выполнение инструментов управления — одобрение, отклонение или изменение вызовов инструментов
- Преобразование результатов — модифицировать выходы инструментов до их обработки
- Добавить контекст — ввести дополнительную информацию при начале сессии
- Обработка ошибок — реализация пользовательской обработки ошибок
- Аудит и журнал — отслеживайте все взаимодействия для соответствия требованиям
Доступные крючки
| Хук | Триггер | Вариант использования |
|---|---|---|
| Крючок для использования до использования инструмента | До запуска инструмента | Контроль разрешений, проверка аргументов |
| Крючок после использования инструмента | После запуска инструмента (только успех) | Преобразование результата, логирование |
| Крючок после использования инструмента | После выполнения инструмента, результат которого оказался неудачным | Инжекция повторных инструкций, сбои журнала |
| Хук, присланный пользовательским запросом | Когда пользователь отправляет сообщение | Изменение подсказок, фильтрация |
| Крючки жизненного цикла сессии | Начало сессии | Добавьте контекст, настройте сессию |
| Крючки жизненного цикла сессии | Сессия завершена | Очистка, аналитика |
| Крюк для обработки ошибок | Ошибка возникает | Обработка пользовательских ошибок |
Быстрый старт
TypeScript
import { CopilotClient } from "@github/copilot-sdk";
const client = new CopilotClient();
const session = await client.createSession({
hooks: {
onPreToolUse: async (input) => {
console.log(`Tool called: ${input.toolName}`);
// Allow all tools
return { permissionDecision: "allow" };
},
onPostToolUse: async (input) => {
console.log(`Tool result: ${JSON.stringify(input.toolResult)}`);
return null; // No modifications
},
onSessionStart: async (input) => {
return { additionalContext: "User prefers concise answers." };
},
},
});
Python
from copilot import CopilotClient
from copilot.session import PermissionHandler
async def main():
client = CopilotClient()
await client.start()
async def on_pre_tool_use(input_data, invocation):
print(f"Tool called: {input_data['toolName']}")
return {"permissionDecision": "allow"}
async def on_post_tool_use(input_data, invocation):
print(f"Tool result: {input_data['toolResult']}")
return None
async def on_session_start(input_data, invocation):
return {"additionalContext": "User prefers concise answers."}
session = await client.create_session(on_permission_request=PermissionHandler.approve_all, hooks={
"on_pre_tool_use": on_pre_tool_use,
"on_post_tool_use": on_post_tool_use,
"on_session_start": on_session_start,
})
Go
package main
import (
"context"
"fmt"
copilot "github.com/github/copilot-sdk/go"
)
func main() {
client := copilot.NewClient(nil)
session, _ := client.CreateSession(context.Background(), &copilot.SessionConfig{
Hooks: &copilot.SessionHooks{
OnPreToolUse: func(input copilot.PreToolUseHookInput, inv copilot.HookInvocation) (*copilot.PreToolUseHookOutput, error) {
fmt.Printf("Tool called: %s\n", input.ToolName)
return &copilot.PreToolUseHookOutput{
PermissionDecision: "allow",
}, nil
},
OnPostToolUse: func(input copilot.PostToolUseHookInput, inv copilot.HookInvocation) (*copilot.PostToolUseHookOutput, error) {
fmt.Printf("Tool result: %v\n", input.ToolResult)
return nil, nil
},
OnSessionStart: func(input copilot.SessionStartHookInput, inv copilot.HookInvocation) (*copilot.SessionStartHookOutput, error) {
return &copilot.SessionStartHookOutput{
AdditionalContext: "User prefers concise answers.",
}, nil
},
},
})
_ = session
}
.NET
using GitHub.Copilot;
var client = new CopilotClient();
var session = await client.CreateSessionAsync(new SessionConfig
{
Hooks = new SessionHooks
{
OnPreToolUse = (input, invocation) =>
{
Console.WriteLine($"Tool called: {input.ToolName}");
return Task.FromResult<PreToolUseHookOutput?>(
new PreToolUseHookOutput { PermissionDecision = "allow" }
);
},
OnPostToolUse = (input, invocation) =>
{
Console.WriteLine($"Tool result: {input.ToolResult}");
return Task.FromResult<PostToolUseHookOutput?>(null);
},
OnSessionStart = (input, invocation) =>
{
return Task.FromResult<SessionStartHookOutput?>(
new SessionStartHookOutput { AdditionalContext = "User prefers concise answers." }
);
},
},
});
Java
import com.github.copilot.sdk.*;
import com.github.copilot.sdk.json.*;
import java.util.concurrent.CompletableFuture;
try (var client = new CopilotClient()) {
client.start().get();
var hooks = new SessionHooks()
.setOnPreToolUse((input, invocation) -> {
System.out.println("Tool called: " + input.getToolName());
return CompletableFuture.completedFuture(PreToolUseHookOutput.allow());
})
.setOnPostToolUse((input, invocation) -> {
System.out.println("Tool result: " + input.getToolResult());
return CompletableFuture.completedFuture(null);
})
.setOnSessionStart((input, invocation) -> {
return CompletableFuture.completedFuture(
new SessionStartHookOutput("User prefers concise answers.", null)
);
});
var session = client.createSession(
new SessionConfig()
.setHooks(hooks)
.setOnPermissionRequest(PermissionHandler.APPROVE_ALL)
).get();
}
Контекст вызова крюка
Каждый крюк получает invocation параметр с контекстом текущей сессии:
| Поле | Тип | Description |
|---|---|---|
sessionId | string | ID текущей сессии |
Это позволяет хукам сохранять состояние или выполнять логику, специфичную для сессии.
Распространенные шаблоны
Логирование всех вызовов инструментов
const session = await client.createSession({
hooks: {
onPreToolUse: async (input) => {
console.log(`[${new Date().toISOString()}] Tool: ${input.toolName}, Args: ${JSON.stringify(input.toolArgs)}`);
return { permissionDecision: "allow" };
},
onPostToolUse: async (input) => {
console.log(`[${new Date().toISOString()}] Result: ${JSON.stringify(input.toolResult)}`);
return null;
},
},
});
Блокировка опасных инструментов
const BLOCKED_TOOLS = ["shell", "bash", "exec"];
const session = await client.createSession({
hooks: {
onPreToolUse: async (input) => {
if (BLOCKED_TOOLS.includes(input.toolName)) {
return {
permissionDecision: "deny",
permissionDecisionReason: "Shell access is not permitted",
};
}
return { permissionDecision: "allow" };
},
},
});
Добавление пользовательского контекста
const session = await client.createSession({
hooks: {
onSessionStart: async () => {
const userPrefs = await loadUserPreferences();
return {
additionalContext: `User preferences: ${JSON.stringify(userPrefs)}`,
};
},
},
});
Гайды по крючкам
- Крючок для использования до использования инструмента - Управление правами на выполнение инструментов
- Крючок после использования инструмента — результаты инструмента преобразования
- Хук, присланный пользовательским запросом — Изменить пользовательские запросы
- Крючки жизненного цикла сессии - Начало и окончание сессии
- Крюк для обработки ошибок — Пользовательская обработка ошибок