Recipes

这页整理了一些基于公开 Ageniti API 的常见集成模式。

面向 CLI 的内部工具

当终端命令是主要入口时,适合这种模式。

import { createAgenitiApp, defineAction, s } from "@ageniti/core";
 
const searchTasks = defineAction({
  name: "search_tasks",
  description: "Search tasks by status.",
  input: s.object({
    status: s.enum(["open", "blocked", "done"]),
  }),
  run(input, ctx) {
    return ctx.services.tasks.search(input);
  },
});
 
const app = createAgenitiApp({
  name: "ops-tools",
  actions: [searchTasks],
  services: { tasks },
});
 
await app.createCli().main();

这种模式的优点:

  • 单一命令入口
  • 参数自动有 JSON Schema
  • 对 shell 包装层和测试来说,返回结构稳定

复用现有 React 按钮逻辑

当应用已经有 UI handler,而你想把同一能力复用给 agent-facing 场景时,适合这种模式。

const { useAction } = app.createReactAdapter();
const runSearchTasks = useAction(searchTasks);
 
async function onClick() {
  const result = await runSearchTasks({ status: "open" });
  if (result.ok) {
    setTasks(result.data.items);
  }
}

推荐做法:

  • 确认流程放在 UI 层
  • 权限上下文通过 invokeOptions 传入
  • 后续其他 surface 继续复用同一个 action

用 JSON Runner 做自动化调用

适合脚本、队列、cron job 或测试 harness。

const runner = app.createJsonRunner();
 
const result = await runner.invoke({
  action: "search_tasks",
  input: { status: "open" },
  metadata: { source: "nightly-job" },
});

如果你只是想把 Ageniti 套在自己的 transport 外层,这通常是最直接的做法。

仓库示例:

  • ageniti/examples/task-app.js

给 Agent 平台暴露 MCP Tools

当宿主系统已经使用 MCP 风格 JSON-RPC 时,适合这种模式。

const handle = app.createMcpHandler();
 
const list = await handle({
  jsonrpc: "2.0",
  id: 1,
  method: "tools/list",
});
 
const call = await handle({
  jsonrpc: "2.0",
  id: 2,
  method: "tools/call",
  params: {
    name: "search_tasks",
    arguments: { status: "open" },
  },
});

如果宿主不是内存内 handler,而是要求 stdio 方式,可以使用:

await app.createCli().run(["mcp", "--stdio"]);

仓库示例:

  • ageniti/examples/mcp-host.js

OpenAI 与 AI SDK Tool Adapter

当宿主应用本身已经会消费 OpenAI 兼容 schema 或 AI SDK tool object 时,适合这种模式。

const openaiTools = app.createOpenAITools();
const responsesTools = app.createOpenAIResponsesTools();
const aiSdkTools = app.createAISDKTools({ returnEnvelope: true });

建议:

  • destructive action 默认不要放出去
  • 高风险工具再叠加显式 filter
  • 当调用方需要日志或 artifacts 时,使用 returnEnvelope: true

OpenAI Responses 宿主接入

当你的宿主应用已经在调用 OpenAI Responses API,只是需要从 app SDK 拿到一组稳定 tool 时,适合这种模式。

import OpenAI from "openai";
 
const client = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });
const tools = app.createOpenAIResponsesTools();
 
const response = await client.responses.create({
  model: "gpt-4.1",
  input: "Find the blocked tasks and summarize the owners.",
  tools,
});

这个模式的价值在于:

  • 宿主自己决定模型和 prompt
  • Ageniti 负责应用能力 contract
  • tool schema 和 runtime 语义保持一致

仓库示例:

  • ageniti/examples/openai-responses-host.js

Vercel AI SDK Route Handler

当 Next.js 或其他服务端宿主已经在用 AI SDK,而你想把 shared runtime 直接接成 executable tool 时,适合这种模式。

import { generateText } from "ai";
 
const tools = app.createAISDKTools({ returnEnvelope: true });
 
const result = await generateText({
  model,
  prompt: "Create a high-priority follow-up task for the open incident.",
  tools,
});

推荐做法:

  • auth 放在宿主层,通过 runtime option 注入
  • 需要 logs 或 artifacts 时返回 envelope
  • 非受信任宿主默认继续过滤高风险工具

仓库示例:

  • ageniti/examples/ai-sdk-route.js

HTTP Gateway Wrapper

当你希望自己的后端统一掌控 transport、auth 和部署,而 Ageniti 只负责 action 执行时,适合这种模式。

const handle = app.createHttpHandler();
 
const response = await handle({
  method: "POST",
  url: "/ageniti/actions/create_task/invoke",
  body: {
    input: {
      title: "Write the release review summary",
      priority: "high",
    },
    auth: {
      permissions: ["task:create"],
    },
  },
});

推荐做法:

  • 调用方身份和鉴权收口在 gateway 层
  • 只把应用级 permission context 传进 Ageniti
  • HTTP payload 尽量贴近 runtime envelope,方便调试

仓库示例:

  • ageniti/examples/http-gateway.js

限制 Surface 暴露范围

可以通过 action 元数据把高风险操作限制在受信任入口上。

const deleteTask = defineAction({
  name: "delete_task",
  description: "Delete a task by id.",
  sideEffects: "destructive",
  supportedSurfaces: ["cli", "react", "dev"],
  input: s.object({
    taskId: s.string(),
  }),
  run(input, ctx) {
    return ctx.services.tasks.remove(input.taskId);
  },
});

这样 action 仍可用于受信任的操作员路径,但不会进入 MCP 和 LLM tool 暴露面。

在 CI 中检查 Manifest 与 Lint

适合在发布前把 contract 显式化。

const manifest = app.manifest();
const lint = app.lint();
 
if (!lint.ok) {
  process.exitCode = 1;
}

你可以在测试里对 manifest 做 snapshot,也可以把它作为内部 contract artifact 提供给其他工具链使用。