Robonaissance

Robonaissance

Written in Python, Part 7: Code as Action Space

The man who wrote the industry’s serialization format now says machines should write code, not fill in schemas. Code won the layer where agents act, and Python does not own it.

Hugo's avatar
Hugo
Aug 02, 2026
∙ Paid

A series on how one language shaped artificial intelligence, and how intelligence is now reshaping it.


Stop Filling In the Form

Kenton Varda spent his career on the problem of how structured data moves between programs.

At Google he was the primary author of Protocol Buffers version 2, the version the company open sourced and the one the industry adopted. Later he built Cap’n Proto, a serialization format and capability-based remote procedure call system, designed around his conclusions about what the first system had got wrong. Then he became the architect of Cloudflare Workers. If there is a person whose professional life has been the question of how one program tells another program what it wants, in a form both can agree on, it is him.

His thinking over that career did not change so much as continue. Protocol Buffers is a schema system: you declare the shape of your data, a compiler generates code, and both ends agree in advance. Cap’n Proto kept the schema and moved away from rigidity elsewhere, treating fine-grained validation at the protocol level as something that constrains a system’s ability to evolve rather than as a safety feature. A person who has concluded that protocols should carry less ceremony, not more, is a person predisposed to notice when a new consumer arrives who does not need the ceremony at all.

Which is the connection, and it is why this particular person matters here. A tool-calling protocol is a serialization format. The model forms an intention, the runtime has to receive it, and something in between must carry it in a form both ends agree on. That is the problem Varda spent his career on, and in the early 2020s it arrived in a new domain, with a new kind of consumer at one end of the wire.

In September 2025, with Sunil Pai, he shipped something called Code Mode, built on the premise that for AI agents this entire tradition is the wrong approach. Do not hand the model a schema to fill in, meaning a declared shape with named fields waiting for values. Convert the tools into an API, hand the model the API, and let it write code.

His reasoning was about what models have actually seen. The training corpus contains an enormous quantity of real code written by people solving real problems. It contains a small quantity of tool-call examples, most of them contrived. Varda put it in an analogy nobody has improved on. Asking a model to master tool calling is like sending Shakespeare on a crash course in a foreign language and then asking for a play. The result would be good, because it is Shakespeare. It would not be his best work.

This instalment is about how the industry arrived at that position, what it means that code became the interface through which machines act on the world, and about one specific fact that complicates everything this series has argued so far.

What a Tool Call Is

An action space is the set of things a system is able to do, expressed in whatever form it has to express them. Varda’s wire, in other words, seen from the sending end. For a chess engine it is the legal moves. For a language model acting on the world it is whatever the model is permitted to emit that causes something to happen elsewhere. The question this instalment turns on is what that form should be, and until recently there was one answer.

To see why code won, it helps to be precise about what it beat.

When a language model acts on the world, something has to carry the intent from the model to the system that will execute it. The dominant answer from roughly 2023 onward was a structured call: the model is shown a list of available tools, each with a name, a description, and a schema for its arguments, and it emits an object naming one tool and supplying its arguments. A runtime validates the object, calls the corresponding function, and returns the result into the model’s context. Then the loop runs again.

This works. It is legible, it is easy to validate, it is easy to log, and it maps cleanly onto how APIs are already described. It became the standard for good reasons.

It has one structural problem, and everything that follows comes out of it. A tool call is a single call, so anything requiring several calls in sequence has to be performed by the model rather than expressed by it, one step at a time, with every intermediate result passing through the model’s own context on the way.

Concretely, and the concrete case has to span two systems, since within one database a join answers the question and the protocol is fine. A spreadsheet of accounts sits in one cloud service, the customer records in another, and each record needs updating from its row. The model reads the sheet, which arrives in context in full, every row and every column including the ones the task does not touch, then calls the second service once per account, each call and each returned record passing through the transcript as well. It is performing a for loop by hand, in a medium where every step it takes is also a step it must read.

Any programmer would write that as six lines. The protocol has no loop and no variable, which is the whole of it: cost grows with the size of the data rather than the complexity of the task, and the model’s attention fills with material it is only relaying.

User's avatar

Continue reading this post for free, courtesy of Hugo.

Or purchase a paid subscription.
© 2026 Robonaissance · Privacy ∙ Terms ∙ Collection notice
Start your SubstackGet the app
Substack is the home for great culture