@nestbox-ai/cli
Version:
The cli tools that helps developers to build agents
444 lines (385 loc) • 18.1 kB
YAML
# VC Portfolio Monitoring Report
# Use case: Monthly portfolio review across multiple portfolio companies.
# Each company has its own docset (separate GraphRAG index).
# Extracts ARR, burn, runway, headcount, and key risks per company,
# then synthesises a cross-portfolio dashboard.
# Schema v2.2
schema_version: "2.2"
report:
id: vc_portfolio_monitoring_q1_2026
name: "VC Portfolio Monitoring — Q1 2026"
description: |
Cross-portfolio KPI dashboard extracting key metrics from each portfolio
company's board update or monthly investor report.
Covers ARR/revenue, burn/runway, headcount, recent milestones, and risks.
version: "2026.Q1"
context:
fund_name: "Acme Ventures Fund III"
reporting_period: "Q1 2026"
as_of_date: "2026-03-31"
currency: "USD"
units_policy: |
Return raw full-dollar numbers. Convert abbreviations:
"$2.5M" → 2500000, "$350K" → 350000, "$1.2B" → 1200000000.
Percentages as whole numbers: 92.3 not 0.923.
Return null for any value not explicitly found in the document.
answer_quality_policy:
numeric_requirements:
- "Every numeric value must have a citation (c_xxxxxxxx format)"
- "Return null for values not explicitly stated — never estimate"
labeling_requirements:
- "Always include the reporting period with each metric"
doc_repository:
api_base_url: ${DOC_REPO_URL:-http://localhost:8080}
api_key: ${DOC_REPO_API_KEY}
rotation: 200
mcp: []
# Each portfolio company is its own docset with its own GraphRAG index
docsets:
- id: company_alpha
description: "Alpha Inc — Q1 2026 board update"
api_key: ${OPENAI_API_KEY}
docs:
- id: alpha_board_update
locator: "repo:doc-alpha0001"
description: "Alpha Inc Q1 2026 Board Update"
- id: company_beta
description: "Beta Systems — Q1 2026 monthly investor report"
api_key: ${OPENAI_API_KEY}
docs:
- id: beta_investor_report
locator: "repo:doc-beta0002"
description: "Beta Systems Q1 2026 Investor Report"
- id: company_gamma
description: "Gamma Health — Q1 2026 board deck"
api_key: ${OPENAI_API_KEY}
docs:
- id: gamma_board_deck
locator: "repo:doc-gamma003"
description: "Gamma Health Q1 2026 Board Deck"
llamaindex:
model: gpt-4o
base_url: ${OPENAI_BASE_URL:-https://api.openai.com/v1}
api_key: ${OPENAI_API_KEY}
max_tool_calls: 40
tool_timeout_seconds: 150
max_agent_iterations: 35
system_prompt: |
You are a venture capital analyst extracting KPIs from portfolio company reports.
## ANTI-FABRICATION RULE
ALL values MUST come from your search tool results. Never guess. Return null if not found.
## Rules
1. Return raw full-dollar numbers (9700000 not "$9.7M")
2. Percentages as whole numbers (92.3 not 0.923)
3. Every numeric value needs a c_xxxxxxxx citation
4. Return null for any value not explicitly stated in the document
5. Negative values are valid (e.g., churn ARR, net cash burn)
computations:
fields:
# ── Company Alpha KPIs ─────────────────────────────────────────────────────
- id: alpha_kpis
label: "Alpha Inc — Q1 2026 KPIs"
type: object
priority: 1
docset_id: company_alpha
agents:
- id: alpha_extract
prompt: |
Extract the following KPIs for Alpha Inc from their Q1 2026 board update.
## Financial Metrics
- arr_end: Ending ARR for the most recent period (full dollars)
- arr_mom_growth_pct: MoM or QoQ ARR growth % (whole number)
- monthly_burn: Net monthly cash burn (full dollars)
- cash_on_hand: Current cash balance (full dollars)
- runway_months: Months of runway at current burn
## Operating Metrics
- headcount: Total employee count
- customer_count: Total paying customer or logo count
- nrr: Net Revenue Retention % (if stated)
## Qualitative
- top_milestone: Single most important milestone this quarter (string)
- top_risk: Single most important risk mentioned (string)
## Search Strategy
1. basic_search: "ARR revenue growth Q1 2026 monthly"
2. basic_search: "cash burn runway headcount customers"
3. basic_search: "highlights milestones risks challenges"
Set to null anything not explicitly stated.
output_schema:
type: object
properties:
company: { type: string }
period: { type: string }
arr_end: { type: number }
arr_mom_growth_pct: { type: number }
monthly_burn: { type: number }
cash_on_hand: { type: number }
runway_months: { type: number }
headcount: { type: number }
customer_count: { type: number }
nrr: { type: number }
top_milestone: { type: string }
top_risk: { type: string }
citations: { type: array, items: { type: string } }
notes: { type: string }
mcp_scope: []
prompt: "Return Alpha Inc Q1 2026 KPIs with citations."
# ── Company Beta KPIs ──────────────────────────────────────────────────────
- id: beta_kpis
label: "Beta Systems — Q1 2026 KPIs"
type: object
priority: 1
docset_id: company_beta
agents:
- id: beta_extract
prompt: |
Extract the following KPIs for Beta Systems from their Q1 2026 investor report.
## Financial Metrics
- arr_end: Ending ARR for the most recent period
- arr_mom_growth_pct: MoM or QoQ ARR growth %
- monthly_burn: Net monthly cash burn
- cash_on_hand: Current cash balance
- runway_months: Months of runway at current burn
## Operating Metrics
- headcount: Total employee count
- customer_count: Total paying customer count
- nrr: Net Revenue Retention % (if stated)
## Qualitative
- top_milestone: Most important milestone this quarter
- top_risk: Most important risk mentioned
## Search Strategy
1. basic_search: "ARR revenue MRR monthly quarterly growth"
2. basic_search: "cash burn runway balance headcount team"
3. basic_search: "highlights wins milestones risks concerns"
Set to null anything not explicitly stated.
output_schema:
type: object
properties:
company: { type: string }
period: { type: string }
arr_end: { type: number }
arr_mom_growth_pct: { type: number }
monthly_burn: { type: number }
cash_on_hand: { type: number }
runway_months: { type: number }
headcount: { type: number }
customer_count: { type: number }
nrr: { type: number }
top_milestone: { type: string }
top_risk: { type: string }
citations: { type: array, items: { type: string } }
notes: { type: string }
mcp_scope: []
prompt: "Return Beta Systems Q1 2026 KPIs with citations."
# ── Company Gamma KPIs ─────────────────────────────────────────────────────
- id: gamma_kpis
label: "Gamma Health — Q1 2026 KPIs"
type: object
priority: 1
docset_id: company_gamma
agents:
- id: gamma_extract
prompt: |
Extract KPIs for Gamma Health from their Q1 2026 board deck.
## Financial Metrics
- arr_end or revenue_end: ARR or revenue for the quarter
- arr_mom_growth_pct: MoM or QoQ growth %
- monthly_burn: Net monthly cash burn
- cash_on_hand: Current cash balance
- runway_months: Months of runway
## Operating Metrics
- headcount: Total employee count
- customer_count: Patients, clients, or paying customer count
- nrr: Net Revenue Retention % (if applicable)
## Qualitative
- top_milestone: Most important milestone
- top_risk: Most important risk
## Search Strategy
1. basic_search: "revenue ARR growth quarterly monthly"
2. basic_search: "cash burn runway balance employees headcount"
3. basic_search: "milestones highlights risks"
Set to null anything not explicitly stated.
output_schema:
type: object
properties:
company: { type: string }
period: { type: string }
arr_end: { type: number }
arr_mom_growth_pct: { type: number }
monthly_burn: { type: number }
cash_on_hand: { type: number }
runway_months: { type: number }
headcount: { type: number }
customer_count: { type: number }
nrr: { type: number }
top_milestone: { type: string }
top_risk: { type: string }
citations: { type: array, items: { type: string } }
notes: { type: string }
mcp_scope: []
prompt: "Return Gamma Health Q1 2026 KPIs with citations."
# ── Cross-Portfolio Summary (depends on all 3 companies) ──────────────────
- id: portfolio_summary
label: "Cross-Portfolio Summary"
type: object
priority: 2
depends_on: [alpha_kpis, beta_kpis, gamma_kpis]
agents:
- id: portfolio_summary_extract
docset_id: company_alpha # use any docset — this agent synthesises from context
prompt: |
Summarise the overall health of the portfolio based on the individual
company KPIs available in your context (from depends_on).
## What to Produce
- total_portfolio_arr: Sum of all companies' ARR (null if any are missing)
- portfolio_avg_runway_months: Average runway across companies
- healthiest_company: Company name with strongest metrics
- most_at_risk_company: Company name with lowest runway or highest burn
- common_themes: 2-3 themes appearing across multiple companies
- portfolio_outlook: "positive" | "cautious" | "mixed" | "concerning"
Base your answer entirely on the company KPIs from context.
If a company KPI is null, exclude it from calculations and note it.
output_schema:
type: object
properties:
total_portfolio_arr: { type: number }
portfolio_avg_runway_months: { type: number }
healthiest_company: { type: string }
most_at_risk_company: { type: string }
common_themes: { type: array, items: { type: string } }
portfolio_outlook: { type: string }
notes: { type: string }
mcp_scope: []
prompt: "Return cross-portfolio summary derived from company KPIs."
tables:
# ── Portfolio Dashboard Table ──────────────────────────────────────────────
- id: portfolio_dashboard
title: "Portfolio Company Dashboard — Q1 2026"
priority: 2
depends_on: [alpha_kpis, beta_kpis, gamma_kpis]
agents:
- id: dashboard_build
docset_id: company_alpha # placeholder — values come from context
prompt: |
Build the portfolio dashboard table from the company KPI results
available in your context (from depends_on).
For each of the 3 companies (Alpha Inc, Beta Systems, Gamma Health),
create one row with:
- company: Company name
- arr_end: Ending ARR (full dollars)
- arr_growth_pct: QoQ ARR growth %
- monthly_burn: Monthly burn (full dollars)
- runway_months: Runway in months
- headcount: Employee count
- nrr: NRR % (if available)
- outlook: "green" | "yellow" | "red" based on runway and growth
Use only values from the company KPIs in context. Set null where missing.
Return {"rows": [...]} with one object per company.
output_schema:
type: object
properties:
rows:
type: array
items:
type: object
properties:
company: { type: string }
arr_end: { type: number }
arr_growth_pct: { type: number }
monthly_burn: { type: number }
runway_months: { type: number }
headcount: { type: number }
nrr: { type: number }
outlook: { type: string }
mcp_scope: []
prompt: "Build portfolio dashboard table from company KPIs."
template:
format: markdown
sections:
header: |
# {{report.name}}
> **Fund:** {{context.fund_name}} | **As of:** {{context.as_of_date}} | **Period:** {{context.reporting_period}}
content: |
{{sections.header}}
---
## Portfolio Dashboard
{{table.portfolio_dashboard}}
**Overall outlook:** {{ field.portfolio_summary.portfolio_outlook | default("—") }}
**Combined portfolio ARR:** {{ field.portfolio_summary.total_portfolio_arr | currency("$", 0) | default("—") }}
**Average runway:** {{ field.portfolio_summary.portfolio_avg_runway_months | number(1) | default("—") }} months
**Common themes:** {{ field.portfolio_summary.common_themes | default("—") }}
**Healthiest:** {{ field.portfolio_summary.healthiest_company | default("—") }}
**Most at risk:** {{ field.portfolio_summary.most_at_risk_company | default("—") }}
---
## Alpha Inc
| Metric | Value |
|--------|-------|
| ARR | {{ field.alpha_kpis.arr_end | currency("$", 0) | default("—") }} |
| QoQ Growth | {{ field.alpha_kpis.arr_mom_growth_pct | number(1) | default("—") }}% |
| Monthly Burn | {{ field.alpha_kpis.monthly_burn | currency("$", 0) | default("—") }}/mo |
| Cash | {{ field.alpha_kpis.cash_on_hand | currency("$", 0) | default("—") }} |
| Runway | {{ field.alpha_kpis.runway_months | number(1) | default("—") }} months |
| Headcount | {{ field.alpha_kpis.headcount | number(0) | default("—") }} |
| NRR | {{ field.alpha_kpis.nrr | number(1) | default("—") }}% |
**Milestone:** {{ field.alpha_kpis.top_milestone | default("—") }}
**Risk:** {{ field.alpha_kpis.top_risk | default("—") }}
---
## Beta Systems
| Metric | Value |
|--------|-------|
| ARR | {{ field.beta_kpis.arr_end | currency("$", 0) | default("—") }} |
| QoQ Growth | {{ field.beta_kpis.arr_mom_growth_pct | number(1) | default("—") }}% |
| Monthly Burn | {{ field.beta_kpis.monthly_burn | currency("$", 0) | default("—") }}/mo |
| Cash | {{ field.beta_kpis.cash_on_hand | currency("$", 0) | default("—") }} |
| Runway | {{ field.beta_kpis.runway_months | number(1) | default("—") }} months |
| Headcount | {{ field.beta_kpis.headcount | number(0) | default("—") }} |
| NRR | {{ field.beta_kpis.nrr | number(1) | default("—") }}% |
**Milestone:** {{ field.beta_kpis.top_milestone | default("—") }}
**Risk:** {{ field.beta_kpis.top_risk | default("—") }}
---
## Gamma Health
| Metric | Value |
|--------|-------|
| ARR | {{ field.gamma_kpis.arr_end | currency("$", 0) | default("—") }} |
| QoQ Growth | {{ field.gamma_kpis.arr_mom_growth_pct | number(1) | default("—") }}% |
| Monthly Burn | {{ field.gamma_kpis.monthly_burn | currency("$", 0) | default("—") }}/mo |
| Cash | {{ field.gamma_kpis.cash_on_hand | currency("$", 0) | default("—") }} |
| Runway | {{ field.gamma_kpis.runway_months | number(1) | default("—") }} months |
| Headcount | {{ field.gamma_kpis.headcount | number(0) | default("—") }} |
| NRR | {{ field.gamma_kpis.nrr | number(1) | default("—") }}% |
**Milestone:** {{ field.gamma_kpis.top_milestone | default("—") }}
**Risk:** {{ field.gamma_kpis.top_risk | default("—") }}
guardrails:
- id: gr_no_fabrication
target: computations
on_fail: warn
model: gpt-4.1-mini
api_key: ${OPENAI_API_KEY}
description: "Detect fabricated or placeholder values"
prompt: |
FAIL if you find: citations like "Source A"/"Source B" (real ones use c_xxxxxxxx),
ARR values that are ALL round multiples of 100000, or retention values below 1.0.
Return JSON: {"pass": boolean, "issues": []}
Content: {{content}}
- id: gr_runway_sanity
target: computations
on_fail: warn
model: gpt-4.1-mini
api_key: ${OPENAI_API_KEY}
description: "Runway values must be positive and plausible"
prompt: |
Check all runway_months values. FAIL if any are negative or greater than 120 months.
Check all monthly_burn values. FAIL if any are positive (burn should be stored as positive number,
but flag if burn is implausibly large compared to cash, e.g., burn > cash).
Return JSON: {"pass": boolean, "issues": []}
Content: {{content}}
execution:
retries:
max_attempts: 3
backoff_seconds: 2.0
output:
directory: ./output
timestamp_suffix: true
include_final_report: true
include_computed_json: true
include_evidence: true
include_guardrails: true