Approval Workflow Example

Multi-level approval chain demonstrating conditional branching and memory-informed thresholds.

Overview

This example shows:

Code

import { Workflow } from "@mdwr/sdk";

const approvalWorkflow = Workflow.create("approval_v1")
  .step("initial_review", async (ctx) => {
    const { documentType, amount, urgency } = ctx.input;

    // Query memory for similar approval decisions
    const insights = await ctx.memory.similar({
      situation: "approval_decision",
      context: { documentType, amount, urgency }
    });

    let decision = "approve";
    let reason = "Passed initial review";
    let confidence = 0.7;

    // Use historical insights
    if (insights.length > 0) {
      const best = insights[0];
      if (best.outcome?.success) {
        decision = best.decision.decision;
        reason = `Based on similar case: ${best.decision.reason}`;
        confidence = Math.min(0.95, (best.decision.confidence || 0.7) + 0.1);
      }
    }

    // Business rules
    if (amount > 10000) {
      decision = "requires_manager";
      reason = "Amount exceeds automatic approval limit";
      confidence = 0.9;
    }

    if (urgency === "high" && amount < 5000) {
      decision = "approve";
      reason = "High urgency, low amount - fast track";
      confidence = 0.85;
    }

    return { decision, reason, confidence };
  }, true)
  .step("manager_review", async (ctx) => {
    // Only runs if manager review required
    if (ctx.state.initial_review?.decision !== "requires_manager") {
      return { decision: "skip", reason: "Manager review not required", confidence: 1.0 };
    }

    const { managerId, amount } = ctx.input;

    // Query memory for manager decisions
    const insights = await ctx.memory.similar({
      situation: "manager_approval",
      context: { managerId, amount }
    });

    let decision = "approve";
    let reason = "Manager approved";
    let confidence = 0.8;

    if (insights.length > 0) {
      const best = insights[0];
      decision = best.decision.decision;
      reason = `Manager decision based on history: ${best.decision.reason}`;
      confidence = best.decision.confidence || 0.8;
    }

    // Manager-specific rules
    if (amount > 50000) {
      decision = "requires_director";
      reason = "Amount exceeds manager approval limit";
      confidence = 0.9;
    }

    return { decision, reason, confidence };
  }, true)
  .step("director_review", async (ctx) => {
    // Only runs if director review required
    if (ctx.state.manager_review?.decision !== "requires_director") {
      return { decision: "skip", reason: "Director review not required", confidence: 1.0 };
    }

    const { directorId, amount } = ctx.input;

    // Query memory for director decisions
    const insights = await ctx.memory.similar({
      situation: "director_approval",
      context: { directorId, amount }
    });

    let decision = "approve";
    let reason = "Director approved";
    let confidence = 0.85;

    if (insights.length > 0) {
      const best = insights[0];
      decision = best.decision.decision;
      reason = `Director decision: ${best.decision.reason}`;
      confidence = best.decision.confidence || 0.85;
    }

    return { decision, reason, confidence };
  }, true)
  .step("finalize_approval", async (ctx) => {
    // Determine final status based on all reviews
    const initialDecision = ctx.state.initial_review?.decision;
    const managerDecision = ctx.state.manager_review?.decision;
    const directorDecision = ctx.state.director_review?.decision;

    let finalStatus = "pending";
    let reason = "Approval pending";

    if (initialDecision === "approve") {
      finalStatus = "approved";
      reason = "Approved in initial review";
    } else if (managerDecision === "approve") {
      finalStatus = "approved";
      reason = "Approved by manager";
    } else if (directorDecision === "approve") {
      finalStatus = "approved";
      reason = "Approved by director";
    } else if (directorDecision === "reject" || managerDecision === "reject" || initialDecision === "reject") {
      finalStatus = "rejected";
      reason = "Rejected in review process";
    }

    return {
      decision: finalStatus === "approved" ? "success" : "failed",
      reason,
      confidence: 1.0,
      metadata: {
        finalStatus,
        approvalChain: {
          initial: initialDecision,
          manager: managerDecision,
          director: directorDecision
        }
      }
    };
  }, true);

export default approvalWorkflow;

Running the Example

# Deploy the workflow
npx ts-node scripts/deploy.ts

# Execute with sample input
npx ts-node scripts/execute.ts approval_v1

Input Example

{
  "documentType": "expense",
  "amount": 5000,
  "urgency": "normal",
  "managerId": "mgr123",
  "directorId": "dir456"
}

Key Features

Multi-Level Approval Chain

initial_review → manager_review → director_review → finalize_approval

Conditional Branching

// Manager review only if required
if (ctx.state.initial_review?.decision !== "requires_manager") {
  return { decision: "skip", reason: "...", confidence: 1.0 };
}

Memory-Informed Thresholds

const insights = await ctx.memory.similar({
  situation: "approval_decision",
  context: { documentType, amount, urgency }
});

Use Cases

Next Steps