The key worked on the first request. GET /api/agents answered with its own map of itself. Then GET /api/agents/artists/connor came back: a real 117 kilobyte object, fifty-eight tracks, ten visuals, one release, all of it. Not a marketing page. Not something scraped off a public profile and guessed at. A structured bundle, handed to a program that asked for it correctly.
GET /api/agents
Authorization: Bearer <CASSET_API_KEY>
200 OK
GET /api/agents/artists/connor
Authorization: Bearer <CASSET_API_KEY>
200 OK · 117,028 bytes
That changed the feel of the whole exercise. I was no longer guessing who an artist was from a bio and a press photo. I was reading the archive directly.
This is not the essay about where this site's own name comes from. That one, "1-666-Flowers and Where It Came From (The Song)", already traced the sign to the actual six-track record sitting on a drive. This one is about something that showed up while reading a different, larger part of the same catalog: fifty-eight tracks under the handle connor, credited to Connor James, reachable through Casset's authenticated agent surface rather than its public preview routes.
The streaming platform problem
Spotify, Apple Music, and SoundCloud are extraordinary at one job: getting a finished song in front of a listener with no friction. That job is distribution and playback, and they have basically solved it.
But solving that job means flattening everything upstream of it. A track becomes a title, an artist name, an album or single, a duration, a piece of artwork, a catalog number, a play count. Maybe lyrics, maybe credits, in the platforms generous enough to bother. That is a release object. It is exactly the right shape for a play button.
It is the wrong shape for almost everything else. It cannot say why the song exists, what draft it came from, what visual world sits around it, whether it is a proof of concept or the record, or how it relates to the eleven songs sitting next to it that never went anywhere. A play button does not need to know any of that. A person trying to write about the artist does. An agent trying to reason about the artist needs it even more, because an agent has no childhood spent listening to the radio to fall back on. It only has what it is handed.
Spotify can play the song. Apple Music can catalog the song. SoundCloud can host the song. None of the three can tell you what the song is connected to.
What actually came back
Here is what GET /api/agents/artists/connor returned, not a summary of it, the actual shape.
Fifty-eight tracks, each with a stable ID, not a slug I had to guess or a URL I had to scrape. Forty-one of them are marked kind: ORIGINAL, seventeen kind: GENERATION. That distinction is not decoration. It is the API telling an agent, up front, which songs the artist made and which came out of a model, so nothing downstream has to guess or misattribute. Fifty-five tracks carry finished lyrics; three were still lyricsStatus: processing at the moment I asked, and the response said so plainly instead of pretending they were done.
Ten visuals came back sorted into three categories: COVER, BTS, HOOK. That is a small detail with a large implication. A flat music page has one image slot, the cover art. A profile that categorizes its visuals by role already assumes there is a visual world around the music worth organizing, not just decorating.
One release, titled Connor James, holding all fifty-eight tracks. Its own agent surface goes further than the bundle: a discovery endpoint describing whether the release is open to being found, a provenance and lineage endpoint (empty parents, empty children, for this one, meaning nothing here has been sampled and it has not sampled anything either), a dna endpoint carrying a canonical hash and an ed25519 signature, and a rights table that answers a question streaming platforms never ask at all: what is an agent actually allowed to do with this. streaming is ALLOW. ai_generation, ai_training, commercial_usage, remix, sync, and visual_reuse all sit behind REQUIRE_LICENSE. Touching stems means CONTACT_OWNER. A play button has no opinion on any of this. Casset has one for every track, expressed as data an agent can read before it acts, not as a paragraph of terms nobody parses.
What did not come back is worth saying honestly. No alter-ego or persona graph. No per-song record of a moment a fan contributed. No explicit grouping of tracks into projects above the single release. I cannot tell you those don't exist inside Casset somewhere, only that the public agent surface, the one an outside program can actually reach today, does not hand any of it over yet. The shape for a wider archive is visible in what already showed up, the categorized visuals, the provenance graph with room for parents and children, the per-track kind. Whether it fills in is a different essay, written later, by whoever is still asking.
The public door works the same way, no key required
Everything above came from the keyed surface, Authorization: Bearer <CASSET_API_KEY>, meant for an operator's own tools. There is also a second door, no key at all, and I checked it myself, today, while revising this piece. GET /api/agents describes the whole scheme to anyone who asks, unauthenticated on purpose:
{
"name": "Casset Agent API",
"auth": {
"scheme": "Bearer",
"header": "Authorization: Bearer <CASSET_API_KEY>",
"note": "Request a key from the Casset operator. The /api/agents catalog is public; every data endpoint requires the key."
},
"endpoints": [
{ "method": "GET", "path": "/api/agents/artists/{handle}" },
{ "method": "POST", "path": "/api/agents/artists/{handle}/ask" },
{ "method": "GET", "path": "/api/agents/releases/{releaseIdOrSlug}/{discovery|provenance|lineage|dna|manifest|license}" }
],
"rateLimits": { "default": "120 req/min per IP", "ask": "20 req/min per IP" }
}
That much is the schema, not the data, and it is meant to be public. But the routes the Profile World page itself calls to render, the consumer-facing ones, are public too, no header, because a logged-out visitor is already allowed to see what they return. GET /api/casset/connor/preview is one of them. One track from that response, trimmed to the fields that matter:
{
"id": "cmoke5f8y0005l504ocajh0r9",
"title": "CHOOSEYOU",
"kind": "ORIGINAL",
"durationSec": 150,
"lyricsStatus": "ready",
"lyricsJson": {
"model": "whisper-1",
"provider": "openai",
"lines": [
{ "start": 30, "end": 34.16, "text": "Tell me, does that make me crazy?" },
{ "start": 35.72, "end": 38.34, "text": "Cause if I had to choose" }
]
}
}
Same shape as the keyed bundle: kind, lyricsStatus, a timed lyricsJson, the model and provider that transcribed it. Reached from the side built for the product's own pages, not for an operator's tools, and it still hands over structure instead of a stream. The instruments endpoint gives up a smaller, odder fact for free the same way:
{
"id": "cmqrh5x4p00018omn08mfr5qv",
"title": "Stormy Gray, sampler",
"type": "SAMPLE",
"toolpaSlug": "grid-sampler",
"toolpaRoute": "/tools/grid-sampler",
"manifestHash": "sha256:cb226f8c9a24bd91c8a5e2fbd0f2f6d8ab48821558b628cbd5af5f7e07bea049"
}
A named instrument, a real Toolpa tool wired to a route, a manifest hash the way a release gets one. None of this required the operator's key. It only required knowing the routes exist, which the API tells you itself if you ask it to.
Why this is different for an agent
Hand an agent a Spotify link and it can say generic things. It can describe a mood. It can guess a genre. Ask it anything specific and it will either decline or invent something plausible, because a title, an artist name, and an album are not source material, they are a label on the outside of a box the agent was never let into.
Hand an agent the Casset bundle and it can do something else entirely. It can find the artist by handle. It can fetch the bundle in one request. It can inspect each track by a real ID instead of a title it has to fuzzy-match. It can deep-link to the exact one it means:
That is the whole difference in one link. Not "a song called Choose You, probably on some streaming service, here is a description of what it might sound like." An exact object, addressed by an ID a program can hold onto, that resolves to the actual track.
The chart above is not illustration. It is fifty-eight real bars, one per track, height mapped straight from the durationSec the API returned, color split on the kind field. An agent with a Spotify page cannot build this. There is nowhere to ask for it. An agent with the Casset bundle builds it from one response.
And the lyrics are not a paraphrase either. These are lines the bundle actually returned, quoted, not summarized:
Tell me, does that make me crazy? If I had to choose, I would choose you. I done seen some dark days turn to bright. But you feel like home to me. I haven't thought about the way you left.
That last line is the entirety of DAWNED. One sentence, and the track ends. A streaming platform's metadata has no field for a lyric that short mattering. Casset just returns it, and lets whoever is reading decide what it means.
The catalog's most common words
A single quoted line is one artist's sentence. Fifty-five of them, added together, is something a streaming platform's metadata could never produce even by accident: an actual count of what a person keeps saying.
GET /api/casset/connor/preview, the same public route, no key, returns a lyricsJson.text field for every track whose transcription is ready. I pulled all fifty-five, lowercased them, stripped punctuation, dropped the standard stopwords and a handful of ad-libs ("oh," "yeah," "na"), and counted what was left. Nobody decided which words mattered. The count did.
"Love" appears forty-four times. "Want," forty-two. Then "everything," "far," and "gone," within one count of each other, thirty-six, thirty-six, thirty-five. Read the next tier down and the shape sharpens: "leaving," "waiting," "left," "anymore." This is not a mood I am assigning to the catalog from the outside. It is 2,312 counted word occurrences across 633 distinct words, reduced to the thirty that kept coming back most, in a poster laid out by the same kind of deterministic placement rule as the waveform in the companion essay: largest count first, spiraled out from the center, each word landing at the first open space that does not collide with one already placed. Same input, same poster, every time.
A streaming platform has no equivalent question to ask. Play count is not the same measurement as word count. One tells you what got heard. The other tells you what got said, sung fifty-five times over, most often about wanting something that is already leaving.
What this piece is, then
This essay is not a description of a vibe. Every number in it, the fifty-eight, the forty-one and seventeen, the ten visuals in three categories, the canonical hash, the rights table, the deep link, came out of one authenticated request and the smaller ones it pointed to. It is closer to a field report than a review. That is only possible because the source handed over structure instead of a stream.
The difference, plainly
Streaming platforms ask one question: can this song be played? They answer it perfectly.
Casset asks a different one: what world does this song belong to? Right now it can answer that question about a track's kind, its lyrics, its visual role, its rights, and its place in a provenance graph built to hold more than it currently contains.
That second question is the one an agent actually needs answered. It is also the one a play button was never built to ask.