Docs
Creating a Workflow
Creating a Workflow
How POST /api/workflows works — from goal text to a saved plan sent to your inbox.
The API Call
POST /api/workflows
Authorization: Bearer <session>
{
"goal": "Publish a weekly LinkedIn post about AI news every Monday morning",
"schedule": "0 9 * * 1" // optional cron string
}The response returns the created workflow with its generated steps:
{
"workflowId": "abc123",
"title": "Weekly AI News LinkedIn Post",
"steps": [...],
"status": "draft",
"message": "Plan created. Check your email to approve and activate."
}How the Plan is Generated
The endpoint calls generateWorkflowPlan(goal, businessName, coreMemory) from lib/ai/workflows/planner.ts:
const { output } = await generateText({
model: openai("gpt-4o"),
output: Output.object({ schema: WorkflowPlanSchema }),
system: `...planner instructions with available tools...`,
prompt: `Goal: ${goal}`,
});This is a single deterministic LLM call — not a ToolLoopAgent. It returns a strongly-typed WorkflowPlan:
WorkflowPlanSchema = z.object({
title: z.string(), // max 60 chars
steps: z.array(z.object({
stepIndex: z.number(), // 0-based, no gaps
description: z.string(), // shown in UI and emails
toolName: z.enum(WORKFLOW_TOOL_NAMES),
})).min(1).max(20),
})Available Planner Tools
The planner can choose from these tools when generating steps:
| Tool | When to Use |
|---|---|
web_search | Find current facts, news, trending topics |
web_extract | Pull full content from a specific URL |
generate_outline | Structure content before writing |
generate_report | Internal research summaries and reports |
format_post | Produce the final formatted post |
generate_image | Create a visual asset |
memory | Read or update team memory |
llm_response | Free-form assistant message (summarize, transition, explain) |
The planner system prompt enforces two rules:
generate_outlinemust always come beforeformat_postformat_postandgenerate_imagealways getrequiresApproval: true
After the Plan is Saved
- Workflow saved with
status: "draft"and all steps inworkflowSteps - If a
schedulewas provided, it's stored inworkflows.schedule(cron string) - A 24-hour JWT is signed with
WORKFLOW_TOKEN_SECRET sendPlanApprovalEmail()sends an HTML email with the step table and an "Approve & Activate" button
If the approval email fails to send, the workflow is still saved in draft state and can be approved programmatically via POST /api/workflows/[id]/approve.