@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.

bash
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

ts
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

GroupEndpoints
AgentsGET /api/agents, GET /api/agents/:name, PATCH /api/agents/:name, DELETE /api/agents/:name
SessionsGET /api/sessions, POST /api/sessions/:id/messages (SSE), DELETE /api/sessions/:id
WorkflowsGET /api/workflows, POST /api/workflows/:name/run, GET /api/workflow-runs/:id
TasksGET /api/tasks, POST /api/tasks, PATCH /api/tasks/:id, DELETE /api/tasks/:id
ProjectsGET /api/projects, POST /api/projects
MemoryGET /api/memory/recall, POST /api/memory/notes, POST /api/memory/search
ResourcesGET /api/resources, POST /api/resources/install, GET /api/skills
ApprovalsGET /api/approvals, POST /api/approvals/:id/respond
WebhooksPOST /webhooks/:name (payloads route to configured workflows)
Static UIGET / 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:

  1. Local only: keep the default 127.0.0.1 bind.
  2. Programmatic clients: set server.authToken; clients send it as a bearer token on every request.
  3. Bundled browser UI: enable server.proxyAuth with 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:

yaml
# 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.

Source

packages/server/.