Skip to main content
Every code block receives input (array from previous step) and must return an array (for the next step).

The Basics

// input: records from previous step
// return: records for next step

return input.map(record => ({
  ...record,
  processed: true,
}));

input

ScenarioWhat’s in input
First step[] or trigger data
After company discoveryCompany objects
After people searchPerson objects
After contact enrichmentContact objects with emails/phones

return

PatternCode
Transformreturn input.map(r => ({ ...r, new_field: "value" }))
Filterreturn input.filter(r => r.employee_count > 50)
New datareturn await canvas.companies.find({...})
Passthroughreturn input
Rules:
  • Must return an array
  • return [] stops the flow
  • No return = passthrough

Common Patterns

Add fields to each record

return input.map(record => ({
  ...record,
  tier: record.employee_count > 500 ? "Enterprise" : "SMB",
}));

Enrich with AI

for (const record of input) {
  record.summary = await canvas.ai.research({
    prompt: "Summarize this company",
    data: record,
  });
}
return input;

Filter + transform

return input
  .filter(r => r.industry === "SaaS")
  .map(r => ({ ...r, priority: "high" }));

Execution Environment

Not allowed: fetch(), require(), import, eval(), file system, env vars
Available: All canvas.* methods, async/await, ES2020+ JavaScript, 30s timeout