Sales · 03 · Pipeline ops & reportingLesson 3 of 4
The self-writing pipeline report
- Assemble weekly pipeline reports from your real systems
- Schedule it so Monday 8am just happens
What Monday 8am should look like
A report nobody assembles, waiting in Slack before the team sits down: every campaign's numbers against benchmark, every pipeline movement explained, and three sentences saying what needs attention this week. Not a dashboard you have to go stare at - a narrative that already did the staring. By the end of this lesson that report exists, built from your real campaigns and CRM, scheduled for Monday 7:40am with a heartbeat.
You have all the pieces. Sending stats live in your sender's analytics API (Instantly, in the course build). Pipeline state lives in the CRM you can query by MCP. Call context lives in the extraction JSONs from last lesson. The report is a script that pulls all three, compares against benchmarks, and has Claude write what a good sales manager would say about it.
- The benchmarks the report judges against: ~3.5% average reply rate, 5.5%+ top quartile, 10.7%+ top decile (vendor-reported, 2026 - treat as directional). Keep them in a dated benchmarks.json the report reads, so updating a number next year is a config edit, not a prompt archaeology dig.
- Bounce rate above 2% on any campaign or inbox = red flag, automatically, every time.
- Campaign-vs-own-history beats campaign-vs-benchmark for trend: a campaign at 4% falling from 6% needs attention more than a steady 3.5% one.
Pull: one script, three sources
One script gathers everything the narrative will need. Build it source by source and keep each pull's raw output on disk - the report reads files, never live APIs, so a flaky endpoint can't eat your Monday.
- Have Claude write pull_report_data.py: from Instantly's API, per-campaign sends, opens, replies, bounces, and per-inbox health for the trailing 7 days; write to state/report/sending_YYYY-MM-DD.json.
- From the CRM (MCP or API): deals created, stage changes, deals gone quiet (no activity in 14 days), plus reply-triage outcomes by category from lesson 9's logs.
- From the call extractions: this week's risks and next_steps across active deals - this is what lets the narrative say WHY.
- From your own ledgers: enrichment credits by provider, LLM tokens by provider and model, priced per model at read time, and the resulting $/verified lead by source. The engine's cost is a pipeline metric; it goes in the same report as reply rate.
- Keep each week's raw pulls on disk. Week-over-week deltas - the actually interesting numbers - come free when last week's file sits next to this week's.
Write: the narrative skill
The difference between a report that gets read and one that gets skimmed-and-ignored is the narrative: "Campaign X is dying because its bounce rate crossed 2% on Thursday - pause inbox 3 and re-verify the segment" beats a table row every time.
---
name: weekly-report
description: Write the Monday pipeline report from computed
metrics. Never recompute numbers - narrate them.
---
Input: this week's metrics JSON + last week's + flags +
benchmarks.json (dated - the team updates it; never
hardcode benchmark numbers in this prompt).
Structure (strict):
1. TL;DR - 3 sentences max. Lead with the most important
change, good or bad.
2. Sending - each campaign vs the avg / top-quartile reply
benchmarks from benchmarks.json AND vs its own trailing
4 weeks. Bounce >2% anywhere = its own red-flagged line
with the prescribed action.
3. Pipeline - deals advanced / stalled / created, with the
WHY pulled from call-extraction risks where available.
4. This week - max 3 actions, each with an owner.
Rules: every claim cites a number from the input. No
hedging filler. If something is bad, say it plainly and
say what to do about it.- Build the skill - report-writer skills exist in the libraries (skillsmp.com), and starting from one is faster than a blank page; your structure and benchmarks are what you swap in. Write benchmarks.json with today's numbers and their source date - the skill reads it, so next year's benchmark update is a config edit, never a prompt edit. Then run the full chain by hand: pull, compute, narrate. Read the output hard - does the TL;DR match what YOU would have flagged?
- Tune for two or three weekly cycles. Reports earn trust by being right about what matters, and the strict structure is what keeps week 30's report as sharp as week 3's.
- Add delivery: post to your team Slack channel (webhook or Slack MCP), with the full report as a thread reply under the TL;DR.
Schedule: Monday 8am just happens
Two solid ways to make it automatic. Pick based on where the job needs to live:
# crontab -e - Monday 07:40, report in Slack by 08:00
40 7 * * 1 cd ~/sales-engine && \
python scripts/pull_report_data.py && \
claude -p "/weekly-report state/report/latest.json" \
--output-format text \
--allowedTools "Read,Bash(python scripts/post_slack.py *)" \
>> logs/report.log 2>&1- Option A - cron +
claude -p: runs on your machine or a small server, sees your local files and state directory, fully under your control. The classic choice for this stack since the pull scripts and state live on disk anyway.-pstarts in Manual permission mode on every plan, so the--allowedToolslist is what lets it act. Leave--bareoff this one: bare mode skips skills and CLAUDE.md (so/weekly-reportwould not load) and ignores your subscription login, billing anANTHROPIC_API_KEYinstead. It suits skill-less scripted calls. Caveat: a laptop that's closed at 7:40 doesn't run cron - this wants an always-on host. - Option B - Routines: Claude Code's scheduled cloud runs (
/schedulein the CLI, also/routines, or claude.ai/code/routines). Cron-style triggers with a 1-hour minimum, plus one-off runs (/schedule tomorrow at 9am, ...), on Anthropic's cloud - no machine of yours needs to be awake. The constraint that decides it: a routine reaches your claude.ai connectors only; servers you added locally withclaude mcp addare not visible to it (an MCP server declared in a committed.mcp.jsonworks for a single-repo routine). Best when every source is connector-reachable. Still a research preview as of September 2026. - Not an option for this job:
/loop. It repeats a prompt inside an open session (/loop 5m <prompt>, or self-paced), expires after 7 days, and dies with the session. Use it for a morning of babysitting a launch, not for Monday 8am. - Billing: headless
claude -pand Agent SDK runs still draw from your subscription's usage limits. The separate Agent SDK credit that was announced for June 15, 2026 was paused that day and never took effect. Check/usagebefore scheduling anything heavy; a gateway credential switches you to per-token billing. - Delivery beyond Slack: Claude Code can publish the report as an Artifact, a private page on claude.ai that updates in place each week (
/artifactslists yours). Team and Enterprise plans can share it inside the org; Pro and Max share by public link only, so keep pipeline numbers on Slack unless you are on a team plan.
Do this now
Sources and further reading
Want us to set it up with you, end to end?
Three one-on-one sessions. We train you on your real stack and build your first agents together, until you can run it yourself. You keep everything.