First workflow
This guide walks you through creating a real workflow from scratch. You'll write a YAML definition, a TypeScript handler, and run it locally.
Define the workflow
Create workflows/greet.yaml:
id: greet
name: Hello workflow
steps:
- id: say-hello
handler: plugins/hello/say-hello
input:
name: "World"
- id: log-result
handler: plugins/hello/log
input:
message: "{{ steps.say-hello.output.greeting }}"
Write the handler
Create plugins/hello/say-hello.ts:
import type { HandlerContext } from '@kb-labs/sdk';
type Input = { name: string };
type Output = { greeting: string };
export async function handler(input: Input, ctx: HandlerContext): Promise<Output> {
ctx.logger.info(`Greeting ${input.name}`);
return { greeting: `Hello, ${input.name}!` };
}
Handlers are plain async functions. No framework, no magic — just TypeScript with a typed context object.
Run the workflow
kb workflow run greet
Output:
✓ Step say-hello completed in 12ms
→ { greeting: "Hello, World!" }
✓ Step log-result completed in 3ms
✓ Workflow greet finished in 18ms
How step outputs flow
Each step's output is available to subsequent steps via template syntax:
message: "{{ steps.say-hello.output.greeting }}"
The engine resolves these at runtime before passing input to the handler.
Next steps
- Plugin System — Learn how plugins are structured and deployed
- State Broker — Persist state across workflows