Flue Zero to Expert, Part 2: Typed Workflows
Build a finite Flue workflow with Valibot boundaries, run it from the CLI, and inspect its validated result.
Series map
Part 1: Your First Flue Agent · Part 2: Typed Workflows · Part 3: Safe Tools · Part 4: Autonomous Agents · Part 5: Persistence and Durable Execution · Part 6: Production Routing and Deployment · Part 7: Operate Like an Expert
Tested with Flue 1.0.0-beta.9. Beta APIs and CLI behavior may change in later releases.
Choose a finite workflow
An agent can continue across messages. A workflow handles one finite operation. Each invocation creates a separate run with its own result and event history.
Use a workflow for a review, transformation, background job, or CI task. Use an agent when later messages must continue the same conversation.
A workflow does not make model output deterministic. It gives the operation a fixed entry point, validated boundaries, and an inspectable run.
Build a typed review workflow
If you followed Part 1, add Valibot and create the workflow directory:
npm install valibot
mkdir -p src/workflowsCreate src/workflows/review.ts:
import { defineAgent, defineWorkflow } from '@flue/runtime';
import * as v from 'valibot';
export default defineWorkflow({
agent: defineAgent(() => ({
model: 'anthropic/claude-haiku-4-5',
})),
input: v.object({
text: v.string(),
}),
output: v.object({
review: v.string(),
}),
async run({ harness, input }) {
const session = await harness.session();
const response = await session.prompt(
`Review this text. Be concise and identify the main risk:\n\n${input.text}`,
);
return {
review: response.text,
};
},
});In beta.9, the filename makes the discovered workflow name review, and its default export must be the value returned by defineWorkflow().
Valibot validates input before the agent or sandbox is initialized. It also validates and serializes the returned object. Invalid data fails the run instead of silently crossing the workflow boundary.
The schemas infer typed input and output in application code and define the JSON-compatible data stored for the run.
The model uses a provider/model specifier. This example requires ANTHROPIC_API_KEY in the runtime environment. Keep credentials out of source files and committed configuration.
Run it from the CLI
Pass the workflow input as JSON:
npx flue run review --input '{"text":"Deploy every change directly to production."}'In beta.9, flue run validates the JSON, starts the configured application temporarily, and invokes the workflow through its existing flue() mount. It reports run events, prints the successful JSON result, and exits.
The normal application pipeline and middleware still execute. Local invocation does not bypass application behavior.
Invoke it from server code
Inside an application-owned route, channel, schedule, or other code running in a Flue-built server, use ambient invoke():
import { invoke } from '@flue/runtime';
import review from './workflows/review.ts';
const { runId } = await invoke(review, {
input: { text: 'Deploy every change directly to production.' },
});
console.log(runId);invoke() admits work and returns a run ID; it does not wait for completion. The workflow value must be the exact default export of a discovered module in the current built application. Outside a configured Flue-built server, ambient invocation fails.
For user-facing code, consume run events or use an exposed SDK invocation with wait: 'result' rather than adding an ad hoc polling loop.
Workflow HTTP access is private by default in beta.9. Invoking a workflow route and reading its run records are separate capabilities, controlled by separate route and runs exports. Run records can contain prompts, results, and model activity. Protect both surfaces with authorization, and never treat a run ID as a credential.
Keep Actions earned
Define behavior inline when only this workflow uses it.
Extract an Action when the same validated operation must be reused by workflows, agents, or both. An Action owns its input schema, output schema, and handler.
Binding an Action to a workflow does not automatically expose it to the model. Adding an Action to an agent also does not create a workflow or public endpoint. Configure each capability deliberately.
Next, continue to Part 3: Safe Tools to add a narrow, authorized capability.