oh-my-pi Coding Agent SDK 编程接入指南:基于 createAgentSession 的会话编排、工具与事件系统
2026/9/10 14:43:57 网站建设 项目流程

oh-my-pi Coding Agent SDK 编程接入指南:基于 createAgentSession 的会话编排、工具与事件系统

【免费下载链接】oh-my-pi⌥ Coding agent with the IDE wired in项目地址: https://gitcode.com/GitHub_Trending/oh/oh-my-pi

导读

本文面向希望以编程方式(而非命令行)驱动 oh-my-pi Coding Agent 的开发者,系统讲解@oh-my-pi/pi-coding-agent包的核心入口createAgentSession():从最简会话、模型与思考等级选择、系统提示词定制,到技能(Skills)、工具(Tools)、扩展(Hooks/Extensions)、上下文文件(AGENTS.md)、提示词模板(Prompt Templates)的发现与替换,再到 API Key/OAuth 凭据解析、设置覆盖、会话持久化与事件流订阅。文中的全部示例均来自仓库packages/coding-agent/examples/sdk/目录,可直接运行验证;读完本文你将掌握用十余行代码启动一个完整的 Coding Agent 会话、并对它的每一步行为进行精细控制的实战能力。

一、SDK 是什么:将 Coding Agent 变成可编程组件

oh-my-pi 的 Coding Agent(即omp-coding-agent)既可以作为交互式终端程序使用,也可以通过 examples/sdk/README.md 中描述的方式,以 SDK 形式嵌入任意 Node.js/TypeScript 应用。核心入口是一个异步工厂函数createAgentSession(),它负责完成整套“装配”工作:

  • 凭据存储(AuthStorage)与模型注册表(ModelRegistry)的发现与解析;
  • 从当前工作目录与~/.omp/agent配置目录发现技能、扩展、工具、AGENTS.md 上下文文件与提示词模板;
  • 组装系统提示词(buildSystemPrompt);
  • 创建会话管理器(SessionManager)实现持久化;
  • 返回一个可订阅事件、可执行prompt()的会话对象。

一次典型的 SDK 调用只需要一个不带任何参数的createAgentSession()——它会自动完成全部默认装配(见 01-minimal.ts):

import { createAgentSession } from "@oh-my-pi/pi-coding-agent"; const { session } = await createAgentSession(); session.subscribe(event => { if (event.type === "message_update" && event.assistantMessageEvent.type === "text_delta") { process.stdout.write(event.assistantMessageEvent.delta); } }); await session.prompt("What files are in the current directory?"); session.state.messages.forEach(msg => { console.log(msg); });

默认情况下,SDK 会从cwd~/.omp/agent自动发现技能、扩展、工具与上下文文件;模型则按设置选择,或取第一个可用模型。这是理解整个 SDK 的最小模型:一个会话 = 模型 + 凭据 + 工具 + 提示上下文 + 持久化,而createAgentSession()的每个可选参数都可以覆盖其中任意一环。

二、示例清单与运行方式

examples/sdk/目录下提供了一组渐进式的可运行示例,每个示例对应一个独立的配置主题(README 表格中的示例编号与文件名一一对应,其中部分示例已按最新 API 演进为新的命名,例如06-extensions.ts对应 Hooks、08-prompt-templates.ts对应文件型 Slash 命令):

文件主题
01-minimal.ts全默认的最简用法
02-custom-model.ts选择模型与思考等级
03-custom-prompt.ts替换或修改系统提示词
04-skills.ts发现、过滤或替换技能
05-tools.ts内置工具与自定义工具
06-hooks.ts/06-extensions.ts日志记录、拦截阻断、结果改写
07-context-files.tsAGENTS.md 上下文文件
08-slash-commands.ts/08-prompt-templates.ts文件型斜杠命令(提示词模板)
09-api-keys-and-oauth.tsAPI Key 解析与 OAuth 配置
10-settings.ts覆盖压缩(compaction)、重试、终端设置
11-sessions.ts内存、持久化、继续、列出会话
12-full-control.ts完全接管,禁用一切发现
12-redis-sessions.ts/13-sql-sessions.tsRedis / SQL 会话后端

运行任一示例只需在仓库根目录执行(示例入口从packages/coding-agent包内加载依赖):

cd packages/coding-agent npx tsx examples/sdk/01-minimal.ts

01-minimal.ts替换为其他示例文件名即可逐个验证;由于使用tsx直接执行 TypeScript,无需预先编译。

三、Options:createAgentSession 全量配置速查

README 给出了createAgentSession()的完整选项表,这是 SDK 的“控制面板”,值得逐项理解(带默认值的项意味着你不传参也能工作):

选项默认值说明
authStoragediscoverAuthStorage()凭据存储(API Key 保存位置)
modelRegistrydiscoverModels(authStorage)模型注册表
cwdprocess.cwd()工作目录
agentDir~/.omp/agent配置目录
model来自设置 / 第一个可用模型使用的模型
thinkingLevel来自设置 /"off"offlowmediumhigh
systemPrompt自动发现组装字符串,或(default) => modified函数
toolNames全部内置工具过滤要包含的工具
customTools自动发现替换自动发现的自定义工具
additionalCustomToolPaths[]与自动发现结果合并
hooks自动发现替换自动发现的扩展
additionalHookPaths[]与自动发现结果合并
skills自动发现用于提示词的技能
contextFiles自动发现AGENTS.md 文件
slashCommands自动发现文件型命令
sessionManagerSessionManager.create(cwd)持久化策略
settingsManager来自 agentDir设置覆盖

注意表中“替换”与“合并”两类语义的区别:customToolshooksskillscontextFilesslashCommands传参后即取代自动发现的结果(传空数组可完全禁用对应能力);而additionalCustomToolPathsadditionalHookPaths则是把额外路径追加到自动发现结果之上。

四、模型与凭据:AuthStorage + ModelRegistry 的装配

4.1 从默认发现到显式装配

discoverAuthStorage()默认读取~/.omp/agent/agent.db中的凭据;discoverModels(authStorage)在此基础上加载内置模型,并合并~/.omp/agent/models.json中的自定义模型。显式装配可以让应用拥有完全独立的凭据与模型空间(见 09-api-keys-and-oauth.ts):

const authStorage = await discoverAuthStorage(); const modelRegistry = await discoverModels(authStorage); // 自定义存储位置:完全脱离 ~/.omp/agent const customAuthStorage = await AuthStorage.create("/tmp/my-app/agent.db"); const customModelRegistry = await ModelRegistry.create(customAuthStorage, "/tmp/my-app/models.json"); // 不传 models.json:仅内置模型 const simpleRegistry = await ModelRegistry.create(authStorage);

4.2 运行时 API Key 覆盖

AuthStorage.setRuntimeApiKey(provider, key)可以注入临时凭据,它只驻留内存、不落盘,适合在运行时从环境变量或密钥管理服务取 Key 的场景:

authStorage.setRuntimeApiKey("anthropic", "sk-my-temp-key");

discoverAuthStorage()的完整调用链(包含 OAuth 配置解析)可从 09-api-keys-and-oauth.ts 与 Quick Reference 片段 中的AuthStorage.create/setRuntimeApiKey用法印证。

4.3 选择模型与思考等级

模型选择有三种途径(见 02-custom-model.ts):

import { ThinkingLevel } from "@oh-my-pi/pi-agent-core"; import { getModel } from "@oh-my-pi/pi-ai"; // 方式一:按 provider/id 直接取内置模型 const opus = getModel("anthropic", "claude-opus-4-5"); // 方式二:通过注册表查找(含 models.json 中的自定义模型) const customModel = modelRegistry.find("my-provider", "my-model"); // 方式三:取当前拥有有效 API Key 的可用模型 const available = modelRegistry.getAvailable();

选定模型后,通过thinkingLevel控制推理深度,取值依次为offlowmediumhigh(对应枚举ThinkingLevel.Off/Low/Medium/High):

const { session } = await createAgentSession({ model: available[0], thinkingLevel: ThinkingLevel.Medium, authStorage, modelRegistry, });

getAvailable()会结合AuthStorage中已有的 Key 过滤出真正可用的模型,避免启动后才发现凭据缺失。

五、系统提示词:替换与函数式改写

systemPrompt选项支持两种形态(见 03-custom-prompt.ts)。

完全替换——传入字符串数组,覆盖自动发现组装的默认提示词:

const { session } = await createAgentSession({ systemPrompt: [ `You are a helpful assistant that speaks like a pirate. Always end responses with "Arrr!"`, ], sessionManager: SessionManager.inMemory(), });

函数式改写——接收默认提示词,返回修改后的版本,适合在保留内置指令体系(工具说明、技能、上下文文件)的基础上追加约束:

const { session } = await createAgentSession({ systemPrompt: defaultPrompt => [ ...defaultPrompt, `## Additional Instructions - Always be concise - Use bullet points when listing things`, ], sessionManager: SessionManager.inMemory(), });

第二种方式与 README Quick Reference 中的(defaultPrompt) => defaultPrompt + "\n\nBe concise."一致,是生产环境最常用的姿势:默认提示词由buildSystemPrompt(结合技能、上下文文件等)生成,改写函数相当于在既有体系上做增量。

六、技能(Skills):发现、过滤、内联定义

技能是注入系统提示词的专业指令片段。SDK 通过discoverSkills()cwd/.omp/skills~/.omp/agent/skills等位置发现技能,并支持三种使用方式(见 04-skills.ts):

import { createAgentSession, discoverSkills, SessionManager, type Skill } from "@oh-my-pi/pi-coding-agent"; // 1. 发现全部技能 const { skills: allSkills } = await discoverSkills(); // 2. 按名称过滤 const filteredSkills = allSkills.filter(s => s.name.includes("browser") || s.name.includes("search")); // 3. 内联定义自定义技能 const customSkill: Skill = { name: "my-skill", description: "Custom project instructions", filePath: "/virtual/SKILL.md", baseDir: "/virtual", source: "custom", }; await createAgentSession({ skills: [...filteredSkills, customSkill], sessionManager: SessionManager.inMemory(), });
  • skills: []可完全禁用技能;
  • discoverSkills(cwd, undefined, { ignoredSkills: ["browser-tools"], includeSkills: ["brave-*"] })支持按 glob 模式过滤——ignoredSkills排除、includeSkills白名单(空表示全部),两者可配合设置项实现“发现但按项目裁剪”。

七、工具(Tools):内置工具、白名单与自定义工具

工具是 Agent 执行操作的通道。README Quick Reference 展示了只读工具白名单的用法:

const { session } = await createAgentSession({ toolNames: ["read", "search", "find"], // 只开放三个只读工具 authStorage, modelRegistry, });

toolNames接受内置工具名列表(如readsearchbash等),用于收紧 Agent 的能力边界;createTools()则负责把工具会话中的工具清单实例化为可执行对象,BUILTIN_TOOLSHIDDEN_TOOLS常量定义了内置工具集合与隐藏工具集合。

7.1 自定义工具与完全接管

customTools选项替换自动发现的工具,可搭配toolNames只开放需要的工具:

const { session } = await createAgentSession({ toolNames: ["read", "bash"], customTools: [{ tool: myTool }], // 替换发现结果,只保留自定义工具 });

若需保留自动发现并追加额外工具路径,使用additionalCustomToolPaths: ["/extra/tools"]

八、扩展(Hooks/Extensions):日志、拦截与安全护栏

Hooks 用于拦截 Agent 生命周期事件,实现日志记录、阻断执行或改写结果。注意 API 演进:Hooks 在新版 API 中更名为 Extensions,示例 06-hooks.ts 对此有明确注释,工厂函数类型为ExtensionFactory,回调注册在api.on(...)上。

import { createAgentSession, type ExtensionFactory, SessionManager } from "@oh-my-pi/pi-coding-agent"; // 日志扩展 const loggingHook: ExtensionFactory = api => { api.on("agent_start", async () => { console.log("[Hook] Agent starting"); }); api.on("tool_call", async event => { console.log(`[Hook] Tool: ${event.toolName}`); return undefined; // 不阻断 }); api.on("agent_end", async event => { console.log(`[Hook] Done, ${event.messages.length} messages`); }); }; // 安全拦截扩展:返回 { block: true, reason } 阻断工具调用 const safetyHook: ExtensionFactory = api => { api.on("tool_call", async event => { if (event.toolName === "bash") { const cmd = (event.input as { command?: string }).command ?? ""; if (cmd.includes("rm -rf")) { return { block: true, reason: "Dangerous command blocked" }; } } return undefined; }); }; const { session } = await createAgentSession({ extensions: [loggingHook, safetyHook], sessionManager: SessionManager.inMemory(), });

关键点:

  • tool_call回调返回undefined表示放行;返回{ block: true, reason }则阻断该次调用,reason会反馈给模型;
  • extensions: []禁用全部扩展;
  • 与发现结果合并使用:const discovered = await discoverExtensions();后传[...discovered.extensions.map(e => e.factory), myHook]
  • 追加路径而不替换发现结果:additionalExtensionPaths: ["/extra/extensions"]

README 的 Options 表中hooks/additionalHookPaths即对应上述扩展语义。

九、上下文文件(AGENTS.md)与提示词模板

9.1 AGENTS.md 上下文文件

discoverContextFiles()会从cwd向上逐级发现 AGENTS.md,将其内容并入系统提示词(见 07-context-files.ts):

const discovered = discoverContextFiles(); for (const file of discovered) { console.log(` - ${file.path} (${file.content.length} chars)`); } await createAgentSession({ contextFiles: [ ...discovered, { path: "/virtual/AGENTS.md", content: `# Project Guidelines ## Code Style - Use TypeScript strict mode - No any types - Prefer const over let`, }, ], sessionManager: SessionManager.inMemory(), });

contextFiles: []可关闭上下文文件注入。

9.2 文件型斜杠命令 = 提示词模板

文件型斜杠命令(/commandname触发)在新 API 中更名为Prompt Templates,通过discoverPromptTemplates()cwd/.pi/prompts/~/.pi/agent/prompts/发现(见 08-slash-commands.ts):

const discovered = await discoverPromptTemplates(); for (const cmd of discovered) { console.log(` /${cmd.name}: ${cmd.description}`); } const deployCommand: PromptTemplate = { name: "deploy", description: "Deploy the application", source: "(custom)", content: `# Deploy Instructions 1. Build: npm run build 2. Test: npm test 3. Deploy: npm run deploy`, }; await createAgentSession({ promptTemplates: [...discovered, deployCommand], sessionManager: SessionManager.inMemory(), });
  • promptTemplates: []禁用全部模板;
  • 需要注意:传统文件型 Markdown 命令走promptTemplates,而TypeScript 编写的命令则通过discoverCustomTSCommands()加载,两者并存于createAgentSession的自动装配中。

十、会话(Session)管理:内存、持久化、继续与列表

SessionManager控制会话的存储策略(见 11-sessions.ts):

// 内存会话:不落盘,适合临时/测试 const { session: inMemory } = await createAgentSession({ sessionManager: SessionManager.inMemory(), }); // 新建持久化会话:按 cwd 编码目录存放 const { session: newSession } = await createAgentSession({ sessionManager: SessionManager.create(process.cwd()), }); console.log("New session file:", newSession.sessionFile); // 继续最近一次会话(无则新建) const { session: continued, modelFallbackMessage } = await createAgentSession({ sessionManager: await SessionManager.continueRecent(process.cwd()), }); // 列出并打开指定会话 const sessions = await SessionManager.list(process.cwd()); const { session: opened } = await createAgentSession({ sessionManager: await SessionManager.open(sessions[0].path), });

SessionManager.create(cwd, customDir)支持自定义会话目录(第二参数,省略时按 cwd 编码);list(cwd, customDir)continueRecent(cwd, customDir)同样接受该参数。仓库中还提供了12-redis-sessions.ts13-sql-sessions.ts两个示例,展示把会话后端替换为 Redis / SQL 的扩展方式——说明SessionManager是接口化的,可对接自定义持久化实现。

十一、事件系统:订阅 Agent 的每一步

session.subscribe()提供流式事件,README 给出了完整的事件类型骨架:

session.subscribe((event) => { switch (event.type) { case "message_update": if (event.assistantMessageEvent.type === "text_delta") { process.stdout.write(event.assistantMessageEvent.delta); } break; case "tool_execution_start": console.log(`Tool: ${event.toolName}`); break; case "tool_execution_end": console.log(`Result: ${event.result}`); break; case "agent_end": console.log("Done"); break; } });
  • message_update:模型消息增量更新,配合assistantMessageEvent.type === "text_delta"可逐 token 输出流式文本(这是所有示例实现“打字机”效果的统一手法);
  • tool_execution_start/tool_execution_end:工具调用生命周期,可用于进度展示或审计;
  • agent_end:一轮 Agent 循环结束。

事件的订阅时机在session.prompt()之前完成注册即可捕获全过程。

十二、AST 编辑预览工作流:xd:// 虚拟设备

README 还特别说明了ast_edit工具的新行为:它现在总是返回预览(preview)而非直接落盘。要最终确认修改,需要用write工具向对应的虚拟设备写入纯文本:

  • xd://resolve→ 应用挂起的预览;body 为原因文本;
  • xd://reject→ 丢弃挂起的预览;body 为原因文本。

createAgentSession()/createTools()会在存在可延迟工具(如ast_edit)时自动包含write,因此虚拟设备始终可达:

const tools = await createTools(toolSession, ["ast_edit"]); // write 被自动包含 const writeTool = tools.find(t => t.name === "write")!; await writeTool.execute("call-1", { path: "xd://resolve", content: "Preview matches expected replacements", });

这意味着通过 SDK 接入时,Agent 对代码的修改天然处于“先预览、后裁决”的受控流程中,宿主应用可以在这两步之间插入人工审核或自动化校验。

十三、完全接管模式:Full Control

当需要彻底摆脱自动发现、把 Agent 行为完全握在自己手中时,README Quick Reference 展示了 Full Control 的完整形态:

const customAuth = await AuthStorage.create("/my/app/agent.db"); customAuth.setRuntimeApiKey("anthropic", Bun.env.MY_KEY!); const customRegistry = new ModelRegistry(customAuth); const { session } = await createAgentSession({ model, authStorage: customAuth, // 自定义凭据 modelRegistry: customRegistry, // 自定义模型注册表 systemPrompt: ["You are helpful."], // 完全替换提示词 toolNames: ["read", "bash"], // 工具白名单 customTools: [{ tool: myTool }], // 替换发现的工具 hooks: [{ factory: myHook }], // 替换发现的扩展 skills: [], // 禁用技能 contextFiles: [], // 禁用上下文文件 slashCommands: [], // 禁用文件命令 sessionManager: SessionManager.inMemory(), });

对应示例12-full-control.ts即以此为蓝本。该模式下所有“自动发现”的输入源都被显式指定或清空,应用对会话的每一个组成部分都拥有完全决定权——适合构建需要严格管控的嵌入式 Agent 场景(如受限的执行环境、白名单工具集、固定提示词模板)。

十四、小结:从示例到生产接入

回顾整个 SDK 的使用脉络,可以归纳出三层控制粒度:

  1. 零配置起步createAgentSession()全默认调用即可获得功能完整的 Agent(01-minimal.ts);
  2. 逐项覆盖:通过 Options 表中的 16 个选项按需替换模型、提示词、工具、技能、扩展、上下文、会话与设置(0211系列示例);
  3. 完全接管:禁用一切发现,显式装配全部组件(12-full-control.ts)。

无论哪种粒度,session.subscribe()事件流与session.prompt()调用接口保持一致,这保证了上层代码可以在配置演进过程中保持稳定。对于有更进一步需求的场景,仓库中的12-redis-sessions.ts13-sql-sessions.ts还展示了会话存储可插拔的扩展方向;所有示例均可直接通过npx tsx examples/sdk/<file>.tspackages/coding-agent目录下运行验证。

【免费下载链接】oh-my-pi⌥ Coding agent with the IDE wired in项目地址: https://gitcode.com/GitHub_Trending/oh/oh-my-pi

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询