Quickstart
Authorize your first agent action in under 2 minutes — no account, no Docker, no server setup.
Fastest path: zero setup, no account
One command downloads the Lelu engine, starts it on your machine with a starter policy, and serves it over MCP. Everything runs locally — nothing is sent to our cloud.
npx -y lelu-mcp start
Or wire it straight into your agent host — Claude Code, Claude Desktop, or Cursor — so every tool call is policy-gated:
claude mcp add lelu -- npx -y lelu-mcp start --transport stdio
The starter policy lands in ~/.lelu/policy.yaml — it denies destructive actions, routes payments to human review, allows reads, and default-denies the rest. Edit it and restart to change the rules. When you want cloud-managed policies and audit history, continue below.
Get an API key
No account needed — Lelu is free while in beta. The local engine accepts any API key you choose (whatever API_KEY you start it with). Want the hosted engine instead? Ask for early access.
Prefer to run everything locally? No account or key needed — npx -y lelu-mcp start runs the engine on your machine with a self-generated key, and the TypeScript SDK discovers that engine automatically. A self-hosted engine accepts any key you set at startup. See the MCP guide or self-hosting.
Copy the key and store it as LELU_API_KEY in your .env file. Never commit it to version control.
Install the SDK
Add lelu-agent-auth to your project:
npm install lelu-agent-auth # or: pnpm add lelu-agent-auth | yarn add lelu-agent-auth
Connect and authorize
The SDK talks to a Lelu engine. If npx lelu-mcp start is running on your machine, lelu() finds it automatically — its address and key live in ~/.lelu, so there is nothing to configure:
import { lelu } from "lelu-agent-auth";
// Zero-config: discovers the engine `npx lelu-mcp start` is running.
// Point it elsewhere with lelu({ baseUrl, apiKey }) — e.g. a Docker
// or self-hosted engine — or via LELU_BASE_URL / LELU_API_KEY.
const auth = lelu();
const result = await auth.authorize({
tool: "refund_payment",
context: { confidence: 0.85 },
});
if (result.decision === "allow") {
// proceed with the action
} else if (result.decision === "human_review") {
// queued — agent pauses, awaiting human approval
} else {
throw new Error(`Denied: ${result.reason}`);
}The instance also exposes the full engine API under auth.api (tokens, review queue, audit, policies) and a mountable auth.handler for Next.js / Express routes. createClient() from earlier versions keeps working unchanged.
Or try the hosted API directly with your key:
curl -X POST https://lelu-ai.com/api/v1/authorize \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $LELU_API_KEY" \
-d '{ "tool": "refund_payment" }'Read the response
The hosted API evaluates the request against your policies and returns one of four decisions:
{
"requestId": "req_7f30c2a4e1b8",
"tool": "refund_payment",
"decision": "human_review",
"reason": "Financial operations require a human to approve before execution.",
"rule": "review:financial-ops",
"latencyMs": 6,
"mode": "live"
}decision: "allow"Action is permitted — proceed immediately.decision: "human_review"Action queued for a human. On a self-hosted engine, poll /v1/queue/pending until approved or denied.decision: "deny"Blocked by policy — do not proceed. Inspect reason for details.decision: "compute"Redirected to a safe alternative — use safeTool and safeArgs instead of the original call.Add to your AI framework
Lelu ships framework wrappers so you can gate tool calls with one line:
import { secureTool } from "lelu-agent-auth/vercel";
import { tool } from "ai";
import { z } from "zod";
const processRefund = secureTool(lelu, "billing-agent", {
tool: tool({
description: "Process a customer refund",
parameters: z.object({ orderId: z.string(), amount: z.number() }),
execute: async ({ orderId, amount }) => ({ success: true }),
}),
action: "refund:process",
confidence: 0.9,
});