Home/Blog/What the model doesn't get to decide
Engineering · Inside Desklight

What the model doesn't get to decide.

Allie writes a sentence. What comes back is a finished post in the brand's own colours, type and photography. The layer that makes that true is one most people never see, and it took four days in April, including one where the wrong logo landed on the wrong poster, for it to find its shape. This is what that layer is, how it got that way, and what it still gets wrong. The dates come from the git log.

The part that's ours.

Every model Desklight calls belongs to someone else, and every one of them will be better by the end of the year. So it's fair to ask what, exactly, is ours.

Desklight routes every job through models that didn't exist a year ago: reasoning models for planning and copy, reasoning-class image models for graphics, and a generation of video models that ship with native audio and take reference images as input. They improve every quarter. We don't compete with them. We compose them.

What's ours is the decision graph between your brand and their output. Which model fires for which surface. How one calendar headline becomes a prompt in that model's preferred shape without losing the brand's voice. Why the support text is exactly 18 pixels and not 19. What gets rejected before it reaches you. Those decisions are repeatable, testable and durable. The model behind them is replaceable.

That's what prompt science means here: treating the layer between intent and output as a system of its own, with versioned schemas, contracts enforced in code, and a dossier per model that gets refreshed when a release lands. Most of what follows was built, or rebuilt, between April 23 and the night before this post.

Three layers, one direction.

Allie writes intent. The compressor folds intent and brand DNA into a typed spec. The renderer turns the spec into pixels. Three layers, one direction, no back-channels.

// The shape, simplified

Intent         // Allie reasons in prose and drafts a calendar entry
   ↓
Compression    // brand DNA + entry → flat, typed render spec
   ↓
Render         // layout templates + photo/video model + publisher
   ↓
Brand-locked post

Allie is conversational. She handles ambiguity, asks when something is unclear, and drafts entries that say what you meant. She is not optimized for shape.

The renderer is the opposite. It takes a strictly typed spec (hero copy, supporting copy, kicker, mark placement, alignment, photo prompt, aspect ratio) and produces pixels. It can't handle ambiguity. Hand it a missing field and the output collapses.

The compressor is the bridge between them, and it exists because of two refusals: I won't make Allie speak in JSON, and I won't ask the renderer to interpret prose. Each side stays specialized. That sounds tidy on a diagram. It took a specific stretch of April to make it true.

Four days in April.

On April 23, Desklight had exactly one showcase brand, and the whole pipeline had quietly taken its shape. The next four days are where most of this post comes from.

The first profile was an athletic brand, seeded that afternoon as a test profile with a full brand DNA file: palette, typefaces, a photography lane, and a handful of composition archetypes, each with its own never-list. It was the right way to find out what a brand-locked post even needs. It was also a trap, because every value a template needed had been typed in by hand against one brand, and nothing downstream knew the difference between the brand and this brand.

April 24 was video. By the end of the day a calendar post could render a clip, with the reference images you attach riding along to the video model as images rather than descriptions. One of the first test clips came back with its own headline painted into the frames, with a typo. The prompt had wrapped the headline in double quotes, and this model reads a double-quoted line as something to show on screen. The fix: drop the line, theme the shot with a few plain words from it, and state that no lettering belongs in the frame because the typography is added afterward. That was the first entry in what became the per-model dossiers: a quirk, written down, enforced in code.

By one in the morning on April 25, a poster for a second athletic brand had come out wearing the first brand's mark. The brand mark wasn't a slot the brand filled. It was a constant in the template. By that evening a small set of type treatments had replaced every hand-typed value in the renderer: hero scale, weight, kicker size, mark size, padding, scrim. The fix was plain: stop making every brand look like the first one.

Just after midnight on April 26, image generation got a waterfall: when the preferred model fails, the next eligible one takes the job, and a placeholder appears only if the whole chain declines. Two hours after that came the prompt rewrite, which gets its own section below.

The translation compressor.

One calendar entry plus one brand profile becomes one flat spec: deterministic, validated, and small enough to read in a log line. This is the part of Desklight most people never see, and most teams building on language models never build.

A calendar entry says something like: headline "Off your desk. On brand.", subline "Allie writes the calendar so you can leave the studio at five.", kicker "NOW LIVE", plus a layout preset and an aspect ratio you picked. That's intent.

A brand profile is much larger: palette, typography rules, photography lane, banned vocabulary, voice register, never-list. That's identity.

The compressor folds the two into a render spec that the typography and photo layers can execute without a judgment call. One flat object. No nesting, no optional callbacks. Same shape every time, same fields every time.

Brand DNA is a slot, not a suffix.

The obvious version, pasting brand details onto the end of a prose prompt, falls apart fast. Colour shows up in several places at once: palette, accent, photo background. Typography shows up in headline weight and alignment. Voice shows up in kicker case, headline case, banned words, register and mood. Prose can't keep those straight, so the model averages them, and you get a post that is a little bit every brand. The wrong mark on the second brand's poster was the same mistake in a different costume: a brand fact that wasn't a slot.

So the compressor maps each dimension of brand DNA to a specific slot in the spec, and each consumer gets only its slice, in its shape. The image model sees the photo prompt, clean and structured, with no brand boilerplate lifted in. The layout engine sees the treatment and the resolved tokens, and never a line of prose.

A token graph, not typed-in sizes.

Type sizing is where most generated brand work goes wrong. Hand-typed values look right on one post and wrong across a feed. Desklight resolves every size, weight, letter-spacing and line-height through a token graph anchored on a per-treatment scale: a base size, a step ratio, a hero multiplier. Different treatments share the scale and differ only in weight, case, tracking and alignment. Vary the texture, not the math. On May 1 the templates lost their last literal type value.

Supporting roles are bounded to a few named steps. The hero is anchored separately and always leads. You can nudge the kicker bigger or the subline smaller. You can't make the post incoherent, because the graph won't resolve to incoherent.

A few presets, fewer archetypes.

The designer offers a small, named set of layout presets. Behind them sit fewer rendering archetypes: editorial calm, monumental bleed, photo-driven centre. The compressor maps preset to archetype to treatment to alignment, and the renderer reads only the archetype and the resolved spec. A new preset is a row in a map, not a new template. Composition stays a short list of named choices, never an open prose field.

One dossier per model.

Different image and video models reward different prompt shapes, and treating them as interchangeable gets you flat, generic output. So each model gets a versioned dossier, and the compressor rewrites the prompt into that model's shape at request time.

Each dossier is a working document, refreshed when a new model lands or a release note changes behaviour: capability matrix, API parameters, prompt structure, failure modes, a few worked examples. On May 1 the dossiers stopped being only documents. Each model got its own condenser in code, built from them.

Image models: structure over length.

The current reasoning-class image models reward atomic, structured prompts (subject, composition, action, setting, style, lighting) far more than long ones. Each exposes its own thinking controls and aspect handling, and each reacts badly to negative directives past a small handful. Stack up the "no" instructions and the output gets measurably worse.

Video models: a different shape, with teeth.

Video adds camera, audio and motion as first-class elements, with the audio generated alongside the frames. Each model has quirks the dossier records: text artifacts, the quoted-string trap from April 24, how it weighs scene against style, how it handles dialogue. The compressor enforces them before the prompt ships. The rule I keep coming back to: brand DNA is the frame, the entry is the scene. The brand sets the light, the register and the lane; the post says what's in the shot; when it says nothing, the brand's defaults fill in.

Spoken lines.

Some video models lip-sync spoken dialogue, but only when the prompt carries the actual line. Entries suppress dialogue by default; most posts aren't talking-head clips. When a brand wants one, the compressor reads the brand voice and the entry's intent and writes the line in. Same entry, different dossier, very different output.

Aspect ratios, in code.

Where a model takes native aspect ratios, the platform target maps straight into the call (Instagram Story to 9:16, LinkedIn to 4:5, X to 16:9) instead of hoping the model notices the word "vertical" somewhere in a paragraph. That map is brand-agnostic and lives in code.

The waterfall. When a chosen model fails, whether a verification gate, a transient 5xx, a content refusal or a timeout, Desklight drops to the next eligible model that supports the requested size. A placeholder fires only if every model in the chain refuses. Same intent, same brand DNA, different model, and the dossier rewrites the prompt as the chain advances.

The night the prompt got shorter.

Structural rules belong in code, not in the system prompt. A code check costs microseconds. A prose rule costs tokens on every turn, forever, and depends on the model not forgetting it.

By late April, Allie's working prompt had grown the way these things grow: one rule at a time, each added after a specific failure, until it read like a contract instead of a colleague. Past a certain size, new rules stop helping. Reasoning models do best on atomic prompts, and long ones trigger the well-documented "lost in the middle" effect, where a rule buried mid-prompt is functionally invisible.

At two in the morning on April 26 the fix landed, and it wasn't a shorter prompt. It was moving the structural rules out of the prompt and into a small set of validators that run after the model answers: shape (the required fields are there), self-consistency (a cited number matches the copy around it), posture (if Allie says she made five posts, there are five rows) and voice (banned vocabulary scrubbed). On a failure the pipeline can log, retry with the issues fed back, or reject, chosen per call site rather than per rule.

A validator either fires or it doesn't; a prose rule depends on memory. Validators return structured issues; prose fails silently. Validators have unit tests, and tightening one is a diff, where tightening a prose rule is one more sentence crowding out the last one.

What's left in the prompt is the persona first, because the research on position effects says the top is where attention lives, then a short numbered list of hard rules, then the schema. Allie reads cleaner, invents fewer fields, and stops performing the prompt instead of doing the task.

For the record, the first brand switched to the new prompt failed on its first request. The prompt was fine; it returned its answer in the wrong shape for the request body, and the API refused it on the spot. Fixed the same day, and written into the architecture doc under lessons learned, which is where that kind of lesson stays learned.

Four brands, one pipeline.

Testing across different brand profiles is how you find decisions that still belong to the first one. The examples below use three fictional demo brands alongside our own profile: four visual languages, each with its own colours, type and photography.

A supper club, a sport-tech brand, a strength club and our own editorial voice. Running different profiles back to back tests the wrong-logo problem on purpose. If anything leaks from one profile into the next, this is where it should show.

Marrow editorial poster — Five courses. Zero rush. Cream and peach serif type above a plate of food and a candle on a dark red table.
Marrow · serif-led editorial
A quiet editorial voice. Cream serif type, an italic closing line in peach, and a small mark in the top corner. The photograph looks down onto a single plate and a candle on a dark red table. Warm light and room around the subject carry the supper-club mood.
Forma monumental poster — Every Gram. Oversize white type with an orange accent above a sprinter leaving the blocks on a dark track.
Forma · monumental display
A display-weight athletic voice. Oversize white capitals above a sprinter leaving the blocks, an orange full stop echoed by one shoe, and horizontal light streaks across the track. Small corner labels leave the headline and the athlete to do the work.
Volt monumental poster — Show Up Twice. Oversize white and lime type over an athlete clapping chalk from their hands in a dark gym.
Volt · monumental display
Monumental type with a different rhythm. Three stacked lines sit across a dark gym portrait. Lime picks out “UP” and the closing full stop; a cloud of chalk catches the side light. Forma's speed gives way to a pause before effort. The palette and the photograph change the register without giving up the large type.
Desklight editorial poster — One Color, Used At Full Volume. A person holds a glass prism by a studio window, with an amber closing line and triangle mark.
Desklight · serif-led editorial
Our own house voice. A serif headline at the bottom left, its closing line in amber, a small ruled kicker at the top, and the triangle mark at the bottom right. Window light and a glass prism give this editorial example a different subject from Marrow's candlelit table.

What moved.

An abstraction is only worth its tax if the numbers move. Three of them moved, the last of them the night before this post.

Calendar render
~4–8× faster
Three cuts on May 1: agents whose output the calendar path wasn't using came off it, the spec translator moved to a faster reasoning model, and a fast path skips translation entirely when you've written both headline and subline on a text-only preset.
Working prompt
~75% smaller
April 26. Structural rules became code validators. The persona moved to the top. Rules that had been repeated, sometimes word for word, collapsed into one.
Tool surface
Trimmed
Two tools that fuzzy-matched people and logos from connected storage were retired on May 1. Attaching a reference to the post does that job better, and the model has two fewer definitions to read.

Render time matters because someone is waiting for it. Tokens matter because every one saved compounds across every turn. Tool surface matters because every definition the model reads competes with the actual task.

Still open.

The compressor is the disciplined part. The art still lives in the wild parts. Brand extraction, choosing the photo's subject, and contrast on bottom-text photos are open problems, and I'd rather say so.

Brand extraction from a scraped homepage works for the obvious cases (palette, type, basic voice) and falls down on photography lane and mood for brands that haven't defined them. When those fields are empty the compressor degrades silently: the photo model gets a generic prompt and returns a generic photo. The fix is a richer extractor that reads several pages and screenshots and pulls from a few complementary signals. In flight, not shipped.

Choosing the photo's subject is still a single sentence in the spec. When Allie writes "Allie writes the calendar so you can leave the studio at five," the photo should complement the headline without competing with it. Today that's a reasoning call interpreting the entry. It should be a typed scene selector that reads the brand's photography lane, the entry's intent and the accent target, and resolves to a specific composition.

Contrast on bottom-text photos still occasionally produces white on white when the lower part of the photo turns out bright. The current sampler reads the region where text most often lands, a deliberate trim after bright objects on the far side of the frame kept polluting the decision. Better than sampling the whole frame. Still a heuristic, not a measurement.

None of these are blockers. They're the next entries in the log.

Questions.

What is a translation compressor?

It's the layer between an assistant's free-form intent and a renderer's strict input contract. Allie writes a calendar entry: headline, kicker, copy, references. The compressor folds that entry and the brand DNA (palette, type treatment, photography lane, never-list) into one flat render spec that the layout and photo layers consume. Dozens of decisions collapse into one small, deterministic shape.

Why not just call the image model with a long prose prompt?

Long prose prompts give inconsistent results from one render to the next, which is fatal for brand work. Current image models reward structured density (subject, composition, action, setting, style, lighting) far more than length. A typed spec keeps the photo prompt small, lets the same brand DNA reach the typography and layout layers unchanged, and lets validators reject malformed output before a customer sees it.

How does Desklight handle different image and video models?

With a prompt dossier per model. Each model rewards a different prompt structure, exposes different controls and has its own failure modes around things like quoted strings, on-screen text and dialogue. The compressor reads the chosen model's dossier at request time and rewrites the prompt in that model's preferred shape: same brand inputs, model-appropriate output.

What is validators-as-code?

Moving structural rules out of the system prompt and into code checks. Instead of a paragraph like "never generate a headline-only graphic" that the model has to remember on every turn, Desklight runs a small set of validators after generation that check spec shape, self-consistency, posture and voice. Cheaper, more reliable, observable and testable.

How big are the measurable wins?

Calendar render time dropped roughly four to eight times after unused agents left the hot path, the spec translator moved to a faster reasoning model, and a fast path began skipping translation when the user has written both headline and subline on a text-only preset. Allie's working prompt shrank by about three-quarters while output quality improved, because structural rules became code validators.

Brand-locked, on every render.

The compressor, the validators and the dossiers run on every render in the live product. Desklight is live by invitation. Already invited? Set up your brand and start with 500 credits, then Allie drafts your first post.