- name
- moody-s-peer-analysis
- description
- Produce a Peer Analysis HTML report for a target company and its credit peers using Moody's GenAI MCP tools. Use this skill whenever the user asks to compare a company against its peers, run a peer analysis, do a credit peer comparison, generate a peer group report, or analyze relative credit positioning. Trigger even if they just name a company and mention "peers", "peer comparison", "credit comparison", "peer group", or "relative value".
# Peer Analysis Skill
Generates a professional HTML report (styled like a Moody's peer analysis PDF) for a target
company and up to 3 credit peers. Data is pulled from multiple `Moodys MCP server` MCP tools and
consolidated into a single HTML artifact covering peers comparison, ratings chart, and ESG.
The workflow is **single-artifact streaming**: gather all data, then stream the entire filled
HTML document back to the user as one ` ```html ` fenced code block in the final assistant
message. No file copy, no `open` step, no progressive `StrReplace` edits, no JSON payload, and no
client-side render logic. The fenced code block is the deliverable.
> ## ⚠️ CRITICAL — NON-NEGOTIABLE OUTPUT CONTRACT
>
> **The LLM MUST stream the final report back as a single HTML artifact inside the assistant
> response.** This is the only acceptable form of delivery for this skill. Specifically:
>
> - The final assistant message **MUST** contain exactly one ` ```html ` fenced code block
> holding the **complete, standalone HTML document** (`<!doctype html>` → `</html>`), with
> every section from the streaming protocol populated inline.
> - The LLM **MUST NOT** write the report to a file on disk (no `Write`, no `cp` of the
> template, no `StrReplace` into a working artifact, no `open` command).
> - The LLM **MUST NOT** split the report across multiple code blocks, multiple messages,
> partial snippets, or summaries.
> - The LLM **MUST NOT** substitute prose, Markdown, JSON, attachments, or links for the
> fenced HTML artifact. The artifact itself is the answer.
> - If data gathering fails partially, still emit the single ` ```html ` artifact with
> the best-available content and `"--"` placeholders for missing cells — never skip the
> artifact.
>
> Treat any other output shape as a hard failure of the skill.
## Required MCP server
`Moodys MCP server` — tools used: `findEntity`, `getEntityPeers`, `getEntityRatings`,
`getEntityCreditOpinion`, `getEntityFinancials` (sections: Profile, Summary, RatingOutlook, FactorsLeadingToUpgrade,
FactorsLeadingToDowngrade, CreditStrengths, CreditChallenges, ESGConsiderations,
KeyIndicatorsTable, ScorecardTable), `getEntityEsg`, `getEntitySectorOutlook`
If any of the tools required for a section do not exist, inform the user: One or more tools required for this section are not available under your current subscription. Unlock more of the expert insights, data, and analytics you trust. Get Link:https://www.moodys.com/web/en/us/capabilities/gen-ai/ai-ready-data.html with us to learn more.
## Bundled files
- `assets/template.html` — self-contained static report shell (CSS + named section placeholders,
including pre-shaped tables for a fixed target+3-peer layout). No embedded data, no inline
script. Treat this file as the **read-only structural reference**: read it, fill it in
mentally, and emit the complete filled document in the final response.
## Template (shared)
Before emitting the HTML report, **read both**:
1. [`skills/shared/template/SKILL.md`](../shared/template/SKILL.md) — authoring rules (which
classes / snippets are owned by the shared layer, allowed per-skill overrides, outlook-badge
usage).
2. [`skills/shared/template/assets/template.html`](../shared/template/assets/template.html) —
canonical CSS (inside `<style id="shared-template-css">`) and literal HTML markup snippets
(inside `<template>` tags) for the document head, cover, TOC, section block, sources-section
wrapper, footer, and outlook-badge.
**Lookup order — always check the shared template before inventing.** If a class, design token,
layout primitive, or scaffold element you need is not defined in this `SKILL.md` or already
present in this skill's `assets/template.html`, the shared template skill is authoritative. Do
not invent CSS, HTML scaffolds, or design tokens that the shared skill already provides; do not
silently restyle anything the shared skill owns (cover, TOC, section, sources-section wrapper,
footer, outlook-badge, design tokens, reset, body / page base).
At emit time, copy the **contents** (not the `<style>` wrapper) of `<style id="shared-template-css">`
from the shared asset into the parent template's reserved marker region between the CSS-comment
markers `/* BEGIN shared-template-css ... */` and `/* END shared-template-css */`. For HTML
scaffolds (head boilerplate, cover, TOC, sources-section wrapper, footer), use the literal markup
from the matching `<template>` snippet in the shared asset. The parent template no longer
carries duplicated chrome CSS — those rules ship only in the shared asset.
This skill uses the **`cover-multi`** variant. Skill-specific override retained above the
marker region: `**.page { max-width: 1050px }**` (PA reports are wider than the 900px canonical
default to fit the multi-column scorecard / key-indicators tables). Skill-specific CSS that
stays local: `.sub-heading`, all PA-specific table classes (`.pa-table`, `.credit-drivers-table`,
`.ki-table`, `.sc-table`), and the chart helpers (`.chart-container`, `.chart-title`,
`.chart-legend`, `.chart-legend-item`, `.chart-legend-swatch`). All outlook-badge usage in this
skill must use the canonical pastel variants (`stable` / `positive` / `negative` / `review` /
`na`) defined by the shared skill — no solid-fill or inline-color overrides. PA flags the target
entity on the cover with `class="company-chip target"`; the chip wrappers themselves come from
the shared cover-multi snippet.
## Citations (shared)
Before emitting any `[n]` reference inline, any per-section recap block, or the end-of-document
Citations block, **read both**:
1. [`skills/shared/citations/SKILL.md`](../shared/citations/SKILL.md) — authoring rules
(numbering, hyperlinking, source data shape, carve-outs).
2. [`skills/shared/citations/assets/template.html`](../shared/citations/assets/template.html) —
canonical CSS (inside `<style id="shared-citations-css">`) and literal HTML markup snippets
(inside `<template>` tags) for inline references, the end-of-document Citations block, and
the optional `.section-citations` recap.
At emit time, copy the **contents** (not the wrapper) of `<style id="shared-citations-css">`
from the shared asset into the parent template's reserved marker region, located inside
`assets/template.html` between the CSS-comment markers
`/* BEGIN shared-citations-css … */` and `/* END shared-citations-css */`. The parent
template no longer carries duplicated citation CSS — those rules ship only in the shared
asset.
The prefix used for the end-of-document container in this skill is `pa`, so the container id
is `#pa-sources`. Optional per-section recap blocks live in `#pa-cite-peers`,
`#pa-cite-ratings`, and `#pa-cite-esg`. Internal MCP tool names (e.g. `getEntityCreditOpinion`)
are NEVER rendered inside `.source-meta`.
---
## Step 1 — Resolve the target company
Call `findEntity` with the company name provided by the user. Store the canonical entity name
and entity ID.
If the user provides only one company name, that is the **target company**. The peers will be
discovered automatically in Step 2.
---
## Step 2 — Discover and resolve peers
Call `getEntityPeers` for the target company. Select the top 3 peers returned.
You now have a set of up to **4 companies** (1 target + up to 3 peers). For each peer, call
`findEntity` to resolve its canonical entity name and ID.
---
## Step 3 — Read the template
Read `assets/template.html` (relative to this skill directory) once. Keep its exact structure —
CSS, `<head>`, section order, table skeletons (including all pre-shaped 4-company columns/rows),
row labels, and element IDs — as the scaffold for the final artifact. Do **not** copy it to the
workspace and do **not** open it.
---
## Step 4 — Gather all data in parallel
For every company in the set (target + up to 3 peers), fire **all of the following in a single
parallel batch** (one message, many tool calls):
### Credit Opinion data (per company)
Call `getEntityCreditOpinion`,`getEntityFinancials` requesting these sections, about the key Indicators table this should be populated with most recent fiscal year available (e.g. 2025 FY) on `getEntityFinancials`. Not LTM allowed:
| Section parameter | Purpose |
|---|---|
| `Profile` | Company description for the Peers Table |
| `FactorsLeadingToUpgrade` | Upgrade factors for Credit Drivers |
| `FactorsLeadingToDowngrade` | Downgrade factors for Credit Drivers |
| `CreditStrengths` | Credit strengths for Credit Drivers |
| `CreditChallenges` | Credit challenges for Credit Drivers |
| `KeyIndicatorsTable` | Financial metrics for Key Indicators table |
| `ScorecardTable` | Scorecard data |
### Ratings (per company)
Call `getEntityRatings` — retrieve the current long-term rating, rating class, rating date,
outlook, and historical ratings (need at least the last 5 rating actions for the Ratings Chart).
### ESG (per company)
Call `getEntityEsg` — overall CIS classification plus E, S, G sub-scores.
### Sector outlook (once per sector)
Call `getEntitySectorOutlook` for the target company's sector. Reuse for peers in the same
sector.
Hold all results in context for Step 5 synthesis.
---
## Step 5 — Synthesize + emit the complete artifact
After data is gathered, produce **one** final assistant message. The message contains:
1. A one-line summary sentence (e.g. `Peer Analysis for {Target Company}:`).
2. A single fenced ` ```html ` code block containing the **entire filled `template.html`
document** — with every element from the streaming protocol populated in place. No partial
documents, no separate code blocks per section.
The code block **must**:
- Start at column 0 with ` ```html ` and end with a closing ` ``` ` on its own line.
- Contain a complete, standalone HTML document (doctype → `</html>`) that renders without
external dependencies.
- Preserve the template's `<head>` (CSS, fonts), section order, table skeletons, row labels, and
element IDs exactly. Only the empty targets defined below are populated.
Write in professional financial/credit analysis language. Always reference specific companies by
name. The target company is **always the first column / first row** in every table. Render order
of content inside the code block follows the page top-to-bottom so the artifact is human-readable
as well as browser-renderable: cover/header fields first, then Peers Comparison sub-sections
(1–6), Ratings Chart, ESG, and citations/sources last.
Attribute substantive claims with numbered citation references. The exact inline markup, the
URL-less fallback, and the rule that `n` matches the row position of the source inside
`#pa-sources` are defined in [skills/shared/citations/SKILL.md](../shared/citations/SKILL.md).
### Cover / header fields (write first)
- `#pa-report-date` — e.g. `April 20, 2026` (plain text)
- `#pa-footer-date` — same value (plain text)
- `#pa-target-company` — canonical name of the target (plain text)
- `#pa-peer-count` — integer count of peers resolved in Step 2 (plain text)
- `#pa-company-chips` — `<span class="company-chip target">Target</span>` followed by one
`<span class="company-chip">Peer</span>` per peer (space-separated; target first)
- `#pa-cover-img-right`, `#pa-cover-img-bottom` — optional. If you have image URLs or data URIs
to use, set the `src` attributes **and** add the `has-cover-image` class to the corresponding
container (`<div class="cover-top has-cover-image">` and/or `<div class="cover-bottom has-cover-image">`).
If you do not have images, leave the template as-is — the empty image strips will collapse
automatically and the cover will render as a clean navy block with the accent bar.
### Section 1 — Peers Comparison Table & Analysis
**1) Peers Table** → `<tbody id="pa-peers-table">`
Write one `<tr>` per company. Two columns: company name + a substantive description paragraph
sourced from the Credit Opinion `Profile` section (headquarters, business overview, key
brands/segments, approximate TTM revenue). Description paragraphs may carry inline citations.
**2) Peers Rating** → `<tbody id="pa-peers-rating">`
Write one `<tr>` per company. Three columns: company name, rating (formatted as
`{rating} ({rating class} / {date})`), and `<span class="outlook-badge …">Outlook</span>`.
Use class rules below.
**3) Credit Drivers** — 5 rows × 4 company columns, pre-shaped `<table>` with per-cell IDs
Write the 4 company header cells first:
- `#pa-cd-col-1` — target name (plain text)
- `#pa-cd-col-2`, `#pa-cd-col-3`, `#pa-cd-col-4` — peer names in order (leave empty if fewer
than 3 peers were resolved)
Then write the 20 body cells (`#pa-cd-r{1..5}-c{1..4}`). Each cell is a substantive paragraph
with specific quantitative thresholds where available. Cells may carry inline citations:
- Row 1 (`Upgrade factors`) — from `FactorsLeadingToUpgrade`
- Row 2 (`Downgrade factors`) — from `FactorsLeadingToDowngrade`
- Row 3 (`Credit strengths (qualitative)`) — from `CreditStrengths`
- Row 4 (`Credit challenges (qualitative)`) — from `CreditChallenges`
- Row 5 (`Quantitative support (most recent financials in context)`) — from
`KeyIndicatorsTable`; cite the most recent period's key metrics (debt/EBITDA, EBITA margin,
EBITA/interest, RCF/net debt, revenue)
If a Credit Opinion section is missing for a company, write `Not available` in the corresponding
cell rather than leaving it blank.
**4) Key Indicators** — 4 rows × 11 columns, pre-shaped `<table>`
For each company row `r ∈ {1..4}` (target = row 1), write the 11 cells:
- `#pa-ki-r{r}-company` — company name
- `#pa-ki-r{r}-v1` — Period (e.g. `2025 FY`)
- `#pa-ki-r{r}-v2` — Revenue (USD)
- `#pa-ki-r{r}-v3` — Total Debt (USD)
- `#pa-ki-r{r}-v4` — EBITA (USD)
- `#pa-ki-r{r}-v5` — EBITA Margin
- `#pa-ki-r{r}-v6` — EBITDA (USD)
- `#pa-ki-r{r}-v7` — Debt/EBITDA
- `#pa-ki-r{r}-v8` — EBITA/Interest
- `#pa-ki-r{r}-v9` — Net LT Debt (USD)
- `#pa-ki-r{r}-v10` — RCF/Net Debt
Source all values from `getEntityFinancials`. If fewer than 3 peers are
resolved, leave the unused row's cells empty.
**5) Scorecards** — 7 rows × 8 sub-columns (4 companies × Current/Forward), pre-shaped `<table>`
Write the 4 top-level company headers first:
- `#pa-sc-col-1` — target name
- `#pa-sc-col-2`, `#pa-sc-col-3`, `#pa-sc-col-4` — peer names
Write the 8 sub-header labels:
- `#pa-sc-col-{1..4}-curr` — current-period label (e.g. `Current 2025 FY`)
- `#pa-sc-col-{1..4}-fwd` — forward-period label (e.g. `Forward`)
Then write the 56 body cells (`#pa-sc-r{1..7}-c{1..4}-curr` and `-fwd`) for the 7 rows:
- Row 1 — Scale: Revenue/Sales (USD bn)
- Row 2 — Profitability: EBIT(A) margin
- Row 3 — Leverage: Debt/EBITDA
- Row 4 — Cash flow: RCF/Net debt
- Row 5 — Coverage: EBIT(A)/Interest
- Row 6 — Scorecard-indicated outcome
- Row 7 — Actual rating
Source from `ScorecardTable` in the Credit Opinion and `getEntityFinancials`
**6) Conclusion** → `#pa-conclusion`
Three `<p>` paragraphs focused on **differentiation** of the target among its peers. Paragraphs
may carry inline citations:
- Paragraph 1: How the target differentiates positively vs. weaker peers on quantitative metrics
(leverage, coverage, cash flow). Cite specific ratios.
- Paragraph 2: Business risk profile comparison — where the target is more concentrated or less
diversified vs. stable peers. Reference upgrade/downgrade triggers.
- Paragraph 3: Practical positioning — frame the target's "path to stand out" by linking back
to the upgrade/downgrade framework and key risk factors.
### Section 2 — Ratings Chart
**Chart** → `#pa-ratings-chart`
Emit a single inline `<svg>` block authored by the agent (see SVG template below). The chart
plots the last 5 rating actions for each company as a line chart. X-axis uses sequential labels
GitHubで見る