Pre-built workflow templates for common business scenarios. Clone, customize, and deploy in minutes.
A complete workflow for handling property inquiries in a property management system.
// workflows/property-inquiry.ts
import { createWorkflow, step } from "@/lib/workflows"
export const propertyInquiryWorkflow = createWorkflow({
id: "property-inquiry",
name: "Property Inquiry Handler",
version: "1.0.0",
trigger: {
type: "event",
event: "inquiry.received",
},
steps: [
// Step 1: Validate inquiry data
step({
id: "validate-inquiry",
name: "Validate Inquiry",
agent: "data-validator",
action: async (context) => {
const { inquiry } = context.trigger.data
// Validate required fields
const required = ["name", "email", "property_id", "message"]
const missing = required.filter(f => !inquiry[f])
if (missing.length > 0) {
return {
status: "failed",
error: `Missing fields: ${missing.join(", ")}`
}
}
return { status: "valid", inquiry }
}
}),
// Step 2: Enrich lead data
step({
id: "enrich-lead",
name: "Enrich Lead Data",
agent: "lead-enrichment",
dependsOn: ["validate-inquiry"],
action: async (context) => {
const { inquiry } = context.steps["validate-inquiry"].output
// Look up existing tenant/lead records
const existingLead = await db.leads.findByEmail(inquiry.email)
// Fetch property details
const property = await db.properties.findById(inquiry.property_id)
return {
lead: existingLead || { email: inquiry.email, name: inquiry.name },
property,
isReturningLead: !!existingLead
}
}
}),
// Step 3: Score lead quality
step({
id: "score-lead",
name: "Score Lead",
agent: "lead-scoring",
dependsOn: ["enrich-lead"],
action: async (context) => {
const { lead, property, isReturningLead } = context.steps["enrich-lead"].output
let score = 50 // Base score
// Scoring factors
if (isReturningLead) score += 20
if (lead.verified_income) score += 15
if (lead.previous_rentals > 0) score += 10
if (property.price <= lead.budget * 1.1) score += 15
return {
score,
priority: score >= 80 ? "high" : score >= 60 ? "medium" : "low",
factors: { isReturningLead, hasIncome: !!lead.verified_income }
}
}
}),
// Step 4: HITL approval for high-value leads
step({
id: "approval-gate",
name: "Manager Approval",
type: "hitl",
dependsOn: ["score-lead"],
condition: (context) => {
const { priority } = context.steps["score-lead"].output
return priority === "high"
},
hitl: {
approvers: ["property-manager"],
timeout: "4h",
autoApprove: {
enabled: true,
after: "2h",
conditions: { "score-lead.output.score": { gte: 90 } }
}
}
}),
// Step 5: Schedule viewing
step({
id: "schedule-viewing",
name: "Schedule Viewing",
agent: "scheduling-agent",
dependsOn: ["approval-gate"],
action: async (context) => {
const { lead, property } = context.steps["enrich-lead"].output
// Find available time slots
const slots = await calendar.getAvailableSlots({
propertyId: property.id,
duration: 30,
daysAhead: 7
})
// Send scheduling email
await email.send({
to: lead.email,
template: "viewing-invitation",
data: { property, slots: slots.slice(0, 3) }
})
return { slots, emailSent: true }
}
}),
// Step 6: Create CRM record
step({
id: "create-record",
name: "Create CRM Record",
agent: "crm-agent",
dependsOn: ["schedule-viewing"],
action: async (context) => {
const { lead, property } = context.steps["enrich-lead"].output
const { score, priority } = context.steps["score-lead"].output
const record = await crm.createOpportunity({
lead,
property,
score,
priority,
stage: "viewing-scheduled",
source: "website-inquiry"
})
return { recordId: record.id, stage: "viewing-scheduled" }
}
})
],
onComplete: async (context) => {
// Notify team of new qualified lead
await notifications.send({
channel: "slack",
message: `New qualified lead: ${context.steps["enrich-lead"].output.lead.name}`
})
},
onError: async (context, error) => {
// Log error and notify
await logging.error("property-inquiry-failed", { error, context })
}
})Complete e-commerce order processing with inventory checks, payment, and shipping.
// workflows/order-fulfillment.ts
import { createWorkflow, step, parallel } from "@/lib/workflows"
export const orderFulfillmentWorkflow = createWorkflow({
id: "order-fulfillment",
name: "Order Fulfillment Pipeline",
trigger: {
type: "event",
event: "order.placed",
},
steps: [
// Parallel: Check inventory and validate payment
parallel({
id: "initial-checks",
steps: [
step({
id: "check-inventory",
agent: "inventory-agent",
action: async (ctx) => {
const { items } = ctx.trigger.data.order
const availability = await inventory.checkBulk(items)
return { available: availability.every(i => i.inStock), items: availability }
}
}),
step({
id: "validate-payment",
agent: "payment-agent",
action: async (ctx) => {
const { paymentIntent } = ctx.trigger.data.order
const payment = await stripe.paymentIntents.retrieve(paymentIntent)
return { valid: payment.status === "succeeded", payment }
}
})
]
}),
// Reserve inventory
step({
id: "reserve-inventory",
agent: "inventory-agent",
dependsOn: ["initial-checks"],
condition: (ctx) => ctx.steps["check-inventory"].output.available,
action: async (ctx) => {
const { items } = ctx.trigger.data.order
const reservations = await inventory.reserveBulk(items, { ttl: "24h" })
return { reservations }
}
}),
// Generate shipping label
step({
id: "create-shipment",
agent: "shipping-agent",
dependsOn: ["reserve-inventory"],
action: async (ctx) => {
const { shippingAddress, items } = ctx.trigger.data.order
const shipment = await shipping.createLabel({
to: shippingAddress,
parcels: items.map(i => ({ weight: i.weight, dimensions: i.dimensions })),
carrier: "auto" // Auto-select cheapest carrier
})
return { trackingNumber: shipment.trackingNumber, label: shipment.labelUrl }
}
}),
// Notify warehouse
step({
id: "notify-warehouse",
agent: "notification-agent",
dependsOn: ["create-shipment"],
action: async (ctx) => {
const { reservations } = ctx.steps["reserve-inventory"].output
const { trackingNumber, label } = ctx.steps["create-shipment"].output
await warehouse.createPickList({
orderId: ctx.trigger.data.order.id,
items: reservations,
shippingLabel: label
})
return { pickListCreated: true }
}
}),
// Send confirmation email
step({
id: "send-confirmation",
agent: "email-agent",
dependsOn: ["create-shipment"],
action: async (ctx) => {
const { customer, order } = ctx.trigger.data
const { trackingNumber } = ctx.steps["create-shipment"].output
await email.send({
to: customer.email,
template: "order-confirmation",
data: { order, trackingNumber }
})
return { emailSent: true }
}
})
]
})// Clone and customize a template
import { cloneTemplate, registerWorkflow } from "@/lib/workflows"
// Clone the property inquiry template
const myWorkflow = cloneTemplate("property-inquiry", {
// Override specific configurations
id: "my-property-inquiry",
name: "Custom Property Inquiry",
// Customize steps
steps: {
"score-lead": {
// Add custom scoring logic
action: async (context) => {
const { lead } = context.steps["enrich-lead"].output
// Your custom scoring
let score = 50
if (lead.creditScore >= 700) score += 25
if (lead.employmentYears >= 2) score += 15
return { score, priority: score >= 75 ? "high" : "medium" }
}
}
},
// Add additional steps
additionalSteps: [
step({
id: "background-check",
name: "Background Check",
agent: "verification-agent",
dependsOn: ["score-lead"],
condition: (ctx) => ctx.steps["score-lead"].output.priority === "high",
action: async (ctx) => {
// Run background check for high-priority leads
}
})
]
})
// Register the customized workflow
registerWorkflow(myWorkflow)