Workflow API
The Workflow API is exported from @flue/runtime.
defineWorkflow()
function defineWorkflow<TAction extends ActionDefinition>(options: {
agent: AgentDefinition;
action: TAction;
}): WorkflowDefinition<TAction>;
function defineWorkflow<TInput, TOutput>(options: {
agent: AgentDefinition;
input?: TInput;
output?: TOutput;
run(context: ActionContext<TInput>): unknown | Promise<unknown>;
}): WorkflowDefinition<ActionDefinition<TInput, TOutput>>;
Creates a branded workflow value. Default-export it from a discovered workflows/<name>.ts module.
agent is required and supplies the execution policy and root harness. Exactly one of action or run is required. The extracted form does not accept input or output; those contracts belong to its Action. The inline form creates a workflow-private Action and uses the same schema, context, validation, serialization, and lifecycle contracts as defineAction().
The agent may be private to the workflow. Discovery under agents/ is required only for persistent agent routes and dispatch().
WorkflowDefinition
interface WorkflowDefinition<TAction extends ActionDefinition> {
readonly agent: AgentDefinition;
readonly action: TAction;
}
Treat a Workflow Definition as an opaque identity. The generated runtime associates the exact discovered default-exported value with its module name.
HTTP exports
HTTP routing is not a defineWorkflow() option. Export either middleware separately from the workflow module:
export default defineWorkflow({ agent, action });
export const route: WorkflowRouteHandler = invokeMiddleware;
export const runs: WorkflowRunsHandler = runMiddleware;
route enables and controls POST /workflows/:name only. runs separately exposes and controls every HTTP operation on existing runs owned by this workflow, including GET, HEAD, ?meta, unsupported methods, and future run methods. Both are ordinary Hono middleware and may return a response or call next().
Without runs, the HTTP run resource returns the same generic 404 as an unknown or removed workflow run. Unsupported methods return 405 only after Flue resolves an exposed run and its middleware authorizes the request. Neither export affects invoke(), listRuns(), getRun(), or schedules. Temporary local flue run runtimes additionally expose route-free resources through an existing authored flue() mount; absolute --server attachments do not.
invoke()
function invoke<TWorkflow extends WorkflowDefinition>(
workflow: TWorkflow,
request: WorkflowInvokeRequest<TWorkflow>,
): Promise<WorkflowInvocationReceipt>;
Admits one workflow run through the configured Flue runtime and resolves after admission. It does not wait for Action execution or run route middleware.
The workflow must be the exact default export of a discovered workflow module in the current built application. A workflow with an input schema requires { input }; a workflow without one accepts no input property.
interface WorkflowInvocationReceipt {
readonly runId: string;
}
Input is snapshotted as JSON before admission. Runtime validation against the Action schema occurs when the workflow executes.
Lifecycle
For each invocation, Flue:
- represents omitted input as
undefinedand rejects non-undefinedinput for a workflow without an input schema; - snapshots and admits the caller input for detached invocation;
- validates and transforms declared Action input before initializing the agent or sandbox;
- emits
run_startand initializes the workflow’s agent and root harness; - runs the Action with transformed input;
- validates and serializes output;
- closes invocation resources before persisting
run_endand the terminal result or error.
Schema-invalid input can therefore produce an admitted, observable failed run, but it never initializes the agent definition or sandbox.
RunRecord.input contains the admitted input. The first lifecycle event is normally run_start, whose input field carries the same value. Interrupted admission may instead expose run_resume first. run_end records terminal success or failure.
invoke() and routed/SDK invocation create the same workflow-run model. dispatch() is different: it admits input to a continuing agent instance and returns a dispatchId, not a run.
Errors
| Error | type | Contract |
|---|---|---|
WorkflowInvocationNotConfiguredError | workflow_invocation_not_configured | invoke() ran outside a configured Flue-built server. |
WorkflowNotDiscoveredError | workflow_not_discovered | The exact workflow value is not registered in this application. |
WorkflowInputUnexpectedError | workflow_input_unexpected | Input was supplied to an Action without an input schema. |
WorkflowInputSerializationError | workflow_input_serialization | invoke().input is not JSON-serializable. |
WorkflowAdmissionUnavailableError | workflow_admission_unavailable | This runtime has no workflow admission hook. |
WorkflowAdmissionError | workflow_admission_failed | Target admission failed; meta.workflow identifies the module. |
Action input, output, and serialization errors are documented in the Action API.