2026-07-24 08:00:00
Codeberg recently changed its terms to exclude projects that are largely written with generative AI. Since I want GitHub to face competition I have thoughts.
Codeberg is entirely within its rights to do this. It is an association with members and a democratic process, and that process produced a result. But democracy is a way of making a decision, not a guarantee that the decision is inclusive, wise, or even good for the people already depending on it. A majority can still decide that certain projects and people no longer belong.
GitHub’s governance has never been democratic and there is plenty about the platform that I dislike. Yet democracy is not the main property I need from infrastructure. I need it to be predictable, dependable, and reasonably neutral towards the legal Open Source software hosted on it. A democratic provider without a clear constitution can be worse at those things than a corporation.
The actual wording makes this more difficult. The terms prohibit projects that mostly consist of code written by generative AI tools. In an actively developed codebase, what does “mostly” mean, and who can still tell? I could not reliably assign authorship percentages to many of my own recent projects. The line is open to interpretation precisely where it needs to be enforceable. In practice the center will probably lose out, as it has a bias.
A harsher line would probably be preferable. If Codeberg wants no LLM involvement, it should say so. If it wants to prevent autonomous repository spam and abusive resource consumption, it should write rules for those instead. The current middle ground delegates too much of the policy to moderators and community norms. I’m currently assuming the community around it draws a much harsher social boundary, making projects and maintainers unwelcome even when they technically comply.
It is a real shame that the Open Source and Free Software communities are splitting this deeply over LLMs and agents. There are serious questions about copyright, labor, energy use, slop, and maintainers drowning in generated contributions. But these tools are also becoming part of how software is made. The Open Source world needs to figure out how to engage with that future, not just divide into camps. More importantly, LLMs if done and used well, should be welcome to all of us. They could be used to reclaim control and power, away from large corporations and institutions.
As I mentioned before, I want GitHub to face true competition in the Open Source space. I would particularly like some of it to come from associations rather than another large corporation. As a European project, Codeberg naturally matters to me even more. It can choose to be a smaller community with a stronger political identity, but that is a different ambition from being a broad and dependable European alternative to GitHub.
I wish Codeberg were more forward-looking here: willing to host the Open Source software of tomorrow, not only software made in the ways its community approves of today. It has every right to make the choice it made, but I just do not think it is a good one.
2026-07-13 08:00:00
I feel that some vibecoded software changes somewhat randomly and unexpectedly. That made me think about Bruegel’s “The Tower of Babel” which shows an already quite chaotic depiction of the Tower of Babel. The story is usually told as one about pride and ambition and ultimately why people no longer speak the same language. But it is also a story about the unity that makes technological progress work.
The text begins with a technology upgrade:
And they said one to another, Go to, let us make brick, and burn them thoroughly. And they had brick for stone, and slime had they for morter.
They use it for a civilizational project:
let us build us a city and a tower, whose top may reach unto heaven
But when God assesses the situation the bricks are not what concern him:
the people is one, and they have all one language, […] and now nothing will be restrained from them.1
The source of their power is coordination. They share a language and with that shared language they can combine their work into something no one of them could build alone. God does not take away the bricks or their knowledge of how to make them. He takes away their ability to understand one another, and construction stops.
There is the appealing idea that AI-assisted programming means better tools which lets us build more ambitious software. That is certainly true at the level of the individual and without doubt a developer with an agent will be dramatically more capable of changing a codebase. But large software projects have never been limited only by how quickly an individual can produce code. They are limited by how well people can coordinate their understanding of the system they are changing.
The shared language of a software project is not English or Python but it is the common understanding of what its concepts mean, where the boundaries are, which invariants matter, who owns what, and why the system has the shape it does. This language is rarely written down in one place. It lives partly in documentation and code, but also in code review, conversations, arguments, and the experience of having to explain a change to somebody else.
Before agents, some of this shared understanding was maintained by friction. If I wanted to change your storage layer, I usually had to read your code, ask you questions, and perhaps coordinate with another team whose service depended on it. This was slow, and much of that slowness was waste but not all of it was. Some of it was the process by which your understanding became mine, and by which both of us discovered whether we still agreed about how the system worked. This friction synchronizes people.
Agents remove much of that friction. I can ask an agent to add OAuth, you can ask one to add caching, and somebody else can ask one to rebuild the database from first principles and make the UI pink. Each change can be reasonable in isolation. The code can compile, the tests can pass, and the explanations can be generated on demand. None of us necessarily has to talk to the others, or even acquire the part of the shared model that the change once would have forced us to learn.
As I said many times before: agents do not feel pain, only humans do. Agents now let us act in parts of the system where we would previously have needed other people and in code bases where the people would have revolted.
When I look at some vibecoded scaled-up projects the codebases become Babel not because nobody can communicate, but because nobody needs to. Every developer has a tireless translator that can explain a corner of the tower and make whatever local alteration they ask of it. The changes keep landing, even as the architectural language that would let the humans reason about them together disappears.
But it’s not the biblical story. At Babel, the loss of common language stops construction whereas in AI-assisted engineering, construction can continue after shared understanding has already collapsed. The lack of an immediate failure is what makes it curious and a bit disorienting. The tower does not fall, and so we do not notice what was lost. It just keeps rising.
2026-07-04 08:00:00
A very strange Pi issue
sent me down a rabbit hole over the last two days. The short version is that
newer Claude models sometimes call Pi’s edit tool with extra, invented fields in
the nested edits[] array. And not Haiku or some small model: Opus 4.8. The
edit itself is usually correct but the arguments do not match the schema as
the model invents made-up keys and Pi thus rejects the tool call and asks to
try again.
That alone is not too surprising as models emit malformed tool calls sometimes. Particularly small ones. What surprised me is that this is getting worse with newer Anthropic models as both Opus 4.8 and Sonnet 5 show it but none of the older models. In other words, the SOTA models of the family are worse at this specific tool schema than their older siblings.
In case you are curious about Fable: I intentionally did not test it because I was not sure if the classifiers they are running might downgrade me to Opus silently.
If you have not spent too much time looking at LLM tool calling internals, the important thing to understand is that tool calls are not magic and use some rather crude in-band signalling. The model receives a transcript, a system prompt and a list of available tools. The server munches that into a large prompt with special marker tokens. Because the model was trained and reinforced on examples of that format, at some point during generation it emits something that the API or client interprets as “call this tool with these arguments”.
For a file edit tool, the intended invocation payload might say something like this:
{
"path": "some/file.py",
"edits": [
{
"oldText": "text to replace",
"newText": "replacement text"
}
]
}
A harness then validates the arguments, performs the edit, and feeds the result back into the model. If validation fails, the model sees an error and usually tries again.
How exactly that formatting happens is not known for the Anthropic models, but some people have gotten out “ANTML” markers and they at times do leak also into public communications. To the best of my knowledge, the call above would come out serialized like this from the model:
<antml:function_calls>
<antml:invoke name="edit">
<antml:parameter name="path">some/file.py</antml:parameter>
<antml:parameter name="edits">
[
{
"oldText": "text to replace",
"newText": "replacement text"
}
]
</antml:parameter>
</antml:invoke>
</antml:function_calls>
An important thing to note here is that this thing, while looking like XML, is not really XML. It’s just a thing they found convenient to tokenize and train on. The other thing to note is that a basic top-level string parameter appears in-line whereas an array of objects is implemented via JSON serialization. While I’m not entirely sure that this is how it works, there are some indications that this is not too far off. This will become relevant later.
There are two very different ways to make the model produce a structure like this:
The second approach is what people usually refer to as grammar-aware or
constrained decoding. The sampler masks out tokens that would violate the
grammar. If the model is currently inside a JSON object and the schema says
only oldText and newText are allowed, the sampler can prevent it from
emitting "in_file" or "type". Grammar-aware decoding can be used both to
constrain something to be syntactically valid JSON and also to enforce specific
enum values or keys.
Without any form of constraints the model is merely following a learned convention.
Pi’s edit tool supports multiple exact string replacements in one call. That is
why the arguments contain an edits array. In the failing cases the model
produces entries like this:
{
"oldText": "...",
"newText": "...",
"requireUnique": true
}
or this:
{
"oldText": "...",
"newText": "...",
"oldText2": "",
"newText2": ""
}
Across repeated trials I saw a whole zoo of invented trailing keys: type,
id, kind, unique, requireUnique, matchCase, in_file,
forceMatchCount, children, notes, cost, oldText2, newText2,
oldText_2, newText_2, and even an event.0.additionalProperties key inside
the edit object itself.
The most annoying part is that the actual oldText and newText payloads were
byte-correct in the invalid calls I inspected. The model had in fact produced
the right invocation but then added nonsense at the end of the object.
The failure is also heavily context-dependent. A fresh single-turn prompt like “edit this file” did not reproduce it at all for me. An agentic history where the model had read files, diagnosed a problem and then composed a multi-line edit could reproduce it. And more annoyingly, not all transcripts will show that behavior. In fact, I needed Petr Baudis‘s transcripts to reproduce this for me at all! In that user’s session continuing the session caused Opus 4.8 to fail around 20% of the time. Stripping thinking blocks from history reduced the failure rate by half. Turning on strict tool invocation eliminated it in my runs.
My strongest hypothesis is that this is not random deterioration but a training artifact.
When older Anthropic models were trained, they were trained on some tools (some of which were documented). But that training did not yet have a user-shipped harness like Claude Code as the obvious target. Modern Anthropic models are most likely different because their post-training includes Claude Code or a harness that looks very similar. The model learns what a successful tool call looks like in that environment. It also learns what mistakes are tolerated by that environment.
Claude Code’s own tools are comparatively flat. The ordinary edit tool is not
Pi’s nested edits[] shape; it is closer to file_path, old_string,
new_string, and an optional flag (replace_all). Looking at Claude Code’s
client is very instructive: it contains retry paths for malformed tool use,
parameter aliases, type coercions, Unicode repairs and filtering of unknown
keys. In other words, Anthropic’s own client appears to expect and accept a
fair amount of slop and repairs it, mostly silently.
If reinforcement learning happens in a harness like that, or a simulation of one, then slightly malformed tool calls can still complete the task and receive reward. The harness fully absorbs the error and there is little gradient against inventing an alias, adding a stray field or using a nearby parameter name.
Worse, the model may become very strongly adapted to the canonical Claude Code edit tool shape. A different harness can present a tool with the same semantic intent but a different schema. Such a tool can increasingly be off-distribution. The better-trained model might actually fight you harder because its prior is stronger.
This is not too surprising, but it is a change from how this was a few months ago. When Opus 4.5 launched, it adapted to other edit tools exceptionally well. In fact, I was pretty convinced that we’re on a good path where the models are more likely to adapt to any sort of tool shape that comes around for as long as the instructions are good.
Now I’m somewhat worried about the track we’re on here. Alternative tool schemas might not just be unfamiliar. They might be implicitly punished by post-training that optimizes for one particular, forgiving tool ecology. And that ecology is not documented. While there is a text editor tool that is documented, you will see that this format is in fact not followed by Claude Code. What Claude Code does internally (which is a closed-source harness) is hidden from you.
Claude Code is obviously closed-source but we can look at the minified code and get some idea of what it does. And honestly, it’s very forgiving of incoming data.
For a start, Claude Code checks the model’s visible text for leaked <invoke
markup. It also emits some telemetry when that happens and then it has its
own state machine to retry such bad calls by pushing back to the model.
It has explicit Unicode escape repair which fixes broken \uXXXX sequences and
lone surrogates in string values. It also has per-tool aliases for parameters.
For instance, Edit accepts old_str (presumably from the times when the models
were trained on the officially documented text editor tool), the newer old_string
from the schema, new_str/new_string, path as an alias for file_path, and some more.
It also silently filters out unexpected keys and it does not use strict mode
either. The issue with strict mode is that Anthropic applies complexity
limits to the tool definitions that cause API requests to fail, so presumably
that’s why Claude Code does not attempt to use it.
Will this problem be with us in other harnesses too? One huge issue with Anthropic is that the models are completely closed, and so is the harness. Codex models are also closed, but at least the harness is not. We also have gpt-oss which is at least a bit interesting. The models are explicitly trained to use OpenAI’s harmony response format and there is a lot of documentation that at least tells us how OpenAI people think about this.
Harmony makes channels and tool-call content types part of the prompt format. A function call can look like this:
<|start|>assistant<|channel|>commentary to=functions.get_weather
<|constrain|>json<|message|>{"location":"San Francisco"}<|call|>
The important bit is <|constrain|>json. The model can express in-band that
this message body is JSON, and an inference stack can use that boundary to
switch into JSON-constrained sampling for the body of the tool call. Presumably
a bit of this also happens in Anthropic’s models, at least in strict mode
I would imagine.
The marker in harmony helps the sampler to detect when it needs to sample with a specific grammar, and because it is part of the transcript, it makes that rather easy to do. For hosted GPT models, there is also an option to provide a LARK grammar for custom tools that need to adhere to something like this.
Anthropic appears different from that, though maybe not entirely. If an array
of objects is represented as JSON, as it appears to be, then the model has to
write JSON inside the tool parameter. There is probably basic
grammar-constrained sampling going on, and that may partly explain the extra
keys. For a nested array parameter, that JSON includes escaped multi-line file
content inside string literals, inside one tag. The unexpected,
made-up keys appear exactly at the highest-entropy point of that task: after
closing a several-hundred-token escaped newText string, where the model must
decide } vs , "...".
Opus 4.8 and Sonnet 5 seem to have much stronger priors about what an edit tool
call should look like and that prior appears to be Claude Code’s edit schema: a
flat old/new string pair, plus the optional replace_all flag. My guess is
that Opus has learned that an edit operation may have one extra optional field,
but under Pi’s nested oldText/newText shape it has no trained name for that
field. So it samples a plausible name fresh each time, which is why the
failures produce dozens of random keys rather than one stable alias.
As strict mode in Anthropic appears to fix this, I presume that on the server
side they are refusing to sample a key that is not permitted by the JSON schema
structure. That would also explain why they have limits to the complexity of
the tool definitions when strict mode is enabled.
So far, the Codex models I tested did not show this type of regression. I tested all available ones except 5.6, which I do not have access to yet.
The uncomfortable lesson is that tool schemas are not neutral, at least not on Anthropic models. We like to pretend that a schema is an abstract contract and the model is a general reasoner that will follow it, but that might no longer be the case for some of the tools.
Tool schemas are somewhere in the distribution and some shapes are close to what the model saw during post-training and some are far away. Some are easy for the provider’s hidden encoding (e.g. top-level attributes in ANTML), whereas some require the model to write large escaped JSON objects inside nested arrays after long multiline strings. The model may be smart enough to understand the schema and still be bad at sampling the exact shape under pressure.
If this type of model behavior continues, I wonder what the implications for
harnesses are. Obviously one could turn on strict sampling in
Anthropic and the problem should go away. On the other hand, that the model
has this behavior shows the impact that reinforcement learning has on them.
Fighting that prior is probably futile if you want to get the best model performance.
Right now the reality is that Claude Code is not open source and we cannot really know what they are doing in their RL environments either. We cannot assume Claude-Code-trained behavior will transfer cleanly to your tools unless they are a close match. The more post-training happens inside one dominant harness, the more every other harness will have to inherit its quirks.
I used to be more skeptical of strict grammar-constrained tool invocation because constrained decoding can have quality tradeoffs. I still think that can be true in general, but this bug moved my priors significantly. If the newest models get better at solving the task while getting worse at faithfully emitting an alternative tool schema, then the harness needs stronger guarantees somewhere.
If you want to find out more, or you want to discuss this, consider reading the issue on the Pi tracker.
2026-06-23 08:00:00
I don’t prompt Claude anymore. I have loops running that prompt Claude and figuring out what to do. My job is to write loops.
— Boris Cherny
Over the last months I have watched more and more people build something on top of coding agents that feels meaningfully different from just using a coding agent. Some of this happens on top of Pi which is cool to see for sure! The pattern is the same everywhere though: work is put into a queue of sorts, a machine picks it up, attempts it, stops, and then some harness decides whether that was actually the end.
If not, the harness continues the same session, injects another message, starts a fresh session with modified context, or sends the task to another machine. The task stays alive beyond the point where the model by itself would normally have said: “I am done.”
I think about that type of loop more than I want to admit.
There is already an agent loop inside every coding agent. The model calls a tool, incorporates the result, calls another tool, reads a file, edits a file, runs tests, and eventually produces some answer. That loop is one we have been quite familiar with for a long time. The other loop is the harness level loop: the loop outside the agent loop. That loop is also not new. We have been doing versions of this since early Claude Code days, but that loop is becoming ever more present in agentic engineering and in recent weeks it has started to dominate the Twitter discourse.
My current status is that I have not had much success with this way of working for code I deeply care about which turns out to be quite a lot of code.
Part of that is taste and part of it is control. I attempt to set a high bar for what I want code to look like, and I want to understand the code I ship. Under pressure, or in a discussion with another human, I want to be able to explain what the system does without first having to ask a clanker to explain it to me. Now there is obviously a question if this desire to understand the code is one that I will still have a few years from now. For now I have not moved past the point of comprehension being important to me.
Given this desire, there is something I lack with my experience of code written without me paying attention, particularly from loops. Present-day models tend to produce code that is too defensive, too complex, too local in its reasoning. They avoid strong invariants. They add fallbacks instead of making bad states impossible. They duplicate code, invent bad abstractions, and paper over unclear design with more machinery. Worse though: I so far see very little progress of this improving. If anything, on that front it feels to me that we might even be making steps in the wrong direction. At least for my taste, present-day hands-off harnesses like Claude Code with ultracode produce worse code than what we were producing last autumn. That’s because Claude Code, with Fable for instance will be working uninterrupted on a problem for thirty minutes or more, when previously the process would have been much more human in the loop.
Furthermore it’s well understood that models tend to observe some local failure and add a local defense. Karpathy mentioned how they are “mortally terrified of exceptions”. In systems with important invariants, especially persisted data formats or core infrastructure, the right fix is not “handle every malformed case.” The right fix is to make the malformed case unrepresentable or impossible to write in the first place. Yet even with a lot of manual steering, that type of code does not come out of LLMs naturally, and even if the code comes out naturally like that, they will still attempt to handle now impossible errors.
When you take that behavior and you put it behind loops, you tend to amplify it. If each iteration adds another small defense, the system slowly becomes less understandable while appearing more robust. The more hands-off you are, the more that happens. It also teaches really bad practices when tools like this are given to juniors without clear guidance. Because if you ask them, why they are doing all that, they will convincingly argue their case.
At the same time, it would be dishonest to pretend the loop pattern does not work because it already works astonishingly well in some domains.
Porting code one of them. There are already impressive examples of large automatic porting efforts, including the reported work around moving parts of Bun from Zig to Rust. I have used it with success myself to port MiniJinja to Go. Performance explorations are another case where this works beautifully. A machine can try experiments, benchmark them, discard failures, and keep searching. Security scanning fits naturally too and so does almost any type of research: asking a system to explore a complex problem space and report back without necessarily committing lasting code. One thing that many of these have in common is that they either do not generate new code, but transform code that already exists, or they produce code that intentionally does not have a long shelf life. They either produce proof of concepts or ideas, surface findings or are more akin to mechnical transformation.
I believe that loops that produce artifacts without necessity of longevity or that create some form of clearly verifiable mechnical translation matters more than the general ability of a harness to mechanically measure a goal. Many successful applications of loops use another LLM as a judge or as an orchestrator. The mechnical translation case can be verified with a binary test case, but it can also be judged by an LLM instead!
Claude Code, for instance, is increasingly good at creating entire experimental workflows that it will then execute. Sure, the code it produces is slop, but that’s more the fault of the model than the harness not being a good judge on if a step in the workflow resulted in a net improvement or completion.
The harness just needs some signal that lets it continue. It does not have to be objective or binary, it just has to be useful enough to drive another iteration.
I absolutely love loops already that take the boring parts out of my day to experiment and measure and to give me ideas.
On the other hand using that same looping methodology to write lasting code does not yet sit well with me. The metaphor I like to reach for is one of moving from software as a deterministic machine to software as an organism.
I became a software engineer in an enviornment that encouraged me to understand the machine. There was always a layer you could peel off to deepen your understanding. Machines that did not exhibit deterministic observable behavior were maybe accepted, but generally seen as not exactly optimal. Software architecture-wise, I saw it as desireable to push further towards more determinism rather than less. Likewise the ability to understand the code has been an undeniable goal. In practice not always possible we still took pride in writing code so that it became possible even for new engineers to navigate complex code bases through clever architecture. On well designed systems there were always engineers that knew where the invariantes lived, which parts were load-bearing and which changes were safe. Ideally all of that was also well documented. Where that understanding was lacking, it was generally regarded as something to improve upon.
Obviously that ideal has always been strained. Many software systems, especially very successful ones had periods where engineers on the team were able to keep them clean. Large software systems are not infrequently too big, too dynamic and too dependent on external services to fit into anyone’s head. Even without LLMs we already diagnose distributed systems somewhat like doctors in that we observe symptoms, form hypotheses, “order more tests”, try some remedies, and observe again.
Yet with LLMs we’re pushing much further in that direction and much quicker. We use them to write the code and we also use them for diagnosis and remedy. There are plenty of engineers that already live in a world in which the first step after the occurrence of a production issue is followed by having a clanker read logs, propose root causes and proactively put up a patch. The resulting patch is then often picked up by another machine that reviews, sometimes even landing it on main without any human supervision.
Obviously that is powerful and I cannot deny that it sounds appealing. But giving in to that idea, particularly with less and less human oversight means accepting that we may no longer understand the whole system in the same way. We treat it, we monitor it, we stabilize it, but we do not necessarily comprehend it.
I have no doubts that for some software, that is okay. Not every line of code deserves human authorship and worse code might have been written in the past.
But do I want all software to be authored this way?
What’s very uncomfortable is that opting out of this fully machine-driven future may not be an option.
Security is the clearest example today. Even if you do not use loops to build your software, other people will use loops against your software. Attackers will run machines continuously and even if it’s not attackers, then security researchers will and some of that automated work will throw up dust but also find real issues. And both the signal and the noise will come your way at a volume that makes it almost impossible to deal with unless you yourself throw a machine at the problem.
Daniel Stenberg’s post about curl’s summer of bliss is a good example of the pressure maintainers are already under. As far as I know, AI does not play a tremendous role in the core development of curl today. Yet despite all of this, maintainers are overwhelmed by reports, most of which are now AI-generated ones.
If attackers and reporters loop, defenders will eventually need to loop too to keep up. Maybe not to write patches directly, maybe just to triage and reproduce and pressure will increase.
The same is true competitively as some teams will out-build others through raw speed. Some projects will suddenly move faster because a tiny group figures out how to orchestrate machines effectively. Some startups will do with five people what used to require fifty. Some people might literally put a machine against your product in a loop and ask it to “make it like the other one.” And if their users are happy, does it really matter?
Not all software will be equally affected. Some domains will punish sloppiness and demand trust and responsibility, but a lot of software lives in a world where raw speed, quick experimentation, and vast coverage matter enormously.
The scariest part to me is that we become dependent on these new machines in new ways. Software has always depended on tools. I remember the time when I had to pay for compilers. These new tools are a flashback to times where creating software came with real costs. But now it’s no longer a one-time payment, it’s a constant dependency. Not just a dependency on a filled wallet, but also a cognitive dependency.
If a codebase is produced by loops, reviewed by loops, patched by loops, and kept alive by loops, what happens when you no longer have access to the same class of systems? What happens when some trade restrictions take away access to the most powerful models? What if just the cost becomes unbearable? What if you and your team just lose the last remaining ability to understand the code without using the machine?
We may create codebases that are not merely hard to maintain by humans, but that assume machine participation as part of their maintenance model. This is already happening! It’s not happening everywhere, and it might not even be happening in ways that are seen as problematic, but we see more and more of it. People more and more merge code they cannot fully explain. People lose their ability to create issue reports or discuss things in chat, without augmenting or rephrasing their messages with the context provided by a clanker. Too many people increasingly rely on a machine to summarize or contextualize it. More and more do I encounter people who converse with me through the indirection of an LLM.
Again, maybe that is not even going to be wrong, but it’s a massive change to how we did things.
I have little doubt that this is where things are going but going there will require us to do something about our tooling everywhere, and not just in the coding agents.
Just orchestrating more loops won’t be enough. Better visualizations of changes or orchestration or agents will not restore our understanding. Either we need to find clever ways to jolt the human back into the loop and make the changes of the loops legible long term, or we need to find better ways to compose these ever more complex systems.
This is also where my thinking about the role of Pi is changing. Pi has been cautious, and I think that caution is good. I do not want a future where every interaction turns into an uncontrolled swarm of machines making changes I cannot follow. I would not want Pi to become an unmaintainable mess in an effort to win the race towards software that writes itself and I would not want Pi to promote this type of engineering either. At the same time Pi is a harness and harnesses are at the center of people running these new types of experiments.
Task queues for coding tasks, orchestration of agents, subagents, durable sessions will matter more and more. Even those of us who have their reservations and are not blindly embracing loops will have to start doing those experiments. We need to, because we need to understand how to make this future bounded and survivable.
As you can read from this post, I’m very uneasy about this future. Not cause of fear, but because of caution given experiences with this technology so far.
Adopting the idea of harness loops means that the harness decides when work is finished. In the agent loop, the model eventually says “done” and I review. Even before that, I usually steer along the way. I am involved and I enjoy learning along the way. In the harness operated loop I’m not sure what my role even is. Even the “done” signal loses all meanings and just becomes communicated to yet another machine that judges. My role is reduced to that of a messenger.
Today I do not like much of the code that I see from systems built that way and neither do I enjoy interacting with too much of software built with AI assistence. Looping is powerful but it removes responsibility more and more, and it at least today very much encourages us to give in to the machine.
And yet I have no doubts that this looping future is going to be our future despite the fact that I presently resent it. I already see astonishingly small teams building at impossible speed and I see codebases turning more and more into obscure and confusing organisms that can only be diagnosed by more machines. Those codebases are simultaniously useful and messy.
So I guess I’m coming to terms with that the question is not whether we will loop because clearly we will. Maybe the question is that in a future of loops, how do we don’t abdicate judgment, how we can retain rules of good engineering, how we can ensure that responsible human can continue to supervise, how we need to re-think how we architect code to retain sanity along the way.
2026-06-13 08:00:00
There is a bit of schadenfreude on Twitter right now about Anthropic being hit by the US government’s export control directive to suspend access to Fable and Mythos. Anthropic and their leadership have spent a lot of time and effort describing its own technology as dangerous and in need of strict controls and regulation. Now that the US government appears to have taken that framing seriously and told them to turn it off for foreign nationals I can see why people are making fun of that situation.
I understand the reaction, but I urge you to not entertain it for too long because it is a giant distraction. The important part is not that Anthropic’s safety language came back to bite them but the line the US government is drawing: this technology is apparently so powerful that only Americans should have it.
We are on a clear path towards a world of division. One should think that if a model is too dangerous for everyone, then it is too dangerous for Americans too. Instead the US is treating these models like weapons that need to be controlled. It is not just about capabilities, it is about racism and nationalism. If you have the wrong passport, you are not to be trusted. This is a very different thing from safety, and Europeans should pay close attention to it.
The directive, as Anthropic describes it, applies to foreign nationals whether they are inside or outside the United States, including foreign national Anthropic employees. That is an astonishing boundary if you think about it. We moved from “do not sell this model to hostile governments” to nationality itself being the defining boundary. This should be a wake-up call to Europeans in and outside the US, and quite frankly, any non US citizen.
A lot of AI safety discourse presents itself as universal: humanity, catastrophic risk, safeguards, responsible deployment. Even Anthropic’s own writings start out that way, but yet every time regulation is discussed there is an overtone of national security and that it cannot get into the wrong hands. It’s not just Anthropic, it’s the entire US based discourse on AI. The foundation is that the US has moral superiority and others are not to be trusted. That there are other countries are authoritarian, that they lack freedoms.
That should make us uncomfortable, not just Europeans, but particularly us. It is also a situation you cannot regulate yourself out of. European technology policy is entirely unprepared for this, because this is not a question of regulation but a question of might and power, something that Europe lacks.
Europe has spent years trying to regulate large American technology companies, sometimes for good reasons. I am not reflexively against that. The DMA matters because access matters. Users should have agency over their devices, their data, and the software they run. But regulation is a useless substitute for capability and we are lacking that. Regulation might try to force open doors but if those doors only come from American or Chinese companies, then that accomplishes very little.
Also let’s not be naive in that this is a negotiation of money and force. The US is in that position because the US has a mighty military. The US can bomb nations anywhere in the world, force international trade routes closed and get away with it. That’s true leverage.
Europe is dependent on the United States in ways that are becoming increasingly impossible to ignore. We depend on American cloud providers, operating systems, developer platforms and now AI models and internet from satellites. We also depend on global semiconductor supply chains we do not control. If access to frontier AI becomes a matter of American national security policy, Europe is not a peer in that conversation and might not even be a market.
That is a humiliating position, but one that happened entirely intentionally.
European citizens and politicians still have not managed to move beyond blaming the EU for its failures. We built and maintained fragmented markets and then pretended we had a single one. We let company formation, hiring, equity compensation, tax, notaries, KYC, banking, and cross-border services remain much harder than they need to be and we are playing these rules against each other. Not just on the European level, but within every single member state. We protect the trusts and established enterprises, who are risk averse and entrenched, instead of trusting the next generation to build great companies. We created a culture where process becomes an excuse for low agency. We made it hard to build new and large companies and then act surprised when our most ambitious founders move somewhere else or just decided to incorporate their companies in the US.
Increasingly, Europeans who want to build very large technology companies move to the United States. They do it because the capital markets are better, the startup infrastructure is better, employee equity is better understood. I cannot blame anyone doing it, and I’m guilty of this myself as we have incorporated our holding in Delaware. If you are trying to raise serious money, hire aggressively, and move quickly, the US often looks like the only game in town. Because quite frankly: it is.
But this is why we are on a dangerous death spiral already. Talent leaves because the ecosystem is weak and the ecosystem stays weak because talent leaves. Infrastructure makes the world: build excellent swimming pools and you will grow a generation of great swimmers.
The temporary task is straightforward but uncomfortable: Europeans need to believe in themselves enough not to surrender to American gravity. Moving to the US as a founder or tech employee is rational and individually it is often the right decision. But if every ambitious person treats Europe as a lost cause, then Europe becomes one. If everyone with agency leaves, the only people left to shape the system are the people most comfortable with the system as it is. Then we really should not be surprised when nothing changes.
Europe needs more ambition, more ownership, more urgency, and more willingness to build. It needs less resignation. It needs to stop confusing regulation with strategy and dependency with virtue. We need to deregulate where rules serve mostly as protectionism. We need capital markets that can fund companies at the scale modern technology requires. We need employee ownership to become normal rather than exotic. We need a real single market for services, not just speeches about one. We need countries to stop fighting each other while claiming to act in the European interest.
Most importantly: we need to stop blaming the politicians. Too many European companies are adding to that bureaucracy entirely out of their own choice. They drown you in paperwork. At one point I had to sign a four page contract for a 120 Euro lamp at an Austrian retailer, just to pick up from their store 15 minutes later. Sometimes I cannot get a speaking engagement at a European event without someone sending me complex rights waivers over. It’s all just paperwork protection against potential downsides.
When we do not have the power to influence, we should at least understand why and where things are failing. Too many entrepreneurs are blaming EU regulation for failures that are originating within the member states. EU regulation is the result of a democratic process between countries that are lobbying in favor of their local industries against others in the same economic bloc. No amount of abolishment of the EU is going to fix this harsh reality. Nothing more demonstrates this as the inability for cross-border M&A in the European Union. It’s not the EU that blocks it, it’s the country that loses out.
Strengthening Europe is necessary because weakness makes us pawns. A Europe that cannot build, cannot finance, cannot coordinate and cannot defend its own interests will not be treated as an equal. It will be regulated around, export-controlled around, consulted after the fact or not consulted at all.
I do not want the lesson to be that Europe simply needs to turn itself into a copy of the United States. The US has solved some things that Europe has not. It has deep capital markets, a much stronger culture of ownership, a greater tolerance for risk, and institutions that often try to make progress possible rather than explain why it cannot happen. It also has achieved an internal level of integration that is unparalleled in Europe. Tremendous advantages!
But the American path is not obviously a healthy one in all aspects. It tends to take paths with a lot of conflict and wars, a lot of internal societal division and deep inequalities. It centralizes powers away from citizens in the presidency and people with money. You are still trading one set of failures for another. You are at the whim of the US government and its strict rules and regulations. The US barely manages to uphold the rights for its own citizens today.
We should be honest about both sides. You do not win by pretending that Europe is fine. You also do not win by pretending that America has figured everything out.
We must not be blind to all the signs of how international cooperation is falling apart around us. The US no longer talks to European governments before implementing orders that directly affect Europeans. It is threatening to take Greenland, the territory of Denmark, one of its oldest allies. Treaties, alliances and institutions have lost all their worth.
All that matters even if our own lives are focused on building companies, creating wealth, hiring people and making things. Our individual path to success is one thing, but it depends on a world where contracts work, visas work and don’t change on a moment’s notice, trade routes stay open, payment systems function, and families are not torn apart by border regimes or wars. If the world descends into chaos, our basic needs cannot be considered met just because we have a great salaries or equity or investors that trust us.
This is why strengthening Europe cannot be the final goal. A stronger EU is, at best, a temporary defense against a darker world and not an excuse to replace American nationalism with European nationalism. The long-term answer cannot be bigger and bigger blocs fighting over who may use which model, which chip, which cloud or which trade route.
I’m not asking here for Europeans to get their shit together just to compete with the US or China. Maybe I hope that this is a thing that develops, but the goal absolutely cannot be that we accept the deterioration of international relationships long term.
I truly believe that Open Source matters and international cooperation matters. It is not a magical answer to every problem, but it is one of the few paths we have that does not naturally lead to total concentration of power.
If frontier AI becomes something only large corporations and governments can control, then everyone else becomes dependent on their judgment. That is a bad place to be. Corporations will optimize for their incentives, as well structured as they might be, and governments will optimize for more and more power. Right now we’re on a path in which access to general-purpose capability is mediated by a small number of actors with tremendous powers.
I’m not naive in pretending AI cannot carry inherent risks. Open systems are messy, they can be misused and they create uncomfortable questions about dual-use capabilities. I do not want to wave that away but closed systems do not make those questions disappear either. Moving the power to decide into fewer hands is not a solution I believe in. And I would have the same opinion if I was a US citizen living in the US.
Any path that puts large blocs in a constant fight against each other has despicable downstream effects that result in the removal of individual rights. It’s entirely pointless for the US to talk about freedoms that do not extend to non-US citizens and the same is true for Europe or any other country. We might accept these restrictions temporarily, but we absolutely cannot accept them long term for the inhumane effects that they can cause.
If we believe this technology can be used for good, then broad access matters and our goal should be to restore the international rule of law, and not to further weaken it. If we find ourselves in a war against our friends from other countries, cold or hot, we have failed as society.
The world we should be working back toward is one of international cooperation, globalization in the best sense of the word, and human dignity. The internet has made our lives irreversibly international: every day people fall in love across borders, marry across languages, move across continents, and work with friends they may never meet in countries they may never visit. Identifying too strongly with any one country in that world is a fool’s errand.
Over the last decade too many of the people I got to know through Open Source were directly dragged into a war. I want to believe there is a way for us to break this cycle. We should be repairing failed states, rebuilding trust between people, and finding ways to cooperate again instead of letting the richest countries arm themselves and fight over who gets to control the future and narrative. Of course I want Europe to become stronger so it can stop being a pawn, but if we mistake that temporary need for the destination, I will be deeply disappointed.
The way out is not American supremacy, Chinese supremacy or European supremacy. The way out is to climb back toward cooperation before the alternative becomes war.
Artificial Intelligence is quickly becoming another instrument of militarization and national rivalry, when it could be one of the most powerful tools for cooperation we have. We should be using it to help people across societies and languages understand one another, not fighting over who gets to control it.
2026-06-10 08:00:00
I have been a staunch supporter of Open Source for a long time, including experiments in funding it. I’m a true believer in the idea that Open Source always wins in the long run, but not automatically and not quickly. Right now it is being stressed by AI slop, shifting contributor dynamics, the falling cost of producing code, and large companies learning to close doors behind them.
A lot of that battle today is manipulation of the narrative. Opinion makers on social media and in business circles increasingly frame access as irresponsibility. That is why the EU’s DMA matters, even if many people (including myself) reflexively hate EU regulation. Apple’s fight over delayed AI features in Europe is not about Brussels being annoying: it is about whether users can access their own devices and data. The phone is yours, the data is yours, yet Apple decides who may reach it and takes the agency away from you and then tries to make that sound like it is in your interest (supposedly it’s for your safety and security).
The closer you get to the core of AI, the more this shows up. Anthropic has every financial incentive to restrict what people can do with Mythos and Fable, and they wrap those restrictions in safety and (national) security language. Some restrictions may be defensible, but not all of them are. They trained their models on public works, then block Open Source attempts to learn from and distill these systems.
Disliking the EU, China, or any other large government should not make us forget that true democratized access to technology including AI is in all our interest. Some temporary product pain, including delayed Apple AI features, will be worth paying if it keeps gates open. We should not let companies own the narrative that preventing access is in our interest, particularly not as Europeans where the odds are already stacked against us by our underdeveloped capital markets, brain drain and internal fighting.