会话
会话为 Agents SDK 提供了持久化记忆层。将任意实现了 Session 接口的对象传给 Runner.run,其余工作由 SDK 处理。当会话存在时,runner 会自动:
- 获取先前存储的对话项并在下一轮前预置到输入前部。
- 在每次运行完成后持久化新的用户输入和助手输出。
- 保持会话可用于后续轮次,无论是用新的用户文本调用 runner,还是从中断的
RunState恢复。
这消除了手动调用 toInputList() 或在轮次之间拼接历史的需要。TypeScript SDK 随附两个实现:用于 Conversations API 的 OpenAIConversationsSession,以及用于本地开发的 MemorySession。由于它们共享 Session 接口,您可以接入自定义存储后端。除了 Conversations API 外的灵感,可探索 examples/memory/ 下的示例会话后端(Prisma、文件存储等)。当您使用 OpenAI Responses 模型时,用 OpenAIResponsesCompactionSession 包装任意会话,可通过 responses.compact 自动缩短已存储的对话记录。
提示:要运行本页中的
OpenAIConversationsSession示例,请设置OPENAI_API_KEY环境变量(或在构造会话时提供apiKey),以便 SDK 可调用 Conversations API。
使用 OpenAIConversationsSession 将内存与 Conversations API 同步,或替换为任意其他 Session 实现。
import { Agent, OpenAIConversationsSession, run } from '@openai/agents';
const agent = new Agent({ name: 'TourGuide', instructions: 'Answer with compact travel facts.',});
// Any object that implements the Session interface works here. This example uses// the built-in OpenAIConversationsSession, but you can swap in a custom Session.const session = new OpenAIConversationsSession();
const firstTurn = await run(agent, 'What city is the Golden Gate Bridge in?', { session,});console.log(firstTurn.finalOutput); // "San Francisco"
const secondTurn = await run(agent, 'What state is it in?', { session });console.log(secondTurn.finalOutput); // "California"复用同一个会话实例可确保每轮前智能体都能接收完整对话历史,并自动持久化新项。切换到不同的 Session 实现无需其他代码变更。
Runner 对会话的使用方式
Section titled “Runner 对会话的使用方式”- 每次运行前 获取会话历史,与新一轮的输入合并,并将合并后的列表传递给您的智能体。
- 非流式传输的运行后 一次调用
session.addItems()即可同时持久化原始用户输入和最新一轮的模型输出。 - 流式传输的运行 会先写入用户输入,并在该轮完成后附加流式输出。
- 从
RunResult.state恢复时(用于审批或其他中断)继续传递相同的session。恢复的该轮会被添加到内存中,无需重新准备输入。
历史的查看与编辑
Section titled “历史的查看与编辑”会话暴露了简单的 CRUD 辅助方法,便于构建“撤销”“清空聊天”或审计等功能。
import { OpenAIConversationsSession } from '@openai/agents';import type { AgentInputItem } from '@openai/agents-core';
// Replace OpenAIConversationsSession with any other Session implementation that// supports get/add/pop/clear if you store history elsewhere.const session = new OpenAIConversationsSession({ conversationId: 'conv_123', // Resume an existing conversation if you have one.});
const history = await session.getItems();console.log(`Loaded ${history.length} prior items.`);
const followUp: AgentInputItem[] = [ { type: 'message', role: 'user', content: [{ type: 'input_text', text: 'Let’s continue later.' }], },];await session.addItems(followUp);
const undone = await session.popItem();
if (undone?.type === 'message') { console.log(undone.role); // "user"}
await session.clearSession();session.getItems() 返回已存储的 AgentInputItem[]。调用 popItem() 可移除最后一条记录——在重新运行智能体前用于纠正用户输入很有用。
实现 Session 接口,用 Redis、DynamoDB、SQLite 或其他数据存储为内存提供支持。仅需实现五个异步方法。
import { Agent, run } from '@openai/agents';import { randomUUID } from '@openai/agents-core/_shims';import { logger, Logger } from '@openai/agents-core/dist/logger';import type { AgentInputItem, Session } from '@openai/agents-core';
/** * Minimal example of a Session implementation; swap this class for any storage-backed version. */export class CustomMemorySession implements Session { private readonly sessionId: string; private readonly logger: Logger;
private items: AgentInputItem[];
constructor( options: { sessionId?: string; initialItems?: AgentInputItem[]; logger?: Logger; } = {}, ) { this.sessionId = options.sessionId ?? randomUUID(); this.items = options.initialItems ? options.initialItems.map(cloneAgentItem) : []; this.logger = options.logger ?? logger; }
async getSessionId(): Promise<string> { return this.sessionId; }
async getItems(limit?: number): Promise<AgentInputItem[]> { if (limit === undefined) { const cloned = this.items.map(cloneAgentItem); this.logger.debug( `Getting items from memory session (${this.sessionId}): ${JSON.stringify(cloned)}`, ); return cloned; } if (limit <= 0) { return []; } const start = Math.max(this.items.length - limit, 0); const items = this.items.slice(start).map(cloneAgentItem); this.logger.debug( `Getting items from memory session (${this.sessionId}): ${JSON.stringify(items)}`, ); return items; }
async addItems(items: AgentInputItem[]): Promise<void> { if (items.length === 0) { return; } const cloned = items.map(cloneAgentItem); this.logger.debug( `Adding items to memory session (${this.sessionId}): ${JSON.stringify(cloned)}`, ); this.items = [...this.items, ...cloned]; }
async popItem(): Promise<AgentInputItem | undefined> { if (this.items.length === 0) { return undefined; } const item = this.items[this.items.length - 1]; const cloned = cloneAgentItem(item); this.logger.debug( `Popping item from memory session (${this.sessionId}): ${JSON.stringify(cloned)}`, ); this.items = this.items.slice(0, -1); return cloned; }
async clearSession(): Promise<void> { this.logger.debug(`Clearing memory session (${this.sessionId})`); this.items = []; }}
function cloneAgentItem<T extends AgentInputItem>(item: T): T { return structuredClone(item);}
const agent = new Agent({ name: 'MemoryDemo', instructions: 'Remember the running total.',});
// Using the above custom memory session implementation hereconst session = new CustomMemorySession({ sessionId: 'session-123-4567',});
const first = await run(agent, 'Add 3 to the total.', { session });console.log(first.finalOutput);
const second = await run(agent, 'Add 4 more.', { session });console.log(second.finalOutput);自定义会话可让您实施保留策略、添加加密,或在持久化之前为每个对话轮次附加元数据。
控制历史与新项的合并方式
Section titled “控制历史与新项的合并方式”当您将 AgentInputItem 数组作为运行输入传入时,提供 sessionInputCallback 以确定性地将其与已存储历史合并。runner 会加载现有历史,在模型调用之前调用您的回调,并将返回的数组作为该轮的完整输入传给模型。此钩子非常适合裁剪旧项、去重工具结果,或仅突出您希望模型看到的上下文。
import { Agent, OpenAIConversationsSession, run } from '@openai/agents';import type { AgentInputItem } from '@openai/agents-core';
const agent = new Agent({ name: 'Planner', instructions: 'Track outstanding tasks before responding.',});
// Any Session implementation can be passed here; customize storage as needed.const session = new OpenAIConversationsSession();
const todoUpdate: AgentInputItem[] = [ { type: 'message', role: 'user', content: [ { type: 'input_text', text: 'Add booking a hotel to my todo list.' }, ], },];
await run(agent, todoUpdate, { session, // function that combines session history with new input items before the model call sessionInputCallback: (history, newItems) => { const recentHistory = history.slice(-8); return [...recentHistory, ...newItems]; },});对于字符串输入,runner 会自动合并历史,因此该回调是可选的。
审批与可恢复运行的处理
Section titled “审批与可恢复运行的处理”Human-in-the-loop 流程常常会暂停一次运行以等待审批:
const result = await runner.run(agent, 'Search the itinerary', { session, stream: true,});
if (result.requiresApproval) { // ... collect user feedback, then resume the agent in a later turn const continuation = await runner.run(agent, result.state, { session }); console.log(continuation.finalOutput);}当您从之前的 RunState 恢复时,新的一轮会附加到同一条内存记录上,以保留单一的对话历史。Human-in-the-loop(HITL)流程保持完全兼容——审批检查点仍通过 RunState 往返,而会话则保持完整的对话记录。
自动压缩 OpenAI Responses 历史
Section titled “自动压缩 OpenAI Responses 历史”OpenAIResponsesCompactionSession 可装饰任意 Session,并依赖 OpenAI Responses API 来保持对话记录精简。每次持久化轮次后,runner 会将最新的 responseId 传入 runCompaction,当您的决策钩子返回 true 时调用 responses.compact。默认触发条件是在累计至少 10 个非用户项后压缩;重写 shouldTriggerCompaction,可基于 token 计数或自定义启发式进行决策。该装饰器会用压缩后的输出清空并重写底层会话,因此避免与 OpenAIConversationsSession 搭配使用,后者采用不同的服务端历史管理流程。
import { Agent, MemorySession, OpenAIResponsesCompactionSession, run,} from '@openai/agents';
const agent = new Agent({ name: 'Support', instructions: 'Answer briefly and keep track of prior context.', model: 'gpt-5.2',});
// Wrap any Session to trigger responses.compact once history grows beyond your threshold.const session = new OpenAIResponsesCompactionSession({ // You can pass any Session implementation except OpenAIConversationsSession underlyingSession: new MemorySession(), // (optional) The model used for calling responses.compact API model: 'gpt-5.2', // (optional) your custom logic here shouldTriggerCompaction: ({ compactionCandidateItems }) => { return compactionCandidateItems.length >= 12; },});
await run(agent, 'Summarize order #8472 in one sentence.', { session });await run(agent, 'Remind me of the shipping address.', { session });
// Compaction runs automatically after each persisted turn. You can also force it manually.await session.runCompaction({ force: true });您可在任意时间调用 runCompaction({ force: true }),以在归档或交接前缩短历史。启用 DEBUG=openai-agents:openai:compaction 调试日志以追踪压缩决策。