# Draft a meeting recap email in Gmail

When a meeting lands in Salfio, have a Claude Code routine write the recap email for you — straight into your Gmail Drafts folder.

After a meeting, you usually want to send a short recap to the client: what was decided, what's next, who owes what. Writing it from scratch is the kind of work that quietly never gets done.

This guide wires three pieces together so the recap writes itself:

- **Salfio's meeting bot** (Notetaker) joins the meeting, records it, and produces a transcript, participants, and a summary.
- A **Salfio webhook** fires the `activity.meeting.created` event the moment the meeting lands.
- A **Claude Code remote routine** picks up the event and drafts the recap email directly in your Gmail — as a normal draft, ready for you to review and send.

End-to-end, you go from "I had a Zoom call" to "I have a draft email waiting in Gmail" without writing a line of code.

## Prerequisites

- A Salfio organization with **Gmail** connected — see [Connect Gmail](/docs/getting-started/connect-integration#connect-gmail).
- The **Salfio meeting bot** enabled for your organization. Enable it from **Settings → Integrations** in the Salfio dashboard.
- A Claude Code account with **Routines** enabled and the **Salfio** and **Gmail** connectors authorized. The Salfio connector is the same MCP integration covered in [Connect from Claude.ai web](/docs/mcp/connect-claude-web) — once authorized for your Claude account, it's available to routines too.
- Access to **Settings → Webhooks** in the Salfio dashboard.

## 1. Create a Claude Code remote routine

A routine is a prompt that runs whenever its fire URL is POSTed to — Salfio will be the one POSTing.

In Claude Code, open **Routines** and click **+ New routine**. In the dialog:

1.  **Name** — anything you like, e.g. `Draft meeting recap`.
2.  **Instructions** — paste the prompt below.
3.  **Select a trigger** — pick **API** ("Trigger from your own code by sending a POST request"). Salfio fires the routine through this trigger.
4.  **Connectors** — make sure at least **Salfio** and **Gmail** are in the list. Salfio lets the routine read client context and conversation history; Gmail lets it create the draft. Add whatever else helps (Google Drive, Linear, etc.).
5.  Click **Create**.

Claude Code will warn you that the routine can use **all** tools from the connectors — including writes — without asking for permission during runs. Keep the prompt strict about "draft, never send", and prune connectors you don't actually need.

### Routine prompt

Paste this into **Instructions**:

    You are a meeting recap assistant. You are called once per new
    meeting recorded in Salfio and produce a Gmail draft (never send).

    The request body is `{"text": "<json string>"}` — run JSON.parse(text)
    to get the Salfio webhook envelope. The `activity` field describes the
    meeting (subject, participants, transcript or summary in `content`),
    and `activity.clientId` identifies the Salfio client.

    Identify yourself first. The Gmail connector is authorized against one
    Google account — fetch its profile and treat that as "you" for this
    draft (your email, your name, your signature). You should be one of
    the meeting participants; if you aren't, skip without drafting.

    Then use the Salfio connector to understand the relationship: pull
    the client, the AI-generated cards, and recent activities for that
    client. Pay particular attention to your own prior outbound messages
    to this client — they're the best model for the voice, signature, and
    level of formality you should match.

    If the meeting is internal (only colleagues on your own domain), a
    1:1, or you can't find the client in Salfio, skip without drafting
    and say why.

    Then create a Gmail draft addressed to the external participants (not
    yourself or other colleagues) that reads like you wrote it: same
    language as the prior thread, same level of formality, summarising
    the decisions and action items from the meeting. Reference relevant
    prior context naturally where it helps. End with a concrete next step
    or a specific question. Sign off with your first name. If the
    transcript is sparse, draft a short acknowledgement rather than
    fabricating.

    Reply back with the Salfio activity id, the Gmail draft id, and one
    sentence on what you decided to say.

### Grab the credentials

Right after you click **Create**, Claude Code shows the **API token** in a one-shot dialog (`sk-ant-oat01-…`). Copy it now — Claude won't show it again. Treat it like a password.

Then on the routine's detail page:

- Make sure **Status** is **Active**.
- Under **API**, click the copy icon next to **API trigger enabled** to copy the routine's **fire URL** (it looks like `https://api.anthropic.com/v1/claude_code/routines/<routine_id>/fire`).

You'll paste both into Salfio in the next step.

## 2. Register the routine as a Salfio webhook

Back in Salfio:

1.  Open **Settings → Webhooks**.
2.  Click **Add webhook** and fill in:
    - **Name** — something like `Meeting recap → Gmail draft`.
    - **Event** — `activity.meeting.created`.
    - **Transport** — `Claude routine`.
    - **URL** — paste the fire URL from step 1.
    - **Token** — paste the token from step 1.
3.  Save.

Salfio stores the token encrypted at rest and never shows it again. If you ever need to rotate it, generate a new one in Claude Code and edit the webhook here.

## 3. Send a test event

Don't wait for your next real call to find out something is wrong. Each webhook row has a **Send test event** button. Clicking it opens a small dialog with a single picker:

- **Synthetic sample (placeholder data)** — the default. Useful when you don't have a real meeting yet, or when you want to exercise the routine without sending a real client conversation.
- **Any of your recent meetings** — listed as `Client · "Subject" (relative time)`. Pick one to fire your routine against that exact payload.

Confirm the dialog. Within a few seconds:

- The webhook's **Last delivery** column updates with the delivery status. If you picked a real activity, a "View client" link appears on the success toast so you can jump to it.
- Claude fires the routine with the picked payload.
- A draft email appears in your Gmail **Drafts** folder, addressed to the participants from the payload.

If you don't see a draft, see [Troubleshooting](#troubleshooting) below.

## 4. Have a real call

Schedule a meeting that the Salfio bot joins as a participant — the bot records, transcribes, and hands the result back to Salfio. The moment Salfio finishes importing the meeting:

1.  The new meeting appears under **Activities** for the matching client.
2.  Salfio fires `activity.meeting.created` to your webhook.
3.  Claude reads the payload, decides whether to act, and (if so) drafts the email.
4.  You see the draft in your Gmail Drafts folder, addressed to the external participants, with a recap based on the transcript.

Open the draft, edit anything you want, and send.

## What Salfio sends

Salfio's canonical webhook envelope carries the meeting on the `activity` field:

    {
      "event": "activity.meeting.created",
      "occurred_at": "2026-05-12T11:42:13Z",
      "organization": { "id": "9c1a…" },
      "activity": {
        "id": "8df8…",
        "clientId": "ad44…",
        "type": "meeting",
        "source": "recallai",
        "subject": "Acme — Q2 planning",
        "content": "Full transcript or summary…",
        "occurredAt": "2026-05-12T11:42:13Z",
        "participants": ["[email protected]", "[email protected]"],
        "immutable": true,
        "archivedAt": null,
        "createdAt": "2026-05-12T11:42:14Z",
        "updatedAt": "2026-05-12T11:42:14Z"
      }
    }

Because Anthropic's routine `/fire` endpoint only accepts `{"text": "..."}`, Salfio wraps the envelope as a stringified JSON inside `text` before dispatching to a Claude routine. That's why the routine prompt above starts with `JSON.parse(text)` — once parsed, you get the exact structure shown above.

Full payload reference — including headers, retry behaviour, and the URL-endpoint transport — lives in [Webhooks](/docs/api/webhooks).

## Tips

**Customize the recap style per client.** Add a step at the start of your routine prompt that branches on the `subject` line, the participant domains, or a label you keep on the client in Salfio. One client might want bullet points; another might want a single paragraph.

**Skip internal calls.** If `participants` contains only `@yourcompany.com` addresses, return without drafting. The simplest way is to tell Claude that explicitly in the prompt.

**Don't auto-send.** Always save as a draft. Auto-sending removes the review step that makes this workflow safe to run — the recap should pass under your eye before it leaves your outbox.

**Iterate on the prompt, not the wiring.** The webhook side is set-and-forget. The routine prompt is where the quality lives — refine it as you see drafts you'd want to rewrite.

## Troubleshooting

**The test event went green but no draft appeared.** The webhook fired successfully — the issue is on the routine side. Open the routine's run history in Claude Code and inspect the most recent run. Common causes: the routine has no Gmail tool, the Gmail tool is connected to a different Google account than you expected, or the routine decided "no follow-up needed" for the test payload (the sample participants in the test payload are synthetic — adjust your "skip internal" logic if it's filtering them out).

**The webhook shows a non-`2xx` delivery.** Open the row in **Settings → Webhooks** and look at "Last delivery". The error usually points at the cause: a `401` means the token is wrong or has been revoked in Claude Code; a `404` means the routine was deleted; a `5xx` means Claude is having a bad moment — Salfio will retry on its standard curve.

**Drafts are appearing for meetings that shouldn't trigger one.** This is a prompt-tuning issue, not a wiring issue. Tighten the "decide whether this warrants follow-up" step in your routine prompt — for example, add an explicit allowlist of client domains.

**Drafts go to the wrong Gmail account.** The Gmail tool inside your routine is connected to whichever Google account you authorized it against in Claude Code. Reconnect the tool against the account you want drafts to land in.

## Related

- [Draft a reply to an inbound email](/docs/guides/draft-email-reply) — the sibling recipe for emails.
- [Webhooks](/docs/api/webhooks) — full payload, headers, retry curve.
- [Connect Gmail](/docs/getting-started/connect-integration#connect-gmail) — OAuth setup for the Gmail mailbox the routine will draft into. The Salfio meeting bot is enabled separately from **Settings → Integrations** in the dashboard.
- [Connect from Claude.ai web](/docs/mcp/connect-claude-web) — Salfio MCP authorization (same connector used in routines).

## Related pages

- [Administrator Tools](./administrator-tools.md)
- [Agent Tools](./mcp-external-servers.md)
- [Assign a Slack channel to a client over the API](./guides-assign-slack-channel.md)
- [Authenticated health check](./api-reference-gethealth.md)
- [Authentication](./api-authentication.md)
- [Cards](./cards.md)
- [Changelog](./changelog.md)
- [Changelog](../changelog.md)
- [Connect a workspace](./getting-started-connect-workspace.md)
- [Connect an integration](./getting-started-connect-integration.md)

# Agent Instructions

This portal answers questions programmatically. To receive a synthesized,
source-cited answer instead of crawling page by page, append the `?ask=`
query parameter to any page URL on this site:

    /guides/quickstart?ask=how+do+I+authenticate

Optional parameters:

- `&goal=<what-you-are-trying-to-do>` steers the answer toward your
  objective (e.g. `&goal=write+a+python+client`).
- `&version=<label>` scopes the answer to a mounted version when the
  portal publishes more than one.

The response is `text/markdown`: the answer followed by a `# Sources` list
of the portal pages it was grounded in. Status codes are the contract:

- `200` — the answer; `402` — the portal owner’s plan or answer credits are
  exhausted (surface this to your operator; do NOT retry); `429` — you are
  rate-limited; back off for the `Retry-After` seconds; `503` — the answer
  lane is temporarily unavailable; fall back to crawling the `.md` pages.

For the full corpus map read `llms.txt` at the site root; for the tool
surface (search + page fetch as MCP tools) see `/mcp`.
