Skip to main content
Skip to content

Возобновление сессии и сохранение

Это руководство проведёт вас через возможности сохранения сессий SDK — как поставить работу на паузу, возобновить её позже и управлять сессиями в производственных средах.

Как работают сеансы

Когда вы создаёте сессию, CLI Copilot сохраняет историю разговоров, состояние инструмента и контекст планирования. По умолчанию это состояние остаётся в памяти и исчезает после окончания сессии. С включенной устойчивостью вы можете возобновлять сессии при перезапусках, миграциях контейнеров или даже в разных клиентских инстансах.

Диаграмма: блок-схема, показывающая описанный процесс.

ГосударствоЧто происходит
Создатьsession_id Назначено
АктивныйОтправляйте подсказки, призывы к инструментам, ответы
ПриостановленоСостояние сохранено на диск
РезюмеСостояние, загруженное с диска

Быстрый старт: создание возобновляемой сессии

Ключ к возобновляемым сессиям — это предоставление собственных session_id. Без этого SDK генерирует случайный идентификатор, и сессию нельзя возобновить позже.

TypeScript

import { CopilotClient } from "@github/copilot-sdk";

const client = new CopilotClient();

// Create a session with a meaningful ID
const session = await client.createSession({
  sessionId: "user-123-task-456",
  model: "gpt-5.2-codex",
});

// Do some work...
await session.sendAndWait({ prompt: "Analyze my codebase" });

// Session state is automatically persisted
// You can safely close the client

Python

from copilot import CopilotClient
from copilot.session import PermissionHandler

client = CopilotClient()
await client.start()

# Create a session with a meaningful ID
session = await client.create_session(on_permission_request=PermissionHandler.approve_all, model="gpt-5.2-codex", session_id="user-123-task-456")

# Do some work...
await session.send_and_wait("Analyze my codebase")

# Session state is automatically persisted

Go

ctx := context.Background()
client := copilot.NewClient(nil)

// Create a session with a meaningful ID
session, _ := client.CreateSession(ctx, &copilot.SessionConfig{
    SessionID: "user-123-task-456",
    Model:     "gpt-5.2-codex",
})

// Do some work...
session.SendAndWait(ctx, copilot.MessageOptions{Prompt: "Analyze my codebase"})

// Session state is automatically persisted

C# (.NET)

using GitHub.Copilot;

var client = new CopilotClient();

// Create a session with a meaningful ID
var session = await client.CreateSessionAsync(new SessionConfig
{
    SessionId = "user-123-task-456",
    Model = "gpt-5.2-codex",
});

// Do some work...
await session.SendAndWaitAsync(new MessageOptions { Prompt = "Analyze my codebase" });

// Session state is automatically persisted

Возобновление сессии

Позже — через минуты, часы или даже дни — вы сможете продолжить сессию с того места, где остановились.

Диаграмма: блок-схема, показывающая описанный процесс.

TypeScript

// Resume from a different client instance (or after restart)
const session = await client.resumeSession("user-123-task-456");

// Continue where you left off
await session.sendAndWait({ prompt: "What did we discuss earlier?" });

Python

# Resume from a different client instance (or after restart)
session = await client.resume_session("user-123-task-456", on_permission_request=PermissionHandler.approve_all)

# Continue where you left off
await session.send_and_wait("What did we discuss earlier?")

Go

ctx := context.Background()

// Resume from a different client instance (or after restart)
session, _ := client.ResumeSession(ctx, "user-123-task-456", nil)

// Continue where you left off
session.SendAndWait(ctx, copilot.MessageOptions{Prompt: "What did we discuss earlier?"})

C# (.NET)

// Resume from a different client instance (or after restart)
var session = await client.ResumeSessionAsync("user-123-task-456");

// Continue where you left off
await session.SendAndWaitAsync(new MessageOptions { Prompt = "What did we discuss earlier?" });

Варианты резюме

При возобновлении сессии вы можете опционально перенастроить несколько настроек. Это полезно, когда нужно изменить модель, обновить конфигурацию инструментов или изменить поведение.

ОпцияDescription
modelИзмените модель для возобновлённой сессии
systemMessageОтменить или расширить системный запрос
availableToolsОграничьте доступные инструменты
excludedToolsОтключите определённые инструменты
providerПовторное предоставление учетных данных BYOK (требуется для сессий BYOK)
capi.autoTierПереопределите сохраненные параметры автоматической маршрутизации
capi.enableWebSocketResponsesВыбор транспорта API ответов для возобновленного сеанса
reasoningEffortКорректируйте уровень усилий по рассуждению
streamingВключить/отключить потоковые ответы
workingDirectoryИзменить рабочий каталог
configDirКаталог конфигурации Override
mcpServersНастройка MCP-серверов
customAgentsНастройка пользовательских агентов
agentПредварительный выбор пользовательского агента по имени
skillDirectoriesКаталоги для загрузки навыков
disabledSkillsНавыки для отключения
infiniteSessionsНастройка поведения бесконечных сессий

Сохраняемость автоуровневого уровня

При model: "auto"использовании необязательный capi.autoTier параметр выбирает параметр автоматической маршрутизации: efficiency, , balance``intelligenceили fast. В Python используйте capi={"auto_tier": "balance"}. Этот параметр применяется к автоматической маршрутизации версии 2; Автоматические запросы версии 1 не изменяются.

fast— это предустановка задержки только для интегратора, а не сторонняя GitHub Copilot предпочтения продукта. Пакет SDK не принимает решения о быстрой доступности, проверяет удостоверение клиента, выбирает его в качестве значения по умолчанию или возвращается на другой уровень, если среда выполнения не поддерживает ее, старая среда выполнения возвращает собственную ошибку без изменений.

Среда выполнения сохраняет выбранный уровень, поэтому приложениям не нужно повторно отправлять его в каждом возобновлении:

  • Пропуская уровень при создании сеанса, использует поведение маршрутизации по умолчанию среды выполнения.
  • Холодное возобновление восстанавливает сохраненный уровень. При предоставлении явного уровня переопределяет восстановленное значение для новой активации.
  • При возобновлении сеанса, который уже находится в среде выполнения, опустите уровень сохранения текущего выбора и предоставления того же уровня является no-op. Предоставление другого уровня запрашивает безопасный коммутатор, который среда выполнения применяется после успешного возобновления; Он не может изменить поворот, который уже находится в полете.
  • Старые сеансы без сохраняемого уровня сохраняют поведение маршрутизации по умолчанию.

Выбор уровня не является операцией динамического коммутатора модели. Пакет SDK перенаправит предпочтения; среда выполнения владеет сохраняемостью и проверкой.

session.resume События session.start предоставляют выбранный уровень в необязательном data.autoTier поле (data.auto_tierв Python). Если уровень не выбран, поле опущено.

Изменение уровня "Авто" во время сеанса

Вызов setAutoTier для изменения предпочтения маршрутизации в динамическом сеансе без изменения выбранной модели. Передайте null (PythonNone, Gonil), чтобы вернуться к автоматической маршрутизации поставщика по умолчанию.

const result = await session.setAutoTier("intelligence");
if (result.status === "pending") {
  // Accepted, but not yet in effect.
}

Среда выполнения немедленно не применяет предпочтения. Он записывает запрос и фиксирует его только в том случае, если последующий поворот пользователя с помощью auto модели успешно получает используемую модель от поставщика. Таким pending образом, состояние подтверждает, что запрос был принят, а не вступил в силу. Только последний запрос выживает: новый запрос заменяет любой более ранний, который еще не утверждался.

Следите за результатом с помощью следующих событий:

  • session.model_change при фиксации предпочтения.
  • session.auto_tier_switch_failed если это не так. Это событие является временным, поэтому среда выполнения никогда не сохраняет или воспроизводит его в возобновлении. Его reason поле является одним из policy_rejected, request_failed``setup_failedили , и unsupportedранее действующие предпочтения остаются активными.

Вы также можете прочитать авторитетное состояние в любое время с помощью метода RPC сеанса model.getCurrent , который сообщает об фиксации autoTier, любой неисключаемой pendingAutoTierи activatingAutoTier в настоящее время утверждается активацией во время выполнения.

SDKИзменение уровняВозврат к маршрутизации по умолчанию поставщика
Node.jssession.setAutoTier("balance")session.setAutoTier(null)
Pythonsession.set_auto_tier("balance")session.set_auto_tier(None)
Gosession.SetAutoTier(ctx, &tier)session.SetAutoTier(ctx, nil)
.NETsession.SetAutoTierAsync(AutoTier.Balance)session.SetAutoTierAsync(null)
Rustsession.set_auto_tier(Some(AutoTier::Balance))session.set_auto_tier(None)
Javasession.setAutoTier(AutoTier.BALANCE)session.setAutoTier(null)

Чтобы выбрать модель и ее предпочтения маршрутизации в одном вызове, наведите auto уровень на коммутаторе модели. Среда выполнения отклоняет этот параметр, если модель не является любой autoдругой.

SDKЭтап уровня с помощью коммутатораСброс маршрутизации по умолчанию для поставщика
Node.jssetModel("auto", { autoTier: "balance" })setModel("auto", { autoTier: null })
Pythonset_model("auto", auto_tier="balance")set_model("auto", auto_tier=None)
GoSetModelOptions{AutoTier: &tier}SetModelOptions{ResetAutoTier: true}
.NETnew SetModelOptions { AutoTier = AutoTier.Balance }new SetModelOptions { ResetAutoTier = true }
RustSetModelOptions::default().with_auto_tier(AutoTier::Balance)SetModelOptions::default().with_reset_auto_tier()
Javanew SetModelOptions().setModel("auto").setAutoTier(AutoTier.BALANCE)new SetModelOptions().setModel("auto").setResetAutoTier(true)

Node.js, Python и Rust выражают все три состояния в одном значении: Node.js и Python, так как отличается от опущенного аргумента, и Rust, так как null/None``AutoTierPreference::Reset это отдельный вариант одного и того же параметра. Go, .NET и Java не имеют способа отличить "сброс" от "unset" в одном значении, поэтому они несут отдельный флаг сброса. Опущение обоих всегда означает "оставить текущее предпочтение в одиночку".

Перенос ответов на возобновление

Необязательный capi.enableWebSocketResponses параметр выбирает транспорт для API ответов CAPI. По умолчанию trueиспользуется транспорт WebSocket всякий раз, когда выбранная модель объявляет конечную точку ws:/responses . Если он возвращается false к транспорту HTTP. В Python используйте capi={"enable_web_socket_responses": False}.

При необходимости укажите его в вызове резюме. Следует задать, когда подключения WebSocket завершаются сбоем за прокси-сервером и когда возобновляются отчеты 400 input item ID does not belong to this connectionсеанса, относящиеся к транспорту WebSocket.

const session = await client.resumeSession("user-123-task-456", {
  capi: { enableWebSocketResponses: false },
});

Установка этого false значения эквивалентна переменной COPILOT_CLI_DISABLE_WEBSOCKET_RESPONSES среды, которая имеет противоположное полярность.

Пример: изменение модели в резюме

// Resume with a different model
const session = await client.resumeSession("user-123-task-456", {
  model: "claude-sonnet-4",  // Switch to a different model
  reasoningEffort: "high",   // Increase reasoning effort
});

Использование BYOK (принеси свой ключ) с возобновленными сессиями

При использовании собственных API-ключей при возобновлении работы необходимо повторно указать конфигурацию провайдера. API-ключи никогда не сохраняются на диске по соображениям безопасности.

// Original session with BYOK
const session = await client.createSession({
  sessionId: "user-123-task-456",
  model: "gpt-5.2-codex",
  provider: {
    type: "azure",
    endpoint: "https://my-resource.openai.azure.com",
    apiKey: process.env.AZURE_OPENAI_KEY,
    deploymentId: "my-gpt-deployment",
  },
});

// When resuming, you MUST re-provide the provider config
const resumed = await client.resumeSession("user-123-task-456", {
  provider: {
    type: "azure",
    endpoint: "https://my-resource.openai.azure.com",
    apiKey: process.env.AZURE_OPENAI_KEY,  // Required again
    deploymentId: "my-gpt-deployment",
  },
});

Что настаивает?

Состояние сессии сохраняется в ~/.copilot/session-state/{sessionId}/виде:

~/.copilot/session-state/
└── user-123-task-456/
    ├── checkpoints/           # Conversation history snapshots
    │   ├── 001.json          # Initial state
    │   ├── 002.json          # After first interaction
    │   └── ...               # Incremental checkpoints
    ├── plan.md               # Agent's planning state (if any)
    └── files/                # Session artifacts
        ├── analysis.md       # Files the agent created
        └── notes.txt         # Working documents
ДанныеПродолжался?Notes
История беседы
✅ ДаПолный поток сообщений
Результаты вызова инструментов
✅ ДаКэшировано для контекста
Состояние планирования агента
✅ ДаФайл plan.md
Артефакты сессии
✅ ДаВ files/ справочнике
Ключи провайдера/API
❌ НетБезопасность: необходимо повторно предоставить
Состояние инструмента в памяти
❌ НетИнструменты должны быть безсостоятельными

Лучшие практики идентификатора сессии

Выбирайте идентификаторы сессий, которые кодируют принадлежность и назначение. Это значительно облегчает аудит и уборку.

PatternПримерВариант использования
❌abc123Случайные идентификаторыСложно аудитировать, нет информации о владельце
✅user-{userId}-{taskId}user-alice-pr-review-42Многопользовательские приложения
✅tenant-{tenantId}-{workflow}tenant-acme-onboardingМногопользовательский SaaS
✅{userId}-{taskId}-{timestamp}alice-deploy-1706932800Очистка по времени

Преимущества структурированных ID:

  • Легко аудитировать: «Показать все сессии для пользователя Alice»
  • Простое исправление: «Удалить все сессии старше X»
  • Естественный контроль доступа: разбор user ID из session ID

Пример: генерация идентификаторов сессий

function createSessionId(userId: string, taskType: string): string {
  const timestamp = Date.now();
  return `${userId}-${taskType}-${timestamp}`;
}

const sessionId = createSessionId("alice", "code-review");
// → "alice-code-review-1706932800000"
import time

def create_session_id(user_id: str, task_type: str) -> str:
    timestamp = int(time.time())
    return f"{user_id}-{task_type}-{timestamp}"

session_id = create_session_id("alice", "code-review")
# → "alice-code-review-1706932800"

Управление жизненным циклом сессии

Список активных сессий

// List all sessions
const sessions = await client.listSessions();
console.log(`Found ${sessions.length} sessions`);

for (const session of sessions) {
  console.log(`- ${session.sessionId} (created: ${session.createdAt})`);
}

// Filter sessions by repository
const repoSessions = await client.listSessions({ repository: "owner/repo" });

Уборка старых сессий

async function cleanupExpiredSessions(maxAgeMs: number) {
  const sessions = await client.listSessions();
  const now = Date.now();
  
  for (const session of sessions) {
    const age = now - new Date(session.createdAt).getTime();
    if (age > maxAgeMs) {
      await client.deleteSession(session.sessionId);
      console.log(`Deleted expired session: ${session.sessionId}`);
    }
  }
}

// Clean up sessions older than 24 hours
await cleanupExpiredSessions(24 * 60 * 60 * 1000);

Отключение от сессии (disconnect)

Когда задача завершена, явно отключайтесь от сессии, а не ждите тайм-аутов. Это освобождает ресурсы в памяти, но сохраняет данные сессии на диске, так что сессию можно возобновить позже:

try {
  // Do work...
  await session.sendAndWait({ prompt: "Complete the task" });
  
  // Task complete — release in-memory resources (session can be resumed later)
  await session.disconnect();
} catch (error) {
  // Clean up even on error
  await session.disconnect();
  throw error;
}

Каждый SDK также предоставляет идиоматические автоматические шаблоны очистки:

ЯзыкPatternПример
TypeScriptSymbol.asyncDisposeawait using session = await client.createSession(config);
Pythonasync with диспетчер контекстовasync with await client.create_session(on_permission_request=handler) as session:
C#IAsyncDisposableawait using var session = await client.CreateSessionAsync(config);
Godeferdefer session.Disconnect()

Примечание.

Вместо PackageIconUrl теперь используется PackageIcon. Существующий код, использующий destroy() его, продолжит работать, но его следует перевести.

Постоянное удаление сессии (deleteSession)

Чтобы навсегда удалить сессию и все её данные с диска (история разговоров, состояние планирования, артефакты), используйте deleteSession. Это необратимо — сессия не может быть возобновлена после удаления:

// Permanently remove session data
await client.deleteSession("user-123-task-456");

disconnect() VS deleteSession():disconnect() освобождает ресурсы в памяти, но сохраняет данные сессии на диске для последующего возобновления. deleteSession() Навсегда удаляет всё, включая файлы с диска.

Автоматическая очистка: тайм-аут на холостом ходу

По умолчанию сессии не имеют тайм-аута в простое и живут бесконечно, пока не будут явно отключены или удалены. По желанию вы можете настроить серверный тайм-аут простоя с помощью CopilotClientOptions.sessionIdleTimeoutSecondsследующих методов:

const client = new CopilotClient({
  sessionIdleTimeoutSeconds: 30 * 60, // 30 minutes
});

Когда тайм-аут настроен, сессии без активности в течение этого времени автоматически очищаются. Настройте или 0 пропустите, чтобы отключить.

Примечание.

Эта опция действует только тогда, когда SDK запускает процесс выполнения. При подключении к существующему серверу через cliUrl, применяется собственная тайм-аут сервера.

Диаграмма: блок-схема, показывающая описанный процесс.

Сессии с активной работой (выполняющие команды, фоновые агенты) всегда защищены от очистки в режиме простоя, независимо от настройки тайм-аута.

Прислушивайтесь к событиям простоя, которые могут реагировать на неактивность сессии:

session.on("session.idle", (event) => {
  console.log(`Session idle for ${event.idleDurationMs}ms`);
});

Шаблоны развертывания

Лучше всего для: сильной изоляции, многоарендных сред, динамических сессий Azure.

Диаграмма: блок-схема, показывающая описанный процесс.

**Преимущества:**✅ Полная изоляция | ✅ Простая безопасность | ✅ Простое масштабирование

Шаблон 2: общий CLI-сервер (ресурсоэффективный)

Лучше всего для: внутренних инструментов, доверенных сред, ограниченных ресурсами конфигураций.

Диаграмма: блок-схема, показывающая описанный процесс.

Требования:

  • ⚠️ Уникальные идентификаторы сессий для каждого пользователя
  • ⚠️ Управление доступом на уровне приложений
  • ⚠️ Проверка идентификатора сессии перед операциями
// Application-level access control for shared CLI
async function resumeSessionWithAuth(
  client: CopilotClient,
  sessionId: string,
  currentUserId: string
): Promise<Session> {
  // Parse user from session ID
  const [sessionUserId] = sessionId.split("-");
  
  if (sessionUserId !== currentUserId) {
    throw new Error("Access denied: session belongs to another user");
  }
  
  return client.resumeSession(sessionId);
}

динамические сеансы Azure

Для серверных/контейнерных развертываний, где контейнеры могут перезапускаться или мигрировать:

Монтирование постоянного хранения

Каталог состояния сессии должен быть смонтирован в постоянное хранилище:

# Azure Container Instance example
containers:
  - name: copilot-agent
    image: my-agent:latest
    volumeMounts:
      - name: session-storage
        mountPath: /home/app/.copilot/session-state

volumes:
  - name: session-storage
    azureFile:
      shareName: copilot-sessions
      storageAccountName: myaccount

Диаграмма: блок-схема, показывающая описанный процесс.

Сессия переживает запуск в контейнере!

Бесконечные сессии для долгосрочных рабочих процессов

Для рабочих процессов, которые могут превышать ограничения контекста, включайте бесконечные сессии с автоматической компрессией:

const session = await client.createSession({
  sessionId: "long-workflow-123",
  infiniteSessions: {
    enabled: true,
    backgroundCompactionThreshold: 0.80,  // Start compaction at 80% context
    bufferExhaustionThreshold: 0.95,      // Block at 95% if needed
  },
});

Примечание.

Пороги — это коэффициенты использования контекста (0,0-1,0), а не абсолютное количество токенов. Подробности смотрите в АВТОЗАГОЛОВКЕ .

Ограничения и рекомендации

LimitationDescriptionСмягчение последствий
Повторная аутентификация BYOKКлючи API не сохраняютсяКлючи от хранилища в вашем секретном менеджере; Указывайте в резюме
Регистрируемое хранилище~/.copilot/session-state/ должно быть записаноМонтировать постоянный объём в контейнеры
Нет блокировки сессииПараллельный доступ к одной и той же сессии не определенРеализовать блокировку или очередь на уровне приложения
Состояние инструмента не сохраняетсяСостояние инструмента в памяти теряетсяПроектируйте инструменты так, чтобы они были безсостоятельными или сохраняли своё собственное состояние

Обработка параллельного доступа

SDK не обеспечивает встроенную блокировку сессий. Если несколько клиентов могут получить доступ к одной и той же сессии:

// Option 1: Application-level locking with Redis
import Redis from "ioredis";

const redis = new Redis();

async function withSessionLock<T>(
  sessionId: string,
  fn: () => Promise<T>
): Promise<T> {
  const lockKey = `session-lock:${sessionId}`;
  const acquired = await redis.set(lockKey, "locked", "NX", "EX", 300);
  
  if (!acquired) {
    throw new Error("Session is in use by another client");
  }
  
  try {
    return await fn();
  } finally {
    await redis.del(lockKey);
  }
}

// Usage
await withSessionLock("user-123-task-456", async () => {
  const session = await client.resumeSession("user-123-task-456");
  await session.sendAndWait({ prompt: "Continue the task" });
});

Сводка

ФункцияИспользование
Создать вособновляемую сессиюПредоставляйте свои собственные sessionId
Сессия резюмеclient.resumeSession(sessionId)
Резюме BYOKПовторное предоставление provider конфигурации
Перечисление сеансовclient.listSessions(filter?)
Отключение от активной сессииsession.disconnect()— выпускает ресурсы в памяти; Данные сессии на диске сохраняются для возобновления
Навсегда удалить сессиюclient.deleteSession(sessionId)—навсегда удаляет все данные сессии с диска; возобновить не может
Контейнерное развертываниеМонтирование ~/.copilot/session-state/ на постоянное хранилище

Дальнейшие действия