Lousho — TypeScript AI agent SDK
Open-source TypeScript SDK for agents that run in your own Node process: tool calling, MCP, sessions that survive a restart, human approvals, and OpenTelemetry. No hosted runtime.
Install with @lousho/build-ai-agent.
What still sets it apart (as of October 2026; see the
honest comparison for where rivals are ahead):
- Record/replay evals with trajectory drift.
lousho eval --record runs
each case against the real provider once and saves a cassette, --replay
runs it in CI with no network or API key, and --drift re-records and
reports how the tool-call trajectory changed. defineEval() asserts on
which tools were called, in what order, with which arguments, with JUnit output.
- Durable approvals on your own stores, including Workers KV. Sessions,
checkpoints and approval pauses live in memory, files, one SQLite file or
Cloudflare KV, so a paused run resumes from another request or process.
There is no Postgres store yet.
- Self-hosted single package across AI SDK majors. No platform account or
hosted control plane; the
ai peer accepts v4, v6 and v7, and the same
agent runs in Node, Docker or a Worker (lousho build). It is still
alpha, with fewer native providers and no hosted dashboard; Agent Forge
(lousho studio) is a local visual console. ACP and MCP serving are
features here, not differentiators: other frameworks ship them too.
Quickstart · Features · Examples ·
TypeScript AI agent quickstart ·
Connect an agent to MCP servers ·
Durable sessions that survive a restart ·
Human-in-the-loop tool approvals ·
OpenTelemetry tracing ·
Docs
Installation
Requires Node.js 22.19 or newer (the floor comes from the undici@8 dependency; .ts agent files also rely on Node's built-in type stripping, on by default since 22.18). Scaffold a new project with one command:
npm create lousho-agent my-agent # agent, example tool, offline test
cd my-agent # copy .env.example to .env (cp on macOS/Linux, copy on Windows), put your API key in it
npm run dev # chat in the terminal; `npm test` runs offline
From a locally packed tarball: npx --package=<absolute path to create-lousho-agent-x.y.z.tgz> create-lousho-agent my-agent (npx ../x.tgz fails on Windows).
To add it to an existing project, install the SDK with the current ai major
and the provider packages that pair with it:
npm install @lousho/build-ai-agent ai@^7.0.0 zod
npm install @ai-sdk/openai@^4.0.0 @ai-sdk/anthropic@^4.0.0
Supported ai majors are 4 (^4.3.19), 6 and 7; AI SDK v5 is not supported. For Gemini add @ai-sdk/google@^4.0.0 (google/<model>).
For Ollama, use ai@^7.0.0 with ollama-ai-provider-v2@^4.0.0 and zod 4 (or
ai@^4.3.19 with ollama-ai-provider@^1.2.0 and zod 3);
Installation lists every pairing. npx lousho doctor checks Node, peers and API keys and
prints a fix for anything missing.
Quickstart
The snippet uses top-level await, so the file must be an ES module (.mts, or "type": "module" in package.json).
import { createAgent } from '@lousho/build-ai-agent';
const agent = createAgent({ model: 'openai/gpt-4.1-mini', instructions: 'You are a helpful assistant.' });
const { text } = await agent.send('Hello!');
console.log(text);
model is a provider/model string (openai, anthropic, openrouter,
ollama, pi) and the key comes from the provider's usual variable
(OPENAI_API_KEY, ...). Leave it out to pick the provider from the
environment, or pass provider: with your own or a mock provider. See
Quick Start for runnable, offline versions and
Providers for the details. Prefer config files? The same
agent can be an agent.yaml spec served with npx lousho dev agent.yaml
(Configuration).
Features
- Tools:
defineTool() with a zod input; arguments are typed, validated, and run in parallel. Tools
- Approvals and permission policies:
needsApproval pauses a run; agent.approvals.resolve() continues it, or approve decides in code. permissions rules allow, deny or ask per tool before that, with an audit log. Approvals
- Ask the user a question:
createAgent({ askQuestion: true }) adds the built-in ask_question tool; the run pauses durably until agent.approvals.answer(). Asking the user a question
- Sessions:
agent.session() keeps a multi-turn conversation in memory, files or SQLite. Sessions
- Memory:
defineMemory() slots, scoped globally, per session or per user, are recalled into the prompt at the start of a run and read and written with remember_ / recall_ tools. Memory
- Structured output:
output: zodSchema makes the final reply a typed, validated result.object, with one repair step. Structured output
- Streaming:
agent.stream() and session.stream() yield typed, versioned JSON events ready for SSE. Streaming
- UI bindings:
useLoushoAgent() from @lousho/build-ai-agent/react (and /vue; store from ) turns the event stream into chat state, with approvals. , ,
Usage
A tool-using agent, streamed
import { createAgent, defineTool } from '@lousho/build-ai-agent';
import { z } from 'zod';
const getWeather = defineTool({
name: 'get_weather',
description: 'Current weather for a city',
input: z.object({ city: z.string() }),
execute: async ({ city }) => ({ city, tempC: 21, sky: 'sunny' }), // `city` is a string
});
const agent = createAgent({
model: 'openai/gpt-4.1-mini',
instructions: 'You are a travel assistant. Check the weather before giving advice.',
tools: [getWeather],
});
for await (const event of agent.stream('What should I wear in Lisbon today?')) {
if (event.type === 'tool.start') console.log(`\n[${event.toolName}]`, event.args);
if (event.type === 'text.delta') process.stdout.write(event.text);
}
Pause for approval, then resume
import { createAgent, defineTool } from '@lousho/build-ai-agent';
import { z } from 'zod';
const sendEmail = defineTool({
name: 'send_email',
description: 'Send an email',
input: z.object({ to: z.string().email(), body: z.string() }),
needsApproval: ({ to }) => !to.endsWith('@mycompany.com'), // only external mail pauses
execute: async ({ to }) => ({ sent: true, to }),
});
const agent = createAgent({ model: 'openai/gpt-4.1-mini', tools: [sendEmail] });
const run = await agent.send('Email the Q3 summary to [email protected]');
if (run.finishReason === 'awaiting-approval') {
const [call] = await agent.approvals.list(); // { id, toolName: 'send_email', args, ... }
console.log('Approve?', call.toolName, call.args);
const done = await agent.approvals.resolve({ id: run.approvalId!, approved: true }); // or approved: false, note
console.log(done.text);
}
Durable sessions with SQLite
import { createAgent, resolveProvider } from '@lousho/build-ai-agent';
import { SqliteStore } from '@lousho/build-ai-agent/sqlite';
// Transcripts, per-step checkpoints and approvals in one SQLite file, wired by one option.
const agent = createAgent({ provider: resolveProvider('openai/gpt-4.1-mini'), store: new SqliteStore('./.lousho/agent.db') });
await agent.resume('user-42'); // after a crash: finishes the interrupted turn without redoing finished steps
const { text } = await agent.session({ id: 'user-42' }).send('What is my name?'); // same id, same conversation
A coding agent from the registry
lousho add coding-pi --dir ./my-agent --yes --allow exec,fs-write,network,env
OPENROUTER_API_KEY=... lousho dev ./my-agent
coding-pi is a whole agent directory: workspace file tools with checkpoint
rewind, an allow-listed shell, permission rules (rm denied, writes to
*.test.* refused), a loop guard, a cost cap, a read-only explorer and a Pi
coding sub-agent the lead delegates to through task. coding-kit is the
same rails on the standard providers. Both have offline tests that run in CI;
live OpenRouter runs are manual and are not part of CI. A recorded model run
is committed at scripts/__cassettes__/build-a-coding-agent.json and replays
offline with npx vitest run scripts/buildACodingAgent.test.ts.
Documentation
| Page | What it covers |
|---|
| Installation | Requirements, peer and provider packages, installing from a local build, lousho init, lousho doctor |
| Upgrading to 1.0 | From 1.0.0-alpha.*: moved imports, removed and renamed APIs, deprecations, what 1.0 promises |
| Quick Start | Runnable, verified snippets: createAgent(), tools, streaming, sessions, approvals, offline tests, spec files |
| Configuration | Spec fields, the mcpServers field, provider env vars, retries and fallback, createAgent() options, budgets, project instructions |
| MCP | Use MCP servers as tools (mcpServers, connectMcp(), loadMcpTools()), approval for MCP tools, serve an agent with serveMcp() / lousho mcp |
| Connectors | Connect to Google Docs, Slack, GitHub, Notion: the connector table, OAuth sign-in, approval for connector writes |
| OpenAPI tools | openApiTools(): an OpenAPI 3.0 / 3.1 document becomes one tool per operation, with approval for mutating ones |
| Providers | Model strings, resolveProvider(), which model runs, custom providers |
The full guides are at lousho.com, in English and Arabic.
For AI coding agents. The repo carries its docs in machine-readable form:
llms-full.txt (this README and every docs page in one file, with absolute
links) and llms.txt (an llmstxt.org index), both in
the repo root. Only the small llms.txt index (and the docs/*.md pages it
links to) is in the npm package; fetch llms-full.txt from the repo. They are
generated with npm run docs:llms and checked in CI.
Examples
Most examples run offline with a mock provider; see the
examples index for how to run each one.
| Example | What it shows |
|---|
| ops-pipeline | Flagship: monitor alert, Slack "Fix it" button, human approval, fixer agent, patch-check-gated GitHub PR (npm run pipeline:demo) |
| coding-harness | A coding agent starting point: checkpoints, permission rules, loop guard, the coding-kit and coding-pi registry kits, live OpenRouter runs |
| deep-research | Coordinator fans out parallel task calls to researcher sub-agents, then synthesizes a cited report |
| support-desk | Triage agent handoff()s to billing/tech specialists; approval-gated refund tool |
| evaluator-loop | Writer/critic loop: llmCritique() scores a draft and returns feedback until it passes |
| data-analyst | Text-to-SQL over node:sqlite with read-only enforcement — DELETE/DROP can never run |
| plan-mode | Read and propose in plan mode, then apply edits after setPermissionMode('acceptEdits') |
| waves | Waves: bounded parallel workers, deterministic aggregate, typed verify gate, extend only on named gaps |
|
CLI
| Command | What it does |
|---|
lousho init [dir] | Scaffold a project with an agent, a tool and an offline test |
lousho doctor [spec] | Check Node, peers, API keys and a spec file; print fixes |
lousho dev <spec> | Local chat UI and POST /chat with hot reload |
lousho chat <path> | Terminal REPL: streamed replies, tool calls, approvals and questions |
lousho acp <path> | Serve the agent to Zed and other Agent Client Protocol editors |
lousho add <name> [--registry <url-or-path>] | Copy a tool, skill, channel, schedule, memory slot or kit (a whole agent directory) from the default registry (or a given one) into an agent directory |
lousho mcp <spec> | Serve the agent as an MCP server (stdio or HTTP) |
lousho eval [globs] | Run *.eval.ts files; JUnit and JSON reports |
lousho traces [id] | List saved runs, or print one as a span tree |
lousho build --target=<t> --agent=<spec> | Build a Node server, Docker image or Cloudflare Worker |
lousho studio | Launch Agent Forge, the visual studio |
Flags for each command are in CLI.
Deployment: npx lousho build --target=node-server|docker|cloudflare-worker --agent=agent.yaml
writes a self-contained artifact and prints the command to run or deploy it
(Deployment).
Status
Alpha (1.0.0-alpha, pre-1.0): APIs can still change between releases, and
breaking changes are listed in the CHANGELOG with migration
notes. Known gaps:
- Docker sandbox egress (
network: { allow }) and the credential broker need
Docker Engine on Linux; Docker Desktop is refused
(Workspace tools).
- File (non-image) parts reach the model only for media types the provider
accepts (
application/pdf for OpenAI and OpenRouter, application/pdf and
text/plain for Anthropic, on ai 6/7); other types - and every file part
on ai 4 - fail the call with LOUSHO_UNSUPPORTED_CONTENT, or are replaced
by a text note with unsupportedFiles: 'text-note'
(Providers).
- The
pi provider and piAgent() are Node-only (they run Pi's engine);
lousho build --target=cloudflare-worker refuses pi/... model specs and
engine: 'pi' sub-agent directories.
- The Cloudflare Worker target has a limited provider and tool set (no
ollama, no web-fetch, no sandbox, no stdio MCP servers, no code mode,
cron schedules in UTC only); agent directories with sub-agents, schedules,
channels and memory slots build for it
(Cloudflare Workers).
Contributing
Contributions are welcome: see CONTRIBUTING.md for setup and
the checks a pull request must pass (npm run typecheck, npm run lint,
npm test, npm run test:coverage && npm run fallow).
To report a vulnerability, see SECURITY.md.
License
MIT © Lousho Team