# Ageniti Official documentation snapshot for LLM consumption. Primary docs site: /en/docs Templates gallery: /en/templates ## Product Summary Title: Build Apps for Agents Subtitle: A standard SDK for exposing app capabilities as safe, structured surfaces that agents, operators, and automation can use. ## Choose Your Path - Start with the core flow: Learn the baseline setup, package layout, and the first action-to-surface workflow. - Integrate into an existing app: Follow practical recipes for MCP servers, React apps, route handlers, and automation scripts. - Start from a pattern: Use documented starter patterns when you want a proven integration path instead of guessing the surface wiring. ## Templates - CLI App Starter (CLI, Runtime): Start with one action and expose it through generated CLI commands with flags, JSON input, schema output, and stable envelopes. Link: /en/docs/recipes#cli-first-internal-tool - MCP Server Bundle (MCP, Tools): Expose selected app capabilities through MCP tools and generate the stdio launcher plus descriptor used by MCP hosts. Link: /en/docs/recipes#mcp-tools-for-agent-platforms - Next.js AI SDK Bridge (Next.js, AI SDK): Map selected actions to Vercel AI SDK-style tools from a Node-safe app entry while keeping app logic in the shared runtime. Link: /en/docs/recipes#openai-and-ai-sdk-tool-adapters - React Invocation (React, UI): Call the same Ageniti action from existing React UI handlers without replacing your router, components, or state management. Link: /en/docs/recipes#existing-react-app-button - HTTP API Surface (HTTP, Node.js): Put the lightweight HTTP handler behind your own server, route handler, or API gateway while returning the same runtime envelope. Link: /en/docs/surfaces#http - Tool Adapter Pattern (Adapters, Tools): Use the shared runtime as the stable boundary when adapting actions into another tool ecosystem or internal platform. Link: /en/docs/surfaces#choosing-a-surface - OpenAI Function Tools (OpenAI, Tools): Generate OpenAI Chat Completions and Responses function tool schemas from the same explicit action contract. Link: /en/docs/surfaces#openai-and-ai-sdk-tools - JSON Automation Runner (JSON, Automation): Invoke actions from scripts, tests, and CI using JSON requests without standing up HTTP or MCP infrastructure. Link: /en/docs/recipes#json-runner-for-automation ## Documentation ### Ageniti Path: /en/docs # Ageniti Ageniti helps React and TypeScript applications expose selected app capabilities as structured actions that can run through CLI, HTTP, MCP, OpenAI-compatible tool calling, Vercel AI SDK-style tools, a JSON runner, a local dev console, and direct React invocation. It is for building **apps that agents can use**, not agents. ## What You Get - A typed action contract built with `defineAction()`. - A shared runtime for validation, permissions, middleware, timeout, retry, logs, progress, and artifacts. - Thin surface adapters for CLI, HTTP, MCP, React, JSON automation, local development, and LLM tool calling. - Official packaging helpers for CLI launchers, MCP stdio launchers, manifests, and bundle metadata. - Project tools for `init`, `doctor`, config-driven builds, and zero-config app entry discovery. - A consistent success and failure envelope across surfaces. - A docs model that keeps app boundaries explicit instead of inferring tools from arbitrary UI code. ## Core Model ```text Existing app capability | v Typed action contract | v Shared runtime | +--> CLI +--> JSON runner +--> MCP +--> OpenAI tools +--> AI SDK tools +--> Dev console +--> React invocation ``` Ageniti keeps most decisions in the runtime and keeps each external surface thin. That means one action definition can be reused across tooling without rewriting the business logic for every integration. ## Install ```text npm install @ageniti/core ``` Ageniti is ESM-only and requires Node.js 20 or newer. ## Minimal Example ```js import { createAgenitiApp, defineAction, s } from "@ageniti/core"; const searchTasks = defineAction({ name: "search_tasks", description: "Search workspace tasks by status.", input: s.object({ status: s.enum(["open", "blocked", "done"]).describe("Task status"), }), output: s.object({ items: s.array( s.object({ id: s.string(), status: s.string(), }) ), }), run(input, ctx) { ctx.logger.info("Searching tasks.", { status: input.status }); return ctx.services.tasks.search(input); }, }); export const app = createAgenitiApp({ name: "workspace-tools", actions: [searchTasks], services: { tasks }, }); ``` From there you can expose the same action through `app.createCli()`, `app.createMcpHandler()`, `app.createAISDKTools()`, `app.createReactAdapter()`, or `app.createDevServer()`. ## React And Expo Workflow For React, Next.js, and Expo projects, the intended model is: - keep business logic in shared services - wrap selected capabilities as Ageniti actions - add one headless Node-safe app entry such as `src/ageniti/app.ts` - use `npx @ageniti/core init react`, `npx @ageniti/core init expo`, `npx @ageniti/core init next`, and `npx @ageniti/core doctor` for project setup - use your generated app CLI, such as `task-app build` and `task-app publish`, to generate and ship official artifacts That keeps your UI unchanged while giving you a stable packaging path for the surfaces agents and automation systems can use. ## Documentation Map - [Getting Started](/en/docs/getting-started): build the first action and expose it through the main surfaces. - [Core Concepts](/en/docs/concepts): app, action, contract, runtime, surface, and headless entry. - [Surfaces](/en/docs/surfaces): when to use CLI, MCP, HTTP, JSON, React, tools, and the dev console. - [Safety Model](/en/docs/safety): visibility, permissions, confirmation, side effects, and metadata. - [Packaging](/en/docs/packaging): generated bundles, MCP descriptors, package, publish, and release review. - [API Reference](/en/docs/api): detailed reference for the public SDK API. - [Entry Points](/en/docs/entry-points): package exports and when to import each subpath. - [Runtime Semantics](/en/docs/runtime): envelopes, errors, retry, timeout, confirmation, logs, and artifacts. - [Recipes](/en/docs/recipes): copyable integration patterns for common setups. - [SDK Readiness](/en/docs/sdk-readiness): product bar for shipping an SDK that exposes app capabilities to agents. - [Roadmap](/en/docs/roadmap): prioritized next steps for turning the SDK into a more trusted product. - [Skill Guide](/en/docs/skill): compact reference for the skills an Ageniti app exposes. - [Scope](/en/docs/scope): what Ageniti deliberately does and does not do. - [FAQ](/en/docs/faq): direct answers about positioning and usage. - [Release Checklist](/en/docs/release-checklist): packaging and publish checks. ## Design Boundaries Ageniti does not inspect your React tree, replace routing, own state management, or orchestrate planning loops. You explicitly declare the capabilities you want to expose, then choose which surfaces should be allowed to invoke them. ### Getting Started Path: /en/docs/getting-started # Getting Started Ageniti helps an existing React or TypeScript application expose selected app capabilities to agents and automation tools. It does not create an agent. It makes your app callable by agents. ## Install ```text npm install @ageniti/core ``` Requirements: - ESM-only package - Node.js 20 or newer ## 1. Pick One Existing Capability Start with one application capability you already trust: - create a task - search workspace records - export a report - send a message - summarise a document Do not start by rewriting the app. Start by wrapping one stable capability. ## 2. Define An Action ```js 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); }, }); ``` Useful defaults from `defineAction()`: - `title` defaults to a humanised version of `name`. - `input` defaults to `s.object({})`. - `visibility` defaults to `"local"`. - `sideEffects` defaults to `"read"`. - `idempotency` defaults to `"unspecified"`. - `supportedSurfaces` defaults to `cli`, `json`, `http`, `mcp`, `react`, `dev`, and `ai-sdk`. - Destructive actions require confirmation unless you override `requiresConfirmation`. ## 3. Create An App ```js 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: "Workspace task operations exposed to agents.", docs: { summary: "Use this app to create tasks and inspect task state.", }, actions: [createTask], services: { tasks, }, permissionChecker({ action, context }) { return action.permissions.every((permission) => context.auth?.permissions?.includes(permission) ) || "Missing required permission."; }, }); ``` `createAgenitiApp()` gives you a shared runtime plus convenience methods for every supported surface. ## 4. Write Natural-Language Guidance Ageniti can export one unified guide from natural-language fields on the app and actions. It does not call a model or infer hidden behaviour from your UI. It reads the contract you explicitly wrote. ```js 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: "Workspace task operations exposed to agents.", docs: { summary: "Use this app to create tasks and inspect task state.", audience: "Internal agents, automation scripts, and operator tools.", whenToUse: [ "Use it when an agent needs structured task creation or lookup.", "Use it when the caller needs CLI, MCP, HTTP, or LLM tool surfaces.", ], setup: [ "Make sure the caller has the required permissions.", "Test action input through the dev console or CLI first.", ], operationalNotes: [ "Destructive actions are not exposed to MCP and LLM tools by default.", "Put internal-only details in metadata, and exposed guidance in publicMetadata or docs.", ], }, actions: [createTask], }); ``` Those fields are merged into one `GUIDE.md`, which can include: - app overview - intended audience - when to use it - setup and usage steps - operational notes - available actions - each action's description, permissions, side effects, surfaces, example input, and example output Export it with: ```text 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` prints the guide to stdout. With `--out-dir`, it writes `GUIDE.md`. `build bundle` automatically includes `GUIDE.md` in the final bundle. The guide is useful for: - agent host documentation - MCP server installation notes - internal operator docs - package-level usage instructions - human review of the action contract ## 5. Expose CLI ```js #!/usr/bin/env node import { app } from "./app.js"; await app.createCli().main(); ``` Example commands: ```text 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 ``` Notes: - Action names can be called as snake_case or kebab-case. - `--schema` prints the input JSON Schema. - `--confirm` is required for actions that require confirmation. - CLI exit codes are mapped from runtime error codes. See [Runtime Semantics](/en/docs/runtime). ## 6. Expose JSON Automation ```js const runner = app.createJsonRunner(); const result = await runner.invoke({ action: "create_task", input: { title: "Follow up with design review", priority: "high", }, }); ``` Use the JSON runner when a script, test harness, worker, or HTTP wrapper already has structured input and output. ## 7. Expose MCP ```js 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 exposure is filtered by default: - actions must support the `mcp` surface - `private` actions are excluded unless you opt in - `destructive` actions are excluded unless you opt in ## 8. Expose OpenAI And AI SDK Tools ```js 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", }); ``` Default LLM tool filtering: - private actions are excluded - destructive actions are excluded - the action must support the `ai-sdk` surface If you want the full runtime envelope instead of raw `data`, pass `returnEnvelope: true` when you build AI SDK tools. ## 9. Use From Existing React UI ```js const { useAction } = app.createReactAdapter(); const runCreateTask = useAction(createTask); const result = await runCreateTask({ title: "Follow up with design review", priority: "high", }); ``` React invocation uses the same runtime but forces the surface to `react`. Confirmation is not blocked at runtime for the `react` surface, so your UI should own the confirmation flow. ## 10. Start The Local Dev Console ```text task-app dev --port 4321 ``` The dev console provides: - action list - generated input schema - JSON input editor - structured runtime result preview ## 11. Build Official Artifacts When you want to ship CLI or MCP launchers from the same app definition: ```js await app.build({ targets: ["bundle"], appModule: "./src/ageniti/app.js", appExport: "app", outDir: "./dist/ageniti", }); ``` If you prefer the CLI flow: ```text 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 ``` If `appModule` is omitted, Ageniti tries to discover a default Node-safe entry such as `./src/ageniti/app.js`. Bundle output includes: - `ageniti.manifest.json` - `ageniti.actions.json` - `cli.mjs` - `mcp-stdio.mjs` - `ageniti.mcp.json` - `GUIDE.md` - `package.json` - `README.md` - `ageniti.bundle.json` If you also want a distributable tarball, run: ```text task-app package --app-module ./src/ageniti/app.js --app-export app --out-dir ./dist/ageniti ``` That command builds the bundle and runs `npm pack` inside it. For publish rehearsal or release: ```text 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` defaults to `npm publish --dry-run`. Pass `--live` only for a real publish. ## 12. Bootstrap Or Diagnose A Project If you are starting from an existing React or Expo application, Ageniti also includes project tools: ```text npx @ageniti/core init react npx @ageniti/core init expo npx @ageniti/core init next npx @ageniti/core doctor ``` Use `init` to scaffold a headless entry. Use `doctor` to inspect whether the current project already has a valid build entry and whether it looks safe for launcher generation. If you want reproducible defaults for every teammate, add `ageniti.config.json`: ```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" } } ``` After that, your generated app CLI can run `build` without repeating the same flags, for example `task-app build`. ## 13. TypeScript-Only Entrypoints If your project uses `src/ageniti/app.ts` without a JavaScript wrapper, Ageniti can still generate CLI and MCP launchers when the `tsx` runtime is available. Typical options: - install `tsx` and set `build.typescriptRuntime` to `tsx` - point `--app-module` at compiled JavaScript - create a tiny `src/ageniti/app.js` wrapper that re-exports the app When Ageniti detects a React page, layout, or component file instead of a headless entry, `doctor` and `build` fail with a targeted error so you do not accidentally package UI modules as MCP or CLI launchers. ## 14. Know What To Read Next - [API Reference](/en/docs/api) for the full public API. - [Entry Points](/en/docs/entry-points) for package export paths. - [Runtime Semantics](/en/docs/runtime) for envelopes, retry, timeout, and errors. - [Recipes](/en/docs/recipes) for common integration patterns. - [Release Checklist](/en/docs/release-checklist) for packaging and publish checks. ### Core Concepts Path: /en/docs/concepts # Core Concepts Ageniti is an SDK for building apps that agents can use. The SDK does not create an agent. It gives your app a clear boundary where selected product capabilities become callable, structured, and reviewable. ## App An Ageniti app is the container for the capabilities you choose to expose. ```js export const app = createAgenitiApp({ name: "workspace-tools", description: "Workspace capabilities exposed through controlled surfaces.", actions: [searchTasks, createTask], services: { tasks }, }); ``` The app object is where you create CLI, MCP, HTTP, React, JSON, docs, and packaging surfaces from the same action list. ## Action An action is one explicit app capability. It should represent something your product already knows how to do: - search records - create a task - export a report - inspect account state - trigger a controlled internal workflow An action is not a React component, route, prompt, or agent plan. ## Contract The action contract is the source of truth. It includes: - `name` - `description` - `input` - `output` - `sideEffects` - `permissions` - `supportedSurfaces` - `visibility` - `docs` Every surface should be generated from this contract instead of reimplementing business logic. ## Runtime The runtime executes actions consistently. It handles: - action lookup - surface checks - input validation - confirmation gates - permission checks - middleware - timeout and retry - logs, progress, and artifacts - output validation - structured success and failure envelopes ## Surface A surface is a way for a caller to use an action. Supported surfaces include CLI, HTTP, MCP, JSON runner, React invocation, local dev console, OpenAI-compatible tools, and AI SDK-style tools. Surfaces should stay thin. They translate their own input format into a runtime invocation and return the runtime result. ## Headless Entry React, Next.js, and Expo apps should keep UI files separate from the Ageniti entry used for CLI, MCP, HTTP, package, and publish artifacts. Recommended layout: ```text src/ageniti/app.js src/ageniti/actions/create-task.js src/ageniti/services/tasks.js ``` The headless entry should import services and actions, not React components or browser-only APIs. ## Skill Guide Ageniti can export one deterministic `GUIDE.md` from app and action docs fields. This guide is for agents, coding assistants, and automation systems that need to understand how to use the app safely. It is not model-generated. It is derived from the contract you wrote. ### Surfaces Path: /en/docs/surfaces # Surfaces Surfaces are the callable interfaces generated from an Ageniti app. Each surface should reuse the shared runtime instead of duplicating validation, authorization, logging, or output handling. ## CLI Use CLI when humans, scripts, CI jobs, or local operators need a command entry point. ```js await app.createCli().main(); ``` Generated action commands support flags, `--json`, `--schema`, stable JSON output, and confirmation for protected actions. ## MCP Use MCP when an MCP host should discover and call selected app capabilities. ```js const handleMcp = app.createMcpHandler(); ``` A bundled app can also generate a stdio launcher: ```text node ./dist/ageniti/mcp-stdio.mjs ``` Private and destructive actions are filtered from MCP discovery by default. ## HTTP Use HTTP when you want to put Ageniti behind your own server, API gateway, route handler, or internal platform. Default routes: - `GET /ageniti/actions` - `POST /ageniti/actions/:name/invoke` The HTTP handler returns the same structured runtime envelope as other surfaces. ## JSON Runner Use the JSON runner for tests, local scripts, automation, and deterministic invocation without a network server. ```js const result = await app.createJsonRunner().invoke({ action: "create_task", input: { title: "Review release" }, }); ``` ## React Invocation Use React invocation when an existing UI wants to call the same action as CLI or MCP. ```js const { useAction } = app.createReactAdapter(); const runCreateTask = useAction(createTask); ``` Ageniti does not replace your components, router, state management, or form library. ## OpenAI And AI SDK Tools Use tool adapters when an LLM stack needs function/tool schemas generated from action contracts. ```js const openaiTools = app.createOpenAITools(); const responsesTools = app.createOpenAIResponsesTools(); const aiSdkTools = app.createAISDKTools(); ``` LLM-oriented adapters filter private and destructive actions by default. ## Dev Console Use the dev console during integration to inspect action schemas and invoke actions locally. ```text task-app dev --port 4321 ``` The dev console is for local testing, not a hosted production UI. ## Choosing A Surface - Start with CLI when you want the fastest local proof. - Add MCP when an agent host needs tool discovery. - Add HTTP when your own backend should own transport and auth. - Add React invocation when existing UI should reuse the same action. - Add generated tool schemas when an LLM stack needs structured function definitions. ### Safety Model Path: /en/docs/safety # Safety Model Ageniti is built around explicit exposure. Your app chooses which capabilities become actions and which surfaces are allowed to call them. ## Visibility Use `visibility` to describe who should be able to discover or use an action. ```js defineAction({ name: "create_task", visibility: "public", // ... }); ``` Common meanings: - `private`: internal only - `local`: local development or operator usage - `agent`: suitable for agent/tool usage - `public`: safe for public manifests and docs Private actions are hidden from public tool surfaces by default. ## Supported Surfaces Use `supportedSurfaces` to explicitly limit where an action can run. ```js defineAction({ name: "export_report", supportedSurfaces: ["cli", "json", "dev"], // ... }); ``` If a runtime invocation arrives from an unsupported surface, it returns `UNSUPPORTED_SURFACE`. ## Side Effects Use `sideEffects` to communicate operational risk. - `read`: no external mutation - `write`: changes external state - `destructive`: deletes, overwrites, cancels, closes, or performs irreversible work Destructive actions require confirmation by default and are filtered from MCP and LLM adapters unless explicitly included. ## Permissions Permissions are declared on the action and enforced through the app-level `permissionChecker`. ```js createAgenitiApp({ actions, permissionChecker({ action, context }) { return action.permissions.every((permission) => context.auth?.permissions?.includes(permission) ) || "Missing required permission."; }, }); ``` Ageniti does not replace your auth system. It gives your app a consistent hook for applying it across surfaces. ## Public Metadata Use `publicMetadata` for data that can safely appear in manifests, MCP tools, and LLM tool schemas. Use `metadata` for internal app-only fields. ## Confirmation Set `requiresConfirmation: true` when an action should not run without an explicit confirmation flag. Destructive actions inherit this behavior by default. ## Practical Checklist - Keep actions narrow and named clearly. - Prefer structured output over prose-only strings. - Mark write and destructive operations honestly. - Limit high-risk actions with `supportedSurfaces`. - Use `permissions` plus `permissionChecker` for real authorization. - Put safe usage guidance in `description` and `docs`. - Review generated manifests before publishing. ### Runtime Semantics Path: /en/docs/runtime # Runtime Semantics Ageniti keeps the important behaviour in the runtime so that CLI, HTTP, MCP, React, JSON automation, dev tools, and LLM adapters all share one execution model. ## Execution Flow When you invoke an action, the runtime performs these steps: 1. Resolve the action by name or object reference. 2. Check whether the action supports the requested surface. 3. Validate input against the action input schema. 4. Enforce confirmation for protected actions. 5. Run the permission checker. 6. Execute middleware. 7. Run the action with timeout and retry handling. 8. Ensure the output can be serialised as JSON. 9. Validate output against the output schema, if present. 10. Return a structured success or failure envelope. ## Surface Rules Supported surfaces are declared on each action through `supportedSurfaces`. Default supported surfaces: ```text cli, json, http, mcp, react, dev, ai-sdk ``` If a surface is not supported, the runtime returns `UNSUPPORTED_SURFACE`. ## Confirmation Rules Actions with `requiresConfirmation: true` require an explicit confirmation flag. By default, destructive actions inherit confirmation automatically. Runtime confirmation is enforced for most surfaces, but not for: - `react` - `dev` That means UI surfaces should handle confirmation in the UI layer before invoking the action. ## Permission Checks `permissionChecker({ action, input, context })` must return either: - `true` to allow execution - `false` to deny execution with a generic authorisation message - a string to deny execution with a custom message If the check fails, the runtime returns `AUTHORIZATION_ERROR`. ## Timeout And Retry Timeout is controlled by: - action-level `timeoutMs` - per-invocation `timeoutMs` Retry is controlled by: - action-level `retry` - per-invocation `retry` Retry only happens when the thrown error is retryable. That usually means the action throws an `AgenitiError` with `retryable: true`, or the timeout logic marks the failure as retryable. `retry: true` normalises to: ```json { "retries": 2, "delayMs": 100 } ``` Retries use linear backoff based on attempt count. ## Logging, Progress, And Artifacts Every invocation accumulates structured logs and artifacts. From `context.logger`: - `debug(message, fields?)` - `info(message, fields?)` - `warn(message, fields?)` - `error(message, fields?)` From `context.progress.report()`: - records a log entry with `fields.type = "progress"` - may include `percent` - may include additional structured fields From `context.artifacts.add()`: - normalises missing `id` - defaults `type` to `"file"` - stores `metadata` as an object ## Success Envelope ```json { "ok": true, "data": {}, "artifacts": [], "logs": [], "meta": { "action": "create_task", "invocationId": "invocation-id", "surface": "cli", "durationMs": 12 } } ``` ## Failure Envelope ```json { "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 } } ``` ## Common Runtime Error Codes Core runtime codes: - `ACTION_NOT_FOUND` - `UNSUPPORTED_SURFACE` - `VALIDATION_ERROR` - `CONFIRMATION_REQUIRED` - `AUTHORIZATION_ERROR` - `OUTPUT_SERIALIZATION_ERROR` - `OUTPUT_VALIDATION_ERROR` - `TIMEOUT` - `CANCELLED` - `INTERNAL_ERROR` Wrapper-specific codes you may also see: - `INVALID_JSON_RUNNER_PAYLOAD` - `DEV_SERVER_ERROR` - `NOT_FOUND` from the local dev server HTTP routes ## How Errors Are Normalised If an action throws: - `AgenitiError`, its `code`, `message`, `issues`, and `retryable` fields are preserved - `AbortError`, the runtime returns `CANCELLED` - any other error, the runtime returns `INTERNAL_ERROR` ## CLI Exit Codes The built-in CLI maps runtime errors to process exit codes. Important mappings: - `VALIDATION_ERROR` -> `2` - `AUTHENTICATION_ERROR` -> `3` - `AUTHORIZATION_ERROR` -> `3` - `ACTION_NOT_FOUND` -> `4` - `EXTERNAL_SERVICE_ERROR` -> `5` - `TIMEOUT` -> `124` - `CANCELLED` -> `130` - anything else -> `1` ## Output Guarantees Ageniti only returns values that can be serialised safely as JSON. If an output schema exists, the runtime validates the action result against it before returning success. This makes the result envelope suitable for CLI output, MCP structured content, tests, and machine-to-machine integrations. ### Skill Guide Path: /en/docs/skill Description: A compact reference for the skills an Ageniti app exposes to agents, coding assistants, and automation systems. # Skill Guide This page describes how an Ageniti app exposes its skills to agents, coding assistants, and automation systems. The docs site also exposes `/llms.txt`, which includes this page in a plain-text bundle for machine readers. ## What Ageniti Is Ageniti is an SDK for building apps that agents can use. It lets a React or TypeScript app expose selected capabilities as structured actions that can be called through CLI, HTTP, MCP, OpenAI-compatible tools, Vercel AI SDK-style tools, JSON automation, a local dev console, and React invocation. Ageniti does not create an agent. It makes an app callable by agents. ## Core Mental Model ```text Existing app capability | v Ageniti action contract | v Shared runtime | +--> CLI +--> HTTP +--> MCP +--> OpenAI tools +--> AI SDK tools +--> JSON runner +--> Dev console +--> React invocation ``` The action contract is the source of truth. Every external surface should go through the shared runtime so validation, permissions, confirmation, timeout, retry, middleware, logging, artifacts, and output validation behave consistently. ## Canonical Import ```js import { createAgenitiApp, defineAction, s } from "@ageniti/core"; ``` Use subpath imports only when the host needs a narrower boundary: ```js import { createMcpHandler } from "@ageniti/core/mcp"; import { createHttpHandler } from "@ageniti/core/http"; import { createAISDKTools, createOpenAITools } from "@ageniti/core/ai-sdk"; ``` ## Minimal Action Pattern ```js import { createAgenitiApp, defineAction, s } from "@ageniti/core"; export const createTask = defineAction({ name: "create_task", version: "1.0.0", 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"), priority: s.enum(["low", "normal", "high"]).default("normal"), }), output: s.object({ taskId: s.string(), status: s.string(), }), async run(input, ctx) { return ctx.services.tasks.create(input); }, }); export const app = createAgenitiApp({ name: "task-app", description: "Workspace task operations exposed to agents.", actions: [createTask], services: { tasks, }, }); ``` ## Recommended React And Expo Shape For React, Next.js, Expo, or any app with UI code, keep Ageniti in a headless Node-safe entry: ```text src/ageniti/app.js src/ageniti/actions/create-task.js src/ageniti/services/tasks.js ``` Do not import React components, browser-only APIs, route handlers, or mobile runtime code from the Ageniti entry used for CLI, MCP, HTTP, package, or publish artifacts. Put reusable business logic in services and call those services from actions. ## Surfaces - `app.createCli()` creates a CLI with action commands, schemas, manifests, docs, build, package, publish, init, doctor, lint, MCP, and dev commands. - `app.createHttpHandler()` creates a lightweight HTTP JSON handler that invokes actions through the shared runtime. - `app.createMcpHandler()` creates an MCP JSON-RPC handler for `tools/list` and `tools/call`. - `app.createOpenAITools()` creates OpenAI Chat Completions-style tool definitions. - `app.createOpenAIResponsesTools()` creates OpenAI Responses-style function tool definitions. - `app.createAISDKTools()` creates Vercel AI SDK-style executable tools. - `app.createJsonRunner()` creates a structured runner for scripts, tests, and automation. - `app.createDevServer()` starts a local action inspection and testing console. - `app.createReactAdapter()` creates a React-friendly action invocation adapter for existing UI code. ## Safety Rules For Agents - Call actions through the runtime or through app-created adapters. Do not call `action.run()` directly. - Respect `visibility`, `supportedSurfaces`, `sideEffects`, `requiresConfirmation`, `permissions`, `version`, `deprecated`, and `deprecation`. - Private actions are not public API. Do not expose or invoke them from external agent surfaces. - Destructive actions require confirmation by default and are filtered from LLM-oriented surfaces unless explicitly allowed. - Put secrets, internal identifiers, and non-public implementation notes in `metadata`, not `publicMetadata`. - Put agent-facing instructions in `description`, `docs`, and `publicMetadata`. - Treat `GUIDE.md`, manifests, schemas, and action metadata as the public contract. ## Documentation Export Ageniti can export one deterministic guide from app-level and action-level natural-language fields. It does not call a model and does not infer hidden behavior from UI code. Useful fields: - app `description` - app `docs.summary` - app `docs.audience` - app `docs.whenToUse` - app `docs.setup` - app `docs.operationalNotes` - action `description` - action `docs.whenToUse` - action `docs.whenNotToUse` - action `docs.usageNotes` - action `docs.inputExample` - action `docs.outputExample` - action `publicMetadata` Export commands: ```text 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 ``` The output file is `GUIDE.md`. A bundle includes it automatically. ## Build And Package ```text npx @ageniti/core init react npx @ageniti/core init expo npx @ageniti/core init next npx @ageniti/core doctor task-app build task-app build bundle --app-module ./src/ageniti/app.js --app-export app --out-dir ./dist/ageniti task-app package --app-module ./src/ageniti/app.js --app-export app --out-dir ./dist/ageniti task-app publish --app-module ./src/ageniti/app.js --app-export app --out-dir ./dist/ageniti ``` `bundle` produces: - `ageniti.manifest.json` - `ageniti.actions.json` - `ageniti.mcp.json` - `cli.mjs` - `mcp-stdio.mjs` - `GUIDE.md` - `package.json` - `README.md` - `ageniti.bundle.json` The generated npm package is an app distribution package containing runnable CLI and MCP launchers plus manifests and documentation. ## Do Not - Do not describe Ageniti as an agent framework. - Do not make Ageniti own planning, memory, workflow orchestration, routing, or UI state. - Do not scan arbitrary React components and expose them as tools automatically. - Do not bypass runtime validation and permissions. - Do not put secrets in generated docs, public metadata, manifests, or examples. - Do not expose hidden actions just because a caller guessed the action name. ## Useful Files - `README.md`: human overview. - `docs/getting-started.md`: first working integration. - `docs/api.md`: public API reference. - `docs/scope.md`: explicit product boundary. - `docs/release-checklist.md`: publish checklist. - `docs/skill.md`: skill-facing SDK guide included in the npm package. ### Packaging Path: /en/docs/packaging # Packaging Ageniti can turn one app definition into distributable artifacts for CLI, MCP, manifests, and skill documentation. ## What Gets Built The bundle target writes: ```text ageniti.manifest.json ageniti.actions.json ageniti.mcp.json cli.mjs mcp-stdio.mjs GUIDE.md package.json README.md ageniti.bundle.json ``` These files describe the app, expose runnable launchers, and package the app for installation or review. ## Required App Module Launcher targets need a Node-safe module that exports your Ageniti app. ```text src/ageniti/app.js ``` Avoid importing React components, browser-only APIs, route files, or mobile runtime code from this entry. ## Build ```text task-app build bundle --app-module ./src/ageniti/app.js --app-export app --out-dir ./dist/ageniti ``` If your project has an `ageniti.config.json`, build commands can read defaults from it. ## Package ```text task-app package --app-module ./src/ageniti/app.js --app-export app --out-dir ./dist/ageniti ``` This builds the bundle and runs `npm pack` inside the generated output directory. ## Publish ```text task-app publish --app-module ./src/ageniti/app.js --app-export app --out-dir ./dist/ageniti ``` `publish` defaults to a dry run. Use `--live` only when you intentionally want a real npm publish. ```text task-app publish --live --access public --tag latest --app-module ./src/ageniti/app.js --app-export app --out-dir ./dist/ageniti ``` ## MCP Descriptor `ageniti.mcp.json` includes command metadata and snippets for common MCP host configuration. The generated stdio command points at: ```text node ./mcp-stdio.mjs ``` ## Skill Documentation `GUIDE.md` is generated from app and action metadata. It gives agents, coding assistants, and automation systems a compact usage guide for the capabilities exposed by the app. ## Release Review Before publishing a new bundle: - inspect `ageniti.manifest.json` - inspect `ageniti.actions.json` - inspect `ageniti.mcp.json` - run the generated `cli.mjs` - run the generated `mcp-stdio.mjs` with an MCP host - compare old and new manifests with `task-app diff` ### Entry Points Path: /en/docs/entry-points # Entry Points `@ageniti/core` ships a root export plus narrower subpath exports. ## Recommended Default Most applications should start with the root package: ```js import { createAgenitiApp, defineAction, s } from "@ageniti/core"; ``` That keeps usage simple and matches the examples in the documentation. ## Available Exports ### Root Export ```text @ageniti/core ``` Use the root export when you want the main authoring API in one place. The root export is also where the higher-level packaging and project helpers live, including: - `buildArtifacts()` - `packageArtifacts()` - `publishArtifacts()` - `initProject()` - `doctorProject()` - `findDefaultAppModule()` - `loadProjectConfig()` - `detectTypeScriptRuntime()` ### Subpath Exports ```text @ageniti/core/ai-sdk @ageniti/core/adapters @ageniti/core/app @ageniti/core/cli @ageniti/core/core @ageniti/core/dev @ageniti/core/http @ageniti/core/json-runner @ageniti/core/lint @ageniti/core/manifest @ageniti/core/mcp @ageniti/core/react @ageniti/core/schema ``` ## What Each Subpath Contains - `@ageniti/core/ai-sdk`: OpenAI-compatible tools, Responses tools, AI SDK tools, and combined manifests. - `@ageniti/core/adapters`: built-in surface adapters plus adapter helpers. - `@ageniti/core/app`: `createAgenitiApp()`. - `@ageniti/core/cli`: `createCli()`. - `@ageniti/core/core`: runtime and action primitives such as `defineAction()` and `createRuntime()`. - `@ageniti/core/dev`: `createDevServer()`. - `@ageniti/core/http`: `createHttpHandler()` and `createHttpServer()`. - `@ageniti/core/json-runner`: `createJsonRunner()`. - `@ageniti/core/lint`: `lintActions()`. - `@ageniti/core/manifest`: manifest helpers such as `describeAction()`, `createSurfaceManifest()`, and `diffActionManifests()`. - `@ageniti/core/mcp`: MCP manifest, handler, and stdio server helpers. - `@ageniti/core/react`: `createReactActionAdapter()`. - `@ageniti/core/schema`: `s`, `toJSONSchema()`, and `SchemaValidationError`. ## Example Import Patterns Authoring app actions: ```js import { defineAction, s } from "@ageniti/core"; ``` Building only an MCP server wrapper: ```js import { createMcpHandler } from "@ageniti/core/mcp"; ``` Running a validation or tooling step: ```js import { lintActions } from "@ageniti/core/lint"; ``` Generating AI tool definitions without pulling the app helper: ```js import { createAISDKTools, createOpenAITools } from "@ageniti/core/ai-sdk"; ``` ## When To Prefer Subpaths Prefer a subpath when: - you are building a narrowly scoped integration layer - you want imports to reflect architectural boundaries - you are exposing only one surface from a package or service - you are writing tooling around manifests, linting, or schema conversion Prefer the root export when: - you are writing the main application integration - you want the shortest onboarding path - you do not need explicit module-level separation - you need build helpers or project setup helpers that do not have dedicated subpath exports ## Type Declarations All public entry points share the same generated type declarations. The runtime contracts, result envelopes, action metadata, and schema types are consistent across the package exports. ### API Reference Path: /en/docs/api # API Reference This page documents the public SDK surface exported by `@ageniti/core`. ## Top-Level Import For most applications, start with the root export: ```js import { createAgenitiApp, createRuntime, defineAction, s, } from "@ageniti/core"; ``` Use subpath exports only when you want a narrower import boundary. See [Entry Points](/en/docs/entry-points). ## `defineAction(config)` Defines a typed action contract. Required fields: - `name`: lowercase snake_case action name - `description`: human-readable action description - `run(input, context)`: action implementation Optional fields: - `version` - `title` - `input` - `output` - `visibility` - `sideEffects` - `idempotency` - `permissions` - `supportedSurfaces` - `timeoutMs` - `retry` - `requiresConfirmation` - `metadata` - `publicMetadata` - `docs` - `deprecated` - `deprecation` Metadata model: - `metadata`: internal metadata kept in manifests and available at runtime through `context.metadata` - `publicMetadata`: safe-to-expose metadata copied into public manifests, MCP tool metadata, and LLM tool adapters Docs model: - `docs`: natural-language guidance used to generate a unified `GUIDE.md` - app-level `docs` supports `summary`, `audience`, `whenToUse`, `quickStart`, `setup`, `operationalNotes`, `sections`, and `examples` - action-level `docs` supports `whenToUse`, `whenNotToUse`, `usageNotes`, `inputExample`, and `outputExample` - `GUIDE.md` is deterministic output; it does not call a model or infer behaviour from UI code Versioning model: - `version`: action contract version, default `1.0.0` - `deprecated`: marks an action as deprecated without removing it - `deprecation`: optional message, replacement, and timeline metadata Important defaults: - `title`: derived from `name` - `input`: `s.object({})` - `visibility`: `"local"` - `sideEffects`: `"read"` - `idempotency`: `"unspecified"` - `permissions`: `[]` - `supportedSurfaces`: `cli`, `json`, `http`, `mcp`, `react`, `dev`, `ai-sdk` - `retry`: normalised to `{ retries, delayMs }` - `requiresConfirmation`: `true` for destructive actions unless overridden Example: ```js 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)` Creates an app object that owns actions, runtime, and surface helpers. ```js const app = createAgenitiApp({ name: "task-app", description: "Workspace task operations for agents.", docs: { summary: "Use this app to create tasks and inspect status.", }, actions, services, permissionChecker, middleware, adapters, build, }); ``` Options: - `name`: required app name - `actions`: array of Ageniti actions - `services`: shared services injected into `context.services` - `permissionChecker`: authorisation hook - `middleware`: runtime middleware chain - `adapters`: custom surface adapter list for manifest generation - `build`: default build settings reused by `app.build()` and CLI build commands Returned members: - `name` - `actions` - `adapters` - `runtime` - `manifest()` - `actionManifest()` - `lint()` - `build()` - `createGuideDoc()` - `exportDocs()` - `createCli()` - `createJsonRunner()` - `createHttpHandler()` - `createHttpServer()` - `createMcpHandler()` - `createMcpManifest()` - `createOpenAITools()` - `createOpenAIResponsesTools()` - `createAISDKTools()` - `createFunctionCallingManifest()` - `createReactAdapter()` - `createDevServer()` Use `createAgenitiApp()` when you want one app definition and convenient access to every supported surface. ## `createRuntime(options)` Creates the headless runtime used by all app capability surfaces. Options: - `actions` - `services` - `permissionChecker` - `middleware` Returned API: - `registry`: `Map` - `listActions({ surface? })` - `invoke(actionOrName, input?, invokeOptions?)` `invokeOptions` supports: - `invocationId` - `surface` - `user` - `auth` - `env` - `services` - `metadata` - `signal` - `timeoutMs` - `retry` - `confirm` The runtime is responsible for: - action lookup - supported surface checks - input validation - confirmation checks - permission checks - middleware execution - timeout and retry - output serialisation and output validation - success and failure envelopes Read [Runtime Semantics](/en/docs/runtime) for the full execution model. ## Manifest And Registry Helpers ### `createActionRegistry(actions)` Builds a `Map` keyed by action name and throws on duplicates. ### `createActionManifest(actions)` Returns a plain array describing actions with schemas and metadata. This helper is useful for inspection, tooling, tests, or custom wrappers. ### `describeAction(action)` Normalises a single action into a manifest-friendly object. ### `createSurfaceManifest({ appName, actions, adapters })` Returns a manifest object with: - app name - generation timestamp - action descriptions - surface descriptions and capabilities ## CLI API ### `createCli(options)` Creates a CLI object. ```js const cli = createCli({ name: "task-app", actions, runtime, runtimeOptions, env, adapters, buildOptions, }); ``` Returned members: - `name` - `actions` - `runtime` - `run(argv?, io?)` - `main(argv?, io?)` Built-in commands: ```text [options] --json '{"field":"value"}' --schema actions manifest diff --previous old.json --next new.json build [manifest|cli|mcp|docs|bundle] [options] docs [options] package [options] publish [options] init [options] doctor [options] lint mcp mcp --stdio dev --port 4321 ``` Input behaviour: - snake_case actions can also be called as kebab-case commands - boolean flags accept `--flag`, `--flag true`, or `--no-flag` - array, object, and `any` inputs are parsed from JSON strings - runtime confirmation maps to `--confirm` Build command options: - `--out-dir ` - `--app-module ` - `--app-export ` - `--package-json` - `--cwd ` - `--filename ` for `docs` Launcher targets need a Node-safe app module so the generated files know what to import. If `--app-module` is omitted, Ageniti tries to discover a default entry such as `./src/ageniti/app.js`. ## JSON Runner API ### `createJsonRunner(options)` Creates a small structured invocation wrapper. ```js const runner = createJsonRunner({ actions, runtime, runtimeOptions }); ``` Returned API: - `runtime` - `invoke(payload)` Payload fields: - `action` - `input` - `confirm` - `user` - `auth` - `metadata` If the payload is not an object, the runner returns `INVALID_JSON_RUNNER_PAYLOAD`. ## MCP API ### `createMcpManifest(actions, options)` Returns: ```js { tools: [ { name, title, description, inputSchema, metadata, }, ], } ``` Filtering rules: - action must support the `mcp` surface - private actions are excluded unless `includePrivate: true` - destructive actions are excluded unless `includeDestructive: true` ### `createMcpHandler(options)` Creates a JSON-RPC handler for `tools/list` and `tools/call`. ```js const handle = createMcpHandler({ actions, runtime, runtimeOptions, includePrivate, includeDestructive, }); ``` `tools/call` returns both a text block and `structuredContent` containing the runtime result. ### `createMcpStdioServer(options)` Creates a line-delimited stdio transport around `createMcpHandler()`. ```js await createMcpStdioServer({ actions, runtime }).start(); ``` Use this when another process expects one JSON-RPC message per line over stdin and stdout. ## LLM Tool Adapters ### `createOpenAITools(actions, options)` Returns Chat Completions-style function tools. ### `createOpenAIResponsesTools(actions, options)` Returns Responses-style function tools. ### `createAISDKTools(actions, options)` Returns a Vercel AI SDK-style tools object. ```js const tools = createAISDKTools(actions, { runtime, returnEnvelope: true, }); ``` Each tool contains: - `description` - `parameters`: Ageniti schema object - `inputSchema`: JSON Schema representation - `execute(input, options?)` ### `createFunctionCallingManifest(actions, options)` Returns a combined summary: - `openaiChatTools` - `openaiResponsesTools` - `aiSdkTools` as action names Shared adapter options: - `runtime` - `strict` - `includePrivate` - `includeDestructive` - `surface` - `returnEnvelope` - `filter` Filtering rules: - action must support the selected surface, default `ai-sdk` - private actions are excluded unless `includePrivate: true` - destructive actions are excluded unless `includeDestructive: true` - `filter(action)` can apply additional filtering ## React API ### `createReactActionAdapter(options)` Creates a React-friendly wrapper over the shared runtime. ```js const { runtime, useAction } = createReactActionAdapter({ actions, runtime }); ``` `useAction(action)` returns an async function that invokes the action with `surface: "react"`. ## Dev Server API ### `createDevServer(options)` Creates the local dev console server. ```js const devServer = createDevServer({ name: "task-app", actions, runtime, }); const listener = await devServer.listen(4321, "127.0.0.1"); ``` Routes: - `GET /`: HTML dev console - `GET /api/actions`: action manifest for the dev surface - `POST /api/actions/:name/invoke`: invoke one action ## HTTP API ### `app.createHttpHandler(options)` Creates a framework-friendly HTTP JSON handler. ```js 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", }, }, }); ``` Routes: - `GET /ageniti/actions` - `POST /ageniti/actions/:name/invoke` ### `app.createHttpServer(options)` Creates a small Node HTTP server around the same handler. ```js const server = app.createHttpServer(); const listener = await server.listen(4322); ``` HTTP actions must support the `http` surface. Private and destructive actions are filtered out by default. ## Build API ### `app.build(options)` Builds official Ageniti distribution artifacts from an app object. ```js await app.build({ targets: ["bundle"], appModule: "./src/ageniti/app.js", appExport: "app", outDir: "./dist/ageniti", }); ``` Common options: - `targets`: `manifest`, `cli`, `mcp`, `docs`, or `bundle` - `outDir`: output directory, default `dist/ageniti` - `appModule`: headless Node-safe module that exports your app - `appExport`: export name, default `app` - `includePackageJson`: force a generated `package.json` - `cwd`: working directory used for path resolution - `filename`: custom file name for `docs`, default `GUIDE.md` `bundle` expands to: - `ageniti.manifest.json` - `ageniti.actions.json` - `cli.mjs` - `mcp-stdio.mjs` - `ageniti.mcp.json` - `GUIDE.md` - `package.json` - `README.md` - `ageniti.bundle.json` ### `app.createGuideDoc(options)` Returns one Markdown guide string. ```js const markdown = app.createGuideDoc(); ``` It reads the app `description` / `docs`, plus each action's `description`, permissions, side effects, surfaces, `publicMetadata`, and `docs`. ### `app.exportDocs(options)` Writes a unified guide document to disk. ```js await app.exportDocs({ outDir: "./dist/ageniti", }); ``` Default output: - `GUIDE.md` The same capability is available through the CLI: ```text task-app docs task-app docs --out-dir ./dist/ageniti task-app build docs --out-dir ./dist/ageniti ``` ### `app.package(options)` Builds a bundle and then runs `npm pack` in the generated output directory. ```js const result = await app.package({ appModule: "./src/ageniti/app.js", outDir: "./dist/ageniti", }); ``` The result includes: - `outDir` - `packageDir` - `packageFile` - `build` ### `app.publish(options)` Builds a bundle, runs `npm pack`, and then runs `npm publish`. ```js const result = await app.publish({ appModule: "./src/ageniti/app.js", outDir: "./dist/ageniti", dryRun: true, access: "public", }); ``` Important defaults: - `dryRun` defaults to `true` - pass `dryRun: false` only for a real publish The returned result includes: - `ok` - `name` - `outDir` - `targets` - `files` - `report` ### `buildArtifacts(options)` Lower-level build helper used by `app.build()`. ## Manifest Diff ### `diffActionManifests(previous, next)` Compares two action manifests or surface manifests and reports breaking changes, warnings, and informational changes. ```js const diff = diffActionManifests(previousManifest, nextManifest); ``` Breaking changes include removed actions and input/output schema changes. ```js const result = await buildArtifacts({ appName: "task-app", actions, adapters, targets: ["bundle"], appModule: "./src/ageniti/app.js", appExport: "app", }); ``` Use this helper when you want to build launchers or manifests without first constructing an app object. ## Project Tools ### `initProject(options)` Scaffolds a React- or Expo-friendly headless Ageniti entry. ```js const result = await initProject({ cwd: process.cwd(), template: "react", }); ``` The result includes: - `ok` - `template` - `cwd` - `files` - `appModule` - `nextSteps` ### `doctorProject(options)` Inspects a project for framework type, default Ageniti entry discovery, and common launcher or build issues. ```js const result = await doctorProject({ cwd: process.cwd() }); ``` The result includes: - `ok` - `kind` - `cwd` - `defaultAppModule` - `checks` - `recommendations` ### `findDefaultAppModule(options)` Finds the default Node-safe Ageniti app entry used by zero-config build flows. ```js const result = await findDefaultAppModule({ cwd: process.cwd() }); ``` Possible outcomes include: - `found: true` with `modulePath` and reason `node-safe-default` - `found: true` with `modulePath` and reason `configured` - `found: false` with reason `typescript-only-entry` - `found: false` with reason `missing` ### `loadProjectConfig(options)` Loads `ageniti.config.json`, `ageniti.config.js`, `ageniti.config.mjs`, or `ageniti.config.cjs` from a project root. ```js const config = await loadProjectConfig({ cwd: process.cwd() }); ``` Returned fields may include: - `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)` Detects whether the current project is configured to generate TypeScript launchers. ```js const runtime = detectTypeScriptRuntime({ packageJson, config }); ``` Current built-in support: - returns `tsx` when `tsx` is configured or installed - returns `undefined` when no supported TypeScript runtime is available ## Surface Adapter API ### `defineSurfaceAdapter(adapter)` Creates a custom adapter description. Required field: - `name` Defaulted fields: - `description: ""` - `capabilities: {}` - `canExpose: () => true` - `describe: (action) => action` ### Built-In Adapters - `cliAdapter` - `jsonAdapter` - `mcpAdapter` - `reactAdapter` - `devAdapter` - `aiSdkAdapter` ### `defaultSurfaceAdapters()` Returns the built-in adapter list used by `createAgenitiApp()` and `createCli()`. ### `findAdapter(adapters, name)` Finds one adapter by name. ## Lint API ### `lintActions(actions)` Runs static checks against action definitions. Current findings include: - duplicate action names - invalid action naming - weak descriptions - destructive MCP exposure - unspecified idempotency on write or destructive actions - non-object input shapes - write or destructive actions without permissions ## Schema API ### `s` Lightweight schema builder. Available builders: - `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()` Common modifiers: - `.describe(text)` - `.default(value)` - `.optional()` - `.nullable()` - `.meta(data)` Type-specific helpers: - string: `.min()`, `.max()`, `.pattern()`, `.url()`, `.datetime()` - number: `.min()`, `.max()`, `.int()` - object: `.passthrough()` ### `toJSONSchema(schema)` Converts an Ageniti schema into JSON Schema. ### `SchemaValidationError` Thrown by schema parsing paths when validation fails. ## Error And Result Types ### `AgenitiError` Custom runtime error with: - `code` - `issues` - `retryable` ### Runtime Result Shape Success: ```json { "ok": true, "data": {}, "artifacts": [], "logs": [], "meta": { "action": "create_task", "invocationId": "invocation-id", "surface": "cli", "durationMs": 12 } } ``` Failure: ```json { "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 } } ``` ### Recipes Path: /en/docs/recipes # Recipes This page collects practical integration patterns built on top of the public Ageniti API. ## CLI-First Internal Tool Use this pattern when the main interface is a terminal command for operators or scripts. ```js 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(); ``` Why this works well: - one command entry point - JSON schema for arguments - structured results for shell wrappers and tests ## Existing React App Button Use this pattern when the app already has UI handlers and you want to reuse the same business capability for agent-facing flows. ```js const { useAction } = app.createReactAdapter(); const runSearchTasks = useAction(searchTasks); async function onClick() { const result = await runSearchTasks({ status: "open" }); if (result.ok) { setTasks(result.data.items); } } ``` Recommended practice: - keep confirmation UX in the UI - keep permission context in `invokeOptions` - reuse the same action in non-UI surfaces later ## JSON Runner For Automation Use this pattern for scripts, queues, cron jobs, or test harnesses. ```js const runner = app.createJsonRunner(); const result = await runner.invoke({ action: "search_tasks", input: { status: "open" }, metadata: { source: "nightly-job" }, }); ``` This is often the simplest way to wrap Ageniti behind your own transport. Repository example: - `ageniti/examples/task-app.js` ## MCP Tools For Agent Platforms Use this when a host system already speaks MCP-style JSON-RPC. ```js 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" }, }, }); ``` If the host expects stdio instead of an in-process handler, use: ```js await app.createCli().run(["mcp", "--stdio"]); ``` Repository example: - `ageniti/examples/mcp-host.js` ## OpenAI And AI SDK Tool Adapters Use this when your host application already knows how to call tools through OpenAI-compatible schemas or AI SDK tool objects. ```js const openaiTools = app.createOpenAITools(); const responsesTools = app.createOpenAIResponsesTools(); const aiSdkTools = app.createAISDKTools({ returnEnvelope: true }); ``` Recommendations: - keep destructive actions excluded by default - add explicit filters for high-risk tools - use `returnEnvelope: true` when the caller needs logs or artifacts ## OpenAI Responses Host Use this pattern when your host app is already calling the OpenAI Responses API and only needs a stable tool set from the app SDK. ```js 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, }); ``` Why this matters: - the host owns model choice and prompting - Ageniti owns app capability contracts - tool schemas stay aligned with the runtime Repository example: - `ageniti/examples/openai-responses-host.js` ## Vercel AI SDK Route Handler Use this when a Next.js or server-side host already uses the AI SDK and you want executable tools backed by the shared runtime. ```js 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, }); ``` Recommended practice: - keep app auth outside the model call and inject it through runtime options - return envelopes when the host needs logs or artifacts - keep risky tools filtered unless the host is trusted Repository example: - `ageniti/examples/ai-sdk-route.js` ## HTTP Gateway Wrapper Use this when your own backend should own transport, auth, and deployment, while Ageniti stays focused on action execution. ```js 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"], }, }, }); ``` Recommended practice: - keep caller identity and authorization in the gateway layer - pass only the app-specific permission context into Ageniti - keep the HTTP payload close to the runtime envelope for debugging Repository example: - `ageniti/examples/http-gateway.js` ## Restricting Surface Exposure Use action metadata to keep high-risk operations off agent-facing surfaces. ```js 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); }, }); ``` This keeps the action available for trusted operator paths while excluding it from MCP and LLM tool exposure. ## Manifest And Lint In CI Use this pattern to keep the contract observable during release checks. ```js const manifest = app.manifest(); const lint = app.lint(); if (!lint.ok) { process.exitCode = 1; } ``` You can snapshot the manifest in tests, or publish it as an internal contract artifact for tooling teams. ### SDK Readiness Path: /en/docs/sdk-readiness # SDK Readiness Use this page when you are evaluating whether Ageniti is mature enough as an SDK for building apps that agents can use. This is not a checklist for autonomous agent orchestration. It is a checklist for an app-facing SDK that must expose product capabilities safely and predictably to external hosts. ## What "ready enough" means For Ageniti, "ready enough" does not mean: - it owns planning loops - it ships long-term memory - it routes between models - it becomes an agent runtime It does mean: - developers can expose one real app capability without restructuring the whole app - hosts can discover and call that capability through standard surfaces - operators can review the contract before release - risky actions can be filtered, confirmed, or denied consistently - every surface returns the same execution semantics If those properties are strong, the SDK is doing its job. ## Release Bar For An Agent-App SDK These are the capabilities that should feel solid before you call the SDK broadly usable. ### 1. Stable action contract The SDK should make app capabilities explicit and reviewable. Minimum bar: - typed input schema - typed output schema - stable action names - side effect metadata - visibility controls - natural-language documentation for hosts and operators In Ageniti, this is the role of `defineAction()`, action metadata, and exported manifests. ### 2. Shared runtime semantics Every surface should execute through the same runtime rules. Minimum bar: - input validation - output validation - timeout handling - retry support - permission checks - confirmation for risky actions - structured logs, progress, and artifacts - stable success and failure envelopes Without this layer, each adapter becomes its own behavior fork. ### 3. Standard host surfaces An SDK for apps that agents use needs enough surfaces to meet hosts where they already are. Current high-value surfaces are: - CLI for operators, scripts, and CI - MCP for tool discovery - HTTP for internal gateways - OpenAI-compatible tools - OpenAI Responses tools - AI SDK executable tools - JSON runner for tests and automation The key question is not "how many surfaces exist?" but "do they all preserve the same contract?" ### 4. Safety defaults If an app SDK exposes product capabilities to external callers, safety defaults matter more than feature count. Minimum bar: - destructive actions require confirmation by default - private actions stay off public surfaces - high-risk actions can be restricted to trusted surfaces - auth hooks can reuse the host app's authorization model - public metadata stays separate from internal metadata This is part of product credibility, not only security. ### 5. Package and artifact model The SDK should generate artifacts that downstream teams can actually install, inspect, and review. Minimum bar: - CLI launcher - MCP stdio launcher - action manifest - surface manifest - deterministic guide or contract docs - bundle metadata for release review If shipping requires custom glue every time, the SDK is still too thin. ## What To Improve Next If the core runtime and surfaces already exist, the next gains usually come from adoption quality rather than more framework breadth. ### Host integration examples The SDK should show real host-facing examples, not only primitive API snippets. Highest-value examples: - OpenAI Responses API host - Vercel AI SDK route handler - MCP desktop host setup - internal HTTP gateway wrapper These examples help developers answer "how do I plug this into my stack this week?" ### Contract maintenance workflow The SDK should help teams evolve app capabilities without accidental breakage. High-value additions: - manifest diff in CI - compatibility notes on renamed or deprecated actions - examples of versioned action rollout - release review guidance for risky contract changes ### Operator-facing debugging Teams adopting an app SDK need to diagnose failures quickly. High-value additions: - clearer error taxonomy - invocation replay examples - artifact inspection guidance - examples of logging and progress conventions - doctor checks for common integration mistakes ### Better positioning docs Many SDKs get misunderstood because they are compared against agent frameworks. The docs should make these distinctions obvious: - app SDK versus agent framework - app capability versus agent skill - host integration versus orchestration - product boundary versus workflow engine When the positioning is sharp, the right users self-select faster. ## A Simple Maturity Test If a new team can do all of the following in one afternoon, the SDK is in good shape: 1. Wrap one existing product capability as an action. 2. Run it through CLI locally. 3. Expose it through MCP or tool calling. 4. Restrict one risky action from public surfaces. 5. Export a reviewable guide and manifest. 6. Understand failures without reading SDK internals. If any of those steps still feel fragile, that points to the next documentation or product gap to fix. ## Bottom Line Ageniti does not need to grow into an agent framework to become stronger. It becomes stronger by making app capability exposure: - clearer to adopt - safer by default - easier to review - easier to package - easier to integrate into real hosts That is the standard to optimize for. ### Roadmap Path: /en/docs/roadmap # Roadmap This roadmap assumes Ageniti is already positioned as an SDK for building apps that agents can use. The goal is not to add agent orchestration. The goal is to make adoption, release, and upgrade confidence much stronger. ## P0 Must Ship These are the highest-leverage gaps to close next. ### 1. End-to-end adoption path A new team should be able to go from install to a working host integration without reading SDK internals. Target outcome: - install the package - scaffold a host starter - run one action locally - connect the starter to a real host - export docs and manifests - build a distributable bundle Acceptance bar: - one documented path works in under 10 minutes - one path covers an existing app - one path covers a host-oriented starter ### 2. Full project creation flow `init` is good for adding Ageniti to an existing project. It is not yet the smoothest path for greenfield users. Target outcome: - add `ageniti create