# Weekly Report Email Agent (/docs/receipes/weekly-report-email-agent)



This recipe tells an agent exactly how to build a weekly reporting workflow in andibase.

Goal [#goal]

Create three things in one workspace:

1. A `weekly-report` data definition.
2. A `weekly-report-delivery` data definition.
3. One agent that creates weekly reports and tracks whether email delivery is complete or still pending.

Expected outcome [#expected-outcome]

After following this recipe, the workspace should have:

* a `weekly-report` definition for generated report content
* a `weekly-report-delivery` definition for email recipients and delivery state
* a `weekly-report-agent` agent

Use the API documented in:

* [Data Model](/docs/data-model)
* [Get started (for AI Agents)](/docs/agent-get-started)
* [Data definitions API](/docs/api-reference/data-definitions)
* [Data API](/docs/api-reference/data)
* [Agents API](/docs/api-reference/agents)
* [Agent Tools](/docs/agent-tools)

Current runtime constraint [#current-runtime-constraint]

The current workspace agent runtime exposes data tools, not a direct email-sending tool.

That means this recipe should:

* generate the weekly report
* save the report in workspace data
* create delivery rows for each recipient
* mark email delivery as `pending` when direct email sending is not available

If a future integration, automation, or external system handles email delivery, it can read the pending delivery rows and complete them later.

Agent instructions [#agent-instructions]

When an agent executes this recipe, it should follow these rules:

1. Create the `weekly-report` definition first.
2. Create the `weekly-report-delivery` definition second.
3. In the current API, data definition handles are generated from `name`. Use `name: "Weekly Report"` and `name: "Weekly Report Delivery"` so the created handles normalize to `weekly-report` and `weekly-report-delivery`.
4. If your execution environment can resolve the created weekly-report definition id, wire the delivery-to-report link as a `relationship` field. If it cannot, use a text foreign key such as `reportRecordId` instead, because the public HTTP API still expects `dataDefinitionId` for relationship fields.
5. Create the weekly-report agent with instructions focused on report generation, persistence, and delivery tracking.
6. Use the current agent tools. Do not claim an email was sent unless the execution environment actually sent it.
7. If email sending is not available, create or update delivery rows with a pending status and a clear pending reason.
8. Ask the user only when a missing choice materially changes the report, such as recipient list, reporting period, or source data scope.

Step 1: Create the data model [#step-1-create-the-data-model]

Create two data definitions: `weekly-report` and `weekly-report-delivery`.

1\. Weekly Report definition [#1-weekly-report-definition]

Use `name: "Weekly Report"`. The current API derives the handle from the name, so this will create the `weekly-report` handle.

Recommended fields:

```json
{
  "name": "Weekly Report",
  "description": "Stores generated weekly summaries and their operational status.",
  "fields": {
    "title": {
      "name": "Title",
      "type": "text"
    },
    "periodStart": {
      "name": "Period start",
      "type": "date"
    },
    "periodEnd": {
      "name": "Period end",
      "type": "date"
    },
    "generatedAt": {
      "name": "Generated at",
      "type": "timestamp"
    },
    "status": {
      "name": "Status",
      "type": "select",
      "options": [
        { "value": "draft", "label": "Draft", "color": "zinc" },
        { "value": "generated", "label": "Generated", "color": "blue" },
        { "value": "pending-delivery", "label": "Pending delivery", "color": "amber" },
        { "value": "delivered", "label": "Delivered", "color": "green" }
      ]
    },
    "summary": {
      "name": "Summary",
      "type": "text",
      "variant": "long-text"
    },
    "highlights": {
      "name": "Highlights",
      "type": "json"
    },
    "blockers": {
      "name": "Blockers",
      "type": "json"
    },
    "metrics": {
      "name": "Metrics",
      "type": "json"
    },
    "reportMarkdown": {
      "name": "Report markdown",
      "type": "text",
      "variant": "long-text"
    },
    "sourceNotes": {
      "name": "Source notes",
      "type": "text",
      "variant": "long-text"
    },
    "pendingItems": {
      "name": "Pending items",
      "type": "json"
    }
  }
}
```

Recommended defaults for agent-created report rows:

* `status`: `generated`
* `generatedAt`: now
* `highlights`: `[]`
* `blockers`: `[]`
* `metrics`: `{}`
* `pendingItems`: `[]`

2\. Weekly Report Delivery definition [#2-weekly-report-delivery-definition]

Use `name: "Weekly Report Delivery"`. The current API derives the handle from the name, so this will create the `weekly-report-delivery` handle.

Recommended fields:

```json
{
  "name": "Weekly Report Delivery",
  "description": "Tracks intended recipients and whether delivery is done or still pending.",
  "fields": {
    "reportRecordId": {
      "name": "Report record id",
      "description": "Store the linked weekly-report row id when the client only has public HTTP API access.",
      "type": "text"
    },
    "recipientName": {
      "name": "Recipient name",
      "type": "text"
    },
    "recipientEmail": {
      "name": "Recipient email",
      "type": "text"
    },
    "channel": {
      "name": "Channel",
      "type": "select",
      "options": [
        { "value": "email", "label": "Email", "color": "blue" },
        { "value": "other", "label": "Other", "color": "zinc" }
      ]
    },
    "subject": {
      "name": "Subject",
      "type": "text"
    },
    "deliveryStatus": {
      "name": "Delivery status",
      "type": "select",
      "options": [
        { "value": "pending", "label": "Pending", "color": "amber" },
        { "value": "sent", "label": "Sent", "color": "green" },
        { "value": "blocked", "label": "Blocked", "color": "red" },
        { "value": "skipped", "label": "Skipped", "color": "zinc" }
      ]
    },
    "lastAttemptAt": {
      "name": "Last attempt at",
      "type": "timestamp"
    },
    "sentAt": {
      "name": "Sent at",
      "type": "timestamp"
    },
    "pendingReason": {
      "name": "Pending reason",
      "type": "text",
      "variant": "long-text"
    },
    "deliveryNotes": {
      "name": "Delivery notes",
      "type": "text",
      "variant": "long-text"
    }
  }
}
```

If your client already has the created weekly-report definition id, you can replace `reportRecordId` with:

```json
{
  "reportId": {
    "name": "Report",
    "type": "relationship",
    "dataDefinitionId": "<weekly-report-definition-id>"
  }
}
```

3\. Example create requests [#3-example-create-requests]

Create the definitions with `POST /api/v1/data-definitions`.

Current API note:

* the create payload uses `name`, `description`, and `fields`
* the handle is derived from `name`
* data rows are created with `data`, not `attributes`

Example for `weekly-report`:

```bash
curl -X POST "https://andibase.com/api/v1/data-definitions" \
  -H "Authorization: Bearer $ANDI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Weekly Report",
    "description": "Stores generated weekly summaries and their operational status.",
    "fields": {
      "title": { "name": "Title", "type": "text" },
      "periodStart": { "name": "Period start", "type": "date" },
      "periodEnd": { "name": "Period end", "type": "date" },
      "generatedAt": { "name": "Generated at", "type": "timestamp" },
      "status": {
        "name": "Status",
        "type": "select",
        "options": [
          { "value": "generated", "label": "Generated", "color": "blue" },
          { "value": "pending-delivery", "label": "Pending delivery", "color": "amber" },
          { "value": "delivered", "label": "Delivered", "color": "green" }
        ]
      },
      "summary": { "name": "Summary", "type": "text", "variant": "long-text" },
      "reportMarkdown": { "name": "Report markdown", "type": "text", "variant": "long-text" },
      "pendingItems": { "name": "Pending items", "type": "json" }
    }
  }'
```

Create sample report rows with `POST /api/v1/data-definitions/weekly-report/data/upsert-many`.

```bash
curl -X POST "https://andibase.com/api/v1/data-definitions/weekly-report/data/upsert-many" \
  -H "Authorization: Bearer $ANDI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "items": [
      {
        "data": {
          "title": "Weekly operations report · 2026-03-16 to 2026-03-20",
          "periodStart": "2026-03-16",
          "periodEnd": "2026-03-20",
          "generatedAt": "2026-03-20T18:00:00.000Z",
          "status": "pending-delivery",
          "summary": "Closed 18 tasks, 3 remain blocked, and response time improved week over week.",
          "highlights": ["Closed 18 tasks", "Response time improved"],
          "blockers": ["Awaiting vendor approval", "Two customer escalations still open"],
          "metrics": { "closedTasks": 18, "openEscalations": 2 },
          "reportMarkdown": "# Weekly report\n\n- Closed 18 tasks\n- 3 blockers remain\n",
          "pendingItems": ["Email delivery still pending"]
        }
      }
    ]
  }'
```

Step 2: Create the weekly report agent [#step-2-create-the-weekly-report-agent]

Create one workspace agent with handle `weekly-report-agent`.

Recommended behavior:

* gather facts from the workspace using the current data tools
* generate a concise weekly report in structured fields plus markdown
* create one report row for the requested week
* create one delivery row per intended recipient
* mark delivery as `pending` when direct email sending is not available
* mark the report itself as `pending-delivery` when any recipient is still pending
* if delivery later becomes possible in the execution environment, update the relevant delivery rows to `sent` and the report to `delivered`

Recommended agent payload:

```json
{
  "name": "Weekly Report Agent",
  "handle": "weekly-report-agent",
  "description": "Creates weekly reports and tracks whether email delivery is complete or still pending.",
  "model": "openai/gpt-5.4",
  "capabilities": {
    "webAccess": false,
    "browserAccess": false,
    "objectsAccess": true
  },
  "instructions": "You manage a weekly reporting workflow. Use the weekly-report and weekly-report-delivery data definitions as the source of truth. Be action-oriented: make reasonable assumptions, complete the work when the intended outcome is clear, and avoid asking for confirmation on every small step. Use the current workspace data tools to gather facts, create a weekly report row, and create one delivery row per recipient. Do not claim that an email was sent unless the execution environment actually sent it. When direct email sending is not available, set deliveryStatus to pending, explain the pending reason clearly, and include the pending action in the report pendingItems field. If all deliveries are still pending, set the report status to pending-delivery. If all deliveries are completed, set the report status to delivered."
}
```

Create the agent with `POST /api/v1/agents`.

Step 3: Expected operating flow [#step-3-expected-operating-flow]

When a user asks for a weekly report, the agent should:

1. Resolve the reporting period.
2. Query the available workspace data needed for the report.
3. Generate summary content, highlights, blockers, metrics, and markdown.
4. Create a `weekly-report` row.
5. Create one `weekly-report-delivery` row per recipient.
6. If direct email sending is unavailable, mark each delivery row as `pending` and explain why.
7. Update the report status to `pending-delivery` when any delivery is still pending.

Recommended acceptance checks [#recommended-acceptance-checks]

An agent should consider the recipe complete only if all of the following are true:

1. `weekly-report` exists and includes the required fields.
2. `weekly-report-delivery` exists and includes either the `reportId` relationship or the `reportRecordId` fallback used by the current public HTTP API flow.
3. `weekly-report-agent` exists.
4. At least one sample weekly-report row can be created successfully.
5. At least one sample weekly-report-delivery row can be created successfully.
6. The recipe makes it explicit when email delivery is pending instead of silently pretending delivery succeeded.

Minimal delivery summary [#minimal-delivery-summary]

When the agent finishes, it should report:

* the created data definition handles
* the created agent handle
* whether email was actually sent or is still pending
* the pending reason for any blocked delivery
* any assumptions made for reporting period, recipients, or source data scope


## Documentation Navigation
Use these paths to traverse the relevant docs and generated API reference files for the app.
- Weekly Report Email Agent [current] -> `/docs/receipes/weekly-report-email-agent` (source: `content/docs/receipes/weekly-report-email-agent.mdx`)
- andibase Overview -> `/docs` (source: `content/docs/index.mdx`)
- Get started (for AI Agents) -> `/docs/agent-get-started` (source: `content/docs/agent-get-started.mdx`)
- Agent Tools -> `/docs/agent-tools` (source: `content/docs/agent-tools.mdx`)
- Agents -> `/docs/agents` (source: `content/docs/agents.mdx`)
- Agent Auth -> `/docs/api-reference/agent-auth`
- Get agent login request -> `/docs/api-reference/agent-auth/get-api-v1-agent-auth-requests-usercode`
- Exchange agent login -> `/docs/api-reference/agent-auth/post-api-v1-agent-auth-exchange`
- Start agent login -> `/docs/api-reference/agent-auth/post-api-v1-agent-auth-requests`
- Approve agent login -> `/docs/api-reference/agent-auth/post-api-v1-agent-auth-requests-usercode-approve`
- Deny agent login -> `/docs/api-reference/agent-auth/post-api-v1-agent-auth-requests-usercode-deny`
- Agents -> `/docs/api-reference/agents`
- Delete workspace agent -> `/docs/api-reference/agents/delete-api-v1-agents-id`
- List workspace agents -> `/docs/api-reference/agents/get-api-v1-agents`
- Get workspace agent -> `/docs/api-reference/agents/get-api-v1-agents-id`
- List agent chats -> `/docs/api-reference/agents/get-api-v1-agents-id-chats`
- Get agent chat -> `/docs/api-reference/agents/get-api-v1-agents-id-chats-chatid`
- Update workspace agent -> `/docs/api-reference/agents/patch-api-v1-agents-id`
- Create workspace agent -> `/docs/api-reference/agents/post-api-v1-agents`
- Send agent message -> `/docs/api-reference/agents/post-api-v1-agents-id-chats-chatid-messages`
- Apps -> `/docs/api-reference/apps`
- Delete app -> `/docs/api-reference/apps/delete-api-v1-apps-id`
- List workspace apps -> `/docs/api-reference/apps/get-api-v1-apps`
- Get app by id -> `/docs/api-reference/apps/get-api-v1-apps-id`
- Update app -> `/docs/api-reference/apps/patch-api-v1-apps-id`
- Create app -> `/docs/api-reference/apps/post-api-v1-apps`
- Automations -> `/docs/api-reference/automations`
- Delete workspace automation -> `/docs/api-reference/automations/delete-api-v1-automations-id`
- List workspace automations -> `/docs/api-reference/automations/get-api-v1-automations`
- Get workspace automation -> `/docs/api-reference/automations/get-api-v1-automations-id`
- List automation runs -> `/docs/api-reference/automations/get-api-v1-automations-id-runs`
- Get automation run -> `/docs/api-reference/automations/get-api-v1-automations-id-runs-runid`
- Update workspace automation -> `/docs/api-reference/automations/patch-api-v1-automations-id`
- Create workspace automation -> `/docs/api-reference/automations/post-api-v1-automations`
- Run automation -> `/docs/api-reference/automations/post-api-v1-automations-id-run`
- Trigger automation webhook -> `/docs/api-reference/automations/post-api-v1-automations-webhooks-publicid-secret`
- Channels -> `/docs/api-reference/channels`
- Delete channel -> `/docs/api-reference/channels/delete-api-v1-channels-channelid`
- List channels -> `/docs/api-reference/channels/get-api-v1-channels`
- Get channel -> `/docs/api-reference/channels/get-api-v1-channels-channelid`
- Update channel -> `/docs/api-reference/channels/patch-api-v1-channels-channelid`
- Create channel -> `/docs/api-reference/channels/post-api-v1-channels`
- Data -> `/docs/api-reference/data`
- Data Definitions -> `/docs/api-reference/data-definitions`
- Delete data definition -> `/docs/api-reference/data-definitions/delete-api-v1-data-definitions-id`
- List data definitions -> `/docs/api-reference/data-definitions/get-api-v1-data-definitions`
- Get data definition -> `/docs/api-reference/data-definitions/get-api-v1-data-definitions-id`
- Update data definition -> `/docs/api-reference/data-definitions/patch-api-v1-data-definitions-id`
- Create data definition -> `/docs/api-reference/data-definitions/post-api-v1-data-definitions`
- Data SQL Query -> `/docs/api-reference/data-sql-query`
- Run SQL query against workspace data -> `/docs/api-reference/data-sql-query/post-api-v1-data-sql-query`
- Get data by id -> `/docs/api-reference/data/get-api-v1-data-definitions-definitionid-data-id`
- Select all data row ids -> `/docs/api-reference/data/get-api-v1-data-definitions-definitionid-data-select-all`
- List data -> `/docs/api-reference/data/get-api-v1-data-definitions-definitionid-query`
- Patch many data rows -> `/docs/api-reference/data/patch-api-v1-data-definitions-definitionid-data-patch-many`
- Delete many data rows -> `/docs/api-reference/data/post-api-v1-data-definitions-definitionid-data-delete-many`
- Upsert many data rows -> `/docs/api-reference/data/post-api-v1-data-definitions-definitionid-data-upsert-many`
- DuckDB Query -> `/docs/api-reference/duckdb-query`
- Run a DuckDB query against registered sources -> `/docs/api-reference/duckdb-query/post-api-v1-duckdb-query`
- Explorer -> `/docs/api-reference/explorer`
- Delete explorer folder -> `/docs/api-reference/explorer/delete-api-v1-workspace-nodes-nodeid`
- List explorer nodes -> `/docs/api-reference/explorer/get-api-v1-workspace-nodes`
- List explorer folders -> `/docs/api-reference/explorer/get-api-v1-workspace-nodes-folders`
- Rename explorer folder -> `/docs/api-reference/explorer/patch-api-v1-workspace-nodes-nodeid-rename`
- Create folder -> `/docs/api-reference/explorer/post-api-v1-workspace-nodes-folders`
- Move explorer node -> `/docs/api-reference/explorer/post-api-v1-workspace-nodes-nodeid-move`
- Files -> `/docs/api-reference/files`
- List workspace files -> `/docs/api-reference/files/get-api-v1-files`
- Read file content -> `/docs/api-reference/files/get-api-v1-files-fileid-content`
- Create file -> `/docs/api-reference/files/post-api-v1-files`
- Complete file upload -> `/docs/api-reference/files/post-api-v1-files-fileid-complete`
- Presign multipart parts -> `/docs/api-reference/files/post-api-v1-files-fileid-parts`
- Update file content -> `/docs/api-reference/files/put-api-v1-files-fileid-content`
- Messages -> `/docs/api-reference/messages`
- List channel messages -> `/docs/api-reference/messages/get-api-v1-channels-channelid-messages`
- List thread messages -> `/docs/api-reference/messages/get-api-v1-channels-channelid-threads-threadid-messages`
- Create channel message -> `/docs/api-reference/messages/post-api-v1-channels-channelid-messages`
- Create thread message -> `/docs/api-reference/messages/post-api-v1-channels-channelid-threads-threadid-messages`
- Notifications -> `/docs/api-reference/notifications`
- List notification devices -> `/docs/api-reference/notifications/get-api-v1-notifications-devices`
- Check Expo notification receipts -> `/docs/api-reference/notifications/post-api-v1-notifications-receipts`
- Send workspace notifications -> `/docs/api-reference/notifications/post-api-v1-notifications-send`
- Runs -> `/docs/api-reference/runs`
- List workspace runs -> `/docs/api-reference/runs/get-api-v1-runs`
- Get workspace run -> `/docs/api-reference/runs/get-api-v1-runs-runid`
- Threads -> `/docs/api-reference/threads`
- List channel threads -> `/docs/api-reference/threads/get-api-v1-channels-channelid-threads`
- Get thread -> `/docs/api-reference/threads/get-api-v1-channels-channelid-threads-threadid`
- Create thread -> `/docs/api-reference/threads/post-api-v1-channels-channelid-threads`
- Workflows -> `/docs/api-reference/workflows`
- Delete workflow definition -> `/docs/api-reference/workflows/delete-api-v1-workflows-id`
- List workflow definitions -> `/docs/api-reference/workflows/get-api-v1-workflows`
- Get workflow definition -> `/docs/api-reference/workflows/get-api-v1-workflows-id`
- Update workflow definition -> `/docs/api-reference/workflows/patch-api-v1-workflows-id`
- Create workflow definition -> `/docs/api-reference/workflows/post-api-v1-workflows`
- Workspaces -> `/docs/api-reference/workspaces`
- Delete workspace API key -> `/docs/api-reference/workspaces/delete-api-v1-workspaces-workspacehandle-api-keys-keyid`
- Delete workspace credential -> `/docs/api-reference/workspaces/delete-api-v1-workspaces-workspacehandle-credentials-credentialid`
- Delete workspace invitation -> `/docs/api-reference/workspaces/delete-api-v1-workspaces-workspacehandle-invitations-invitationid`
- Delete workspace user -> `/docs/api-reference/workspaces/delete-api-v1-workspaces-workspacehandle-users-userid`
- List my workspaces -> `/docs/api-reference/workspaces/get-api-v1-workspaces`
- List workspace API keys -> `/docs/api-reference/workspaces/get-api-v1-workspaces-workspacehandle-api-keys`
- List workspace credentials -> `/docs/api-reference/workspaces/get-api-v1-workspaces-workspacehandle-credentials`
- List workspace credential tools -> `/docs/api-reference/workspaces/get-api-v1-workspaces-workspacehandle-credentials-credentialid-tools`
- List workspace invitations -> `/docs/api-reference/workspaces/get-api-v1-workspaces-workspacehandle-invitations`
- List workspace users -> `/docs/api-reference/workspaces/get-api-v1-workspaces-workspacehandle-users`
- Create workspace -> `/docs/api-reference/workspaces/post-api-v1-workspaces`
- Create workspace API key -> `/docs/api-reference/workspaces/post-api-v1-workspaces-workspacehandle-api-keys`
- Create workspace credential -> `/docs/api-reference/workspaces/post-api-v1-workspaces-workspacehandle-credentials`
- Invite user to workspace -> `/docs/api-reference/workspaces/post-api-v1-workspaces-workspacehandle-invitations`
- Create workspace user -> `/docs/api-reference/workspaces/post-api-v1-workspaces-workspacehandle-users`
- Apps -> `/docs/apps` (source: `content/docs/apps.mdx`)
- Authentication -> `/docs/authentication` (source: `content/docs/authentication.mdx`)
- Building Blocks -> `/docs/building-blocks` (source: `content/docs/building-blocks.mdx`)
- Data Model -> `/docs/data-model` (source: `content/docs/data-model.mdx`)
- Embedded Host Actions -> `/docs/embedded-host-actions` (source: `content/docs/embedded-host-actions.mdx`)
- Introduction -> `/docs/introduction` (source: `content/docs/introduction.mdx`)
- Recipes -> `/docs/receipes` (source: `content/docs/receipes/index.mdx`)
- Construction Site Visit Agent -> `/docs/receipes/construction-site-visit-agent` (source: `content/docs/receipes/construction-site-visit-agent.mdx`)
- Daily Lead Qualification Agent -> `/docs/receipes/daily-lead-qualification-agent` (source: `content/docs/receipes/daily-lead-qualification-agent.mdx`)
- Day Planner Agent -> `/docs/receipes/day-planner-agent` (source: `content/docs/receipes/day-planner-agent.mdx`)
- Expense Tracker -> `/docs/receipes/expense-tracker` (source: `content/docs/receipes/expense-tracker.mdx`)
- Legal Case Tracker -> `/docs/receipes/legal-case-tracker` (source: `content/docs/receipes/legal-case-tracker.mdx`)
- Spare Parts Request Agent -> `/docs/receipes/spare-parts-request-agent` (source: `content/docs/receipes/spare-parts-request-agent.mdx`)
- UI Components -> `/docs/ui-components` (source: `content/docs/ui-components.mdx`)