Projects, workflows and runs
Define a runnable file, choose an execution identity, and run it through the CLI or Studio.
A workflow is a reusable definition. A run is the recorded work for one input identity. Start by making this distinction concrete without an agent.
Add a workflow
After initializing a project, save this file at
laufwerk/workflows/estimate/workflow.ts.
import { Workflow } from "@effect/workflow";
import { Effect, Schema } from "effect";
export const workflow = Workflow.make({
name: "estimate",
payload: {
requestId: Schema.String,
pages: Schema.Number.pipe(Schema.int(), Schema.between(1, 100)),
},
success: Schema.Struct({ minutes: Schema.Number }),
error: Schema.String,
idempotencyKey: input => input.requestId,
});
export const layer = workflow.toLayer(input =>
Effect.succeed({ minutes: input.pages * 3 }),
);payload validates input. success describes the result. toLayer registers the
implementation. Constructing an Effect describes work; the runtime executes it.
For multiple operations, Effect.gen and yield* let you use each successful
value in the next operation.
Start and inspect it
From the project root:
bunx laufwerk@0.0.1-alpha.13 run estimate --input '{"requestId":"estimate-1","pages":4}' --jsonThe workflow result is {"minutes":12}, inside the CLI's run response.
Repeat the command: the same request ID addresses the same run. Changing pages
while keeping requestId is not a request to recalculate it. Use estimate-2
for genuinely new work. Existing runs also retain their original workflow bundle;
editing the file changes future runs.
Studio's Start run uses the same definition and identity. Applications can start it through HTTP.
Organize only what you need
laufwerk/
workflows/estimate/workflow.ts # Discovered definition and registration
agents/ # Reusable model/tool configurations
tools/ # Your callable integration code
components/ # Reusable workflow logic
project.json # Stable project identity
laufwerk.config.ts # Project configurationThose helper folders do not execute themselves. Import their code from workflows.
Keep project.json when updating so your project retains its connection to run
history. Runtime state lives outside this source tree by default.
Reference: Workflow options and methods · Project configuration