The way it used to be
In classical software development, when two systems need to talk to each other, a developer reads one system's API documentation, then writes integration code for the other system that calls those APIs in the right order with fittingly structured data. It works, and we have decades of practice at it. But the calling system never actually understands the API it is calling. Only the developer does. The system is just faithfully carrying out instructions written by a human during design time.
That arrangement has already started to look somewhat quaint. When at least the calling system is agentic, deciding at runtime what it needs from the other system, the human in the middle must go.
The top-down approach: mathematical musings
We humans have the built-in ability to "prompt" each other. We call it a conversation.
This technique has proven so successful over the centuries that we even modeled our latest human-machine interface after it. So, why stop there? If it's this successful, it makes sense to apply the concept to machine-machine interfaces, right? Let one system tell the other, in plain English, what it wants, and together they can purposefully harness each other's capabilities to achieve a common goal.
It would work. It would go down in IT history as the most generic, most flexible interface technology ever invented.
And as the most memorable security vulnerability ever shipped.
This naive approach is doomed. Plain natural language is unbounded by design. There are no limits to what can be said, and no formal guarantees about what the words mean.
But there need to be boundaries. System boundaries.
So if we want one system to tell another what to do, two things have to be true:
- there have to be limits on what can be said, and
- what is said has to have unambiguous meaning.
These requirements clearly point to formal languages in the mathematical sense. And programming languages are of course exactly formal languages with finite syntax, precise semantics, and bounded expressiveness. We invented them to talk to machines, and they happen to be the right shape for machines talking to other machines, too.
The bottom-up approach: tool time
Early in the development of agentic systems, it became clear that they needed a way to interact with the outside world. So a string of techniques was invented, which we now refer to as tool calling. In essence, it is a way for an agent to first absorb an API spec and then execute API calls.
Sounds straightforward. It wasn't.
In November 2025, the creators of the MCP standard published an article highlighting two important lessons learned about tool calling.
First, for an agent to call a tool, it needs to know it exists; hence, all tool definitions are loaded into the agent's context up-front. This did not pose a problem for a handful of tools, but, as it turned out, customers actually needed to expose an agent to hundreds, even thousands, of tools. This led to cluttered contexts, increased response times, and also increased costs.
Second, since the agent acts as the orchestrator of tool calls, every intermediate tool call result is added to the context, leading to the same problems as above, plus reliability and even data protection issues.
The proposed remedy, in a nutshell, is to make the agent write code against the API and add only the end result to its context.
What is interesting is that we arrive at the very same conclusion as in our top-down approach, although we started from two very distinct places:
The seam between two systems is no longer a wire that carries structured data. It is a language, an exposed execution environment that the calling system uses by sending programs to it.
It is worth noting that the above-mentioned article served as my initial inspiration for what I am about to suggest, even though my take on this does not follow the original proposal.
An agent-first programming language
Now that we have arrived at this conclusion, the next step seems obvious: select your favorite language, make an API of your choice available to it, and tell the agent to start sending programs.
Entirely possible. Pragmatic. But is it such a good choice after all?
Practically all of our existing mainstream programming languages are general-purpose languages. By design, you can do literally anything with them. Sure, they will meet our requirements, no matter what they are. And we can always use sophisticated technologies, such as sandboxing, to suppress any superfluous or dangerous features we do not need.
But as the famous quote by Antoine de Saint-ExupΓ©ry goes: "Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away."
So, let's do this the right way round and start from scratch. What do we actually need for this specific use case?
-
Simplicity: An agent-centric language design aimed at API-orchestration. One call, a loop over the result, some conditional logic, another call. That's it. Nothing fancy, and no syntactic sugar.
-
Predictability: Every program is guaranteed to terminate by design. No file I/O, no sockets, no system access. The language is the sandbox.
-
Discoverability: A program can find out about the available APIs and even the language itself at runtime. No upfront documentation, no out-of-band integration step.
The human in the middle has vanished. The seam no longer sits between the two systems where the translator had to place it, but has moved into the called system. It exposes the language, sets the rules, and defines the vocabulary. The calling system arrives ready to speak whatever it finds. And the three design principles above aim to make this integration seamless: simple enough that the calling system doesn't struggle to use it. Predictable enough that the called system doesn't have to fear it. Discoverable enough that no human has to explain it in advance.
With all this in mind, I have created, from the ground up, a new programming language and its runtime reference implementation for precisely this use case.
More on that next time.