Canva Post-Trained an Open Model and Cut Edit Cost 46%. The Playbook Travels
💡 Tool Tip: Image Resizer, WebP Compressor, Color Contrast Checker
On October 29, 2026, Canva announced Brush, a vision-language model for design built by Canva Research — a 160-person AI lab — and shipped it into Canva AI for Pro subscribers. Two numbers in the announcement carry the story: up to 69% faster on general design editing tasks, and 46% lower cost per edit task than Canva's previous design agent. That is not a leaderboard improvement. That is a unit-economics improvement, and it is the kind that decides whether a consumer product can afford to give the feature away. The interesting part for anyone building with models is how ordinary the recipe is: start from an open-weights base, post-train on real edit tasks, then push it with large-scale reinforcement learning.
Generation has freedom. Editing has to be constrained: change this, touch nothing else.
1. What Brush does, and what it replaced
Brush reads a design — layout, layers, overall vibe — and makes the change you asked for, from a single line of copy to every slide in a deck. It lands one week after Canva Craft, the company's image-generation model, which Canva says made it the second most advanced AI lab for image generation on the DesignArena leaderboard. The division of labour is clean: Craft generates, Brush edits the design around what was generated. Canva's framing is the right one — great design happens in the edit. Generating something presentable is hard. Editing something existing without wrecking it is harder.
2. Why editing is the harder problem
Generation starts from nothing, so the model has total freedom. Editing does not: it has to understand what you want changed, how the design is constructed, and — the part everyone underestimates — what must stay exactly as it is. Ask for a bigger headline and a careless model happily reflows the entire layout while it is at it. So the core metric for an editing product is not "does the result resemble the request". It is "did it change the right things and leave the rest alone". That constraint cannot live in a prompt. It has to live in a check.
# A design is a tree. An edit that touches one text node must not silently
# reflow the other eleven. Diff the tree before and after and fail loudly.
import json
def nodes(doc, prefix=""):
for child in doc.get("children", []):
nid = f"{prefix}/{child['id']}"
yield nid, child
yield from nodes(child, nid)
def scope_violations(before, after, allowed_ids):
b, a = dict(nodes(before)), dict(nodes(after))
bad = []
for nid in set(b) & set(a):
if nid in allowed_ids:
continue
if json.dumps(b[nid], sort_keys=True) != json.dumps(a[nid], sort_keys=True):
bad.append(nid)
bad += [f"deleted:{n}" for n in sorted(set(b) - set(a))]
return bad
# This check is why "make the title bigger" does not turn into "make the title
# bigger and also restyle every slide". Boring, deterministic, and load-bearing.3. What the 46% actually measures
46% is cost per edit task; 69% is speed on general edits. For a product serving hundreds of millions of people and billions of designs, a few extra cents per task compounds into a hole in the P&L. Canva states the motive plainly: the efficiency gains let it deliver a stronger Canva AI experience to far more people while making it more affordable. Read that as the only viable path for consumer AI — drive unit cost down until the feature can be given away, because pricing it per use puts it out of reach for most of the audience you were building for.
# The reward signal is the product decision. Canva had to define what makes a
# design good before it could train against it, and so do you.
# Helper functions (type_scale, palette, coverage, contrast) omitted on purpose.
def reward(before, after, brief):
score = 0.0
# Brand consistency: the type scale and palette come from the source doc.
score += 2.0 * (type_scale(after) == type_scale(before))
score += 2.0 * (set(palette(after)) <= set(palette(before)))
# Instruction coverage: everything the brief names should actually change.
score += 3.0 * coverage(after, brief.targets)
# Collateral damage: untouched nodes must stay byte-identical.
score -= 5.0 * len(scope_violations(before, after, brief.allowed))
# Legibility floor: not negotiable, and not something to learn from votes.
score -= 10.0 * count_contrast_failures(after)
return score4. The training recipe: open base, post-train, then RL
Brush started from a leading open-weights model and was post-trained on real designs and real editing tasks, using design expertise plus anonymised insights from people who opted in to improve Canva AI. On top of that sits large-scale reinforcement learning, where the model works through complete design and editing tasks, learns from what worked, and reshapes its behaviour. The load-bearing piece is the reward system: before Canva could train against "a great design", it had to define one. Brand consistency, instruction coverage, collateral damage, legibility — features you can actually compute are the skeleton of a design reward, and everything else is opinion.
# The loop worth copying: act with code, then look at the page. An agent that
# cannot see the result of its own edit is guessing.
def edit_loop(design, brief, model, max_turns=4):
history = []
for _ in range(max_turns):
action = model.propose(design, brief, history=history)
result = run_in_sandbox(action.code, working_copy=design)
if result.error:
history.append(f"runtime error: {result.error}")
continue
shot = render(design) # screenshot the actual page
verdict = verify(shot, brief) # cheap, deterministic checks
if verdict.ok:
return design
history.append(verdict.summary) # "title overflows frame 3"
return design # ship last good state, still editable5. The agentic loop: write code, then look at the page
Brush runs an agentic loop that writes and runs code to adjust design elements, then inspects what is happening on the page to guide the next step. That observe-after-acting structure is what makes multi-page consistency and format adaptation tractable: the model is not guessing about the result, it is looking at it. The other decision worth stealing is that output stays fully editable — text, imagery, colour, layout, all of it. A rendered flat image would be cheaper and would not survive contact with a real design workflow, where the designer keeps editing, the client rewrites copy, and marketing needs ten sizes by Friday.
# "46% cheaper per edit" is a unit-economics claim, so measure it as one.
def cost_per_edit(runs, price_in, price_out, gpu_usd_per_second):
gen = sum(r.tokens_in * price_in + r.tokens_out * price_out for r in runs) / 1_000_000
infra = sum(r.gpu_seconds for r in runs) * gpu_usd_per_second
retries = sum(max(0, r.turns - 1) for r in runs)
retry_gen = gen * (retries / max(len(runs), 1))
return (gen + infra + retry_gen) / len(runs)
# The line that moves when you post-train your own model is tokens and GPU
# seconds. The invoice from a model provider is the line you are trying to
# shrink, and it only shrinks if the task is narrow enough to specialise on.6. Three questions before you copy this
First, is your task narrow enough? Post-training beats a larger general model on narrow tasks and loses on broad ones. Second, do you have a reward signal? Without a computable definition of good, reinforcement learning amplifies noise and calls it taste — and defining good is a product decision, not an ML one. Third, do you have a verifier? An agent that acts without looking at the result is guessing, and for high-dimensional output like design you need both deterministic checks (contrast, overflow, out-of-bounds) and visual ones. Get all three and train. Miss any of them and spend the quarter on prompts and plumbing instead, which is usually the better trade anyway.
# Head-to-head on the same edit set, with humans voting. Offline similarity
# will not tell you whether the design is usable.
def pairwise_wins(old_agent, new_agent, cases, raters):
wins = total = 0
for case in cases:
a = old_agent.edit(case.design, case.brief)
b = new_agent.edit(case.design, case.brief)
for rater in raters:
if rater.prefers(b, a, case.brief):
wins += 1
total += 1
return wins / total
# Report it next to the share of edits a user accepts without a second pass.
# That second number is what the product actually sells, and it is the one a
# pure cost optimisation will quietly destroy.For an editing product the metric is not resemblance. It is whether the right things changed and the rest did not.
📌 Frequently Asked Questions
What is Canva Brush, and how is it different from Craft?
Brush is a vision-language model from Canva Research built for design editing: it reads layout, layers and style, then applies the change you asked for to an existing design. Craft, announced October 22, is Canva's image-generation model. In Canva's own framing, Craft generates and Brush refines the design around the generated result.
Faster and cheaper than what, exactly?
Than Canva's previous design agent. The 69% figure is the upper bound on speed for general design editing tasks, and 46% is the reduction in cost per edit task. Both are Canva's internal measurements against its own prior system, not against competitors.
Is Brush built on a proprietary or an open model?
Canva says Brush started from a leading open-weights model, then was post-trained on real design and editing tasks and combined with large-scale reinforcement learning. The base is open weights; the differentiation comes from post-training data, the reward system, and the inference loop.
Why does it write code instead of just emitting an image?
Because design edits need precision: which layer, which value, which properties must not move. Expressing edits as code makes them controllable and verifiable — after execution the agent can inspect the actual page state and decide the next step, which is not possible when the only output is pixels.
Can a small team reproduce this approach?
The approach yes, the scale no. A viable small version: pick an open base, narrow the task to one class of edit, post-train on your own real data, define computable rewards (brand consistency, collateral damage, legibility), and add deterministic verifiers. Running RL without a reward signal and a verifier only produces more confident mistakes.
🔧 Recommended Tools
📚 Sources
- Canva Newsroom — Introducing Canva Brush, a vision-language model for design (Oct 29, 2026)
- Canva Newsroom — Canva Craft, the image-generation model (Oct 22, 2026)
- DesignArena — image generation leaderboard (the ranking Canva cites)
- Capital Brief — Canva launches AI design editing model Brush
- arXiv — Medusa (speculative decoding, the other half of the same cost story)