Building Agents
Purpose and Scope
This page explains the main authoring workflow for a Flue agent: create an agent file, define its behavior with defineAgent(...), attach capabilities such as tools, actions, skills, and a sandbox, then expose the continuing agent instance over HTTP. In Flue terminology, an agent is useful when an application needs a model to keep working within an ongoing context rather than performing one single background operation. If the work is single-use or structured around a fixed input and output, the guide points readers toward workflows instead of agents.
A Flue agent is not just a prompt wrapped around a model call. The agent definition describes a harness: the model, instructions, environment, callable capabilities, and routing surface that let the model keep working over time. The Building Agents guide teaches this through concrete files under src/agents/, where the filename becomes part of the agent identity, and where the default export created by defineAgent(...) supplies the runtime configuration. Sources: apps/docs/src/content/docs/guide/building-agents.md
Relevant Source Files
apps/docs/src/content/docs/guide/building-agents.md— First-party guide for creating an agent, configuring model and instructions, adding actions, tools, skills, and sandbox support, importing markdown instructions, and understanding agent IDs and routes.
Core Primitives
The smallest useful Flue agent file lives in src/agents/ and default-exports defineAgent(...) from @flue/runtime. The guide’s joke-teller example also exports an optional description and a route handler typed as AgentRouteHandler. These three pieces answer different questions: the filename gives the agent its name, the description becomes build-time metadata returned by inspection APIs, and the route controls how the agent is exposed over HTTP. The default export is the actual behavior and environment definition that the runtime uses.
The object returned from defineAgent(...) is where composition happens. At minimum it can specify a model and instructions; for real application work it can also include cwd, actions, tools, skills, and sandbox. The guide’s repository reviewer example uses anthropic/claude-sonnet-4-6, review-oriented instructions, a working directory under /srv/repositories/catalog-service, imported skill content, a reusable action, shared repository tools, and local() from @flue/runtime/node for sandboxing. Sources: apps/docs/src/content/docs/guide/building-agents.md
Creating an Agent File
Start by adding a TypeScript module under src/agents/. In the guide, src/agents/joke-teller.ts defines a joke-teller agent because the filename is used as the agent name. The file imports defineAgent and optionally AgentRouteHandler from @flue/runtime, exports a non-empty static description, and defines a route that calls next(). The route makes the agent reachable at POST /agents/joke-teller/:id, while event streaming is available at GET /agents/joke-teller/:id.
import { defineAgent, type AgentRouteHandler } from '@flue/runtime';
export const description = 'Tells a short joke in response to each message.';
export const route: AgentRouteHandler = async (_c, next) => next();
export default defineAgent(() => ({
model: 'anthropic/claude-haiku-4-5',
instructions: 'Tell a short joke in response to each message.',
}));This structure separates deployment metadata, HTTP exposure, and runtime behavior without requiring separate registration code. The description is optional, but when present it must be a non-empty string and is collected into the deployment manifest. The route is also an explicit safety boundary: applications can expose, protect, or wrap agent access using normal route-handler logic before work reaches the agent implementation. Sources: apps/docs/src/content/docs/guide/building-agents.md
Composing Capabilities
After the basic agent exists, expand the returned configuration object around the work the agent must perform. Instructions tell the model how to behave, while the model string selects the provider-backed model. Tools execute bounded application functions, actions let the model call finite durable agent-backed operations, and skills provide reusable guidance that can be shared across agents. Sandboxes give the agent a controlled environment for filesystem or command work, and cwd establishes the working directory for that environment.
import { defineAgent } from '@flue/runtime';
import { local } from '@flue/runtime/node';
import reviewChecklist from '../skills/review-checklist/SKILL.md' with { type: 'skill' };
import { reviewChange } from '../actions/review-change.ts';
import { repositoryTools } from '../shared/repository-tools.ts';
export default defineAgent(() => ({
model: 'anthropic/claude-sonnet-4-6',
instructions: 'Review the requested change and report only findings supported by evidence.',
cwd: '/srv/repositories/catalog-service',
actions: [reviewChange],
tools: repositoryTools,
skills: [reviewChecklist],
sandbox: local(),
}));Use this composition step to make the harness match the task, not to make the model generally powerful. A repository reviewer needs evidence-oriented instructions, repository-aware tools, review actions, checklist skills, and a sandboxed workspace. A support assistant or triage agent would choose different tools, skills, and routes. The important pattern is that capabilities are declared close to the agent definition, so the runtime can build a coherent environment from the file. Sources: apps/docs/src/content/docs/guide/building-agents.md
Instructions and Skill Imports
Short instructions can be embedded directly as a string, but longer instructions can live in a markdown file. The guide shows importing a .md file with the with { type: 'markdown' } import attribute and passing the imported value as instructions. That import attribute is required: a plain .md import without the attribute fails the build. This keeps long behavioral guidance readable while still making the final agent definition explicit and statically analyzable.
import { defineAgent } from '@flue/runtime';
import instructions from './repository-reviewer.md' with { type: 'markdown' };
export default defineAgent(() => ({
model: 'anthropic/claude-sonnet-4-6',
instructions,
}));Skills use a different import contract. A SKILL.md file is not treated as ordinary markdown instructions; it must be imported with with { type: 'skill' } and then provided through the skills array. This distinction matters because instructions describe the agent’s primary behavior, while skills are reusable packets of specialized guidance that augment the agent when the task calls for them. Sources: apps/docs/src/content/docs/guide/building-agents.md
Agent IDs and HTTP Surface
Each agent request includes an id that identifies the continuing instance of that agent. In the documented route shape, POST /agents/support-assistant/ticket-8472 uses ticket-8472 as the instance identifier. Flue leaves the meaning of that identifier to the application, so it can represent a support ticket, account, repository review, user session, or any other durable unit of work. The key point is that the same configured agent can have many continuing instances, each addressed by its own ID.
That ID is what makes an agent appropriate for ongoing interaction. Instead of treating every model call as independent, the application can route follow-up messages and streaming reads to the same logical agent instance. The guide pairs this with an event-streaming endpoint at GET /agents/:name/:id, allowing clients to observe progress after submitting work. When designing IDs, choose values that line up with your product’s authorization and persistence model, because the route makes them part of the public interaction contract. Sources: apps/docs/src/content/docs/guide/building-agents.md
Implementation Checklist
- Create
src/agents/<agent-name>.ts; the filename becomes the agent name. - Export
default defineAgent(() => ({ ... }))with at leastmodelandinstructions. - Add a non-empty
descriptionwhen the agent should appear in build-time manifest metadata and inspection output. - Add an
AgentRouteHandlerexport when the agent should be exposed through an HTTP route such asPOST /agents/<agent-name>/:id. - Use
with { type: 'markdown' }for long instruction files andwith { type: 'skill' }forSKILL.mdimports. - Add
actions,tools,skills,cwd, andsandboxonly when they are part of the agent’s real operating environment.
Next Steps
After defining the first agent, continue by tightening the pieces around it. Read the models guide to decide which provider and model string to use, the tools and actions guides to expose application capabilities safely, the skills guide to package reusable expertise, and the sandboxes guide before allowing filesystem or command execution. If the agent must delegate specialist work, move next to subagents; if the task is single-use or structured, use workflows instead of forcing it into a continuing agent shape.