快速开始

Ageniti 用来把现有 React 或 TypeScript 应用中的部分能力暴露给 agent 和自动化工具调用。

它不会替你创建 agent,而是让你的应用可以被 agent 调用。

安装

npm install @ageniti/core

要求:

  • 纯 ESM 包
  • Node.js 20 或更高版本

1. 先选一个已有能力

先从你已经信任的一项应用能力开始:

  • 创建任务
  • 搜索工作区记录
  • 导出报表
  • 发送消息
  • 总结文档

不要一开始就重构整个应用。先把一个稳定能力包成 action。

2. 定义 Action

import { defineAction, s } from "@ageniti/core";
 
export const createTask = defineAction({
  name: "create_task",
  description: "Create a workspace task.",
  visibility: "public",
  sideEffects: "write",
  idempotency: "conditional",
  permissions: ["task:create"],
  input: s.object({
    title: s.string().min(1).describe("Task title"),
    assignee: s.string().optional().describe("Optional assignee id"),
    priority: s.enum(["low", "normal", "high"]).default("normal"),
  }),
  output: s.object({
    taskId: s.string(),
    status: s.string(),
    priority: s.string(),
  }),
  async run(input, ctx) {
    ctx.logger.info("Creating task.", { title: input.title });
    return ctx.services.tasks.create(input);
  },
});

defineAction() 的重要默认值:

  • title 默认由 name 自动生成人类可读标题。
  • input 默认是 s.object({})
  • visibility 默认是 "local"
  • sideEffects 默认是 "read"
  • idempotency 默认是 "unspecified"
  • supportedSurfaces 默认包含 clijsonhttpmcpreactdevai-sdk
  • destructive action 默认会要求确认,除非显式覆盖 requiresConfirmation

3. 创建 App

import { createAgenitiApp } from "@ageniti/core";
import { createTask } from "./actions/create-task.js";
import { tasks } from "./services/tasks.js";
 
export const app = createAgenitiApp({
  name: "task-app",
  description: "面向 agent 暴露的任务能力。",
  docs: {
    summary: "当 agent 需要创建任务或查看任务状态时使用这个 app。",
  },
  actions: [createTask],
  services: {
    tasks,
  },
  permissionChecker({ action, context }) {
    return action.permissions.every((permission) =>
      context.auth?.permissions?.includes(permission)
    ) || "Missing required permission.";
  },
});

createAgenitiApp() 会给你一套共享 runtime,以及各 surface 对应的便利方法。

4. 写自然语言说明

Ageniti 可以从 app 和 action 上的自然语言字段导出一份统一说明书。它不会调用模型,也不会猜测你的业务逻辑;它只读取你已经明确写下来的 contract。

export const createTask = defineAction({
  name: "create_task",
  description: "Create a workspace task.",
  docs: {
    whenToUse: "Use this when an agent needs to create a trackable task.",
    whenNotToUse: "Do not use this for multi-step approvals.",
    usageNotes: [
      "The caller should provide a short, human-readable title.",
      "High priority tasks may trigger downstream notifications.",
    ],
    inputExample: {
      title: "Follow up with design review",
      priority: "high",
    },
    outputExample: {
      taskId: "task_123",
      status: "open",
      priority: "high",
    },
  },
  run(input, ctx) {
    return ctx.services.tasks.create(input);
  },
});
 
export const app = createAgenitiApp({
  name: "task-app",
  description: "面向 agent 暴露的任务能力。",
  docs: {
    summary: "当 agent 需要创建任务或查看任务状态时使用这个 app。",
    audience: "内部 agent、自动化脚本和 operator 工具。",
    whenToUse: [
      "当 agent 需要创建或查询结构化任务时使用。",
      "当调用方需要 CLI、MCP、HTTP 或 LLM tool surface 时使用。",
    ],
    setup: [
      "确保调用方具备所需权限。",
      "先用 dev console 或 CLI 测试 action 输入。",
    ],
    operationalNotes: [
      "destructive action 默认不会暴露给 MCP 和 LLM tools。",
      "内部信息放在 metadata,对外说明放在 publicMetadata 或 docs。",
    ],
  },
  actions: [createTask],
});

这些字段会被合并成一份 GUIDE.md,默认包含:

  • app 概览
  • 适合谁使用
  • 什么时候使用
  • 初始化和使用步骤
  • 运维注意事项
  • 可用 action 列表
  • 每个 action 的描述、权限、副作用、surface、示例输入输出

导出方式:

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

task-app docs 会把说明书打印到 stdout。带 --out-dir 时会写入 GUIDE.mdbuild bundle 会自动把 GUIDE.md 放进最终 bundle。

这份说明书适合给:

  • agent host 阅读
  • MCP server 安装说明
  • 内部 operator 文档
  • 发布包里的使用说明
  • 团队对 action contract 的人工 review

5. 暴露 CLI

#!/usr/bin/env node
import { app } from "./app.js";
 
await app.createCli().main();

示例命令:

task-app create-task --title "Follow up with design review" --priority high
task-app create-task --json '{"title":"Follow up with design review","priority":"high"}'
task-app create-task --schema
task-app actions
task-app manifest
task-app build
task-app build docs
task-app docs
task-app package
task-app publish
task-app lint
task-app mcp
task-app mcp --stdio
task-app dev --port 4321

说明:

  • snake_case 的 action 也可以用 kebab-case 命令调用。
  • --schema 会打印输入 JSON Schema。
  • 对需要确认的 action,需要额外传 --confirm
  • CLI exit code 和 runtime 错误码有关,见 Runtime 语义

6. 暴露 JSON Automation

const runner = app.createJsonRunner();
 
const result = await runner.invoke({
  action: "create_task",
  input: {
    title: "Follow up with design review",
    priority: "high",
  },
});

如果你的脚本、测试、worker 或 HTTP 包装层本来就以结构化 JSON 交互,JSON runner 往往是最直接的入口。

7. 暴露 MCP

const handleMcp = app.createMcpHandler();
 
await handleMcp({
  jsonrpc: "2.0",
  id: 1,
  method: "tools/list",
});
 
await handleMcp({
  jsonrpc: "2.0",
  id: 2,
  method: "tools/call",
  params: {
    name: "create_task",
    arguments: {
      title: "Follow up with design review",
      priority: "high",
    },
  },
});

MCP 默认过滤规则:

  • action 必须支持 mcp surface
  • private action 默认不会暴露,除非显式开启
  • destructive action 默认不会暴露,除非显式开启

8. 暴露 OpenAI 和 AI SDK Tools

const openaiTools = app.createOpenAITools();
const responsesTools = app.createOpenAIResponsesTools();
const aiSdkTools = app.createAISDKTools();
 
const task = await aiSdkTools.create_task.execute({
  title: "Follow up with design review",
  priority: "high",
});

面向 LLM 的默认过滤规则:

  • private action 默认被过滤
  • destructive action 默认被过滤
  • action 必须支持 ai-sdk surface

如果你希望拿到完整 runtime envelope,而不是只拿 data,创建 AI SDK tools 时传 returnEnvelope: true

9. 在现有 React UI 中使用

const { useAction } = app.createReactAdapter();
const runCreateTask = useAction(createTask);
 
const result = await runCreateTask({
  title: "Follow up with design review",
  priority: "high",
});

React 调用会复用同一套 runtime,但会把 surface 固定为 reactreact surface 不会在 runtime 层阻塞确认,所以确认流程应当由你的 UI 自己负责。

10. 启动本地 Dev Console

task-app dev --port 4321

Dev console 提供:

  • action 列表
  • 自动生成的输入 schema
  • JSON 输入编辑器
  • 结构化运行结果预览

11. 构建官方产物

如果你希望基于同一个 app 定义产出 CLI 或 MCP launcher:

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

如果你更偏好走 CLI:

task-app build bundle --app-module ./src/ageniti/app.js --app-export app --out-dir ./dist/ageniti
task-app build docs --out-dir ./dist/ageniti
task-app docs --out-dir ./dist/ageniti

如果省略 appModule,Ageniti 会尝试自动发现默认的 Node-safe 入口,例如 ./src/ageniti/app.js

bundle 产物包含:

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

如果你还希望直接得到可分发的 tarball,可以运行:

task-app package --app-module ./src/ageniti/app.js --app-export app --out-dir ./dist/ageniti

这个命令会先生成 bundle,再在其中执行 npm pack

如果你要做发布预演或正式发布,可以运行:

task-app publish --app-module ./src/ageniti/app.js --app-export app --out-dir ./dist/ageniti
task-app publish --live --access public --tag latest --app-module ./src/ageniti/app.js --app-export app --out-dir ./dist/ageniti

publish 默认执行的是 npm publish --dry-run。只有准备好真实发布时才传 --live

12. 初始化或诊断项目

如果你是从现有 React 或 Expo 应用接入,Ageniti 还提供 project tools:

npx @ageniti/core init react
npx @ageniti/core init expo
npx @ageniti/core init next
npx @ageniti/core doctor

init 用来生成 headless 入口,doctor 用来检查当前项目是否已经具备有效的构建入口,以及它是否适合作为 launcher 生成源。

如果你希望团队内都复用同一套默认构建参数,可以添加 ageniti.config.json

{
  "build": {
    "appModule": "./src/ageniti/app.ts",
    "appExport": "app",
    "outDir": "./dist/ageniti",
    "includePackageJson": true,
    "typescriptRuntime": "tsx"
  },
  "mcp": {
    "transport": "stdio"
  },
  "package": {
    "name": "task-app-bundle",
    "version": "0.1.0",
    "description": "CLI and MCP bundle for task-app",
    "private": false,
    "binName": "task-app"
  }
}

配置好之后,你生成的 app CLI 就可以直接运行 build,例如 task-app build,不需要重复传同样的参数。

13. TypeScript Only 入口

如果你的项目只有 src/ageniti/app.ts,没有额外的 JavaScript wrapper,只要可用 tsx runtime,Ageniti 也能生成 CLI 和 MCP launcher。

常见做法有三种:

  • 安装 tsx,并把 build.typescriptRuntime 设为 tsx
  • --app-module 指向编译后的 JavaScript
  • 创建一个很薄的 src/ageniti/app.js wrapper 重新导出 app

当 Ageniti 检测到你传入的是 React page、layout 或 component 文件,而不是 headless 入口时,doctorbuild 现在都会给出明确错误,避免把 UI 模块误打包成 MCP 或 CLI launcher。

14. 接下来读什么