# How we turn the pipeline into a forecast every week

Each week our agent reads HubSpot's open deals, weights them into a forecast against quota by stage, rep and segment, names the deals slipping out of the quarter, and posts it to Slack. It only reads.

Canonical page: https://themachine.myapps.ai/use-cases/sales-forecast

Each quarter your sales team is chasing a target, and most teams check progress
the same way. Somebody exports the open deals from HubSpot, weights them by
instinct or by a spreadsheet formula whose author left long ago, and calls the
result a forecast. It holds up for roughly a day, the day it was made. It will
not tell you about the deal whose close date drifted past last week, or the
six-figure opportunity with no logged activity for a month.

Our answer is an agent on Machine that reads HubSpot once a week and posts a
weighted forecast in our sales Slack channel. It splits the number by stage, by
rep and by segment, measures it against quota, and names the deals that put it
at risk. It only reads the pipeline, and the Slack post is the one thing it
produces. We forecast our own quarter this way.

- **Team:** Machine
- **CRM:** HubSpot
- **Runs on:** A weekly schedule
- **Mode:** Reads only · one Slack post a week

## The problem

Seeing your pipeline stage by stage is not the same as having a forecast. The
pipeline will tell you a deal is open and parked in "Proposal Sent". It will not
tell you whether it is likely to close this quarter, whether the rep's commit
squares with what that stage usually delivers, or whether a big deal has gone
quiet while still padding the total. Getting from open deals to a forecast
means weighting each deal by how often its stage really converts, adding those
up three ways (by stage, by rep, by segment) and setting the result against
quota.

The usual approach is a spreadsheet rebuilt the week before the forecast
meeting. Someone exports the deals, applies a weighting rule by hand, and checks
it against what each rep says they will close. It is out of date as soon as it
is finished, it only exists if someone remembers to make it, and it seldom
spots a deal past its close date, or one stuck late in the pipeline, until the
quarter is nearly gone.

## What we built

With Machine, a weekly cron starts an agent. Each run gets a fresh **session**,
a clean cloud computer (a sandbox) for that week only, with read-only access to
HubSpot. The agent collects every open deal with its stage, amount, close date,
owner and segment. It weights each deal using the probability already set on
its HubSpot pipeline stage, then totals the weighted amounts by stage, by rep
and by segment. It sets the total against this quarter's quota. It flags deals
whose close date has already passed, or that have too little time left in their
current stage to plausibly close this quarter. It also flags large deals that
look shaky for other reasons, such as no recent activity or being stuck in a
late stage. Then it posts the full forecast to Slack, and writes nothing back
to HubSpot.

## How it works

### Run it once a week

A **cron trigger** starts the agent every week. Each run opens a new
**session** in a sandbox of its own: one week, one run, no leftovers. Because
the forecast is rebuilt from what HubSpot holds right now, it can never wander
away from the CRM.

### Teach it how to add things up

The rules live in a **skill**, the playbook the agent brings to every run:
how deals are weighted, which ones belong to this quarter, and what "slipping"
and "at risk" mean. Every deal is weighted by the probability HubSpot already
has on its stage, never by a fixed guess. A deal belongs to the quarter
according to its close date. A deal counts as slipping once its close date is
behind us, or when its stage leaves too little time to close before the quarter
ends.

### Give it a look-only link to HubSpot

With a narrow **connector**, whose keys stay on our servers so the model never
sees a raw token, the agent reads:

- **Open deals.** Amount, stage, close date, owner, and the segment field that
drives the breakdown.
- **How the stages are set up.** It uses the win probability HubSpot already
assigns to each stage as the weighting, rather than assuming one.
- **Slack, for posting.** The weekly forecast goes there, split by stage, rep
and segment, with slipping and at-risk deals named.

### Set the limits

Across HubSpot, the agent is **read-only**. It cannot write to a deal's amount,
close date, stage or owner, so whatever the numbers show, it has no way to
change the figure attached to any deal. A Slack post is all it produces.
Credentials are stored encrypted in the **Secrets Manager** and only handed to
the agents you grant them to.

### Share the forecast

Every week there is a single Slack post. It shows the total weighted forecast
next to quota, the split by stage, by rep and by segment, the deals that have
slipped or are running short of time this quarter, and the large deals with
other warning signs. The sales team reads it and chooses what to do next.
HubSpot is never updated automatically.

> **The pattern**
> A weekly **cron** opens a session with a look-only **connector** to HubSpot.
> The weighting and totalling rules sit in a **skill**. The agent reads the
> entire pipeline and produces one thing: the weekly Slack post.

## Guardrails

Reading the whole pipeline every week only works if people trust it, so the
agent's access is narrow and runs in one direction:

- **Isolation.** Each run happens in a sandbox of its own. The session can reach
  only HubSpot and Slack, and the forecast post is the one thing it sends out.
- **Scoped secrets.** The HubSpot key is stored encrypted in the Secrets Manager
  and only handed to the agents you grant it to.
- **Read-only, no exceptions.** The HubSpot connector can only read. The agent
  never alters a deal's amount, close date, stage or owner. All it can do is
  report what it sees.
- **Everything is code.** The weighting rule, the quarter window and the
  definitions of slipping and at risk are files in the repo. They keep their
  history, and any change goes through a reviewed **change request** instead of
  a dashboard toggle.

## The outcome

- **Every week:** Forecast rebuilt from what HubSpot holds right now
- **Read-only:** No deal amount, date, stage or owner is ever changed
- **3 cuts:** Stage, rep and segment totals in a single weekly post

The forecast someone used to rebuild by hand before each call now turns up
every Monday in the channel the team already lives in. It is weighted by
HubSpot's own stage probabilities and names the exact deals that threaten the
number. The agent reads and reports, nothing more. Every deal still belongs to
the sales team.
