Creating Workflows
Workflows are sequences of steps that execute in order. Each step can make decisions based on input, state, and historical memory.
Basic Workflow
import { Workflow } from "@mdwr/sdk";
const workflow = Workflow.create("my_workflow_v1")
.step("step1", async (ctx) => {
return {
decision: "proceed",
reason: "Step 1 completed",
confidence: 1.0
};
}, true)
.step("step2", async (ctx) => {
return {
decision: "completed",
reason: "Step 2 completed",
confidence: 1.0
};
}, true);
Step Handlers
Step handlers receive a context object with:
ctx.input- Input data for the workflowctx.state- State from previous stepsctx.memory- Memory interface for querying decisions
.step("my_step", async (ctx) => {
const { userId, amount } = ctx.input;
const previousDecision = ctx.state.previous_step?.decision;
// Query memory
const insights = await ctx.memory.similar({
situation: "my_decision",
context: { userId, amount }
});
return {
decision: "approve",
reason: "Based on analysis",
confidence: 0.9
};
}, true)
Decision Structure
Steps with decision_required: true must return:
{
decision: string; // Required: decision value
reason: string; // Required: explanation
confidence?: number; // Optional: 0-1 confidence score
metadata?: object; // Optional: additional data
}
Conditional Execution
Steps can check previous step decisions:
.step("next_step", async (ctx) => {
if (ctx.state.previous_step?.decision !== "approve") {
return {
decision: "skip",
reason: "Previous step did not approve",
confidence: 1.0
};
}
// Continue execution
return {
decision: "completed",
reason: "Step executed",
confidence: 1.0
};
}, true)
Memory Integration
Query similar historical decisions:
const insights = await ctx.memory.similar({
situation: "refund_decision",
context: {
amount: ctx.input.amount,
userTier: ctx.input.userTier
}
});
if (insights.length > 0) {
const best = insights[0];
// Use best.decision, best.reason, best.confidence
}
Workflow Patterns
Sequential Steps
const workflow = Workflow.create("sequential")
.step("validate", handler1, true)
.step("process", handler2, true)
.step("finalize", handler3, true);
Conditional Branching
.step("branch", async (ctx) => {
const decision = ctx.state.validate?.decision;
if (decision === "approve") {
return { decision: "route_a", reason: "...", confidence: 1.0 };
} else {
return { decision: "route_b", reason: "...", confidence: 1.0 };
}
}, true)
Memory-Informed Decisions
.step("decide", async (ctx) => {
const insights = await ctx.memory.similar({
situation: "my_decision",
context: ctx.input
});
let decision = "default";
let reason = "Default decision";
if (insights.length > 0) {
const best = insights[0];
decision = best.decision.decision;
reason = `Based on history: ${best.decision.reason}`;
}
return { decision, reason, confidence: 0.9 };
}, true)
Next Steps
- Memory Integration - Use memory effectively
- Replay Modes - Replay workflows
- Examples - See real examples