Runtime 语义
Ageniti 把关键行为集中在 runtime 中,因此 CLI、HTTP、MCP、React、JSON automation、dev tool 和 LLM adapter 都共享同一套执行模型。
执行流程
调用一个 action 时,runtime 会按顺序执行这些步骤:
- 根据名称或对象引用解析 action。
- 检查该 action 是否支持当前 surface。
- 用输入 schema 做输入校验。
- 对受保护 action 执行确认检查。
- 执行权限检查。
- 执行中间件链。
- 结合超时和重试运行 action。
- 确保输出可以安全序列化为 JSON。
- 如果声明了输出 schema,则继续做输出校验。
- 返回结构化的成功或失败 envelope。
Surface 规则
每个 action 通过 supportedSurfaces 声明可用入口。
默认支持的 surface:
cli, json, http, mcp, react, dev, ai-sdk如果某个 surface 不被支持,runtime 会返回 UNSUPPORTED_SURFACE。
确认规则
当 action 的 requiresConfirmation: true 时,runtime 需要显式确认标记。
默认情况下,destructive action 会自动继承该要求。
不过以下 surface 不会在 runtime 层强制阻塞确认:
reactdev
也就是说,UI 场景下确认流程应由 UI 自己负责,再去调用 action。
权限检查
permissionChecker({ action, input, context }) 可以返回:
true:允许执行false:拒绝执行,并返回通用授权错误- 字符串:拒绝执行,并把该字符串作为错误信息
权限检查失败时,runtime 返回 AUTHORIZATION_ERROR。
超时与重试
超时来源:
- action 级别的
timeoutMs - 单次调用级别的
timeoutMs
重试来源:
- action 级别的
retry - 单次调用级别的
retry
只有当错误是可重试的,runtime 才会重试。通常这意味着 action 抛出了 retryable: true 的 AgenitiError,或者超时逻辑把该错误标记为可重试。
retry: true 会被标准化为:
{
"retries": 2,
"delayMs": 100
}重试采用按尝试次数递增的线性退避。
日志、进度与 Artifacts
每次调用都会累积结构化日志和 artifacts。
context.logger 提供:
debug(message, fields?)info(message, fields?)warn(message, fields?)error(message, fields?)
context.progress.report():
- 会追加一条日志,其中
fields.type = "progress" - 可包含
percent - 可附带额外结构化字段
context.artifacts.add():
- 若缺少
id会自动补全 type默认是"file"metadata会被标准化成对象
流式事件
每次调用都可以被另一个 caller 通过 runtime.stream(name, input, options) 实时观察,返回 async iterable,runtime 执行过程中按顺序 yield { type: "log" | "artifact" | "progress" | "result", ... }。流总是以一个 result 事件收尾,里面是最终的 envelope。
事件来自 action 里调用的 ctx.logger.* / ctx.progress.report() / ctx.artifacts.add()。CLI 的 --ndjson 模式、React 的 useAction hook,以及类型化 client 的 $stream 方法都建在这个原语之上。
Idempotency Key
在 invoke options 里传 idempotencyKey 可以对 retry 去重。非 read 类 action 的成功 envelope 会按 action 名、key、校验后的输入、surface 以及可信调用方指纹共同缓存。命中时会返回缓存 envelope 的一份新副本,并在 meta.idempotent 里标记 "replayed"。缓存有大小上限(默认 1000 条,可通过 idempotencyMaxEntries 配置)和 TTL(默认 5 分钟,idempotencyTtlMs)。
并发限制
在 action 上设 concurrency: { max: N } 可以限制同时活跃的调用数。超出会返回 CONCURRENCY_LIMIT(retryable)。常用来保护上游限流。
取消
在 invoke options 里传 signal: AbortSignal 可以从外部取消调用。CLI 默认把 SIGINT 接到 abort。每次 retry attempt 内部会创建独立的 AbortController,所以 timeout 之后的 retry 仍能看到一个新鲜的 signal。
Hooks 与脱敏
在 createRuntime 里传 hooks 用于调用埋点,传 redact 配置 logs / artifact metadata / error message 的脱敏行为。
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"] },
});默认脱敏 key:password / passwd / secret / token / apikey / api_key / authorization / cookie / session / x-api-key / access_token / refresh_token / private_key / client_secret。Error message 中的常见 token 形式(Bearer ...、JWT、sk-...、ghp_...、xoxb-...、key=value)也会被自动脱敏。
成功 Envelope
{
"ok": true,
"data": {},
"artifacts": [],
"logs": [],
"meta": {
"action": "create_task",
"invocationId": "invocation-id",
"surface": "cli",
"durationMs": 12
}
}失败 Envelope
{
"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
}
}常见 Runtime 错误码
核心 runtime 错误码:
ACTION_NOT_FOUNDUNSUPPORTED_SURFACEVALIDATION_ERRORCONFIRMATION_REQUIREDAUTHORIZATION_ERROROUTPUT_SERIALIZATION_ERROROUTPUT_VALIDATION_ERRORTIMEOUTCANCELLEDINTERNAL_ERROR
你还可能在包装层中看到:
INVALID_JSON_RUNNER_PAYLOADDEV_SERVER_ERROR- 本地 dev server HTTP route 返回的
NOT_FOUND
错误是如何被标准化的
如果 action 抛出:
AgenitiError,则保留其code、message、issues和retryableAbortError,runtime 返回CANCELLED- 其他任意错误,runtime 返回
INTERNAL_ERROR
CLI Exit Code
内建 CLI 会把 runtime 错误码映射成进程退出码。
重要映射:
VALIDATION_ERROR->2AUTHENTICATION_ERROR->3AUTHORIZATION_ERROR->3ACTION_NOT_FOUND->4EXTERNAL_SERVICE_ERROR->5TIMEOUT->124CANCELLED->130- 其他错误 ->
1
输出保证
Ageniti 只返回可安全序列化为 JSON 的结果。
如果 action 定义了输出 schema,runtime 会在返回成功前再做一次输出校验。这使得返回 envelope 可以稳定用于 CLI 输出、MCP structured content、自动化测试和机器间集成。