本文是把 IGA Pages Agent SDK 接入主流 Agent 框架的统一指南。使用 OpenAI Agents SDK、LangGraph 或 DeepAgents 时,您可以用同一个业务 conversationId 关联 Sandbox(沙箱)、Tools(工具)与 Store(会话存储)。Claude Agent SDK 另有 Claude session ID 和稳定项目键,应用需要自行维护它们与业务 conversationId 的映射。各模块自身的方法参考对应模块的参考文档,本文聚焦按框架从零搭建并把多个模块拼到一起。
Agent SDK 的核心包为 @iga-pages/agent。本文涉及的公开接入入口包括 Store、Sandbox、Tools 以及各框架适配子路径;具体导入方式以对应模块参考文档和下文示例为准。
框架适配分为两条线,二者相互独立、可按需组合:
./store/* 子路径为各框架提供 Store 挂接层,让框架把会话历史或执行状态直接落到 Store 上。@iga-pages/agent/tools 的各框架子路径为各框架返回适配后的工具集,让模型可以调用沙箱内的内置工具。上述两条适配只处理 Store 和 Tools。Sandbox 不参与框架适配:应用通过 getConversationSandbox(conversationId) 等入口获取沙箱,再传给 getTools()。框架接收的是基于该沙箱生成的适配工具和会话存储适配器,而非沙箱实例。
OpenAI Agents SDK、LangGraph 和 DeepAgents 遵循同一骨架:先取会话沙箱,再取该框架的工具集,最后挂上会话存储适配器,并复用业务 conversationId。
Claude Agent SDK 的工具仍可使用业务 conversationId 获取会话沙箱,但恢复 Claude 会话时必须使用 Claude session ID,并保持项目键稳定。
DeepAgents 没有专用的会话存储子路径导出,它复用 LangGraph 的 ./store/langgraph;工具侧则复用 LangGraph 的 @iga-pages/agent/tools/langchain 子路径接入,返回类型与 LangGraph 相同。
下文按框架分别给出从零搭建到多模块整合的完整示例。
在按任一框架接入之前,请确认您已完成以下准备:
@iga-pages/agent,并按安装与环境准备配置好运行环境、通过 CLI 完成登录与项目关联。modelName 为已配置凭证的模型名称,模型凭证由您的应用自行提供,IGA Pages Agent SDK 不代管。从 @iga-pages/agent/tools 的各框架子路径导入的 getTools 只改变工具格式,不改变工具操作的沙箱。不要把全部工具无条件交给模型;应按当前任务选择需要的工具。应用直接调用模型 API 时,应让工具声明与实际执行名单一致;Claude Agent SDK 还应同步设置 allowedTools。
内置工具可以执行命令、运行代码、读写文件和访问页面。OpenAI Agents SDK 适配后的内置工具默认启用且不要求审批;这不代表终端用户已经获得业务授权。应用必须先校验当前用户或任务对会话、沙箱和文件的归属,再决定是否暴露工具。conversationId 和文件路径不是访问凭证,metadata.ownerId 也不会自动启用用户隔离。
对于命令执行、代码运行和文件写入等有副作用的工具,如业务需要额外授权或确认,应由应用在执行前封装,并限制可访问的沙箱与文件范围。框架报告一次工具调用完成,也不等于底层命令、代码或文件操作符合业务预期;应用仍需检查 ToolResult 及底层结果。
接入 OpenAI Agents SDK 需要三样东西:会话沙箱、从 @iga-pages/agent/tools/openai-agents 导入 getTools 取得的工具集、./store/openai 的会话适配器。安装 @openai/agents 后,把它们组装到 Agent 与 Runner/run 上,会话历史会在同一 conversationId 下自动加载与续写。
工具侧只需获取框架专用工具,并把需要的工具直接传入 Agent:
import { Agent, run } from "@openai/agents"; import { getConversationSandbox } from "@iga-pages/agent/sandbox"; import { getTools } from "@iga-pages/agent/tools/openai-agents"; export async function runAgent(conversationId: string, modelName: string) { const sandbox = getConversationSandbox(conversationId); const tools = getTools(sandbox); const agent = new Agent({ name: "计算助手", model: modelName, instructions: "使用工具计算,并根据执行结果回答。", tools: [tools.code_run], }); const result = await run(agent, "计算 2 的 20 次方。"); return result.finalOutput; }
要在此基础上接上会话存储,把 ./store/openai 的 createSession(conversationId) 作为 session 传给 run(),框架就会在同一 conversationId 下自动加载并续写历史:
import { Agent, run } from "@openai/agents"; import { createSession } from "@iga-pages/agent/store/openai"; const agent = new Agent({ name: "Assistant", instructions: "用中文简洁回答。" }); export async function chat(conversationId: string, input: string) { const result = await run(agent, input, { session: createSession(conversationId), }); return result.finalOutput; }
把两者合起来,就是“同一 conversationId → 取会话沙箱 → 取工具集 → 建 Agent → 挂会话存储 → 运行”的完整链路。首次使用一个新的非空字符串作为 ID,且不超过 256 UTF-8 字节,后续调用传入相同 ID 即可接续。请不要在同一会话里混入其他格式的业务记录,也不要重复保存框架已写入的消息。选择和授权工具时,遵循前文的最小允许名单与副作用边界。
接入 LangGraph 需要:会话沙箱、从 @iga-pages/agent/tools/langchain 获取的原生 LangChain 工具、./store/langgraph 的 Checkpointer。安装 @langchain/core、@langchain/langgraph、@langchain/langgraph-checkpoint@^1.1.4 和模型集成包后,把需要的工具直接传给 createReactAgent,把 Checkpointer 传给图,用 conversationId 作为 thread_id 恢复执行状态。
工具侧的最短接入方式如下:
import { ChatOpenAI } from "@langchain/openai"; import { createReactAgent } from "@langchain/langgraph/prebuilt"; import { getConversationSandbox } from "@iga-pages/agent/sandbox"; import { getTools } from "@iga-pages/agent/tools/langchain"; export async function runAgent(conversationId: string, modelName: string) { const sandbox = getConversationSandbox(conversationId); const tools = getTools(sandbox); const agent = createReactAgent({ llm: new ChatOpenAI({ model: modelName }), tools: [tools.code_run], }); const result = await agent.invoke({ messages: [{ role: "user", content: "使用工具计算 2 的 20 次方。" }], }); return result.messages.at(-1)?.content; }
会话存储侧,把 ./store/langgraph 的 createCheckpointer() 传给 compile(),图状态就会落到 Store,并按 thread_id 恢复。以下示例每次运行让计数加一,第二次调用会从上一次状态继续:
import { Annotation, END, START, StateGraph } from "@langchain/langgraph"; import { store } from "@iga-pages/agent/store"; import { createCheckpointer } from "@iga-pages/agent/store/langgraph"; const State = Annotation.Root({ visits: Annotation<number>({ reducer: (a, b) => a + b, default: () => 0 }), }); const graph = new StateGraph(State) .addNode("visit", () => ({ visits: 1 })) .addEdge(START, "visit") .addEdge("visit", END) .compile({ checkpointer: createCheckpointer() }); export async function checkpointExample() { const { conversationId } = await store.createConversation(); const config = { configurable: { thread_id: conversationId } }; const first = await graph.invoke({}, config); const second = await graph.invoke({}, config); return [first.visits, second.visits]; // [1, 2] }
组合时,用同一个 conversationId 既作为 getConversationSandbox 的参数,又作为 thread_id 传给图:工具在该会话的沙箱内执行,检查点按该会话持久化。createReactAgent 与自建 StateGraph 均可挂 createCheckpointer()。
参数 serde 是可选的框架序列化器,通常省略;清理某个线程的检查点用 checkpointer.deleteThread(conversationId)。
检查点保存的是执行状态,不会写成通用消息,因此无法用 listMessages() 读回。也可以直接从 @iga-pages/agent/tools/langchain 导入 getTools 取得 LangChain 工具。
DeepAgents 复用 LangGraph 的适配层:工具侧从 @iga-pages/agent/tools/langchain 获取原生 LangChain 工具,会话存储侧复用 ./store/langgraph 的 createCheckpointer。安装 deepagents、@langchain/core 及模型集成包后,把需要的工具传入 createDeepAgent():
import { ChatOpenAI } from "@langchain/openai"; import { createDeepAgent } from "deepagents"; import { getConversationSandbox } from "@iga-pages/agent/sandbox"; import { getTools } from "@iga-pages/agent/tools/langchain"; export async function runAgent(conversationId: string, modelName: string) { const sandbox = getConversationSandbox(conversationId); const tools = getTools(sandbox); const agent = createDeepAgent({ model: new ChatOpenAI({ model: modelName }), tools: [tools.code_run], systemPrompt: "需要计算时使用 code_run,并根据执行结果回答。", }); const result = await agent.invoke({ messages: [{ role: "user", content: "计算 2 的 20 次方。" }], }); return result.messages.at(-1)?.content; }
要接会话存储,在 createDeepAgent 上传入 checkpointer: createCheckpointer(),并在 invoke 时以同一 conversationId 作为 thread_id——用法与上一节 LangGraph 完全一致,因为 DeepAgents 复用 LangGraph Checkpointer 适配。工具与会话存储都不需要 DeepAgents 专用的子路径。
接入 Claude Agent SDK 需要:会话沙箱、从 @iga-pages/agent/tools/claude 获取的工具、./store/claude 的 SessionStore。安装 @anthropic-ai/claude-agent-sdk@>=0.2.113 <0.4 后,调用 toMcpConfig() 选择工具,再创建进程内 MCP server 并传给 query():
import { createSdkMcpServer, query } from "@anthropic-ai/claude-agent-sdk"; import { getConversationSandbox } from "@iga-pages/agent/sandbox"; import { getTools } from "@iga-pages/agent/tools/claude"; export async function runAgent(conversationId: string, modelName: string) { const tools = getTools(getConversationSandbox(conversationId)); const config = tools.toMcpConfig("sandbox", { names: ["code_run"] }); const server = createSdkMcpServer({ name: config.name, tools: config.tools, }); for await (const message of query({ prompt: "使用 code_run 计算 2 的 20 次方。", options: { model: modelName, tools: [], mcpServers: { [config.name]: server }, allowedTools: config.allowedTools, maxTurns: 8, }, })) { if (message.type === "result") return message; } throw new Error("Agent 没有返回最终结果"); }
会话存储侧,把 ./store/claude 的 createSessionStore() 作为 sessionStore 传给 query(),首轮不传 sessionId、保存返回的 ID,下一轮以 resume 传入即可恢复:
import { query } from "@anthropic-ai/claude-agent-sdk"; import { createSessionStore } from "@iga-pages/agent/store/claude"; const sessionStore = createSessionStore(); export async function chatWithClaude(prompt: string, sessionId?: string) { for await (const event of query({ prompt, options: { sessionStore, ...(sessionId ? { resume: sessionId } : {}), env: { ...process.env, CLAUDE_CODE_PROJECT_DIR_NAME: "assistant" }, }, })) { if (event.type === "result") { return { sessionId: event.session_id, output: event.subtype === "success" ? event.result : null, }; } } throw new Error("Claude 未返回最终结果"); }
组合时,在同一次 query() 的 options 里同时传入 mcpServers(工具)与 sessionStore(会话存储)。工具在业务 conversationId 对应的沙箱内执行,会话记录由 SessionStore 持久化。
toMcpConfig(name?, { names?, alwaysLoad? }) 返回 { name, tools, allowedTools }。name 默认 "iga-pages",alwaysLoad 默认 true。names 同时筛选注册工具和预批准名单;省略时包含全部工具。
请分别保存并使用以下三类标识:
| 标识 | 用途 | 应用责任 |
|---|---|---|
业务 conversationId | 关联业务会话,并获取对应的会话沙箱 | 校验归属;不要把它传给 resume 充当 Claude session ID |
| Claude session ID | 由首轮结果的 event.session_id 返回,后续通过 resume 恢复 Claude 会话 | 持久化该 ID,并维护它与业务 conversationId 的映射 |
| 稳定项目键 | 通过 CLAUDE_CODE_PROJECT_DIR_NAME 标识项目上下文 | 为同一项目保持稳定,不要按请求随机生成 |
SessionStore 只保存 Claude 会话记录,不保存工作目录和文件;会话记录无法用通用 listMessages() 读回。这三类标识都不是终端用户的授权凭证,应用仍需执行访问控制。
下表汇总各框架对应的接入入口,便于您按所用框架快速定位:
| 框架 | 会话存储子路径导出 | 会话存储初始化入口 | 工具适配子路径 |
|---|---|---|---|
| OpenAI Agents SDK | ./store/openai | createSession(conversationId) | @iga-pages/agent/tools/openai-agents |
| LangGraph | ./store/langgraph | createCheckpointer(serde?) | @iga-pages/agent/tools/langchain |
| DeepAgents | 复用 ./store/langgraph | createCheckpointer(serde?) | 复用 @iga-pages/agent/tools/langchain |
| Claude Agent SDK | ./store/claude | createSessionStore() | @iga-pages/agent/tools/claude |
各框架的会话存储适配器方法签名与语义详见会话存储 Store的“接入 Agent 框架”;工具集的框架路由与适配出口详见工具 Tools 的“获取和选择工具”。