
The Validation Agent
An AI agent that sits between conversation and distribution, enforcing Apple Music style rules and catching metadata drift.
ONCE Engineering
A rejected release costs time and money. Distributors (especially Apple Music) have strict metadata formatting rules, and a single casing mistake or missing contributor credit can bounce an entire submission. We built an AI-powered Validation Agent that catches these issues automatically before anything reaches the distributor.
Where It Sits
The Validation Agent runs between the chat conversation and the distribution adapter on every release. When a user finishes building a release through conversation with the ONCE chat agent, the payload doesn't go straight to distribution. It passes through validation first.
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ User Chat │────▶│ Validation │────▶│ Distribution │
│ Conversation │ │ Agent (GPT) │ │ Backend │
└─────────────────┘ └─────────────────┘ └─────────────────┘
│
▼
┌─────────────────┐
│ Adjusted │
│ Payload │
└─────────────────┘
The key difference from a traditional validator: it doesn't just flag errors. It makes corrections and explains its reasoning.
Three Sources of Truth
The agent pulls from three inputs simultaneously:
1. Apple Music Style Guide (Live-Fetched)
The agent fetches the Apple Music Style Guide directly from Apple's website at validation time. To stay within context limits, it performs a keyword-driven search against the guide based on the current release metadata (titles, artists, language, explicit flags, genres, and version cues). Only the most relevant excerpts are included in the prompt.
This means the agent stays current with Apple's formatting rules without us manually tracking changes.
2. Conversation History
The full chat conversation between the user and the ONCE agent is included as context. This lets the validator cross-reference the final payload against what the user actually said, catching cases where metadata drifted during the conversation or a contributor was mentioned but not captured.
3. Distribution Backend Requirements
Technical compliance rules from our distribution backend API: required fields, schema constraints, and format specifications that must be met for successful submission.
Priority Order
When rules conflict, the agent follows a strict priority hierarchy:
- Apple Music Style Guide: Required formatting rules (rejectable if violated)
- Distribution Backend Requirements: Technical compliance for distribution
- User Expressed Intent: Honored when it doesn't conflict with store rules
- Conversation Context: Inferred intent when safe and compatible
- Smart Defaults: Reasonable defaults for missing optional fields
This means if a user titles their track in ALL CAPS but the Apple Music Style Guide requires title case, the agent corrects it and explains why.
Contributor Analysis
One of the trickiest parts of release metadata is contributor credits. The agent analyzes the conversation to ensure all mentioned contributors are correctly captured and assigned:
- Every writer, producer, arranger, and engineer mentioned in the conversation gets checked against the payload
- Track-level writer assignments are derived from release-level contributors when missing (the distribution backend requires each track to have a
writersarray) - Writer shares are split evenly among all writers on a track
- A deterministic fallback runs after the AI analysis to ensure no track is left without writers, catching edge cases the model might miss
// After AI analysis, programmatic fallback ensures completeness
for (const track of tracks) {
if (!track.writers || track.writers.length === 0) {
// Derive writers from release.contributors
track.writers = release.contributors
.filter(c => ["Writer", "Composer", "Lyricist"].includes(c.role))
.map(c => ({
name: c.name,
share: Math.floor(100 / matchingContributors.length)
}));
}
}
Other Corrections
Beyond contributor analysis, the agent handles:
- Title and artist formatting: Casing, featuring syntax, parenthetical versions per Apple's rules
- Compound artist splitting: The distribution backend requires a single primary artist, so
Artist A & Artist Bgets restructured - UPC stripping: User-provided UPCs are removed since they must be auto-generated by the distributor
- Explicit content flags: Verified against actual track content discussed in conversation
- Classical music formatting: Enhanced rules for classical releases with specific formatting standards for movements, opus numbers, and performer credits
Output
The agent returns an adjusted payload along with a detailed list of every change made:
{
"success": true,
"adjustedPayload": { "release": { ... }, "tracks": [ ... ] },
"adjustments": [
{
"field": "release.title",
"originalValue": "My Song",
"adjustedValue": "My Song (feat. Artist)",
"reason": "User mentioned featuring another artist in conversation",
"source": "conversation"
}
],
"reasoning": "Analysis summary...",
"errors": []
}
Every adjustment includes the field changed, original and corrected values, reasoning, and which source triggered the change (Apple guide, distribution backend, conversation, or smart default).
Visibility
Validation results surface in three places:
- Slack notifications: Each submission notification includes a validation section showing adjustment count, before/after values, and any errors
- Database records: Full results stored in
release_submit_logsfor auditing - Admin UI: Validation details visible in the release log admin panel
What's Next
We're exploring tighter integration with the chat experience, running validation checks during the conversation rather than only at submission time so issues get caught earlier. We're also looking at learning from past corrections to improve accuracy on common patterns.
The Validation Agent runs automatically on every release submitted through ONCE. It's enabled by default, no user action required.
Try ONCE