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
npm install @ageniti/coreRequirements:
- 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
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():
titledefaults to a humanised version ofname.inputdefaults tos.object({}).visibilitydefaults to"local".sideEffectsdefaults to"read".idempotencydefaults to"unspecified".supportedSurfacesdefaults tocli,json,http,mcp,react,dev, andai-sdk.- Destructive actions require confirmation unless you override
requiresConfirmation.
3. Create An 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: "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.
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:
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/agenititask-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
#!/usr/bin/env node
import { app } from "./app.js";
await app.createCli().main();Example commands:
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 4321Notes:
- Action names can be called as snake_case or kebab-case.
--schemaprints the input JSON Schema.--confirmis required for actions that require confirmation.- CLI exit codes are mapped from runtime error codes. See Runtime Semantics.
6. Expose JSON Automation
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
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
mcpsurface privateactions are excluded unless you opt indestructiveactions are excluded unless you opt in
8. Expose OpenAI And 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",
});Default LLM tool filtering:
- private actions are excluded
- destructive actions are excluded
- the action must support the
ai-sdksurface
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
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
task-app dev --port 4321The 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:
await app.build({
targets: ["bundle"],
appModule: "./src/ageniti/app.js",
appExport: "app",
outDir: "./dist/ageniti",
});If you prefer the CLI flow:
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/agenitiIf appModule is omitted, Ageniti tries to discover a default Node-safe entry such as ./src/ageniti/app.js.
Bundle output includes:
ageniti.manifest.jsonageniti.actions.jsoncli.mjsmcp-stdio.mjsageniti.mcp.jsonGUIDE.mdpackage.jsonREADME.mdageniti.bundle.json
If you also want a distributable tarball, run:
task-app package --app-module ./src/ageniti/app.js --app-export app --out-dir ./dist/agenitiThat command builds the bundle and runs npm pack inside it.
For publish rehearsal or release:
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/agenitipublish 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:
npx @ageniti/core init react
npx @ageniti/core init expo
npx @ageniti/core init next
npx @ageniti/core doctorUse 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:
{
"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
tsxand setbuild.typescriptRuntimetotsx - point
--app-moduleat compiled JavaScript - create a tiny
src/ageniti/app.jswrapper 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 for the full public API.
- Entry Points for package export paths.
- Runtime Semantics for envelopes, retry, timeout, and errors.
- Recipes for common integration patterns.
- Release Checklist for packaging and publish checks.