Skip to content
dhanu docs
Browse pages

Guides

Run a workflow from your backend

Workflows are reusable requests with a form attached, list them, fill the form from your own data, and run them on a schedule or on an event.

A workflow is a prompt someone in the workspace has already written and tested, with typed fields for what changes each time, the week to report on, the customer to write to, the file to summarise. Running one from your backend means the prompt lives with the people who own it, and your code only supplies the values.

1. Find the workflow and its fields

Every workflow the key’s creator can run comes back with its fields, key, type, label, whether it is required, and the options of a select.

const workflows = await dhanu.workflows.list();
const weekly = workflows.find((w) => w.title === "Weekly sales summary")!;
console.log(weekly.fields);
// [{ key: "week", type: "text", required: true }, { key: "region", type: "select", options: [...] }]
weekly = next(w for w in dhanu.workflows.list() if w.title == "Weekly sales summary")
print(weekly.fields)

2. Run it with values

Values are validated on the server against the stored fields, a missing required field or an option that is not in the list answers invalid_workflow_values: and the run starts an ordinary task assigned to whatever the workflow says. Send an idempotency key derived from your schedule so a retried cron job runs it once.

const task = await dhanu.workflows.run(
  weekly.id,
  { week: "2026-W38", region: "Bagmati" },
  { idempotencyKey: "weekly-sales-2026-W38" },
);
task = dhanu.workflows.run(
    weekly.id,
    {"week": "2026-W38", "region": "Bagmati"},
    idempotency_key="weekly-sales-2026-W38",
)

3. Collect the result

The task’s reply arrives like any other: stream it, or subscribe to task.completed and read the messages when the delivery lands. A workflow that produces a document, a page, a sheet, a deck, leaves it on the task; read the task’s messages for the artifact id, then export it as HTML, XLSX or PDF.

for await (const message of dhanu.tasks.stream(task.id)) {
  await mail.send({ to: "sales@example.com", text: message.text });
}
for message in dhanu.tasks.stream(task.id):
    mail.send(to="sales@example.com", text=message.text)

Files as field values

A file field takes a file id. Upload the file first with files.upload and pass the returned id in values; the run attaches it to the task’s first message.