Session

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

Что AgentSession содержит

Поле Цель
StateBag Произвольный контейнер состояния для этого сеанса

C# AgentSession является абстрактным базовым классом. Конкретные реализации (созданные с помощью CreateSessionAsync()) могут добавлять дополнительное состояние, например идентификатор для удаленного хранилища журнала чата, когда используется управляемый службой журнал.

Поле Цель
session_id Локальный уникальный идентификатор для этого сеанса
service_session_id Идентификатор сеанса удалённого сервиса, например идентификатор беседы или ответа, при использовании истории, управляемой сервисом
state Изменяемый словарь, общий с поставщиками контекста и истории
Поле Цель
agent.Session Контейнер состояния «ключ-значение», привязанный к разговору

Сеансы предоставляют хранилище с типизированным ключом-значением:

type UserPrefs struct {
    Theme    string `json:"theme"`
    Language string `json:"language"`
}

session.Set("user_prefs", UserPrefs{Theme: "dark", Language: "en"})

var prefs UserPrefs
session.Get("user_prefs", &prefs)

session.Delete("user_prefs")

Область действия идентификатора сеанса службы

При использовании управляемого службой журнала сеанс может содержать идентификатор сеанса, выданный службой. Например, OpenAI Responses может использовать resp_* в качестве идентификатора ответа, например previous_response_id, а API OpenAI Conversations может использовать conv_* в качестве идентификатора беседы как самой беседы.

По умолчанию OpenAI ограничивает область действия этих идентификаторов связанным API-ключом или проектом. Обычно это достаточно, если этот ключ или проект уже соответствует границе приложения, например однопользовательское приложение или отдельный ключ или проект для каждого клиента. Рискованный подход заключается в использовании одного базового ключа или проекта для нескольких конечных пользователей, передаче клиентам исходных идентификаторов со стороны сервиса и приёме этих идентификаторов обратно без проверки прав владения. В хостируемых или многопользовательских приложениях, которые повторно используют один базовый ключ или проект, не рассматривайте service_session_id, previous_response_id или conversation/conversation_id как границы авторизации для конечных пользователей. Храните идентификаторы на стороне службы в доверенном хранилище приложений, сопоставляйте идентификаторы сеансов с идентификаторами на стороне службы и проверяйте прошедших проверку подлинности пользователей или клиента перед возобновлением беседы.

Встроенный шаблон использования

AgentSession session = await agent.CreateSessionAsync();

var first = await agent.RunAsync("My name is Alice.", session);
var second = await agent.RunAsync("What is my name?", session);
session = agent.create_session()

first = await agent.run("My name is Alice.", session=session)
second = await agent.run("What is my name?", session=session)
session, err := a.CreateSession(ctx)
if err != nil {
    panic(err)
}

resp, _ := a.RunText(ctx, "Hello!", agent.WithSession(session)).Collect()
resp, _ = a.RunText(ctx, "Follow-up question.", agent.WithSession(session)).Collect()

Создание сеанса по существующему идентификатору сессии службы

Создание нового сеанса из существующего идентификатора беседы зависит от типа агента. Ниже приведены некоторые примеры.

При использовании ChatClientAgent

AgentSession session = await chatClientAgent.CreateSessionAsync(conversationId);

При использовании A2AAgent

AgentSession session = await a2aAgent.CreateSessionAsync(contextId, taskId);

Используйте это, если у поддерживающей службы уже имеется состояние диалога.

session = agent.get_session(service_session_id="<service-conversation-id>")
response = await agent.run("Continue this conversation.", session=session)

В размещенных приложениях устраните разрешение <service-conversation-id> из хранилища, принадлежащее приложению, после проверки текущего пользователя или клиента. Не принимайте от клиента необработанные идентификаторы сервиса, если сначала не проверите, что вызывающая сторона является владельцем беседы.

Сериализация и восстановление

var serialized = agent.SerializeSession(session);
AgentSession resumed = await agent.DeserializeSessionAsync(serialized);
serialized = session.to_dict()
resumed = AgentSession.from_dict(serialized)
data, err := json.Marshal(session)
if err != nil {
    panic(err)
}

// Save to disk, database, etc.
if err := os.WriteFile("session.json", data, 0o644); err != nil {
    panic(err)
}

// Later, restore the session.
loaded, err := os.ReadFile("session.json")
if err != nil {
    panic(err)
}

var resumedSession agent.Session
if err := json.Unmarshal(loaded, &resumedSession); err != nil {
    panic(err)
}

resp, _ := a.RunText(ctx, "Continue from where we left off.", agent.WithSession(&resumedSession)).Collect()

Tip

См. пример сохранённого диалога, чтобы увидеть полный пример.

Это важно

Сеансы относятся к конкретному агенту или службе. Повторное использование сеанса с другой конфигурацией агента или поставщиком может привести к недопустимому контексту. Если сериализованный сеанс содержит идентификатор сеанса на стороне службы, восстановите его только для пользователя приложения или клиента, которому принадлежит этот идентификатор.

Дальнейшие шаги