> ## Documentation Index
> Fetch the complete documentation index at: https://synthetiq.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Add a workflow

> Background job that sends a daily task summary via Slack

Workflows provide durable background execution for async processing, scheduled jobs, multi-step pipelines, and data aggregation. Apps define workflows in `src/server/workflows/` and schedule them via `schedules.json`.

## Daily task summary

We want the task tracker to have a daily workflow that aggregates task metrics, generates a human-readable summary with the Anthropic LLM service, and posts it to the team Slack channel.

Define the workflow in `src/server/workflows/dailySummary.ts`:

```typescript theme={null}
import type { JobDefinition } from '@synthetiq/workflows';

export const dailySummary: JobDefinition = {
  name: "Daily Task Summary",
  description: "Aggregate task metrics, generate an AI summary, and post to Slack",
  variables: {
    appId: { type: "param" },
  },
  steps: [
    {
      importFromDatabase: {
        appId: "{{var.appId}}",
        tableName: "Task",
        columns: ["id", "status", "createdAt"],
      },
      outputTable: "tasks",
    },
    {
      sql: `
        SELECT
          COUNT(*) AS totalTasks,
          SUM(CASE WHEN status = 'completed' THEN 1 ELSE 0 END) AS completedTasks,
          SUM(CASE WHEN status = 'active' THEN 1 ELSE 0 END) AS activeTasks
        FROM tasks
      `,
      outputTable: "summary",
    },
    {
      service: "anthropic",
      operation: "streamMessage",
      forEach: { source: "summary" },
      params: {
        model: "claude-sonnet-4-20250514",
        max_tokens: 256,
        messages: [
          {
            role: "user",
            content: "Write a brief daily task summary for a team Slack channel. Total tasks: {{item.totalTasks}}, completed: {{item.completedTasks}}, active: {{item.activeTasks}}. Keep it concise and friendly.",
          },
        ],
      },
      outputTable: "aiSummary",
      outputSchema: {
        text: "VARCHAR",
      },
    },
    {
      service: "slack",
      operation: "sendMessage",
      forEach: { source: "aiSummary" },
      params: {
        channel: "#task-updates",
        text: "{{item.text}}",
      },
      outputTable: "slackResult",
      outputSchema: {
        ok: "BOOLEAN",
        ts: "VARCHAR",
      },
    },
  ],
};
```

Export it from `src/server/workflows/index.ts`:

```typescript theme={null}
export { dailySummary } from './dailySummary';
```

## Scheduling

Configure the workflow to run daily in `schedules.json`:

```json theme={null}
{
  "schedules": [
    {
      "name": "daily-task-summary",
      "cron": "0 2 * * *",
      "timezone": "UTC",
      "skipIfRunning": true,
      "workflow": "./src/server/workflows/dailySummary.ts",
      "params": {
        "appId": "task-tracker"
      }
    }
  ]
}
```

Schedules are registered during the build pipeline and validated against the workflow definitions.

For the full workflow DSL, step types, pagination, forEach, error handling, and worker configuration, see the [Workflows Framework](/docs/platform-docs/workflows-framework/overview).
