Generates a weighted sales forecast from Dataverse opportunity data. Calculates committed, best-case, and pipeline views by rep and team; compares to quota; flags risks and upside. Use when user asks "what's my forecast", "quarterly forecast", "pipeline forecast", "where's my number", "forecast report", "am I going to hit quota", "sales projection", or "revenue forecast".
npx skills add https://github.com/microsoft/dataverse-business-skills --skill forecast
Sales forecasting requires aggregating pipeline data across reps, applying probability weighting, and identifying where the number is at risk or has upside. This skill automates that process from Dataverse opportunity records — producing a structured forecast with committed, best-case, and pipeline totals broken down by owner and by forecast category, with risk and upside annotations.
Accept input from the user:
Calculate period boundaries:
[quarter_start]T00:00:00Z[quarter_end]T23:59:59ZSELECT opportunityid, name, estimatedvalue, estimatedclosedate, closeprobability,
salesstage, msdyn_forecastcategory, ownerid, customerid, accountid,
budgetstatus, decisionmaker, need, purchasetimeframe, purchaseprocess,
createdon, modifiedon, description
FROM opportunity
WHERE statecode = 0
AND estimatedclosedate >= '[period_start]'
AND estimatedclosedate <= '[period_end]'
ORDER BY ownerid, estimatedvalue DESC
Apply owner filter if specified.
Won this period (actuals):
SELECT opportunityid, name, estimatedvalue, actualclosedate, ownerid, customerid
FROM opportunity
WHERE statecode = 1
AND actualclosedate >= '[period_start]'
AND actualclosedate <= '[period_end]'
ORDER BY ownerid, actualclosedate DESC
Lost this period (for win rate context):
SELECT COUNT(opportunityid) as lost_count, SUM(estimatedvalue) as lost_value, ownerid
FROM opportunity
WHERE statecode = 2
AND actualclosedate >= '[period_start]'
AND actualclosedate <= '[period_end]'
GROUP BY ownerid
Group open opportunities by msdyn_forecastcategory:
Forecast category values:
| Code | Label | Description |
|------|-------|-------------|
| 100000001 | Pipeline | Early stage, uncertain |
| 100000002 | Best Case | Possible with favorable conditions |
| 100000003 | Committed | Rep has high confidence in close |
| 100000004 | Omitted | Excluded from forecast |
| 100000005 | Won | Already closed won (use for actuals) |
| 100000006 | Lost | Already closed lost |
For each category, calculate:
Run separate queries per category:
Committed:
SELECT COUNT(opportunityid) as count, SUM(estimatedvalue) as total,
ownerid
FROM opportunity
WHERE statecode = 0
AND msdyn_forecastcategory = 100000003
AND estimatedclosedate >= '[period_start]'
AND estimatedclosedate <= '[period_end]'
GROUP BY ownerid
Repeat for Best Case (100000002) and Pipeline (100000001).
For each opportunity, compute:
Total forecast by rep:
Note: Quota data may be stored in msdyn_quotas or msdyn_forecastconfiguration if Sales Insights forecasting is enabled. Query if available:
SELECT msdyn_forecastdefinitionid, msdyn_forecastdefinitionname, msdyn_quotasource
FROM msdyn_forecastdefinition
WHERE statecode = 0
If quota is not in Dataverse, accept as a user-provided input.
For each deal in Committed category, validate:
Red flags (may deflate number):
Upside signals (may inflate number):
For each Committed and Best Case opportunity:
SELECT TOP 1 activityid, activitytypecode, actualend, subject
FROM activitypointer
WHERE regardingobjectid = '[opportunityid]'
AND statecode = 1
ORDER BY actualend DESC
Flag if last activity > 7 days ago for Committed deals.
SALES FORECAST REPORT
Period: Q[n] [Year] ([Start Date] – [End Date])
Scope: [Rep Name / Team / Organization]
Generated: [Today's Date]
═══════════════════════════════════════════════════════════
PERIOD SUMMARY
───────────────────────────────────────────────────────────
Quota: $[quota]
Won (Actuals): $[won_value] ([n] deals)
Committed: $[committed] ([n] deals)
Best Case: $[best_case_w] ([n] deals, weighted)
Pipeline: $[pipeline_w] ([n] deals, weighted)
─────────────────────────────────────────────
Total Forecast: $[won + committed + best_case_weighted]
Upside Potential: $[pipeline_weighted]
Forecast vs Quota: [n]% | [Gap: $X above/below]
FORECAST BY REP
───────────────────────────────────────────────────────────
Rep Name | Quota | Won | Commit | Best | Fcst | vs Quota
[Rep 1] | $[quota] | $[won] | $[com] | $[bc] | $[tot] | [+/-n]%
[Rep 2] | $[quota] | $[won] | $[com] | $[bc] | $[tot] | [+/-n]%
COMMITTED DEALS ([n] deals, $[value])
───────────────────────────────────────────────────────────
🟢 [Deal Name] — $[Value] | [Stage] | Close: [Date] | Rep: [Name]
Last activity: [n] days ago | BANT: [score]/10
⚠️ [Deal Name] — $[Value] | [Stage] | Close: [Date] | Rep: [Name]
⚠️ No activity in 14 days | Budget not confirmed
BEST CASE DEALS ([n] deals, $[weighted_value] weighted)
───────────────────────────────────────────────────────────
[Deal Name] — $[Value] ([prob]%) = $[weighted] | [Stage] | Close: [Date]
...
PIPELINE (Unweighted: $[value] | Weighted: $[weighted])
───────────────────────────────────────────────────────────
[n] deals in pipeline category for period
Top 3 by value: [Deal 1], [Deal 2], [Deal 3]
FORECAST RISKS
───────────────────────────────────────────────────────────
🔴 [Deal Name] — $[Value] | Committed but no activity in [n] days
🔴 [Deal Name] — $[Value] | Close date today, stage = Qualify
🟡 [Deal Name] — $[Value] | Budget unconfirmed, in Committed
UPSIDE OPPORTUNITIES
───────────────────────────────────────────────────────────
⬆️ [Deal Name] — $[Value] | Best Case, BANT 9/10, meeting 2 days ago
⬆️ [Deal Name] — $[Value] | Pipeline, strong qualification, close date pull-in possible
RECOMMENDED ACTIONS
───────────────────────────────────────────────────────────
1. [Rep Name] — call [Deal Name] today; no activity in [n] days, closes this week
2. Move [Deal Name] from Committed to Best Case — budget not confirmed
3. Accelerate [Deal Name] — strong signals, could be a pull-in to this quarter
═══════════════════════════════════════════════════════════
Deliver a three-part output:
User Input:
"Generate the Q1 2026 forecast for the West team."
Skill Output:
SALES FORECAST — Q1 2026 | West Team
═══════════════════════════════════════════════════════════
Quota: $1,200,000
Won (Actuals): $380,000 (32% attainment)
Committed: $420,000 | Best Case: $180,000 (w) | Pipeline: $95,000 (w)
Total Forecast: $980,000 — 82% of quota
Gap to close: $220,000
FORECAST BY REP
─────────────────────────────────────────────────────
Sarah J. | $400K quota | $150K won | $180K commit | Fcst: $370K | 93%
Mike P. | $400K quota | $120K won | $140K commit | Fcst: $295K | 74% ⚠️
Lisa C. | $400K quota | $110K won | $100K commit | Fcst: $245K | 61% 🔴
RISKS
🔴 Northwind ($85K, Committed) — no activity 12 days, close date March 3
🟡 Fabrikam ($42K, Committed) — budget unconfirmed
UPSIDE
⬆️ Alpine Ski ($65K, Best Case) — BANT 9/10, meeting yesterday
| Table | Purpose |
|-------|---------|
| opportunity | Pipeline data, categories, and values |
| activitypointer | Activity recency per deal |
| account | Account name for display |
| systemuser | Rep names and rollup |
| msdyn_forecastdefinition | Quota data (if Sales Insights enabled) |
opportunity:
estimatedvalue (MONEY) - Deal valueestimatedclosedate (DATE) - Expected closecloseprobability (INT) - Win probability % (0-100)msdyn_forecastcategory (CHOICE) - Pipeline(100000001), Best Case(100000002), Committed(100000003), Omitted(100000004), Won(100000005), Lost(100000006)salesstage (CHOICE) - Qualify(0), Develop(1), Propose(2), Close(3)statecode (STATE) - Open(0), Won(1), Lost(2)ownerid (LOOKUP) - Assigned rep (systemuser)User says: "What's my forecast for this quarter?"
Actions:
Result:
Q1 2026 FORECAST - Sarah Johnson
QUOTA: $400,000
ACTUALS (Won): $150,000 (38%)
COMMITTED: $180,000
BEST CASE: $65,000
PIPELINE: $120,000
WEIGHTED FORECAST: $370,000 (93%)
GAP TO QUOTA: $50,000
RISKS:
🟡 Northwind ($85K) - no activity 12 days
🟡 Fabrikam ($42K) - budget unconfirmed
UPSIDE:
⬆️ Alpine Ski ($65K) - BANT 9/10, strong momentum
User says: "Show me the team forecast"
Actions:
Result:
Q1 2026 TEAM FORECAST
TEAM TOTAL: $1.2M quota | $910K forecast | 76%
BY REP:
| Rep | Quota | Won | Commit | Fcst | % |
|----------|--------|--------|--------|--------|-----|
| Sarah J. | $400K | $150K | $180K | $370K | 93% |
| Mike P. | $400K | $120K | $140K | $295K | 74% ⚠️|
| Lisa C. | $400K | $110K | $100K | $245K | 61% 🔴|
AT RISK: Lisa C. needs $155K more to hit quota
COVERAGE: Mike P. has only 2.1x pipeline (below 3x threshold)
User says: "What's the pipeline look like for Q2?"
Actions:
Result:
Q2 2026 PIPELINE PREVIEW
OPEN PIPELINE: $850,000 (32 deals)
BY CATEGORY:
Committed: $120K (early commits)
Best Case: $280K
Pipeline: $450K
STAGE DISTRIBUTION:
| Stage | Count | Value |
|----------|-------|--------|
| Qualify | 12 | $180K |
| Develop | 14 | $420K |
| Propose | 6 | $250K |
COVERAGE: 2.1x to Q2 quota ($400K)
⚠️ ALERT: Need $350K more qualified pipeline by April 1
Cause: msdyn_forecastdefinition table not configured or empty
Solution:
Cause: Reps not setting msdyn_forecastcategory on opportunities
Solution:
Cause: Many deals have old modifiedon dates
Solution:
Integration with protocols.io API for managing scientific protocols. This skill should be used when working with protocols.io to search, create, update, or publish protocols; manage protocol steps and materials; handle discussions and comments; organize workspaces; upload and manage files; or integrate protocols.io functionality into workflows. Applicable for protocol discovery, collaborative protocol development, experiment tracking, lab protocol management, and scientific documentation.
Analyzes job descriptions and generates tailored resumes that highlight relevant experience, skills, and achievements to maximize interview chances
Generate Excalidraw diagrams from natural language descriptions. Use when asked to "create a diagram", "make a flowchart", "visualize a process", "draw a system architecture", "create a mind map", or "generate an Excalidraw file". Supports flowcharts, relationship diagrams, mind maps, and system architecture diagrams. Outputs .excalidraw JSON files that can be opened directly in Excalidraw.
Build and distribute Expo development clients locally or via TestFlight
Use when you have a written implementation plan to execute in a separate session with review checkpoints
Data structure for annotated matrices in single-cell analysis. Use when working with .h5ad files or integrating with the scverse ecosystem. This is the data format skill—for analysis workflows use scanpy; for probabilistic models use scvi-tools; for population-scale queries use cellxgene-census.
Benchling R&D platform integration. Access registry (DNA, proteins), inventory, ELN entries, workflows via API, build Benchling Apps, query Data Warehouse, for lab data management automation.
Comprehensive molecular biology toolkit. Use for sequence manipulation, file parsing (FASTA/GenBank/PDB), phylogenetics, and programmatic NCBI/PubMed access (Bio.Entrez). Best for batch processing, custom bioinformatics pipelines, BLAST automation. For quick lookups use gget; for multi-service integration use bioservices.
Take microsoft/forecast from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.