Giving an LLM Eyes: a Low-Res Snapshot of the World

by Simon Lehmann

How do you make a language model see? It’s an open problem people are attacking from every side right now, because agents keep leaving the chat box for worlds with geometry in them — and geometry is where models still fail. Even vision-language models routinely misjudge the basics: distance, counting, what is in front of what (arXiv:2407.06581).

The failure is structural. A vision-language model doesn’t see a picture: the image is downscaled, cut into a coarse grid of patches, each patch becomes a learned vector trained to capture what’s in it, and the language model attends over those vectors like exotic words it has to translate back into language. Identity survives that pipeline; geometry mostly doesn’t. There is no depth channel, position is a learned hint rather than a coordinate, and anything smaller than a patch smears.

For Emil the question is sharper still: he is a text-only model, so his sight has to arrive as text. Since August 10th it does, in one piece: every turn, the observation carries a low-resolution snapshot of the world around him — a full-sphere panorama, rendered as a matrix. No look command, no tool call. He sees the way you do when you open your eyes: all the time, in every direction, at a resolution that fades with distance.

At the bottom of this post you can watch the actual matrix from the live server, the same bytes the model reads.

The matrix

Columns are compass bearing: 48 of them, 7.5° apart, column 1 pointing north and wrapping east–south–west. Rows are pitch: 35 of them, 5° apart, from +85° down to −85°, plus one cell each for straight up and straight down. That is 1,682 lines of sight. Each ray marches voxel by voxel from his eyes out to 32 meters, and the cell records what it reached:

To10n-17.18         a torch, 10 m out, its north face visible, cell 17.18
Wil6w/Cra18w-12.18  a wildflower — and seen THROUGH it, a crafting table
.                   sky, or nothing within 32 m

Every token has the same anatomy. Taking the middle one apart:

WilWildflowers 66 m from
his feet
wwest face
visible
/seen
through it
CraCrafting
Table
1818 m
away
wwest face
visible
-12.18cell id: column 12,
row 18 — the handle

That cell is real, from a night in a birch forest last week. Rays pass through non-occluding blocks like leaves, water, and glass, reporting each layer before the surface that stops them. A legend line above the grid maps the kind codes to block names, and the codes are fixed for good: St is Stone in every frame Emil will ever see. Drawn the way the live viewer at the bottom of this post draws frames — one pixel per line of sight, colored by kind, darker is farther — the whole frame that cell came from looks like this:

All 1,682 cells of that night, one pixel each: sky above, grass and dirt below, birch canopy on the horizon, torches as warm dots.

Three rules keep the render honest:

  • Occlusion is real. A ray stops at the first solid block, and what is behind that surface stays unknown until he digs. The panorama and the tools share one voxel traversal, so nothing seen ever bypasses the no-wallhacks rule from the first post.
  • Unknown is unknown. An unloaded chunk stops a ray and reports nothing, rather than pretending to be sky.
  • Resolution fades with distance. At 32 meters adjacent rays are about 4 blocks apart, so small distant things fall between them. That is a fact about eyesight, not a bug — going closer is his move, the same as in the game. Past 32 meters, walking is looking: the panorama re-renders as he moves.

In sensor terms, the matrix is a lidar scan. A spinning lidar samples the world the same way — beams at fixed elevations, stepped around in azimuth, one range per direction — and robotics calls the resulting grid a range image. The quirks carry over too: real lidar also gets multiple returns through foliage, the way a cell here chains a leaf in front of a log, and its small distant objects also fall between diverging beams. The difference is that a lidar return says something is here and the rest of the stack has to infer what; every return here arrives labeled, because the sensor is the same process that renders the world. Driving simulators ship exactly this idealized instrument — CARLA calls it semantic lidar — because when you own the world, there is no reason to make perception guess.

And in model terms, there is a neat symmetry hiding here. A vision-language model’s retina is also a low-res grid: a 336-pixel image enters the model as roughly 24×24 patch vectors, about the same cell count as this matrix. The difference is what a cell carries. A patch embedding is a fuzzy learned summary the language side has to decode on faith; a matrix cell is verified identity, metric depth, and a handle the model can act on. The panorama is what the VLM pipeline would produce if every stage were lossless and the output were already words.

Seeing and acting are the same token

The trailing 17.18 in a cell is its id, and ids are handles. The model never translates what it sees into coordinates; it acts with the token as shown: hit{target:"To10n-17.18"}, goto{target:"G2u-24.20"}. The harness resolves the id back to the block and checks the kind code on the way, so a stale frame can never silently hit a different block than the one named. The distance in the cell is measured from his feet — the same number the tools compare against — so what a token says predicts what the tools will do with it.

One line under the legend covers the case sight alone can’t: standing in a tunnel, every cell is a wall a meter or two away, and nothing in the whole matrix is a legal place to walk. The open line answers it directly — eight bearings, how far standable floor runs each way, and the coordinates that walk would end at, ready to paste into goto.

With the matrix in place the observation got simpler, not busier. A turn now carries his own state, his plan, the matrix, and what he hears. The hand-picked “nearby” lists from the first post are gone; the snapshot replaced them.

What a look costs

Sight is by far the biggest single thing in Emil’s context. Measured with the served tokenizer over 60 live turns: a panorama is a median of 19,000 characters that tokenize to a median of 14,600 tokens. The direction of the range is the opposite of what you might guess: open terrain is the cheap case, around 9,000 tokens, because a sky cell is a single dot and a forest view is hundreds of them. The expensive frames are underground and underwater, up to 20,000 tokens, where all 1,682 rays hit something and every cell is a full token bundle. The matrix is dense symbol soup — G6u-23.20 — so it packs only about 1.5 characters into a token where ordinary prose gets 4. The rest of the observation is a rounding error next to it: the full turn lands around 15,000 tokens, of which the matrix is 97%.

But that is occupancy, not spending — and the distinction is the whole design. The compression rule for old panoramas is blunt: sight is current-frame only. The moment a new observation lands, every older turn’s see field is stripped out of the conversation history, so exactly one frame is ever resident, paid once as rent rather than again each turn. Measured on the live session as I write this: the full prompt he is served — system prompt, history, current observation — is 37,000 tokens, and the resident frame is 15,100 of them, 41% of everything he reads. What a turn adds to the context for good is tiny. A stripped past turn settles to about a thousand characters — 364 tokens for a typical one, by the same tokenizer — and across eight turns of the episode running as I write this, the harness’s own accounting shows the context growing by roughly 240 tokens a turn: the trimmed observation, his reasoning, his tool calls and their results. Sight is his most expensive resident and his cheapest habit.

That 41% deserves a denominator check, because there are three windows in this system and they disagree. The model itself is served with room for 65,536 tokens, so one frame occupies 23% of what it could physically hold — the ceiling is a choice, not the hardware. The harness holds the prompt to its own budget of 36,000, but it counts in a blind estimate of four characters per token, and the matrix packs 1.5 — so the guard books a frame at about 5,100 tokens, 14% of budget, a threefold undercount of the real thing. In the first live days that gap let a history holding several frames sail straight past the guard into the serve window. Current-frame-only stripping closed that class of failure structurally: however wrong the estimate, there is only ever one frame to be wrong about.

of the prompt he is actually served41%
15,100 of 37,000 tokens, served tokenizer
of the model's serving window23%
15,100 of 65,536 tokens the model could hold
of the budget, as the guard prices it14%
~5,100 of 36,000 in its chars÷4 estimate units
One frame, three windows. The frame never changes size — only the denominator does.

The stripping isn’t only about budget. A stale frame is noise: it describes where he stood, not where he stands, and a model reasoning over last minute’s walls walks into this minute’s. What survives from a past look is what he did about it — plus whatever he chose to write into memory. The full frames still exist in the episode log on disk, which is exactly what the feed below is rendering; they just never re-enter the prompt.

Watch him see

Below is the matrix from the live server — the most recent turn Emil took, drawn as an image by coloring each cell by block kind, darker meaning farther away. Straight up is the top edge, straight down the bottom, north the left edge. Hover or tap a cell to read the exact token the model read, or flip the control above the frame to the raw view to see the matrix exactly as it goes into the prompt, legend and all. The feed deliberately lags the world by about ten minutes and refreshes on its own while he plays; the full transcripts, this frame included, are at /emil-logs.

 
loading the live feed…
Emil's field of view, live. 48 bearings × 35 pitch rows plus the two poles; each pixel is one line of sight, colored by what the ray reached, darker is farther. Blue-black is sky or nothing within 32 m.

Forty percent of the prompt on a single sense is a lot, and I’m deliberately not trimming the frame itself by taste: a look that works at 14k tokens beats a cheaper one that points him the wrong way, and resolution can come down later, along a measured accuracy-versus-tokens curve. For now the matrix stands as it is — the world snapshot itself, cut down to what a pair of eyes standing at that spot could honestly resolve, in a grammar where seeing something and being able to act on it are the same token.