# Weekly summary

{/* Generated from backend/features/recipes/catalogue/weekly_summary.yaml by `make arch`. Never edit this page: edit the recipe and run `make arch`, or `--check` fails. */}

Tell one person, once a week, what one of the organization's collections gained, in a few short paragraphs a model writes.

This page is made from the recipe `weekly_summary`, version 1, and says nothing the recipe does not. [How a recipe is composed](/cookbook) explains every word it uses.

## Its setup

Every \[When it is sent, in the organization's timezone\], a summary of what \[The collection to summarise\] gained that week is emailed to \[Who receives the summary\].

Each phrase in brackets is a parameter the recipe asks for, named as the table of parameters below names it.

## Its parts, in the order data travels

1. **automation `schedule`** — Runs the weekly summary at the weekly moment chosen.
   - set off by a schedule, `${param.when.cron}` (replace with the `cron` of the parameter `when`)
   - runs the flow `weekly`
2. **flow `weekly`** — Reads the week's new records, has them summarised, sends the summary and keeps it.
   - step `query` runs the tool `${param.collection.query_tool}` (the `query_tool` of the parameter `collection`)
   - step `draft` runs the tool `draft`
   - step `send` runs the tool `send`
   - step `keep` runs the tool `${resource.summaries.write_tool}` (the `write_tool` of this recipe's `summaries`)
3. **tool `draft`** — Writes a short summary of what the chosen collection gained in the week.
   - runs the built-in `draft_text`
4. **tool `send`** — Emails the summary to the person chosen.
   - runs the built-in `send_email`
5. **collection `summaries`** — Keeps every weekly summary sent, one per row.

## Its parameters

| Parameter | Kind | What it asks | Value |
|---|---|---|---|
| `collection` | collection | The collection to summarise | required |
| `recipient` | email | Who receives the summary | required |
| `when` | weekly_moment | When it is sent, in the organization's timezone | default `{"weekday": "monday", "hour": 8}` |
| `focus` | text | Anything the summary should pay attention to | default `""` |

## How its data moves

The flow `weekly`:

| Step | Input | Value | Comes from |
|---|---|---|---|
| `query` | `created_after` | `$ref:trigger.previous_scheduled_for` | `previous_scheduled_for` of what set the run off |
| `query` | `created_before` | `$ref:trigger.scheduled_for` | `scheduled_for` of what set the run off |
| `query` | `limit` | `200` | fixed |
| `draft` | `input.records` | `$ref:query.records` | `records` of the step `query`'s answer |
| `draft` | `input.count` | `$ref:query.count` | `count` of the step `query`'s answer |
| `send` | `body` | `$ref:draft.text` | `text` of the step `draft`'s answer |
| `keep` | `period_start` | `$ref:trigger.previous_scheduled_for` | `previous_scheduled_for` of what set the run off |
| `keep` | `period_end` | `$ref:trigger.scheduled_for` | `scheduled_for` of what set the run off |
| `keep` | `records_counted` | `$ref:query.count` | `count` of the step `query`'s answer |
| `keep` | `summary` | `$ref:draft.text` | `text` of the step `draft`'s answer |
| `keep` | `sent_to` | `${param.recipient}` | replace with the value of the parameter `recipient` |
| `keep` | `focus` | `${param.focus}` | replace with the value of the parameter `focus` |

A value written `$ref:<step>.<path>` is what an earlier step answered, and `$ref:trigger.<path>` is what set the run off. A value with `${...}` in it is a placeholder: building it by hand, replace it with your own.

## Build it yourself

To install it as it is: `POST /api/v1/recipes/{key}/install` with the key `weekly_summary` and a value for each parameter. To build the same thing with your own particulars, make each part in this order -- each one may name the ones before it -- with the operations below.

The YAML under each part is the recipe's declaration, not a request body: the API takes other names for the same things (a tool's `builtin` is `source` and `config.builtin`, a step's `tool` is `tool_id`, an edge's `from` is `source_step_id`). [From a recipe to the API](/cookbook#from-a-recipe-to-the-api) on the lead page maps every field, kind by kind.

### 1. collection `summaries`

Keeps every weekly summary sent, one per row.

- `POST /api/v1/collections` creates the collection with its fields.
- `PATCH /api/v1/collections/{collection_id}` sets the identity field once the fields exist.

```yaml
kind: collection
key: summaries
name: Weekly summaries
says: Keeps every weekly summary sent, one per row.
description: Every weekly summary sent, one per row.
fields:
- key: period_start
  label: Period start
  type: text
- key: period_end
  label: Period end
  type: text
- key: records_counted
  label: Records counted
  type: number
- key: summary
  label: Summary
  type: text
- key: sent_to
  label: Sent to
  type: text
  personal: true
- key: focus
  label: Focus
  type: text
```

### 2. tool `draft`

Writes a short summary of what the chosen collection gained in the week.

- `POST /api/v1/tools` creates the instance: a built-in's, or a flow offered as one tool by its `config.flow_id`.

```yaml
kind: tool
key: draft
name: Draft the weekly summary
says: Writes a short summary of what the chosen collection gained in the week.
description: Writes the weekly summary of ${param.collection.name}.
builtin: draft_text
fixed:
  instructions: 'Summarise for a busy reader, in a few short paragraphs, the records added
    to the collection "${param.collection.name}" this week, and say how many there were. Pay
    particular attention to: ${param.focus}'
deadline_seconds: 120
```

### 3. tool `send`

Emails the summary to the person chosen.

- `POST /api/v1/tools` creates the instance: a built-in's, or a flow offered as one tool by its `config.flow_id`.

```yaml
kind: tool
key: send
name: Send the weekly summary
says: Emails the summary to the person chosen.
description: Emails the weekly summary of ${param.collection.name}.
builtin: send_email
config:
  from: ${platform.mail_sender}
fixed:
  subject: Weekly summary · ${param.collection.name}
  to: ${param.recipient}
input_schema:
  type: object
  properties:
    subject:
      type: string
    to:
      type: string
    body:
      type: string
  required:
  - subject
  - to
  - body
```

### 4. flow `weekly`

Reads the week's new records, has them summarised, sends the summary and keeps it.

- `POST /api/v1/flows` creates the flow.
- `POST /api/v1/flows/{flow_id}/steps` adds each step, naming the tool it runs.
- `POST /api/v1/flows/{flow_id}/edges` adds each edge.
- `PATCH /api/v1/flows/{flow_id}/entry-step` sets the step a run starts at.

```yaml
kind: flow
key: weekly
name: Weekly summary of ${param.collection.name}
says: Reads the week's new records, has them summarised, sends the summary and keeps it.
steps:
- key: query
  tool: ${param.collection.query_tool}
  params:
    created_after: $ref:trigger.previous_scheduled_for
    created_before: $ref:trigger.scheduled_for
    limit: 200
- key: draft
  tool: ${resource.draft}
  params:
    input:
      records: $ref:query.records
      count: $ref:query.count
- key: send
  tool: ${resource.send}
  params:
    body: $ref:draft.text
- key: keep
  tool: ${resource.summaries.write_tool}
  params:
    period_start: $ref:trigger.previous_scheduled_for
    period_end: $ref:trigger.scheduled_for
    records_counted: $ref:query.count
    summary: $ref:draft.text
    sent_to: ${param.recipient}
    focus: ${param.focus}
edges:
- from: query
  to: draft
- from: draft
  to: send
- from: send
  to: keep
```

### 5. automation `schedule`

Runs the weekly summary at the weekly moment chosen.

- `POST /api/v1/automations` creates the automation on its trigger, running the flow.
- `PUT /api/v1/automations/{automation_id}/enabled` switches it on: an automation is created switched off.

```yaml
kind: automation
key: schedule
name: Weekly summary of ${param.collection.name}
says: Runs the weekly summary at the weekly moment chosen.
flow: ${resource.weekly}
cron: ${param.when.cron}
```

## How to adapt it

Choose the collection, who receives the summary and the weekly moment, and say in the focus what matters to the reader. To build your own, keep its shape -- a schedule, a query bounded by the trigger's previous and current scheduled times, a drafting step, a sending step and a write that keeps the result -- and swap the sending step for any tool that takes a text.

## What cannot change once installed

Installed, every part is the recipe's: it is listed where its kind lives, marked as the recipe's, and refuses every edit and deletion by hand, naming the recipe.

- collection `summaries`: its fields.
- tool `draft`: its configuration and fixed values.
- tool `send`: its configuration and fixed values.
- flow `weekly`: its steps and edges.
- automation `schedule`: its trigger and flow.

What stays the organization's:

- the records in `summaries`, read, written and deleted as any records are;
- the values of `collection`, `recipient`, `when`, `focus`, changed on the installed recipe and written through to every part that uses them;
- whether the recipe is on, which switches its automations on and off together;
- presentation -- a column's width, a step's position -- which changes nothing it runs.

## What it costs

What its parts consume -- a tool execution, a model's tokens, a message, storage -- is recorded and charged as those parts are, exactly as your own use of them is; nothing is charged for the recipe itself.
