Documentation Index
Fetch the complete documentation index at: https://docs.xhipai.com/llms.txt
Use this file to discover all available pages before exploring further.
Express REST Server
Serve any agent over HTTP with createAgentRouter. It auto-generates /agents/:name/run and /agents/:name/stream endpoints for every agent passed in.
import express from "express";
import { Agent, openai, defineTool } from "@agentium/core";
import { createAgentRouter } from "@agentium/transport";
import { z } from "zod";
const lookupOrder = defineTool({
name: "lookup_order",
description: "Look up an order by ID",
parameters: z.object({ orderId: z.string() }),
execute: async ({ orderId }) => `Order ${orderId}: shipped, arriving Friday`,
});
const agent = new Agent({
name: "support",
model: openai("gpt-4o"),
instructions: "You are a helpful customer-support agent.",
tools: [lookupOrder],
});
const app = express();
app.use(express.json());
app.use("/api", createAgentRouter({ agents: { support: agent } }));
app.listen(3000, () => console.log("Listening on :3000"));
// POST /api/agents/support/run { "input": "Where is order 42?" }
Streaming Responses
The router exposes an SSE streaming endpoint at /agents/:name/stream automatically. Clients receive incremental data: frames as the model generates tokens.
import express from "express";
import { Agent, openai } from "@agentium/core";
import { createAgentRouter } from "@agentium/transport";
const agent = new Agent({
name: "writer",
model: openai("gpt-4o"),
instructions: "Write creative short stories.",
});
const app = express();
app.use(express.json());
app.use("/api", createAgentRouter({ agents: { writer: agent } }));
app.listen(3000);
// Client-side consumption:
// const es = new EventSource("/api/agents/writer/stream");
// es.onmessage = (e) => {
// if (e.data === "[DONE]") return es.close();
// const chunk = JSON.parse(e.data);
// process.stdout.write(chunk.text ?? "");
// };
Or call the streaming endpoint directly with fetch:
const res = await fetch("http://localhost:3000/api/agents/writer/stream", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ input: "Tell me a story about a robot." }),
});
const reader = res.body!.getReader();
const decoder = new TextDecoder();
while (true) {
const { done, value } = await reader.read();
if (done) break;
const text = decoder.decode(value);
for (const line of text.split("\n")) {
if (line.startsWith("data: ") && line !== "data: [DONE]") {
const chunk = JSON.parse(line.slice(6));
process.stdout.write(chunk.text ?? "");
}
}
}
Socket.IO Gateway
For real-time bidirectional communication, use createAgentGateway with Socket.IO. Agents registered in the global registry are immediately available.
import http from "node:http";
import { Server as SocketIO } from "socket.io";
import { Agent, openai } from "@agentium/core";
import { createAgentGateway } from "@agentium/transport";
const server = http.createServer();
const io = new SocketIO(server, { cors: { origin: "*" } });
createAgentGateway({ io });
new Agent({
name: "assistant",
model: openai("gpt-4o"),
instructions: "You are a helpful assistant.",
});
server.listen(3001, () => console.log("WebSocket gateway on :3001"));
// Client:
// const socket = io("http://localhost:3001");
// socket.emit("agent:run", { agent: "assistant", input: "Hello!" });
// socket.on("agent:response", (data) => console.log(data));
// socket.on("agent:stream", (chunk) => process.stdout.write(chunk.text));
Swagger UI
Enable auto-generated OpenAPI docs with interactive Swagger UI by passing swagger config. The spec is derived from your registered agents, teams, and workflows.
import express from "express";
import { Agent, openai } from "@agentium/core";
import { createAgentRouter } from "@agentium/transport";
const agent = new Agent({
name: "analyst",
model: openai("gpt-4o"),
instructions: "You are a data analyst.",
});
const app = express();
app.use(express.json());
app.use(
"/api",
createAgentRouter({
agents: { analyst: agent },
swagger: {
enabled: true,
title: "Agent API",
description: "AI agent endpoints",
version: "1.0.0",
docsPath: "/docs",
specPath: "/docs/spec.json",
servers: [{ url: "http://localhost:3000/api", description: "Local" }],
},
}),
);
app.listen(3000, () => {
console.log("API: http://localhost:3000/api");
console.log("Swagger: http://localhost:3000/api/docs");
});
File Upload
Accept multimodal inputs (images, PDFs, audio) alongside text by enabling fileUpload. Files are automatically converted into multi-part content arrays.
import express from "express";
import { Agent, openai } from "@agentium/core";
import { createAgentRouter } from "@agentium/transport";
const agent = new Agent({
name: "vision",
model: openai("gpt-4o"),
instructions: "Describe uploaded images in detail.",
});
const app = express();
app.use(express.json());
app.use(
"/api",
createAgentRouter({
agents: { vision: agent },
fileUpload: {
maxFileSize: 10 * 1024 * 1024, // 10 MB
allowedMimeTypes: ["image/png", "image/jpeg", "application/pdf"],
},
}),
);
app.listen(3000);
// curl -X POST http://localhost:3000/api/agents/vision/run \
// -F 'input=What is in this image?' \
// -F 'file=@photo.jpg'
Per-Request API Keys
In multi-tenant deployments, each request can supply its own API key via headers. The router extracts provider-specific keys and forwards them to the model.
import express from "express";
import { Agent, openai } from "@agentium/core";
import { createAgentRouter } from "@agentium/transport";
const agent = new Agent({
name: "assistant",
model: openai("gpt-4o"),
instructions: "You are a helpful assistant.",
});
const app = express();
app.use(express.json());
app.use("/api", createAgentRouter({ agents: { assistant: agent } }));
app.listen(3000);
// Clients forward their own OpenAI key:
// POST /api/agents/assistant/run
// Headers:
// X-OpenAI-API-Key: sk-tenant-abc123...
// Content-Type: application/json
// Body: { "input": "Hello!" }
//
// Supported headers:
// X-OpenAI-API-Key → OpenAI
// X-Google-API-Key → Google
// X-Anthropic-API-Key → Anthropic
// X-API-Key → Generic fallback
Multiple Agents on One Server
Serve several agents under distinct routes from a single Express app. Each agent gets its own /run and /stream endpoints.
import express from "express";
import { Agent, openai, google, defineTool } from "@agentium/core";
import { createAgentRouter } from "@agentium/transport";
import { z } from "zod";
const getWeather = defineTool({
name: "get_weather",
description: "Get weather for a city",
parameters: z.object({ city: z.string() }),
execute: async ({ city }) => `${city}: 72°F, sunny`,
});
const weatherBot = new Agent({
name: "weather",
model: openai("gpt-4o-mini"),
instructions: "You provide weather forecasts.",
tools: [getWeather],
});
const codeBot = new Agent({
name: "coder",
model: openai("gpt-4o"),
instructions: "You are an expert TypeScript programmer.",
});
const researchBot = new Agent({
name: "researcher",
model: google("gemini-2.0-flash"),
instructions: "You research topics and provide summaries.",
});
const app = express();
app.use(express.json());
app.use(
"/api",
createAgentRouter({
agents: {
weather: weatherBot,
coder: codeBot,
researcher: researchBot,
},
swagger: { enabled: true, title: "Multi-Agent API" },
}),
);
app.listen(3000);
// POST /api/agents/weather/run
// POST /api/agents/coder/run
// POST /api/agents/researcher/run
// GET /api/agents → list all agents
Teams and Workflows via REST
Serve teams and workflows alongside agents. Each gets typed endpoints under /teams/:name/run and /workflows/:name/run.
import express from "express";
import { Agent, Team, TeamMode, Workflow, openai } from "@agentium/core";
import { createAgentRouter } from "@agentium/transport";
const researcher = new Agent({
name: "researcher",
model: openai("gpt-4o-mini"),
instructions: "Research the given topic.",
});
const writer = new Agent({
name: "writer",
model: openai("gpt-4o"),
instructions: "Write a polished article from research notes.",
});
const team = new Team({
name: "content-team",
agents: [researcher, writer],
mode: TeamMode.SEQUENTIAL,
instructions: "Research a topic, then write an article about it.",
});
const workflow = new Workflow({
name: "publish-pipeline",
steps: [
{ type: "agent", agent: researcher, input: "Research AI trends" },
{ type: "agent", agent: writer },
],
});
const app = express();
app.use(express.json());
app.use(
"/api",
createAgentRouter({
agents: { researcher, writer },
teams: { "content-team": team },
workflows: { "publish-pipeline": workflow },
swagger: { enabled: true, title: "Content Platform API" },
}),
);
app.listen(3000);
// POST /api/teams/content-team/run { "input": "Write about quantum computing" }
// POST /api/teams/content-team/stream (SSE)
// POST /api/workflows/publish-pipeline/run
CORS and Security
Configure CORS origins, rate limiting, and custom auth middleware through createAgentRouter options.
import express from "express";
import { Agent, openai } from "@agentium/core";
import { createAgentRouter } from "@agentium/transport";
const agent = new Agent({
name: "secure-bot",
model: openai("gpt-4o"),
instructions: "You are a secure assistant.",
});
function authMiddleware(req: any, res: any, next: any) {
const token = req.headers.authorization?.replace("Bearer ", "");
if (!token || token !== process.env.API_TOKEN) {
return res.status(401).json({ error: "Unauthorized" });
}
next();
}
const app = express();
app.use(express.json());
app.use(
"/api",
createAgentRouter({
agents: { "secure-bot": agent },
cors: ["https://app.example.com", "https://admin.example.com"],
rateLimit: { windowMs: 60_000, max: 50 },
middleware: [authMiddleware],
}),
);
app.listen(3000);
Health Check Endpoint
Add a health and readiness probe alongside the agent router for production deployments behind load balancers.
import express from "express";
import { Agent, openai, registry } from "@agentium/core";
import { createAgentRouter } from "@agentium/transport";
const agent = new Agent({
name: "bot",
model: openai("gpt-4o"),
instructions: "You are a helpful bot.",
});
const app = express();
app.use(express.json());
app.get("/health", (_req, res) => {
res.json({ status: "ok", timestamp: new Date().toISOString() });
});
app.get("/ready", (_req, res) => {
const agents = registry.list().agents;
if (agents.length === 0) {
return res.status(503).json({ status: "not_ready", reason: "No agents registered" });
}
res.json({ status: "ready", agents });
});
app.use("/api", createAgentRouter({ cors: true }));
app.listen(3000, () => console.log("Server ready on :3000"));
// GET /health → { "status": "ok", "timestamp": "..." }
// GET /ready → { "status": "ready", "agents": ["bot"] }