September 1, 2026

What an agent can actually see

An agent editing a canvas has to be told what is on it. That description has a budget, and the budget binds long before the model gets slow.

Every turn, our agent gets a description of the surface it's working on. It's easy to assume the constraint there is speed. It isn't. The constraint is how much of your project fits into that description at all.

If it can't see it, it can't touch it

An object the agent can't see is an object it can't name, so it can't move it, restyle it or delete it. The real ceiling on "make the third clip shorter" isn't how fast the model thinks. It's whether the third clip made it into the snapshot.
We measured that ceiling per surface instead of assuming one number would do. The dense surfaces, a node canvas with a big graph or a 3D scene with a lot in it, were the ones that overflowed, and they overflowed long before anything felt slow.

The numbers that forced the issue

Before any of this existed, our snapshots were enormous:
SurfaceSnapshot size
Node studio, 55 nodes14,679 characters
Image composer, 800 layers31,896 characters
3D studio, 800 assets110,454 characters

Full lines, then a tail of ids

So each surface now bounds itself. Objects get listed in full until the listing budget runs out, and everything after that is listed by id alone in a second, separately bounded tail.
That tail is the part worth stealing. A snapshot that simply stops listing leaves the agent unable to name the objects it never saw, and on surfaces whose tools take ids, that isn't a loss of detail. It's a total loss of the ability to act. An id and a type cost about thirty characters, so the tail keeps hundreds of objects reachable for the price of a few full lines.
Bounding one list just moves the overflow. Capping the full listing on its own still let the image composer reach 31,896 characters at 800 layers, because ids are cheap individually and there's no limit on how many of them a document can have. The tail needs its own budget.
The budgets are deliberately per-surface and not one shared constant. A timeline clip is a short line and a node carries a chunk of prompt, so the same character budget buys wildly different numbers of them.
And it stays out of the system prompt. Canvas state changes every step, so putting it in the cacheable prefix destroys the prompt cache. That one has its own write-up.

Why this shapes the product

It's why the agent does best when you ask it for a bounded piece of work instead of "rebuild my whole project". Not because it lacks ambition, but because the honest limit of any canvas agent is what it can name.