Глава 11

Храните собственный журнал, provider state используйте как ускоритель

Provider-managed state удобно продолжает диалог, но это ускоритель, а не источник истины. Для аудита, миграции, eval replay и поддержки вы должны знать, какой пользовательский вход, tool call, результат и outcome реально прошли через систему. Поэтому свой event log обязателен, а провайдерское продолжение - опция поверх него.

Способы продолжения у трёх API разные, и это стоит держать перед глазами.

Провайдер · Продолжение · Важная особенность

  • OpenAI Responses - previous_response_id или Conversations API; Responses хранятся по умолчанию; store: false отключает хранение. Instructions текущего вызова лучше передавать явно.
  • Anthropic Messages - Полный массив messages у клиента; Messages API stateless; assistant content blocks и tool results нужно сохранять без потерь.
  • Gemini Interactions - previous_interaction_id; Tools, system instruction и generation config повторяются на каждом interaction. store: true является значением по умолчанию; при store: false продолжение через previous id недоступно.

Разница не косметическая. У OpenAI Responses хранятся по умолчанию, а store: false их отключает, и тогда instructions лучше передавать явно. Anthropic Messages stateless - весь массив сообщений и tool results держите у себя без потерь. У Google previous_interaction_id хранит историю, но не переносит tools и system_instruction. Ваш же журнал не зависит от провайдера и переживает смену любого из них.

TypeScript
type AgentEvent =
  | { type: "user_input"; text: string; at: string }
  | { type: "model_turn"; provider: string; model: string; at: string }
  | { type: "tool_call"; name: string; argsHash: string; at: string }
  | { type: "tool_result"; name: string; resultHash: string; at: string }
  | { type: "approval"; previewId: string; actorId: string; at: string }
  | { type: "outcome"; status: AgentOutcome["status"]; at: string };

И правило, без которого журнал сам становится проблемой.

Не логируйте всё подряд. Redact персональные данные и секреты, храните hashes для чувствительных аргументов, задайте retention, разграничьте доступ. Tracing полезен только тогда, когда сам не становится утечкой.

Мы знаем, что агент помнит. Осталось решить, чем он заканчивает, - и свободная строка тут не годится.

Ссылки