@agentuity/runtime
Server runtime for building Agentuity applications with Bun and Hono.
Installation
bun add @agentuity/runtime
Overview
@agentuity/runtime provides the server-side runtime for Agentuity applications. Built on Hono and optimized for Bun, it enables you to create type-safe agents with automatic routing, validation, and observability.
Quick Start
Creating an Application
import { createApp } from '@agentuity/runtime';
const { server, logger } = await createApp();
logger.info('Server running on %s', server.url);
Defining an Agent
import { createAgent } from '@agentuity/runtime';
import { s } from '@agentuity/schema';
const agent = createAgent('greeting', {
description: 'A simple greeting agent',
schema: {
input: s.object({
message: s.string(),
}),
output: s.object({
response: s.string(),
}),
},
handler: async (ctx, input) => {
ctx.logger.info('Processing message:', input.message);
return { response: `You said: ${input.message}` };
},
});
export default agent;
Creating Custom Routes
import { createRouter } from '@agentuity/runtime';
import greetingAgent from './agent/greeting';
const router = createRouter();
router.get('/hello', (c) => {
return c.json({ message: 'Hello, world!' });
});
router.post('/greeting', greetingAgent.validator(), async (c) => {
const data = c.req.valid('json');
const result = await greetingAgent.run(data);
return c.json(result);
});
export default router;
Using Plain Hono with Agentuity Types
If you prefer using new Hono() directly instead of createRouter(), import the Env type to type Agentuity context variables (c.var.logger, c.var.thread, c.var.session, c.var.kv, etc.). These values are populated at runtime when the router is mounted through the Agentuity runtime (via createApp()):
import { type Env } from '@agentuity/runtime';
import { Hono } from 'hono';
const router = new Hono<Env>();
router.get('/hello', (c) => {
c.var.logger.info('Request from thread %s', c.var.thread.id);
return c.json({ sessionId: c.var.sessionId });
});
export default router;
With custom application state:
import { type Env } from '@agentuity/runtime';
import { Hono } from 'hono';
interface MyAppState {
db: Database;
}
const router = new Hono<Env<MyAppState>>();
router.get('/data', (c) => {
const db = c.var.app.db;
return c.json({ connected: true });
});
Streaming Responses
import { createRouter, stream } from '@agentuity/runtime';
const router = createRouter();
router.post(
'/events',
stream((c) => {
return new ReadableStream({
start(controller) {
controller.enqueue('Event 1\n');
controller.enqueue('Event 2\n');
controller.close();
},
});
})
);
WebSocket Support
import { createRouter, websocket } from '@agentuity/runtime';
const router = createRouter();
router.get(
'/chat',
websocket((c, ws) => {
ws.onOpen(() => {
console.log('Client connected');
});
ws.onMessage((event) => {
const data = JSON.parse(event.data);
ws.send(JSON.stringify({ echo: data }));
});
ws.onClose(() => {
console.log('Client disconnected');
});
})
);
Server-Sent Events (SSE)
import { createRouter, sse } from '@agentuity/runtime';
const router = createRouter();
router.get(
'/updates',
sse((c, stream) => {
for (let i = 0; i < 10; i++) {
stream.writeSSE({
data: JSON.stringify({ count: i }),
event: 'update',
});
}
})
);
API Reference
createApp(config?)
Creates a new Agentuity application instance.
Returns:
router - Hono application instance
server - Server instance with listen() method
logger - Structured logger
createAgent(config)
Creates a type-safe agent with input/output validation.
Config:
schema.input? - Schema for input validation (Zod, Valibot, etc.)
schema.output? - Schema for output validation
handler - Agent handler function (ctx, input) => output
createRouter()
Creates a new Hono router pre-typed with Env for Agentuity context variables. This is equivalent to new Hono<Env>() but is the recommended approach.
Methods:
get/post/put/delete/patch - HTTP method handlers
Middleware Functions:
Use these middleware functions with standard HTTP methods:
websocket((c, ws) => { ... }) - WebSocket connections (use with router.get())
sse((c, stream) => { ... }) - Server-Sent Events (use with router.get())
stream((c) => ReadableStream) - Streaming responses (use with router.post())
cron(schedule, (c) => { ... }) - Scheduled tasks (use with router.post())
Env<TAppState>
The Hono environment type that provides typed access to Agentuity context variables in route handlers. Use this when creating a plain new Hono() instance instead of createRouter().
import { type Env } from '@agentuity/runtime';
import { Hono } from 'hono';
const router = new Hono<Env>();
Variables provided by Env:
logger | Logger | Structured logger |
tracer | Tracer | OpenTelemetry tracer |
meter | Meter | OpenTelemetry meter |
sessionId | string | Current session ID |
thread | Thread | Thread information and state |
session | Session | Session information and state |
kv | KeyValueStorage | Key-value storage |
stream | StreamStorage | Stream storage |
vector | VectorStorage | Vector storage |
sandbox | SandboxService | Sandbox service |
queue | QueueService | Queue service |
email | EmailService | Email service |
schedule | ScheduleService | Schedule service |
task | TaskStorage | Task storage |
app | TAppState | Custom application state |
AgentContext
Context object available in agent handlers:
interface AgentContext {
logger: Logger;
tracer: Tracer;
sessionId: string;
kv: KeyValueStorage;
stream: StreamStorage;
vector: VectorStorage;
state: Map<string, unknown>;
thread: Thread;
session: Session;
config: TConfig;
app: TAppState;
waitUntil: (promise) => void;
}
Storage Services
Agentuity provides built-in storage abstractions:
- KeyValueStorage - Simple key-value storage
- StreamStorage - Streaming data storage
- VectorStorage - Vector embeddings storage
Access these via the agent context:
const agent = createAgent('storage-example', {
schema: {
output: s.object({ value: s.string().optional() }),
},
handler: async (ctx, input) => {
await ctx.kv.set('key', 'value');
const value = await ctx.kv.get('key');
return { value };
},
});
Observability
Built-in OpenTelemetry support for logging, tracing, and metrics:
const agent = createAgent('observability-example', {
schema: {
output: s.object({ success: s.boolean() }),
},
handler: async (ctx, input) => {
ctx.logger.info('Processing request');
const span = ctx.tracer.startSpan('custom-operation');
span.end();
return { success: true };
},
});
TypeScript
Fully typed with TypeScript. Input and output types are automatically inferred from your schemas.
License
Apache 2.0