Create Phoenix release documentation grounded in actual code changes. Use this skill whenever the user asks to write release notes, document a release, update release documentation, or mentions undocumented releases. Also trigger when the user wants to update GitHub release descriptions, add entries to the release notes page, or asks what changed in a recent Phoenix version.
68
86%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
Low
Low-risk findings worth noting
Create and publish release documentation for Phoenix. This skill walks through a structured workflow: identify undocumented releases, analyze commits by reading the actual code, draft MDX files, and update all the documentation touchpoints.
Write for a developer who uses Phoenix daily. The voice is technical, friendly, and informative without being verbose.
**Available in arize-phoenix X.Y.Z+**| Package | Tag pattern |
|---|---|
| arize-phoenix (server) | arize-phoenix-v* |
| arize-phoenix-client (Python SDK) | arize-phoenix-client-v* |
| arize-phoenix-evals | arize-phoenix-evals-v* |
| arize-phoenix-otel | arize-phoenix-otel-v* |
| @arizeai/phoenix-client (TS SDK) | Check js/packages/phoenix-client/package.json |
| @arizeai/phoenix-cli (TS CLI) | Check js/packages/phoenix-cli/package.json |
| @arizeai/phoenix-evals (TS evals) | Check js/packages/phoenix-evals/package.json |
| @arizeai/phoenix-mcp (TS MCP) | Check js/packages/phoenix-mcp/package.json |
| @arizeai/phoenix-otel (TS OTel) | Check js/packages/phoenix-otel/package.json |
Compare GitHub releases against existing documentation to find the gap.
# Recent GitHub releases
gh release list --repo Arize-ai/phoenix --limit 30
# Existing release note files
ls docs/phoenix/release-notes/*/
# Dates already covered in the aggregate file
grep 'ReleaseUpdate label=' docs/phoenix/release-notes.mdxEach <ReleaseUpdate> entry in the aggregate file covers a date. Multiple versions released on the same
date get combined into one entry. Identify releases that have no corresponding coverage.
For each undocumented release, examine the actual changes — not just the commit messages.
gh release view <TAG> --repo Arize-ai/phoenix --json body --jq '.body'The release body from release-please lists conventional commits with PR links. Use this as a starting index, then dig deeper.
For each feat() and significant fix() commit, read the changed files to understand what the
feature actually does. Commit messages are often terse — the code tells the real story. Key places:
src/phoenix/server/api/routers/v1/packages/phoenix-client/src/phoenix/client/js/packages/phoenix-client/src/js/app/src/pages/packages/phoenix-evals/src/phoenix/evals/packages/phoenix-client/src/phoenix/client/cli/INCLUDE — things users interact with directly:
EXCLUDE — internal housekeeping:
chore(deps):, fix(deps):).agents/skills/), or dev workflows with no
product behavior changeIf a release contains only excluded changes, skip it — no release note needed.
Multiple commits often implement a single feature across server + client + UI. A REST endpoint commit, a Python client wrapper, and a TypeScript client wrapper should become one release note entry that mentions all relevant package versions — not three separate entries.
Sort the included changes into tiers before drafting. The page runs top to bottom in this order, and the title, description, intro, aggregate bullets, year card, and Slack overview all lead with whatever landed in the highest tier.
| Tier | What goes here | Examples |
|---|---|---|
| 1 | New integrations, workflows, and evaluation capabilities that change how someone uses Phoenix | Harbor plugin, a new evaluator, PXI doing something new, a new UI surface |
| 2 | New model or provider support | Z.ai / MiniMax / Meta built in, new frontier models |
| 3 | SDK and CLI capabilities | new client methods or parameters, new px commands |
| 4 | Protocol, auth, and infrastructure changes | MCP server upgrades, OAuth changes, config variables |
| 5 | REST-only endpoints and administrative routes | DELETE /v1/projects/{id}/traces, retention policy CRUD |
| 6 | Fixes and small polish | # Additional Improvements |
Rules:
# Additional Improvements.
Endpoint reference docs already cover them; the release note only needs to say they exist.# Additional Improvements or merged into a sibling section (for example, two small
PXI changes become one # PXI: ... section), not its own heading.Prefer one release note over many. Phoenix ships frequently, and a separate page per day produces a noisy, hard-to-scan release feed. Before creating files, look at the whole batch of undocumented releases together and ask: can these become one multi-topic file (Format B)?
Consolidate into a single file when the batch:
Each feature inside the consolidated file keeps its own # Heading, date line, and
**Available in arize-phoenix X.Y.Z+** version line, so per-feature version provenance is
preserved even though they share one page. The frontmatter title and file are dated by the
latest release in the bundle, and the file description summarizes the whole bundle.
Only split into multiple files when a feature is genuinely large enough to deserve a standalone page (a major launch, a breaking change, or a feature with substantial code examples and its own media). When in doubt, consolidate — it is easier to read one well-organized page than five thin ones.
If you are revising an existing batch that was already split into several thin files,
consolidate them: create one combined file dated by the latest release, delete the superseded
files (git rm), and collapse their entries down to a single <ReleaseUpdate> block and a single
year-overview <Card> and a single docs.json page path.
Release notes are skimmed. Cut until each piece fits:
| Piece | Budget |
|---|---|
| Page intro | 1-2 sentences, leading with the tier-1 feature |
| Feature section | 1 short paragraph, 2-4 bullets, at most one snippet per language, one <CardGroup> |
| Bullet | 1-2 sentences. A bold lead plus one clause of detail |
# Additional Improvements bullet | 1 sentence, bold lead, no sub-bullets |
| Whole page | Aim for under ~200 lines for a weekly bundle |
Cut first: restated reference material (parameter tables that exist in the API docs), a second
snippet that shows the same call with different values, export FOO=... blocks, and any sentence
that explains what the previous sentence already said.
docs/phoenix/release-notes/{MM-YYYY}/{MM-DD-YYYY}-{slug-title}.mdxCreate the month directory if it doesn't exist: mkdir -p docs/phoenix/release-notes/MM-YYYY
Every release note MDX file — single-topic or multi-topic — must have a descriptive,
date-prefixed title in its frontmatter. The title appears in browser tabs, the sidebar,
and search results, so a generic "Release Notes" makes the page indistinguishable from
the index page.
Required format: title: "MM.DD.YYYY: Descriptive Title"
title: "04.29.2026: Dataset Upsert"title: "05.05.2026: REST API Updates"title: "04.30.2026: Annotation Enhancements"title: "Release Notes" — never use this; it collides with the index pagetitle: "Dataset Upsert" — missing the date prefixtitle: "04.29.2026 Dataset Upsert" — missing the colon separatorFor multi-topic files, the title summarizes the theme of the bundle (e.g.
"04.30.2026: Annotation Enhancements"), not any single feature inside it.
Use when one feature is significant enough to warrant its own page.
---
title: "MM.DD.YYYY: Feature Title"
description: "One-sentence description of the feature."
---
Introductory paragraph explaining what users can now do.
## Section Heading
- **Bold lead** describing a capability
- **Another point** with technical detail
```python
# Working Python example// Working TypeScript exampleUse when several features from a date range are combined into one file. The frontmatter
title still follows the MM.DD.YYYY: Theme rule (see "Frontmatter title rules" above) —
never use "Release Notes".
---
title: "MM.DD.YYYY: Theme Title"
---
# Feature Title One
Month DD, YYYY
**Available in arize-phoenix X.Y.Z+**
Description paragraph.
- **Bullet** describing capability
```python
# code exampleMonth DD, YYYY
Available in package-name X.Y.Z+
Description paragraph.
### Version line format
Match the version line to which packages are involved:Available in arize-phoenix 13.14.0+ Available in arize-phoenix-client 2.0.0+ (Python) and @arizeai/phoenix-client 6.4.0+ (TypeScript) Available in arize-phoenix 13.13.0+ (server), arize-phoenix-client 1.31.0+ (Python) Available in arize-phoenix 15.1.0+ (beta) Breaking change in arize-phoenix-client 2.0.0
### Choosing between formats
| Situation | Format |
|-----------|--------|
| Multiple features across a short window or shared theme | **Format B — one consolidated file (default)** |
| A single, genuinely major feature or breaking change worth its own page | Format A |
| Feature spans server + client | One entry, mention all package versions |
| Breaking change | Prefix title with "Breaking Change:" |
| TS-only or Python-only feature | Show only the relevant language |
| Video/screenshot available | Use `<video>` or `<Frame>` in the relevant section of the file |
## Step 4: Update the Aggregate File
File: `docs/phoenix/release-notes.mdx`
Insert each new `<ReleaseUpdate>` block at the correct chronological position relative to **all**
existing blocks — not as a contiguous group at the top. Each block is a condensed summary
linking to the individual file.
The file imports the `ReleaseUpdate` component at the top (after the frontmatter):
```mdx
import { ReleaseUpdate } from "../snippets/ReleaseUpdate.jsx";<ReleaseUpdate label="MM.DD.YYYY" href="/docs/phoenix/release-notes/MM-YYYY/MM-DD-YYYY-slug-title" title="Feature Title">
**Available in ...**
Brief 1-3 sentence summary. Action-oriented.
- **Key capability** with brief description
- **Another capability** with brief description
</ReleaseUpdate>Rules:
label uses dot separators: MM.DD.YYYYtitle is the feature title (without date prefix — the component generates label: title as the heading)href is the link to the individual MDX file.mdx extension<ReleaseUpdate> block labeled with the
latest date, whose bullets summarize the bundled features — one block per file, not one per
feature. Only split into multiple blocks when the bundled features fall on clearly distinct dates
that each merit their own line in the feed.The aggregate file is sorted strictly newest-first by date. Existing entries are already ordered, so inserting a batch of new entries is a merge, not an append.
Wrong — stacking all new entries at the top as a contiguous block:
[NEW 05.05] [NEW 05.05] [NEW 04.30] [NEW 04.30] [NEW 04.29] [old 05.01] [old 04.28] ...
^^^^^^^^^^
older date appears AFTER newer dates — brokenRight — interleave each new entry with existing entries by date:
[NEW 05.05] [NEW 05.05] [old 05.01] [NEW 04.30] [NEW 04.30] [NEW 04.29] [old 04.28] ...Procedure when adding multiple entries:
grep -n 'Update label=' docs/phoenix/release-notes.mdxFile: docs/phoenix/release-notes/YYYY.mdx (e.g., 2026.mdx)
Add a <Card> entry at the top of the <CardGroup>:
<Card href="/docs/phoenix/release-notes/MM-YYYY/MM-DD-YYYY-slug-title" arrow="true" title="MM.DD.YYYY" icon="calendar" description="Brief description of the feature"/>The description is one sentence, roughly 200 characters or fewer, naming only the top two or
three features in ranked order. It is a card, not a table of contents: no semicolon-separated
inventory of every section, no fix list, and no version ranges (those live on the page).
File: docs.json (repository root)
Find the "Release Notes" tab. Add new page paths to the appropriate monthly group.
Add the page path to the existing group's pages array (newest first):
{
"group": "MM.YYYY",
"pages": [
"docs/phoenix/release-notes/MM-YYYY/MM-DD-YYYY-new-page",
"docs/phoenix/release-notes/MM-YYYY/existing-page"
]
}Create a new group object in the correct chronological position (newest month first, after the aggregate page entry):
{
"group": "MM.YYYY",
"pages": [
"docs/phoenix/release-notes/MM-YYYY/MM-DD-YYYY-slug-title"
]
}Page paths: forward slashes, no leading slash, no .mdx extension.
Only when explicitly requested. The default release-please changelog is acceptable.
You MUST preserve the existing release body. First fetch it, then prepend a highlights section:
# 1. Fetch the existing release body
EXISTING_BODY=$(gh release view <TAG> --repo Arize-ai/phoenix --json body --jq '.body')
# 2. Prepend highlights and wrap the original body in a details block
gh release edit <TAG> --repo Arize-ai/phoenix --notes "$(cat <<EOF
## Highlights
### Feature Title
Description with user-facing framing.
See the [release notes](https://docs.arize.com/phoenix/release-notes/MM-YYYY/MM-DD-YYYY-slug) for details.
---
<details>
<summary>Conventional commits</summary>
$EXISTING_BODY
</details>
EOF
)"Before considering the work complete, check every touchpoint:
title/docs/phoenix/release-notes/... path in the aggregate
file matches an actual filedocs.json contains all new page paths with no dangling references# Verify aggregate links point to real files
grep -oP '(?<=\()/docs/phoenix/release-notes/[^)]+' docs/phoenix/release-notes.mdx | while read path; do
file="${path}.mdx"
[ -f "$file" ] || echo "MISSING: $file"
done
# Catch any new file that still has the generic "Release Notes" title
grep -l '^title: "Release Notes"$' docs/phoenix/release-notes/**/*.mdx 2>/dev/null \
&& echo "FAIL: file(s) above use the generic 'Release Notes' title — must be 'MM.DD.YYYY: ...'" \
|| echo "OK: all per-date files have descriptive titles"
# Confirm reverse-chronological order in the aggregate file
grep -nP 'ReleaseUpdate label="[\d.]+' docs/phoenix/release-notes.mdx \
| awk -F'[:."]' '{ printf "%s %s%s%s\n", $1, $5, $3, $4 }' \
| awk 'NR>1 && $2>prev { print "OUT OF ORDER at release-notes.mdx:" $1 " — " $2 " appears above " prev; bad=1 } { prev=$2 } END { if (!bad) print "OK: reverse-chronological order intact" }'After the docs are written, produce a short overview of the release that can be copy-pasted directly into Slack. Print it in the final response inside a single fenced code block so the user can grab the whole thing in one click. This is a summary for a team channel, not a replacement for the release notes — link back to the published notes for detail.
Slack does not render standard Markdown. Use its mrkdwn syntax or the message will look wrong:
*bold* — not **bold**_italic_# headings — Slack ignores them. Use a bold line instead.<https://url|label> — not [label](url)• character (not - or *, which don't render as bullets)*🚀 Phoenix release — <MONTH DD, YYYY>*
<One-sentence framing of the highlight(s).>
• *<Feature One>* (`<package X.Y.Z+>`) — one-line user-facing description.
• *<Feature Two>* (`<package X.Y.Z+>`) — one-line user-facing description.
📝 Release notes: <https://docs.arize.com/phoenix/release-notes/MM-YYYY/MM-DD-YYYY-slug|Full notes>Rules:
requires server 17.12.0+).https://docs.arize.com/phoenix/...).| Question | Answer |
|---|---|
| Release has only dep bumps? | Skip — no release note |
| Feature reverted in same release? | Exclude both feat and revert |
| Month directory missing? | Create it with mkdir -p |
| Month nav group missing in docs.json? | Add new group object |
| Feature spans multiple packages? | One entry, list all versions |
| Not sure if user-facing? | Read the code — if a user can't see or call it, exclude it |
| Where does a REST-only endpoint go? | Bottom of the page, just above # Additional Improvements |
| Endpoint also in the SDKs? | Write it as an SDK feature; the endpoint gets one clause or a card |
| Section is only a couple of sentences? | Merge it into a sibling or make it one bullet in # Additional Improvements |
Before opening a PR or considering the work done, walk through every item below. Do not skip any.
release-notes.mdx) with <ReleaseUpdate> blocksYYYY.mdx) with <Card> entriesdocs.json navigation with all new page pathsmrkdwn (not Markdown), carrying version/minimum-version requirements and a link to the published notesReview every MDX file you created as an expert technical writer:
# Additional Improvements, never near the topdescription, intro paragraph, first aggregate bullet, year card, and first Slack bullet all name the same tier-1 feature# Additional Improvements bullets are one sentence; year card description is one sentence# Additional ImprovementsEvery code example must be grounded in real code — no hallucinated APIs:
import or from statements use actual module paths from the codebaseYOUR_KEY or ... unless explicitly documenting a user-provided valuetitle, all JSX components are properly closedtitle: "MM.DD.YYYY: Descriptive Title" — never "Release Notes" (which is reserved for the index page) and never missing the date prefixrelease-notes.mdx. Dates must be monotonically non-increasing — no older date ever appears above a newer one. New entries must be interleaved with existing ones by date, not stacked as a contiguous block at the top.``` block specifies python, typescript, bash, json, etc..mdx extension: All internal doc links use extensionless pathsMM.DD.YYYY in labels and headings, MM-DD-YYYY in file pathsArize-ai/phoenix
8ac3caf
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.