Build AI agents in TypeScript.
Bring your own UI.
AgentNavaKit lets you describe an AI agent in a single TypeScript object and run it on a managed runtime. The runtime executes the agent loop, handles tool calls, and streams typed events back — render them in any UI you like.
Quickstart
One TypeScript file walks the whole lifecycle: push a spec, configure an agent version, optionally deploy to test, then deploy to prod. No CLI, no login flow — just the SDK and an API key.
Set up @agentnava/kit in this project end-to-end. There is no CLI — everything happens through the TypeScript SDK, and agents always run on the AgentNava backend (not locally).
Step 0 — Naming. Ask me for a kebab-case agent name (e.g. `support-bot`, `inbox-triage`). Refer to it as `<agent-name>` below; substitute my answer everywhere.
Step 1 — Package manager. Detect from the lockfile (bun.lockb → bun, pnpm-lock.yaml → pnpm, yarn.lock → yarn, otherwise npm). Use it consistently.
Step 2 — Install `@agentnava/kit`.
Step 3 — API key. Confirm `AGENTNAVA_API_KEY` is set in `.env` (or `process.env`). If not, stop and tell me to generate one at https://console.agentnava.com → Settings → API keys. Don't proceed until I paste it in and confirm.
Step 4 — Scaffold the agent folder at `agents/<agent-name>/`:
• `AGENT.md` — H1 with the display name, then one short paragraph describing what the agent does and how it talks. Ask me for a one-line role if it isn't obvious.
• `skills/<example-skill>/SKILL.md` — YAML frontmatter (`name`, `description`, `allowed-tools`) plus a 2-sentence body. Same format as Claude Code skills.
• `commands/reset.md` — a user-invokable `/reset` slash command that clears session history. Same format as Claude Code commands.
Step 5 — (Optional) If this repo already has `.claude/skills/`, `.claude/agents/`, or `.claude/commands/`, ask whether to import them — copy them in unchanged.
Step 6 — Write `agents/<agent-name>.ts` as the full lifecycle script:
• Import `AgentNava` and `loadAgentDir` from `@agentnava/kit`
• `const an = new AgentNava()`
• `const spec = await an.specs.push(loadAgentDir('./agents/<agent-name>', { key: '<agent-name>' }))` — auto-discovers AGENT.md, skills/, subagents/, workflows/, commands/
• If a `knowledge/` folder exists, move/copy those files into `workflows/` — that's the v0 grounding pattern; `loadAgentDir` picks them up automatically.
• `const v = await an.agents.configure({ key: '<agent-name>', name: '<Display Name>', modelClass: 'standard', spec, triggers: [{ kind: 'chat' }] })`
• `await an.agents.deployToTest(v.versionId)` — test only. Do NOT deploy to prod; I'll do that myself.
• `const session = await an.sessions.start({ agentId: v.agentId, env: 'test' })`
• Stream one chat turn:
for await (const event of an.sessions.chat(session.id, 'Hello.')) {
if (event.type === 'message-delta') process.stdout.write(event.delta)
}
Step 7 — Run it: `bun run agents/<agent-name>.ts` (or `tsx agents/<agent-name>.ts` for npm/pnpm). Wait for the chat reply to stream.
Step 8 — Print a one-paragraph summary: spec id, agent id, version id, and what to try next.
Reference: https://docs.agentnava.com
Don't modify unrelated files. Ask before any ambiguous choice.
Or do it by hand
Install the SDK
npm install @agentnava/kit
# or: bun add @agentnava/kit
# or: pnpm add @agentnava/kit
AgentNavaKit ships TypeScript source. No build step. There is no CLI to install — everything happens via the SDK.
Set your API key
# .env
AGENTNAVA_API_KEY=sk_live_…
Generate the key at console.agentnava.com → Settings → API keys. The SDK reads process.env.AGENTNAVA_API_KEY automatically. You can override per-instance with new AgentNava({ apiKey: '…' }).
Lay out the agent folder
Pick a kebab-case name for your agent (e.g. support-bot, inbox-triage). Below we refer to it as <agent-name> — substitute your choice everywhere.
agents/<agent-name>/
├── AGENT.md # the agent's core instructions (CLAUDE.md equivalent)
├── skills/
│ └── <example-skill>/SKILL.md # auto-invokable mini-modules
├── workflows/
│ └── morning-digest.md # multi-step playbooks
├── commands/
│ └── reset.md # user-invokable slash commands
└── knowledge/ # RAG: .md / .pdf / .txt / .png / .jpg
└── handbook.pdf
This is the same layout as Claude Code's .claude/ folder. Drop your existing skills, subagents, and commands in unchanged — the runtime reads them with the same frontmatter conventions. See Import from Claude Code for details.
# agents/<agent-name>/AGENT.md
# <Display name>
<One paragraph: what this agent does, how it talks, what it won't do.>
Answer in two paragraphs max unless the user asks for detail.
Always address the user as "you".
See File kinds for the full set and their frontmatter.
Write the lifecycle in TypeScript
// agents/<agent-name>.ts
import { AgentNava, loadAgentDir } from '@agentnava/kit';
const an = new AgentNava();
// 1. Push the spec bundle — AGENT.md + skills + subagents + workflows + commands.
const spec = await an.specs.push(
loadAgentDir('./agents/<agent-name>', { key: '<agent-name>' }),
);
// → { id: 'spec_4f1c9a', version: 1 }
// 2. Configure the agent → returns a new agent version.
const v = await an.agents.configure({
key: '<agent-name>', // dev-chosen, stable; backend assigns agt_…
name: '<Display name>', // what users address the agent as in chat
modelClass: 'standard', // or 'premium' / 'advanced'
spec, // pins to spec@v1
triggers: [{ kind: 'chat' }],
});
// → { agentId: 'agt_2b8e', versionId: 'ver_3c5f' }
// 3. (Optional) deploy to test. Dev-only URL; no end-user traffic.
const test = await an.agents.deployToTest(v.versionId);
console.log('test:', test.url);
// 4. Start a session and stream a chat turn.
const session = await an.sessions.start({ agentId: v.agentId, env: 'test' });
for await (const event of an.sessions.chat(session.id, 'Say hello.')) {
if (event.type === 'message-delta') process.stdout.write(event.delta);
}
// 5. When ready, deploy to prod. End users hit this version.
// const prod = await an.agents.deployToProd(v.versionId);
Prefer explicit fields? loadAgentDir is sugar over an.specs.push({ key, instructions, skills, subagents, workflows, commands }) — see Spec. To ground an agent on external content today, pass it in a workflows file on the spec — see Examples → Bring your own knowledge.
Run it
npx tsx agents/<agent-name>.ts
# or: bun run agents/<agent-name>.ts
#
# spec pushed: spec_4f1c9a@v1
# agent version: ver_3c5f (agt_2b8e)
# test: https://<temp-id>.test.agents.agentnava.com
The TS file IS the deployment script. Re-run it whenever you change the spec or the configuration — push is idempotent on key, configure upserts on key, only changed content gets a new version.
Chat with the test agent
curl -N -X POST https://<temp-id>.test.agents.agentnava.com/chat \
-H 'Content-Type: application/json' \
-d '{"messages":[{"role":"user","content":"Hi!"}]}'
SSE stream of AgentEvents. Plug it into any UI that reads SSE — your own React app, Vue, vanilla JS, our embed widget. See Sessions for the full chat protocol with attachments and multi-turn history.
Deploy to prod when ready
const prod = await an.agents.deployToProd(v.versionId);
console.log('prod:', prod.url);
// → https://hello-bot.agents.agentnava.com
Promotes the agent version to the stable production URL. End users now hit this version. See Operate for custom domains, rollbacks, and BYOK.