When your API needs custom mount paths, multiple router mounts, or an exported type for hc<...>(), you can pass a Hono router directly to createApp({ router }). This gives you full control over route composition and where each router is mounted.
Passing a custom router to createApp() is currently marked experimental in the runtime. Use it when you need explicit composition, and verify behavior when upgrading the SDK.
Basic Setup
Create a root router in src/api/index.ts, export its type, and wire it up from the project-root app.ts:
import { Hono } from 'hono';
import type { Env } from '@agentuity/runtime';
const api = new Hono<Env>()
.get('/health', (c) => c.json({ status: 'ok' }))
.post('/users', async (c) => {
const body = await c.req.json();
return c.json({ created: body });
});
export type ApiRouter = typeof api;
export default api;import { createApp } from '@agentuity/runtime';
import api from './src/api/index';
import agents from './src/agent';
const app = await createApp({
router: { path: '/api', router: api },
agents,
});
export default app;All Agentuity middleware is applied automatically at the mount path you provide.
Three Forms
The router property in createApp() accepts three forms, depending on how you want to organize your routes.
Plain Hono Instance
Pass a single router and it mounts at /api:
import { createApp } from '@agentuity/runtime';
import api from './src/api/index';
// Mounted at /api, routes are reachable at /api/health and /api/users
const app = await createApp({ router: api });
export default app;Single Mount with Custom Path
Wrap the router in { path, router } to control the mount path:
import { createApp } from '@agentuity/runtime';
import api from './src/api/index';
// Mounted at /v1, routes are reachable at /v1/health and /v1/users
const app = await createApp({
router: { path: '/v1', router: api },
});
export default app;Multiple Mounts
Pass an array of { path, router } objects for multi-version or domain-split APIs:
import { createApp } from '@agentuity/runtime';
import v1Router from './src/api/v1';
import v2Router from './src/api/v2';
import internalRouter from './src/api/internal';
const app = await createApp({
router: [
{ path: '/api/v1', router: v1Router },
{ path: '/api/v2', router: v2Router },
{ path: '/internal', router: internalRouter },
],
});
export default app;Each mount gets its own Agentuity middleware (CORS, OpenTelemetry, and route services on c.var.*) applied to {path}/*.
Composing Sub-Routers
For larger APIs, split routes across files and compose them with .route(). Keep the root router in chained form when you want to export a stable type for hc<...>().
import { Hono } from 'hono';
import type { Env } from '@agentuity/runtime';
const usersRouter = new Hono<Env>()
.get('/', async (c) => {
return c.json({ users: [] });
})
.get('/:id', async (c) => {
const id = c.req.param('id');
return c.json({ id, name: 'Alice' });
});
export default usersRouter;import { Hono } from 'hono';
import type { Env } from '@agentuity/runtime';
import postsRouter from './posts/route';
import usersRouter from './users/route';
const api = new Hono<Env>()
.route('/users', usersRouter)
.route('/posts', postsRouter);
export type ApiRouter = typeof api;
export default api;This is standard Hono composition. Routes defined in users/route.ts are reachable at /api/users/ and /api/users/:id.
When to Use Explicit Routing
| Scenario | Approach |
|---|---|
Small API mounted only at /api | A single exported router is enough |
Need custom mount paths (e.g., /v1, /internal) | Explicit routing with { path, router } |
| API versioning | Multiple mounts: [{ path: '/v1', router: v1 }, ...] |
Exporting a router type for hc<ApiRouter>() | Compose a root router and export typeof api |
| Monorepo with shared route modules | Explicit routing, compose imported routers |
Explicit routing works well with Hono RPC. When you compose routes into a single router with .route(), you can export its type and use hc<ApiRouter>() for end-to-end type safety. See Hono RPC + TanStack Query for the full pattern.
Migrating Existing Projects
If you're migrating a v1 project, use the dedicated migrator:
npx @agentuity/migrateWhat the Migration Does
- Creates
src/api/index.ts: A root router that imports and mounts your route modules with.route(). - Creates
src/agent/index.ts: An agent barrel if your project does not already have one. - Updates
app.ts: Wires the generated barrels intocreateApp(). - Removes old v1 generated output: Run
agentuity buildafterward so the current v2 build regenerates any files it still needs.
Before and After
Before (v1 route modules):
src/api/
users/
route.ts
posts/
route.ts
health/
route.tsAfter (explicit): You control the composition in src/api/index.ts.
import { Hono } from 'hono';
import type { Env } from '@agentuity/runtime';
import healthRouter from './health/route';
import postsRouter from './posts/route';
import usersRouter from './users/route';
const api = new Hono<Env>()
.route('/health', healthRouter)
.route('/posts', postsRouter)
.route('/users', usersRouter);
export type ApiRouter = typeof api;
export default api;import { createApp } from '@agentuity/runtime';
import api from './src/api/index';
import agents from './src/agent';
const app = await createApp({
router: { path: '/api', router: api },
agents,
});
export default app;Agentuity Context in Routes
new Hono<Env>() gives you access to Agentuity context variables in your route handlers:
import { Hono } from 'hono';
import type { Env } from '@agentuity/runtime';
const router = new Hono<Env>();
router.get('/example', async (c) => {
// All Agentuity services are available on c.var
c.var.logger.info('Handling request');
const data = await c.var.kv.get('cache', 'key');
return c.json({ data });
});
export default router;Use c.json(), c.text(), and other Hono response methods in your handlers. Both new Hono<Env>() and createRouter() provide typed access to c.var.logger, c.var.kv, c.var.vector, c.var.thread, and other services.
Next Steps
- Creating HTTP Routes for route parameters, validation, and request context
- Hono RPC + TanStack Query for end-to-end type safety with explicit routing
- Middleware for authentication, rate limiting, and logging