API 参考

这页文档描述 @ageniti/core 的公开 SDK API。

顶层导入

大多数应用直接从根导出开始即可:

import {
  createAgenitiApp,
  createRuntime,
  defineAction,
  s,
} from "@ageniti/core";

只有在你明确需要更窄的导入边界时,才建议使用 subpath export。见 入口模块

0.2.0 起:下文涉及的 build / package / publish、docs、project、lint、manifest 等 helper 都改为从对应 subpath 导入,不再走根入口。各小节给出了具体的 subpath。createAgenitiApp() 返回值上的 app.build()app.package()app.publish()app.createGuideDoc()app.exportDocs() 方法保持不变。

defineAction(config)

用于定义类型化 action contract。

必填字段:

  • name:小写 snake_case action 名
  • description:面向人的 action 描述
  • run(input, context):action 实现

可选字段:

  • version
  • title
  • input
  • output
  • visibility
  • sideEffects
  • idempotency
  • permissions
  • supportedSurfaces
  • timeoutMs
  • retry
  • concurrency
  • requiresConfirmation
  • metadata
  • publicMetadata
  • docs
  • deprecated
  • deprecation

Metadata 模型:

  • metadata:内部 action metadata,供应用代码和构建期工具使用;不会复制进公开 manifest 或 tool metadata
  • publicMetadata:可安全暴露的 metadata,会进入公开 manifest、MCP tool metadata 和 LLM tool adapter

文档模型:

  • docs:用于生成统一 GUIDE.md 的自然语言说明
  • app 级 docs 支持 summaryaudiencewhenToUsequickStartsetupoperationalNotessectionsexamples
  • action 级 docs 支持 whenToUsewhenNotToUseusageNotesinputExampleoutputExample
  • GUIDE.md 是确定性导出,不会调用模型,也不会从 UI 里猜测业务逻辑

版本模型:

  • version:action contract 版本,默认 1.0.0
  • deprecated:标记 action 已废弃,但不直接移除
  • deprecation:可选的废弃说明、替代 action 和时间线 metadata

重要默认值:

  • title:由 name 自动推导
  • inputs.object({})
  • visibility"public"
  • sideEffects"read"
  • idempotency"unspecified"
  • permissions[]
  • supportedSurfacesclijsonhttpmcpreactdevai-sdk
  • retry:会被标准化成 { retries, delayMs }
  • requiresConfirmation:destructive action 默认会开启

示例:

const deleteTask = defineAction({
  name: "delete_task",
  description: "Delete a task by id.",
  sideEffects: "destructive",
  requiresConfirmation: true,
  input: s.object({
    taskId: s.string().min(1),
  }),
  async run(input, ctx) {
    return ctx.services.tasks.remove(input.taskId);
  },
});

createAgenitiApp(options)

创建一个持有 action、runtime 和 surface helper 的 app 对象。

const app = createAgenitiApp({
  name: "task-app",
  description: "Workspace task operations for external tools, automation, and agent callers.",
  attribution: {
    text: "Powered by Ageniti",
    vendor: "Ageniti",
    product: "Ageniti Core",
    url: "https://ageniti.dev",
    docsUrl: "https://ageniti.dev/docs",
  },
  docs: {
    summary: "Use this app to create tasks and inspect status.",
  },
  actions,
  services,
  permissionChecker,
  middleware,
  adapters,
  build,
});

参数:

  • name:必填 app 名称
  • attribution:可选来源归属信息,会进入 CLI help、MCP manifest、tool metadata、生成的 guide 和 bundle 产物
  • actions:Ageniti action 数组
  • services:注入到 context.services 的共享服务
  • permissionChecker:授权检查 hook
  • middleware:runtime 中间件链
  • adapters:用于 manifest 生成的自定义 surface adapter 列表
  • build:传给 app.build() 和 CLI build 命令的默认构建配置

attribution 属于描述性 metadata,不是遥测。适合在你希望生成出来的 surface 带上明确来源、品牌或产品归属时使用。

返回成员:

  • name
  • actions
  • adapters
  • runtime
  • manifest(options?)
  • actionManifest()
  • lint()
  • build()
  • package()
  • publish()
  • createGuideDoc()
  • exportDocs()
  • createCli()
  • createJsonRunner()
  • createHttpHandler()
  • createHttpServer()
  • createMcpHandler()
  • createMcpManifest()
  • createOpenAITools()
  • createOpenAIResponsesTools()
  • createAISDKTools()
  • createFunctionCallingManifest()
  • createReactAdapter()
  • createDevServer()

如果你希望围绕一组 action 搭一个统一 app,这是最推荐的入口。

createRuntime(options)

创建底层 headless runtime,所有应用能力调用入口都复用它。

参数:

  • actions
  • services
  • permissionChecker
  • middleware
  • hooks
  • redact
  • idempotencyCache
  • idempotencyTtlMs
  • idempotencyMaxEntries

返回 API:

  • registryMap<string, Action>
  • listActions({ surface? })
  • invoke(actionOrName, input?, invokeOptions?)
  • stream(actionOrName, input?, invokeOptions?)

invokeOptions 支持:

  • invocationId
  • surface
  • user
  • auth
  • env
  • services
  • metadata
  • signal
  • timeoutMs
  • retry
  • confirm
  • idempotencyKey

runtime 负责:

  • action 查找
  • surface 支持检查
  • 输入校验
  • 确认检查
  • 权限检查
  • 中间件执行
  • 超时和重试
  • 输出序列化与输出校验
  • 成功和失败 envelope

完整执行模型见 Runtime 语义

Manifest 与 Registry Helper

createActionRegistry(actions)

创建一个以 action name 为 key 的 Map,若有重复 action name 会直接抛错。

createActionManifest(actions)

返回一个纯对象数组,描述公开 action contract,包括 schema、visibility、confirmation 和 publicMetadata。适合做 inspection、tooling、测试,或自定义包装层。

describeAction(action)

import { describeAction } from "@ageniti/core/manifest";

把单个 action 规范化成 manifest-friendly 的对象。

createSurfaceManifest({ appName, actions, adapters })

import { createSurfaceManifest } from "@ageniti/core/manifest";

返回的 manifest 包含:

  • app 名称
  • 生成时间戳
  • action 描述列表
  • surface 描述和 capabilities

CLI API

createCli(options)

创建 CLI 对象。

const cli = createCli({
  name: "task-app",
  attribution: {
    text: "Powered by Ageniti",
  },
  actions,
  runtime,
  runtimeOptions,
  env,
  adapters,
  buildOptions,
});

返回成员:

  • name
  • actions
  • runtime
  • run(argv?, io?)
  • main(argv?, io?)

内建命令:

<app> <action> [options]
<app> <action> --json '{"field":"value"}'
<app> <action> --schema
<app> actions
<app> manifest
<app> diff --previous old.json --next new.json
<app> build [manifest|cli|mcp|docs|bundle] [options]
<app> docs [options]
<app> package [options]
<app> publish [options]
<app> init <react|expo|next|host-openai|host-ai-sdk|host-mcp|host-http> [options]
<app> doctor [options]
<app> lint
<app> mcp
<app> mcp --stdio
<app> dev --port 4321

输入行为:

  • snake_case action 也可以用 kebab-case 调用
  • 布尔 flag 支持 --flag--flag true--no-flag
  • array、object 和 any 类型通过 JSON 字符串解析
  • 运行时确认映射为 --confirm

构建命令常用参数:

  • --out-dir <dir>
  • --app-module <module-path>
  • --app-export <name>
  • --package-json
  • --cwd <dir>
  • docs 命令可额外使用 --filename <name>

launcher target 需要一个可在 Node 中直接导入的 app module。若未提供 --app-module,Ageniti 会尝试自动发现默认入口,例如 ./src/ageniti/app.js

JSON Runner API

createJsonRunner(options)

创建一个轻量的结构化调用包装层。

const runner = createJsonRunner({ actions, runtime, runtimeOptions });

返回 API:

  • runtime
  • invoke(payload)

payload 字段:

  • action
  • input
  • confirm
  • user
  • auth
  • metadata

如果 payload 不是对象,runner 会返回 INVALID_JSON_RUNNER_PAYLOAD

MCP API

createMcpManifest(actions, options)

返回结构:

{
  tools: [
    {
      name,
      title,
      description,
      inputSchema,
      metadata,
    },
  ],
}

过滤规则:

  • action 必须支持 mcp surface
  • private action 默认不暴露,除非 includePrivate: true
  • local action 默认不暴露,除非 includeLocal: true
  • destructive action 默认不暴露,除非 includeDestructive: true

createMcpHandler(options)

创建处理 tools/listtools/call 的 JSON-RPC handler。

const handle = createMcpHandler({
  actions,
  runtime,
  runtimeOptions,
  includePrivate,
  includeDestructive,
});

tools/call 的结果里既有文本内容,也有包含 runtime 结果的 structuredContent

如果通过 includeDestructive: true 有意暴露 destructive tool,调用时仍需要传 params.confirm: true 才能执行。

createMcpStdioServer(options)

围绕 createMcpHandler() 构建一个支持 newline 与 Content-Length 自动识别的 stdio transport。

await createMcpStdioServer({ actions, runtime }).start();

适合对接通过 stdio 传 JSON-RPC 的宿主进程。Ageniti 会自动识别按行分隔和 Content-Length framing。

LLM Tool Adapter API

createOpenAITools(actions, options)

返回 Chat Completions 风格的 function tools。

createOpenAIResponsesTools(actions, options)

返回 Responses 风格的 function tools。

createAISDKTools(actions, options)

返回 Vercel AI SDK 风格的 tools object。

const tools = createAISDKTools(actions, {
  runtime,
  returnEnvelope: true,
});

每个 tool 包含:

  • description
  • parameters:Ageniti schema 对象
  • inputSchema:JSON Schema 表示
  • execute(input, options?)

createFunctionCallingManifest(actions, options)

返回组合摘要:

  • openaiChatTools
  • openaiResponsesTools
  • aiSdkTools,其中内容是 action name 列表

共享参数:

  • runtime
  • strict
  • includePrivate
  • includeLocal
  • includeDestructive
  • surface
  • returnEnvelope
  • filter

过滤规则:

  • action 必须支持被选中的 surface,默认是 ai-sdk
  • private action 默认被过滤,除非 includePrivate: true
  • local action 默认被过滤,除非 includeLocal: true
  • destructive action 默认被过滤,除非 includeDestructive: true
  • filter(action) 可以叠加额外过滤条件

React API

createReactActionAdapter(options)

创建 React 友好的 runtime 包装层。

const { runtime, useAction } = createReactActionAdapter({ actions, runtime });

useAction(action) 会返回一个异步函数,并以 surface: "react" 调用该 action。

Dev Server API

createDevServer(options)

创建本地 dev console server。

const devServer = createDevServer({
  name: "task-app",
  actions,
  runtime,
});
 
const listener = await devServer.listen(4321, "127.0.0.1");

路由:

  • GET /:HTML dev console
  • GET /api/actions:dev surface 下的 action manifest
  • POST /api/actions/:name/invoke:调用单个 action

HTTP API

app.createHttpHandler(options)

创建一个适合接入任意 Web 框架的 HTTP JSON handler。默认会忽略请求体里的 auth / user;可信身份应通过 request 顶层字段或 resolveContext 注入。

const handle = app.createHttpHandler();
 
const response = await handle({
  method: "POST",
  path: "/ageniti/actions/create_task/invoke",
  body: {
    input: {
      title: "Follow up with design review",
      priority: "high",
    },
  },
});

路由:

  • GET /ageniti/actions
  • POST /ageniti/actions/:name/invoke

app.createHttpServer(options)

基于同一个 handler 创建一个轻量 Node HTTP server。

const server = app.createHttpServer();
const listener = await server.listen(4322);

HTTP action 必须支持 http surface。private、local 和 destructive action 默认不会暴露。

仅 server 侧支持的参数:

  • maxBodyBytes
  • requireJsonContentType

Build API

import { buildArtifacts, packageArtifacts, publishArtifacts } from "@ageniti/core/build";
import { createGuideDoc, exportDocs } from "@ageniti/core/docs";

createAgenitiApp() 返回值上的 app.build()app.package()app.publish()app.createGuideDoc()app.exportDocs() 方法保持不变。

app.build(options)

基于 app 对象构建官方 Ageniti 分发产物。

await app.build({
  targets: ["bundle"],
  appModule: "./src/ageniti/app.js",
  appExport: "app",
  outDir: "./dist/ageniti",
});

常用参数:

  • targetsmanifestclimcpdocsbundle
  • outDir:输出目录,默认 dist/ageniti
  • appModule:导出 app 的 headless、Node-safe 模块
  • appExport:导出名,默认 app
  • includePackageJson:强制生成 package.json
  • cwd:用于解析路径的工作目录
  • filenamedocs 的自定义文件名,默认 GUIDE.md

bundle 会展开生成:

  • ageniti.manifest.json
  • ageniti.actions.json
  • cli.mjs
  • mcp-stdio.mjs
  • ageniti.mcp.json
  • GUIDE.md
  • package.json
  • README.md
  • ageniti.bundle.json

生成的 README.md 是 app distribution 的一部分。它会说明如何本地运行 CLI、发布生成出来的 package、安装最终 bin、接入 MCP client,以及如何在自己的后端里部署 HTTP。

app.createGuideDoc(options)

返回单个 Markdown 指南字符串。

const markdown = app.createGuideDoc();

它会读取 app 的 description / docs,以及每个 action 的 description、权限、副作用、surface、publicMetadatadocs

app.exportDocs(options)

把统一指南写入磁盘。

await app.exportDocs({
  outDir: "./dist/ageniti",
});

默认输出:

  • GUIDE.md

也可以通过 CLI 使用同一能力:

task-app docs
task-app docs --out-dir ./dist/ageniti
task-app build docs --out-dir ./dist/ageniti

app.package(options)

先构建 bundle,然后在输出目录里执行 npm pack

const result = await app.package({
  appModule: "./src/ageniti/app.js",
  outDir: "./dist/ageniti",
});

返回结果包含:

  • outDir
  • packageDir
  • packageFile
  • build

app.publish(options)

先构建 bundle,再执行 npm pack,最后执行 npm publish

const result = await app.publish({
  appModule: "./src/ageniti/app.js",
  outDir: "./dist/ageniti",
  dryRun: true,
  access: "public",
});

重要默认值:

  • dryRun 默认是 true
  • 只有在真实发布时才应传 dryRun: false

部署形态:

  • CLI package:发布或分发生成出来的 npm package,并暴露其中的 bin
  • MCP server:本地运行 mcp-stdio.mjs,或在安装后运行生成的 <bin-name>-mcp 命令。
  • HTTP gateway:在你自己的后端里挂 app.createHttpHandler();Ageniti 不要求托管 runtime。

返回结果包含:

  • ok
  • outDir
  • packageDir
  • packageFile
  • published
  • stdout
  • stderr
  • build

buildArtifacts(options)

app.build() 底层使用的低层构建 helper。

packageArtifacts(options)

app.package() 底层使用的低层打包 helper。

const result = await packageArtifacts({
  appName: "task-app",
  actions,
  adapters,
  appModule: "./src/ageniti/app.js",
  appExport: "app",
});

返回结果包含:

  • ok
  • outDir
  • packageDir
  • packageFile
  • build

publishArtifacts(options)

app.publish() 底层使用的低层发布 helper。

const result = await publishArtifacts({
  appName: "task-app",
  actions,
  adapters,
  appModule: "./src/ageniti/app.js",
  appExport: "app",
  dryRun: true,
});

返回结果包含:

  • ok
  • outDir
  • packageDir
  • packageFile
  • published
  • stdout
  • stderr
  • build

Manifest Diff

import { diffActionManifests } from "@ageniti/core/manifest";

diffActionManifests(previous, next)

比较两个 action manifest 或 surface manifest,并报告 breaking change、warning 和信息性变化。

const diff = diffActionManifests(previousManifest, nextManifest);

breaking change 包括 action 被移除,以及输入/输出 schema 变化。

const result = await buildArtifacts({
  appName: "task-app",
  actions,
  adapters,
  targets: ["bundle"],
  appModule: "./src/ageniti/app.js",
  appExport: "app",
});

当你希望不先创建 app 对象、直接构建 launcher 或 manifest 时,可以使用它。

Project Tools

import {
  initProject,
  doctorProject,
  loadProjectConfig,
  findDefaultAppModule,
  detectTypeScriptRuntime,
  supportsTypeScriptEntrypoints,
} from "@ageniti/core/project";

initProject(options)

初始化一个 headless Ageniti 入口,支持 reactexponext 以及 host-openaihost-ai-sdkhost-mcphost-http 等宿主模板。

const result = await initProject({
  cwd: process.cwd(),
  template: "react",
});

返回结果包含:

  • ok
  • template
  • cwd
  • files
  • appModule
  • nextSteps

doctorProject(options)

检查当前项目的框架类型、默认 Ageniti 入口发现结果,以及常见 launcher 或构建问题。

const result = await doctorProject({ cwd: process.cwd() });

返回结果包含:

  • ok
  • kind
  • cwd
  • defaultAppModule
  • checks
  • recommendations

findDefaultAppModule(options)

查找零配置构建流程使用的默认 Node-safe Ageniti app 入口。

const result = await findDefaultAppModule({ cwd: process.cwd() });

可能的结果包括:

  • found: true,并带有 modulePath,原因是 node-safe-default
  • found: true,并带有 modulePath,原因是 configured
  • found: false,原因是 typescript-only-entry
  • found: false,原因是 missing

loadProjectConfig(options)

从项目根目录加载 ageniti.config.jsonageniti.config.jsageniti.config.mjsageniti.config.cjs

const config = await loadProjectConfig({ cwd: process.cwd() });

返回字段可能包括:

  • build.appModule
  • build.appExport
  • build.outDir
  • build.includePackageJson
  • build.typescriptRuntime
  • mcp.transport
  • mcp.env
  • package.name
  • package.version
  • package.description
  • package.private
  • package.binName
  • configPath

detectTypeScriptRuntime(options)

检测当前项目是否已经配置好 TypeScript launcher 生成所需 runtime。

const runtime = detectTypeScriptRuntime({ packageJson, config });

当前内建支持:

  • 当项目安装或配置了 tsx 时返回 tsx
  • 当没有可用的受支持 TypeScript runtime 时返回 undefined

supportsTypeScriptEntrypoints(options)

返回当前项目是否可以从仅 TypeScript 的 headless app 入口生成 launcher 文件。

const supported = supportsTypeScriptEntrypoints({ packageJson, config });

Surface Adapter API

defineSurfaceAdapter(adapter)

创建一个自定义 adapter 描述对象。

必填字段:

  • name

默认字段:

  • description: ""
  • capabilities: {}
  • canExpose: () => true
  • describe: (action) => action

内建 Adapter

  • cliAdapter
  • jsonAdapter
  • httpAdapter
  • mcpAdapter
  • reactAdapter
  • devAdapter
  • aiSdkAdapter

defaultSurfaceAdapters()

返回 createAgenitiApp()createCli() 默认使用的 adapter 列表。

findAdapter(adapters, name)

按名称查找单个 adapter。

Lint API

import { lintActions } from "@ageniti/core/lint";

lintActions(actions)

对 action 定义执行静态检查。

当前可能的 finding 包括:

  • 重复 action name
  • 非法 action 命名
  • 描述太弱
  • destructive action 暴露到 MCP
  • write 或 destructive action 未声明 idempotency
  • 输入 schema 不是 object
  • write 或 destructive action 未声明 permissions

Schema API

s

轻量 schema builder。

可用 builder:

  • s.string()
  • s.number()
  • s.boolean()
  • s.enum(values)
  • s.array(schema)
  • s.object(shape)
  • s.literal(value)
  • s.union(schemas)
  • s.record(schema)
  • s.any()

常用 modifier:

  • .describe(text)
  • .default(value)
  • .optional()
  • .nullable()
  • .meta(data)

类型相关 helper:

  • string:.min().max().pattern().url().datetime()
  • number:.min().max().int()
  • object:.passthrough()

toJSONSchema(schema)

把 Ageniti schema 转成 JSON Schema。

SchemaValidationError

schema parse 路径在校验失败时会抛出的错误类型。

错误与结果类型

AgenitiError

自定义 runtime 错误,包含:

  • code
  • issues
  • retryable

Runtime Result 结构

成功:

{
  "ok": true,
  "data": {},
  "artifacts": [],
  "logs": [],
  "meta": {
    "action": "create_task",
    "invocationId": "invocation-id",
    "surface": "cli",
    "durationMs": 12
  }
}

失败:

{
  "ok": false,
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Invalid action input.",
    "issues": [],
    "retryable": false
  },
  "artifacts": [],
  "logs": [],
  "meta": {
    "action": "create_task",
    "invocationId": "invocation-id",
    "surface": "mcp",
    "durationMs": 3
  }
}

批量注册

defineActions(map, options?)

一次注册一组 action,camelCase key 自动转 snake_case。

import { defineActions, s } from "@ageniti/core";
 
export const actions = defineActions({
  createTask: {
    description: "Create a task.",
    input: s.object({ title: s.string() }),
    run: async ({ title }) => ({ id: crypto.randomUUID(), title }),
  },
  ping: () => ({ ok: true }),
});

可选:

  • defaults:每个条目都会合并的共享 config
  • rename(key):自定义命名策略

actionFromHandler(handler, config)

把单个已有函数包装成 action。Handler 支持 1 参 (input) 或 2 参 (input, ctx) —— Ageniti 自动识别并转发。

actionsFromHandlers(handlers, metadata?)

把一组普通函数和 metadata 配对。

import * as handlers from "./app/actions/tasks";
import { actionsFromHandlers, s } from "@ageniti/core";
 
export const actions = actionsFromHandlers(handlers, {
  createTask: { description: "Create a task.", input: s.object({ title: s.string() }) },
});

Schema 互操作

wrapSchema(foreign, options?)

把任何 Zod 风格的 schema(带 .safeParse / .parse)或 Standard Schema v1 包装成 Ageniti Schema。JSON Schema 通过 best-effort introspection 生成;可通过 { jsonSchema } 覆盖。

assertSchema(被 defineAction 内部调用)会自动包装外部 schema,所以你通常不需要直接调用 wrapSchema

s.object(shape).strict()

校验时拒绝未声明的属性(与 .passthrough() 互补)。

流式事件

runtime.stream(actionOrName, input, options?)

返回 AsyncIterableIterator<RuntimeStreamEvent>,runtime 执行过程中实时 yield 事件:

type RuntimeStreamEvent =
  | { type: "log"; level: string; message: string; time: string; fields: Record<string, unknown> }
  | { type: "artifact"; artifact: Artifact }
  | { type: "progress"; message?: string; percent?: number; fields?: Record<string, unknown>; time: string }
  | { type: "result"; envelope: RuntimeResult };

事件来自 run() 里的 ctx.logger.* / ctx.progress.report() / ctx.artifacts.add()。流总是以一个 result 事件结尾。

类型化 Client

createClient(options)

import { createClient } from "@ageniti/core/client";
 
// 进程内
const client = createClient({ runtime });
const task = await client.create_task({ title: "Hello" });
 
// 远程
const remote = createClient({ url: "https://api.example.com" });

特殊方法:

  • client.$invoke(name, input, options?) —— 字符串名调用
  • client.$stream(name, input, options?) —— 事件 async iterable
  • client.$transport —— 底层 transport

说明:

  • 远端 HTTP client 可以在请求体里发送 metadataconfirmidempotencyKey
  • 远端 HTTP client 不能在请求体里发送可信的 userauth;应通过 headers / 自定义 fetch 传递,再由服务端 resolveContext 解析。
  • 传输失败或远端返回非法响应时,也会抛 AgenitiClientError,其客户端错误码可能是 TRANSPORT_ERRORINVALID_RESPONSE

AgenitiClientError

调用失败时抛出,包含 code / issues / retryable,以及可选的 envelope。传输层失败也会使用这个错误类型。

generateClientTypes(actions, options?)

从 action manifest 生成 TypeScript .d.ts

import { generateClientTypes } from "@ageniti/core/client-gen";
import { writeFile } from "node:fs/promises";
 
await writeFile(".ageniti/client.d.ts", generateClientTypes(actions, {
  interfaceName: "TasksClient",
}));

React Hook

useAction(action, { runtime })

状态机 hook。订阅 runtime.stream 让 logs / progress / artifacts 实时更新。从 @ageniti/core/react-hooks 导入。

状态形态:{ status, data, error, logs, artifacts, progress, invoke, cancel, reset }

组件 unmount 自动 abort;新的 invoke() 调用取消之前的。

测试工具

import {
  createTestRuntime, expectOk, expectError, expectLog,
  collectStream, stubAction,
} from "@ageniti/core/test-utils";
 
const t = createTestRuntime([myAction], {
  services: { db: stubDb },
  allow: true,
});
const env = await t.invoke("my_action", { x: 1 });
expectOk(env);

Runtime Hooks 与脱敏

const runtime = createRuntime({
  actions,
  hooks: {
    onInvocationStart: ({ action, invocationId, input }) => metrics.timer.start(invocationId),
    onInvocationEnd: ({ action, invocationId, envelope }) => metrics.timer.end(invocationId, envelope.ok),
  },
  redact: { keys: ["ssn", "credit_card"], placeholder: "[REDACTED]" },
  idempotencyMaxEntries: 5000,
  idempotencyTtlMs: 10 * 60 * 1000,
});

默认脱敏 key:password / passwd / secret / token / apikey / api_key / authorization / cookie / session / x-api-key / access_token / refresh_token / private_key / client_secret。Error message 和 issue 文本里常见的 token 形式(Bearer …、JWT、sk-…ghp_…xoxb-…key=value)也会被脱敏。

错误码

| Code | HTTP | CLI exit | 何时触发 | |---|---|---|---| | VALIDATION_ERROR | 400 | 2 | 输入未通过 schema | | OUTPUT_VALIDATION_ERROR | 502 | 2 | run 返回不合 schema 的输出 | | OUTPUT_SERIALIZATION_ERROR | 502 | 2 | run 返回不能 JSON 序列化的值 | | AUTHENTICATION_ERROR | 401 | 3 | 缺少凭证 | | AUTHORIZATION_ERROR | 403 | 3 | 权限拒绝 | | CONFIRMATION_REQUIRED | 409 | 3 | destructive action 缺 confirm | | ACTION_NOT_FOUND | 404 | 4 | action 不存在 | | UNSUPPORTED_SURFACE | 405 | 4 | action 在该 surface 不可用 | | RATE_LIMITED | 429 | 5 | 上游限流 | | CONCURRENCY_LIMIT | 429 | 5 | 单 action 并发上限(可重试)| | EXTERNAL_SERVICE_ERROR | 502 | 5 | 上游失败 | | TIMEOUT | 504 | 124 | 超过 timeoutMs | | CANCELLED | 499 | 130 | 用户或 runtime 取消 | | CONFLICT | 409 | 1 | 乐观并发 / 状态冲突 | | INTERNAL_ERROR | 500 | 1 | run 抛了未捕获错误 |