@tailored-ai/server
The HTTP API for TAI. Built on Hono. Streams responses over Server-Sent Events. Hosts webhook endpoints. Optionally mounts a built UI as the root path.
npm install @tailored-ai/server @tailored-ai/core
You usually get this for free via
@tailored-ai/cli. Depend on it directly when
embedding the HTTP routes inside your own service.
Minimal embed
import {
AgentRuntime,
createProvider,
createTools,
initDatabase,
loadConfig,
} from "@tailored-ai/core";
import { createServer } from "@tailored-ai/server";
const configPath = "./config.yaml";
const config = loadConfig(configPath);
const db = initDatabase("./agent.db");
const runtime = new AgentRuntime(
{
configPath,
db,
contextDir: "./data/context",
kbDir: "./data/kb",
createTools,
createProvider,
},
loadConfig,
config,
);
const { start } = createServer({ runtime });
start();
The CLI wires the scheduler, task watcher, workflows, exploratory worker, MCP status, channels, and selected UI provider into the same server. Embedders can pass only the services they use.
Routes
| Group | Endpoints |
|---|---|
| Agents | GET /api/agents, GET /api/agents/:name, PATCH /api/agents/:name, DELETE /api/agents/:name |
| Sessions | GET /api/sessions, POST /api/sessions/:id/messages (SSE), DELETE /api/sessions/:id |
| Workflows | GET /api/workflows, POST /api/workflows/:name/run, GET /api/workflow-runs/:id |
| Tasks | GET /api/tasks, POST /api/tasks, PATCH /api/tasks/:id, DELETE /api/tasks/:id |
| Projects | GET /api/projects, POST /api/projects |
| Memory | GET /api/memory/recall, POST /api/memory/notes, POST /api/memory/search |
| Resources | GET /api/resources, POST /api/resources/install, GET /api/skills |
| Approvals | GET /api/approvals, POST /api/approvals/:id/respond |
| Webhooks | POST /webhooks/:name (payloads route to configured workflows) |
| Static UI | GET / and subpaths (serves the SPA from uiDist if provided) |
See
packages/server/src/index.ts
for the canonical list.
SSE streaming
POST /api/sessions/:id/messages accepts a JSON { content, agent? }
body and streams back an text/event-stream of incremental tokens,
tool calls, and final response. The bundled web UI uses this; any
frontend can.
Event types:
event: token data: {"content": "Hel"}
event: token data: {"content": "lo"}
event: tool_call data: {"name": "read", "args": {...}}
event: tool_result data: {"toolCallId": "…", "result": {...}}
event: done data: {"response": "Hello! …"}
event: error data: {"message": "…"}
Authentication
Three deployment shapes are supported:
- Local only: keep the default
127.0.0.1bind. - Programmatic clients: set
server.authToken; clients send it as a bearer token on every request. - Bundled browser UI: enable
server.proxyAuthwith a strong password. The login route mints a signed session cookie so browser SSE connections can authenticate. A TLS-terminating reverse proxy should sit in front.
The legacy server.apiKey gates mutating requests only and is kept for backward
compatibility. Prefer authToken for new API deployments. See
Self-hosting before binding beyond loopback.
Webhooks
A workflow can declare a webhook trigger:
# workflows/stripe-event.yaml
name: stripe-event
triggers:
- kind: webhook
path: stripe
steps:
…
POST /webhooks/stripe runs the workflow with the request body as
input. Signing is the workflow's responsibility; the server passes raw
bytes plus headers, and your workflow can verify with HMAC or pass to
a downstream tool.