# How we write the first draft of our monthly investor update

Once a month an agent on Machine reads Postgres, Stripe and last month's update, gathers our key metrics, checks them against last month and plan, and drafts the update in our format for a founder.

Canonical page: https://themachine.myapps.ai/use-cases/investor-update

Every founder knows the monthly investor update. It's not a big job, but it
keeps coming back, and it always takes longer than it should. The figures are
spread over a few systems. Each one needs comparing with the previous month and
with the plan. Then it all has to be written up the same way as last time. None
of that is difficult. It's simply an hour or two of collecting and tidying,
every single month.

So we let an agent on Machine do the collecting and write the first version.
Here's how we produce our own update, with the connections and limits that make
it safe.

- **Team:** Machine
- **Runs on:** A schedule that fires once a month
- **Connected systems:** Postgres · Stripe · Last month's update
- **Mode:** Reads only · a founder polishes it and sends it

## The problem

Each month you need MRR and revenue from Stripe, active accounts and growth from
the product database, and burn and runway from the finance figures. Every one of
those then gets lined up against last month and against plan. The data lives in
separate places, the comparisons happen by hand, and the finished write-up has
to look the way investors expect.

The standard fixes only get you part of the way. A BI dashboard shows today's
numbers, but it won't write the story or measure anything against plan. A saved
template still leaves someone typing in every figure. Doing it all yourself
works, but it means a founder's time goes on gathering and formatting instead of
the commentary investors actually read the update for.

## What we built

Once a month a schedule starts an agent on Machine. It gets its own isolated
session, a cloud sandbox, that can read the product database, Stripe and the
previous update but cannot change them. The agent collects the key metrics (MRR,
growth, burn, runway and active accounts), sets them against last month and
against plan, and writes the update as a document in our usual layout. A founder
edits it and sends it.

## How it works

### Start the draft once a month

A **cron trigger** goes off monthly and opens a new **session**, a fresh cloud
computer (sandbox) just for that run. The run collects this month's figures and
produces a single draft. Each run has one session on one throwaway machine.
Between months nothing carries over, apart from what it reads fresh from the
source systems.

### Teach it our format and what we track

Our update's structure travels with the agent as **skills** and **memory**: the
metrics we report, how we define each of them, the layout and section order our
investors are used to, and the plan targets to measure against. Last month's
update sets the tone and the shape. If we change how we report, we write that
down, and the agent follows it the following month.

### Hook up Postgres, Stripe and the last update

The agent works through scoped **connectors**, connections Machine brokers on
the server so the model never sees a raw token. Through them it can:

- **Run queries in Postgres**: active accounts, growth and the product metrics
we follow.
- **Look at Stripe**: the month's MRR and revenue.
- **Open last month's update**: the earlier figures to compare against and the
layout to copy.
- **Write a draft document**: figures and story put together in our format,
ready for a founder to edit.

### Keep it read-only

Across every connected system the agent is **read-only**. It reads the
database, Stripe and the previous update, and changes nothing in any of them.
The only thing it produces is a draft document. Sending is the founder's job;
the agent never sends a thing. Credentials are stored encrypted in the Secrets
Manager and only handed to the agents you grant them to.

### Give a founder a solid first draft

From then on, each new month opens with a draft ready to go: the metrics
collected, the comparisons with last month and with plan filled in, and the
story written in our style. The founder rewrites the commentary, double-checks
the figures and sends it. The legwork is finished, and the judgment stays with
a person.

> **The pattern**
> Every month a **cron** opens a session with read-only **connectors** to
> Postgres, Stripe and the previous update. Our layout and how we define each
> metric live in **skills** and **memory**. The agent writes the draft; a
> founder polishes it and sends it.

## Guardrails

The agent reads revenue and product figures to write a document, so its access
is narrow and contained:

- **Isolation.** Each run takes place in its own sealed sandbox, set up for that
  one task. The session reads only the systems it's allowed to, and the draft
  document is the only thing that comes back out.
- **Scoped secrets.** Postgres and Stripe credentials are stored encrypted in
  the Secrets Manager and only handed to the agents you grant them to.
- **Read-only.** It reads from every source and writes to none. The draft is its
  only output, and it never sends anything. Sending belongs to a founder.
- **Everything is code.** The agent's setup, skills and per-system permissions
  are files in the repo. They're versioned and only change through a reviewed
  **change request**, not a setting in a dashboard.

## The outcome

- **Every month:** A complete first draft waiting as the new month begins
- **Read-only:** No source system ever gets written to
- **3 systems:** Postgres, Stripe and the previous update, handled by a single agent

Our monthly update now turns up as a draft with the figures collected, the
comparisons made and the story written in our layout. The founder's time goes
on the commentary and the decision to send, not on chasing numbers and fixing
formatting. And the data is only ever read, never touched.
