Skip to content

Start typing to search the documentation.

Routing

Last updated View as Markdown

src/app.ts is an optional entrypoint for providing your own HTTP application in a Flue project. Add this file when your application needs authentication, health checks, webhooks, route prefixes, or other routes alongside the agents and workflows exposed by Flue.

It is an ordinary Hono application, so you can compose Flue routes with your own routes and middleware.

app.ts

Without src/app.ts, Flue generates an application that mounts its public routes at /. When you add src/app.ts, export a Hono application and mount flue() explicitly:

import { flue } from '@flue/runtime/app';
import { Hono, type MiddlewareHandler } from 'hono';
import { authenticate } from './auth.ts';

const requireUser: MiddlewareHandler = async (c, next) => {
  const user = await authenticate(c.req.raw);

  if (!user) {
    return c.json({ error: 'Unauthorized' }, 401);
  }

  await next();
};

const app = new Hono();

app.get('/health', (c) => c.json({ ok: true }));

app.use('/agents/*', requireUser);
app.use('/workflows/*', requireUser);
app.use('/runs/*', requireUser);
app.route('/', flue());

export default app;

In this application, /health is an application-owned route, while flue() serves exposed agents, exposed workflows, and workflow run routes. The middleware protects those Flue route families before requests reach their handlers.

Use broader middleware for requirements shared by a group of routes, such as requiring an authenticated user. When access depends on a specific selected resource, apply that check as well: for example, an agent route should verify that the caller may access the agent instance named by its id, and an application that publishes workflow run reads should authorize access to the selected run.

Because your authored application imports Hono, include hono in your application dependencies. See Project Layout for alternative source directories supported by existing projects.

Add custom routes

A custom application can serve any route your service needs. It can also accept an external event, verify and normalize it, and deliver it to an agent without exposing a direct prompt route for that event source:

import { dispatch } from '@flue/runtime';
import { flue } from '@flue/runtime/app';
import { Hono } from 'hono';
import supportAssistant from './agents/support-assistant.ts';
import { parseVerifiedSupportComment } from './support-webhooks.ts';

const app = new Hono();

app.post('/webhooks/support-comments', async (c) => {
  const event = await parseVerifiedSupportComment(c.req.raw);
  const receipt = await dispatch(supportAssistant, {
    id: event.ticketId,
    session: 'customer-follow-up',
    input: {
      type: 'support.comment.created',
      commentId: event.commentId,
      text: event.text,
    },
  });

  return c.json(receipt, 202);
});

app.route('/', flue());

export default app;

Here, the webhook route belongs to your application: it determines which requests are valid and which agent instance receives the accepted input. dispatch(...) delivers that input asynchronously to the continuing agent session. See Agents for agent interaction patterns and Chat for conversational platform integrations.

Customized routing

For most applications, mount Flue at the root with app.route('/', flue()). You can instead mount it beneath a prefix when Flue is one part of a larger API:

import { flue } from '@flue/runtime/app';
import { Hono } from 'hono';

const app = new Hono();

app.get('/health', (c) => c.json({ ok: true }));
app.route('/api', flue());

export default app;

With this mount, an exposed support-assistant agent is available beneath /api/agents/support-assistant/:id, and an exposed summarize-ticket workflow is available beneath /api/workflows/summarize-ticket. Workflow run routes and Flue’s OpenAPI output are mounted beneath the same prefix.

Apply middleware to the mounted paths your application publishes, such as /api/agents/*, /api/workflows/*, and /api/runs/* in this example.

Exposing agents and workflows

Mounting flue() does not make every discovered agent or workflow directly invocable. Each module opts into its public transports:

Module exportAvailable through the mounted Flue application
Agent routeHTTP prompts at POST /agents/:name/:id beneath the mount path.
Agent websocketWebSocket connections at GET /agents/:name/:id beneath the mount path.
Workflow routeHTTP invocation at POST /workflows/:name beneath the mount path.
Workflow websocketWebSocket invocation at GET /workflows/:name beneath the mount path.

HTTP and WebSocket exposure are independent. An agent used only through application-owned dispatch(...) calls does not need either public transport export.

See Agents for creating and exposing continuing agent instances, and Workflows for exposing finite operations and inspecting their runs.

Next steps

  • Agents — create continuing agents and deliver direct or dispatched input.
  • Workflows — create finite operations and inspect workflow runs.
  • Chat — compose conversational platform ingress with agent sessions.
  • Develop & Build — run the application locally, create build output, and continue to deployment.
  • Observability — observe workflow runs and agent activity.