Храните собственный журнал, 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. Ваш же журнал не зависит от провайдера и переживает смену любого из них.
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 полезен только тогда, когда сам не становится утечкой.
Мы знаем, что агент помнит. Осталось решить, чем он заканчивает, - и свободная строка тут не годится.