AI Engineer Europe 2026
LLM codegen fails and how to stop 'em
Read the talk
LLM codegen fails and how to stop them
The PostHog Wizard makes autonomous integration more reliable with fresh documentation, thin example apps, staged instructions, agent feedback and narrow access to secrets.
From a talk by Danilo Campos
Before you start: Familiarity with coding agents, tool calls and application configuration files will help; no PostHog experience is required.
An integration that changes someone else's code
What does it take to hand a software integration to an agent and get back changes the user actually wants? For Danilo Campos, who builds the PostHog Wizard, that question comes after enough failures that robots no longer frighten him: they have already bloodied his nose. Campos describes the Wizard as replacing two hours of integration work with eight minutes of guided setup. He reports that 15,000 people run it each month. These are his reported operating figures; the talk supplies neither a timing methodology nor a definition of the monthly counting unit.
The encouraging evidence is also unusually concrete: Campos points to two unsolicited positive posts on Bluesky and Twitter in the preceding six hours, with screenshots of the terminal interface. People are happy with code a robot put into their projects. That is also the risk. A superficially successful integration can contain invented APIs, awkward architecture or unsafe file access. The Wizard's design comes from learning how those failures happen and changing the conditions under which the agent works.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Give the agent knowledge newer than its training
Model rot is the first failure mode. Training is a substantial capital expense, so a model's knowledge remains a snapshot while software continues changing. Campos describes snapshots that may already be six, eight, twelve or eighteen months old. That knowledge can still be useful, but a fast-moving project's current integration requirements may no longer resemble what the model learned.
An audience member suggests retrieval-augmented generation. Campos agrees that RAG is useful, but with sufficiently large context windows he favors a direct approach: put the relevant Markdown documentation into context. The Wizard offers tools that let the agent select from a menu of fresh PostHog documentation according to the integration it is performing and what it has detected in the project. This is targeted selection, followed by loading the actual instructions the agent needs.
The need became obvious when users began asking Cursor to integrate PostHog. Campos recalls agents making up keys, inventing implementation patterns and calling APIs that did not exist. PostHog had not produced those answers, but users still encountered them as a PostHog integration problem. Current context became part of supporting the product, because leaving the agent to reconstruct the integration from training data made someone else's code-generation failure the team's problem to solve.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Show the shape of a good integration
Correct API knowledge does not guarantee sensible architecture. An agent can produce something technically workable while choosing a strange place or structure for the integration. To give it a better pattern, the Wizard team maintains Model Airplanes: small applications across frameworks and languages with PostHog already integrated. They preserve the parts of an application that demonstrate the integration without carrying an entire production system along with them.
Authentication makes the distinction clear. A Model Airplane's login can accept any password. It is not useful production authentication, but it is auth-shaped: the application still has a recognizable login path. That structure shows the agent where login events and PostHog identity instrumentation belong. The example needs to preserve the relationship between authentication and analytics, not the full machinery of credential validation.
| Example property | What it contributes |
|---|---|
| Recognizable application structure | A place to attach instrumentation |
| PostHog already integrated | A pattern the agent can follow |
| Production complexity omitted | Less context to consume |
The result is a thinner reference application that spends tokens on the integration's shape. Campos reports that this helps the agent complete the desired pattern consistently; he does not supply a measured success rate.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Ask what made the run difficult
The next source of failure is the team maintaining the agent. Human context is limited and fragmentary: someone remembers last week's implementation but forgets a decision from last month. As tools and instructions evolve, those gaps can produce an environment in which the agent cannot follow all of its directives. The Wizard once had an MCP tool instruction that contradicted another tool's instruction. It also required a concluding tool that the agent could not find. Campos says hundreds of runs encountered that missing tool.
To surface these problems, the team added a small piece of inference at the end of every run. At the stop hook, it asks the agent: “What could we have done better to set you up for success in this run?” Campos treats this as user research in which the user happens to be a robot. The question directs attention to the agent's working conditions, including problems that may be invisible in a final completion message.
That feedback exposed several different maintenance errors:
- Unavailable tool: the agent had not been granted permission to access the tool it was instructed to use.
- Contradictory directives: different instructions demanded incompatible behavior.
- Wrong-language guidance: the agent received JavaScript instructions while working in a Python project.
These failures were actionable defects in the supplied environment. Asking about them gave the team information it otherwise would not have had.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Let tools edit secrets without revealing them
Running an agent on someone else's machine requires trust beyond whether the generated code works. An early Wizard version read .env files before modifying them. In that editing workflow, reading supplied the information needed to write, but it also risked sending existing environment values to cloud processing and logs outside the user's control. A successful integration was not sufficient justification for that exposure.
The fix was a narrower capability boundary. The team restricted tool use and reads around environment files, then supplied a dedicated tool with only two operations: check whether a key exists, and write a new value to a key. The agent could request the configuration change without receiving the file's existing values. A JavaScript interface expressing that boundary could look like this:
javascript
export function createEnvironmentTools(localStore) {
return {
async hasKey({ key }) {
return { exists: await localStore.has(key) };
},
async setKey({ key, value }) {
await localStore.set(key, value);
return { written: true };
}
};
}
Here localStore stays behind the tool boundary. Neither response includes an existing value or the file contents. Restricting ordinary file-reading tools is essential: the narrow interface does not help if the agent can obtain the same secrets through another tool.
The protected boundary is existing environment-file content entering inference, not a claim that all project processing stays local. Campos describes removing that content from the model's view while preserving the operations required for setup. The broader obligation remains the same: an agent must not damage a user's project or betray their trust while technically accomplishing the task it was sent to do.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Put engineering effort into the information
These interventions change where engineering effort goes. Developers are accustomed to solving problems by writing more code, adding structure and making that structure reliable. But a new model does not automatically make yesterday's code more valuable. Campos describes code as a depreciating asset: it may already contain technical debt when it ships, even if shipping it was the right decision.
Campos characterizes the Wizard as 90% Markdown files, 8% tools for delivering and processing Markdown, and the remainder agent harness. This is his description of where the system's substance lives, rather than a repository measurement with a stated counting method. His investment thesis follows from it: better models can extract more value from the same well-written prose. Clear instructions, fresh documentation and useful examples can become more effective as the model interpreting them improves.
The metaphor is an octopus: an agent can maneuver around obstacles and squeeze into places that rigid scaffolding would not anticipate. Overconstraining that ability can remove the flexibility that makes the agent useful. The earlier safety boundaries still apply, but within them the design question becomes how to provide enough information, in the right sequence, for the agent to produce the intended result. Breadcrumbs constrain the progression of work while leaving room to solve the local problem.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
How the examples reach the agent
The first audience question asks how the Model Airplanes are actually provided to the model. Campos explains that a context service generates skill files. In the implementation he describes, the service flattens the Model Airplanes into a single Markdown file and includes a reference to it in the skill. The full example remains accessible for the agent to search with grep or inspect in other ways. Referencing the example gives the agent access to its contents without requiring every detail to be reproduced in the top-level instructions.
A follow-up asks why use a Model Airplane rather than a regular skill. They are not competing mechanisms: the example is supplemental content inside the skill. Documentation supplies prose explaining the integration, while the Model Airplane supplies code showing its successful shape. The skill brings both forms of guidance into the agent's working environment.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
The CLI, gateway and authentication boundary
The final implementation question concerns the runtime: is the Wizard built on a coding agent or running independently? Campos says it wraps the Claude Agent SDK in a CLI. Users launch it with a single command and log into PostHog, which provides inference at no charge to them. An LLM gateway lets PostHog cover the token costs on their behalf.
That packaging introduced its own failure mode. Campos recalls Claude Code storing authentication information in unexpected locations, which broke the experience for some users. He describes this way of delivering an agent as a service as still being in its early days. Even after the context, examples and tool boundaries are in place, the service must make authentication and inference access work reliably on the user's machine.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Resources
From the talk
Source repository and usage guide for PostHog's AI integration CLI, including its current privacy and data-processing disclosures.
Further reading
- How PostHog's context mill worksDocumentation
Explains how documentation, prompts and example code become portable, versioned skills and MCP resources.
Updates since the talk
Current installation instructions, supported integrations and commands for configuring and auditing PostHog.
A June 2026 account of the Wizard's context infrastructure, documentation maintenance and reported onboarding outcomes.
Read the complete timestamped transcript
- 0:00
[upbeat music] Good morning.
- 0:18
Who's afraid of robots? Afraid of robots. Afraid of robots. Uh, I'm not afraid of robots because they have already bloodied my nose so many times, there's no more pain that they can give to me.
- 0:33
And that is what I wanna tell you about on this fine morning. Thanks for coming to hang with me. So, my name is Danilo. I work at PostHog, and I make the PostHog Wizard.
- 0:45
And the very strange thing that the PostHog Wizard does
- 0:49
is it skips two hours of misery that you will never get back in your life, and it hands it back to you as eight minutes of pseudo-entertainment.
- 1:03
Now, how do we get away with this? We're talking 15,000 people every single month run this wizard,
- 1:15
and in exchange for their trouble, they get a PostHog integration that works and that they actually like.
- 1:23
How do we do it? I'm gonna tell you all about it today. And
- 1:29
just to underscore the point that this actually works,
- 1:34
within the last six hours, we got two
- 1:39
unprompted posts on Bluesky and Twitter where people are actually happy. Now, this should be terrifying, right? I got a robot out there, it's writing code for people. What if it's doing a bad job?
- 1:56
Well, we learned all the ways that it could do a bad job. I'm gonna tell you the ways that those bad jobs happen. I'm gonna tell you some strategies that you can use
- 2:06
so that your autonomous coding agents do the right thing as well. All right. Let's start with the easy one. We got model rot.
- 2:18
Now, training a model takes a lot of time, but it's not even the time, it's the, it's the money, right? You're not screwing around as Anthropic training a model on a weekend as a lark, right?
- 2:30
This is a serious capital expense. And the trade-off with this is that the models sit there no longer representing reality, right? They are a snapshot of the world and the web as it was, you know, six, eight, 12, 18 months ago, perhaps.
- 2:51
Now, this is useful for many things, but if you're a fast-moving software project, and there are loads of fast-moving software projects, the trade-off of this is that the model doesn't know what the hell is going on anymore.
- 3:04
So, you gotta deal with model rot. Now, this is fairly straightforward stuff. You've probably dealt with this sort of thing before. Does anyone here have a conviction about how you deal with model rot?
- 3:20
Any guesses? I'm see-seeing some shaking heads. What's that? Rags. Rags is good. Yeah. Although I'll tell you what,
- 3:29
with the context windows being what they are at this point, you can't beat just shoving a bunch of markdown files into the context and patching the holes. And this is exactly what we do, uh, with the PostHog Wizard, is that we have documentation that is fresh, hot off the presses on posthog.com, and we allow the agent to
- 3:49
make a selection. We say, "Hey, what are you doing? What are you integrating right here? What have we detected?" And the agent can use tools to go out, pick from a menu of fresh, hot markdown that it can then just slide right into its context, get the job done, do things correctly.
- 4:08
Now, what happened to spur all of this was that a year ago, people started asking their very primitive agents, like, "All right, Cursor, I want you to integrate PostHog for me."
- 4:20
And it would do a terrible job, right? It's just, it's making up keys. It is making up patterns. It is inventing APIs that don't exist. And it is, it's not our fault.
- 4:32
Like, we didn't do anything, but it was our problem. So figuring out ways that we could serve correct, up-to-date context to the agent so that it would do the correct job is part of how we get people posting happy about what the Wizard did for them.
- 4:51
All right. Now, these models, I mean, clearly, they've been scraping every kind of project out there, and I have to guess that not all of them had great architecture, because some of the decisions that these agents make when they're putting a project together
- 5:08
are very strange. Uh, and so what do you do? How do you deal with the fact that an agent's conception of how to put something together may be technically, like, workable,
- 5:21
but not exactly ideal? Well, me and my homies on the PostHog Wizard team, we maintain a fleet of what we call Model Airplanes, and these are projects that have PostHog implemented in them.
- 5:39
They've got them across a bunch of frameworks, a bunch of languages. But what makes it a Model Airplane is that we don't have an entire proper production application going in there.
- 5:50
What we have is something much thinner, something that is a simulacrum of a real application. But for example, the auth doesn't work. Or rather, the auth works for anything.
- 6:03
You can just put whatever you want in the password field, and you're gonna be able to log in.
- 6:07
But the auth is auth-shaped, which means that we can provide these model airplanes to the agent, and then the agent knows, oh, cool. So when auth shows up, this is a great place to put the particular event tracking that one would want to use when they want it to track logins and identity in PostHog.
- 6:27
And so through the maintenance of a thing that isn't quite as elaborate as the real production application, which means also, of course, it is more token efficient, what you get is the correct shape of an integration as a pattern that the model and agent are able to complete consistently every time.
- 6:48
All right. So in addition to weird architecture, the agent can find a weird path through the problem space, and with fifteen thousand integrations per month, it might find fifteen thousand ways to get a PostHog integration done.
- 7:09
And while this would satisfy the requirements of we've automated integration, it would leave us with a very strange support burden because we would have too many different ways that PostHog was set up.
- 7:19
It's like, what, what, what the hell is this? How do I make sense of this, right? This would be a problem at scale. This would be some sorcerer's apprentice stuff.
- 7:28
So to limit improvisation, what we do is breadcrumb the agent. We don't tell the agent up front exactly what we're gonna do. You know, maybe you've seen this before, even when you're using Claude Code, is that if you tell them exactly where you wanna go, it might make a Claude Code-shaped hole through the first four tasks and
- 7:50
then just get really rock polishy with the fifth, right? And this is not what we want for our case. And so one of the things that we do is we start off barely even telling the agent that this is what we're doing.
- 8:03
We don't even mention really that we're doing a PostHog integration. We start with something like,
- 8:09
where are the files with interesting business value in this project? Can you find something that looks like a login or a, a Stripe interface or something that might indicate someone's about to churn, right?
- 8:24
We go looking for the files that would be responsive to impact in somebody's business. And the funny thing is that business stuff casts a huge shadow in code. And so we can very reliably detect this kind of stuff.
- 8:40
Now, from there, we say, okay, here are some cool files. What are the interesting events going on in those files? Don't write any code right now. Just like, l- let's think about some cool events that we might wanna sprinkle through here.
- 8:51
What might those be? So we make a list of these, and we get the event names, we get the descriptions for those events, and we just tuck them into a little file.
- 8:58
And this is the start of things, right? Like, we don't even know where we're going necessarily. And so the next breadcrumb is like, okay, let's start to actually implement PostHog.
- 9:07
We now know a bunch of events, and we've really thought carefully about what those events might be. And now we have documentation and everything which we can load, uh, at whim according to the framework and language that we care about here.
- 9:20
And so we can reliably go in there and start to make modifications to people's files, and the modifications are, once again, not stupid, um, and, and they're not mad about it.
- 9:31
Okay. Now, we can do all of the thoughtful stuff that we can to make the agent successful. But the biggest threat to our agent outcomes is ourselves. We're, we're, we're feeble little beings, and we got a little bit of meat right here locked inside of our heads, and we have a context limit too.
- 9:55
We can't really quantify it, and it varies by how long ago we had some coffee and if we had breakfast that morning. Our context is not just limited, but fragmentary.
- 10:06
There's stuff that we remember implementing last week, and there's stuff that we forgot from last month. And so we're making changes and we're editing code and we're evolving the stuff that our agent is working around, and sometimes we are dropping things that really matter.
- 10:22
And so there is a point where we had an MCP, uh, tool instruction that was contradictory to a different tool. [laughs] And the agent's like, "Man, I don't know what to do here.
- 10:33
You're, you're, you're putting me into an impossible spot." Um, we had, um, a situation where we were telling it, "Hey, there's a tool that you definitely need to use to conclude this setup."
- 10:45
And the agent's getting there, "All right, cool. Let's, let's use the tool. Wait, the, the MCP does not have a tool by this name." And we're talking, like, hundreds of runs going with this missing tool.
- 10:56
And what's going on there? So if we didn't ask, we wouldn't know. And so one of the things that you can do that is really handy and fairly cheap is a little bit of inference time interrogation of what just happened with your agent.
- 11:15
So at the end of every run, uh, right at the stop hook, we ask a very simple question. We're doing a little bit of user research, but the user is, in this case, a robot.
- 11:26
And we ask the, the robot user, "Hey, what could we have done better to set you up for success in this run?"
- 11:35
And then it tells us, and that's how we found out, like, all right, we've [laughs]-- we didn't give you permission to access the tool, and so there was no tool.
- 11:43
Hey, you've got these contradictory directives. Um, without this ongoing interrogation, uh... Oh, a, a good one is that we kept giving it instructions for JavaScript, and it was a Python project that it was working in.
- 11:55
Um, of course, very, um... Well, not frustrating, but, you know, we would identify it that way. Um, so the human error, big deal. You have to ask to find out.
- 12:07
Now- There's also shenanigans that you gotta be concerned about here because running an agent on someone else's machine demands a huge amount of trust, right? We, we, we've got this robot that could do anything potentially, and we don't want to do something, uh, bad or destructive to the user's project.
- 12:27
We don't wanna put them in a worse spot. Um, and one of the early versions of our wizards would actually just read .env files, which is necessary to do writes, right?
- 12:40
You can't just write blind to a file. It's just one of the mechanics of how, you know, these agents work. But it's also not ideal to be sending people's env contents up to a cloud and just like, "All right.
- 12:52
Cool. That's sitting in someone's damn log that you don't know about." Um, so this was obviously bad news. But when you're designing these things, you have fine grain control over tool usage, right?
- 13:03
You can decide, all right, these tools are okay, these kinds of reads are okay, these kinds of reads are not okay. So we really locked down what the agent was allowed to do around anything that was an env file.
- 13:17
And then we were able to build it a tool that could do two things. It could check the presence of a key. Does this key exist? And it could write to a key a new value.
- 13:32
And that was it. There was nothing that was going up in terms of inference for this env file. And so as a result, we were no longer touching this stuff.
- 13:42
Uh, but again, man, you, you are setting loose these robots on anybody's computer. You gotta keep an eye on these shenanigans because even if you're g- kind of solving the problem you promised you'd solve, you might be doing it in a way that makes you look like an asshole.
- 14:00
All right. Now, this is the big one. This is the weird one. Because our whole careers, we have been rewarded by writing the code. We write the code. We write more, more code.
- 14:15
We write the clever code. Oh, I got a structure in here. This thing works. This thing is reliable. This thing is elaborate, but the performance is really good. And, and, we j- man, we just gotta code the shit out of this thing.
- 14:29
If we code our way out of this problem, everything's gonna be great. All right?
- 14:33
That is not the world that we live in anymore. And a very funny thing about code is that if today you have written some code that you think is good and tomorrow a new model drops, the code that you wrote has the exact same value.
- 14:51
If anything, it might be declining a bit, right? Code has always been a depreciating asset. You write it. You might ship it into the world a little bit rotten 'cause it's got some tech debt, and you gotta deal with that at some point.
- 15:05
But meanwhile, you shipped on time. You got what you had to do.
- 15:10
The wizard that makes everybody so happy is ninety percent markdown files, eight percent tools for delivering and processing markdown files, and then the rest is, like, agent harness stuff, right?
- 15:27
Plain text prose is where so much of our value now lives. When you write great prose today, and tomorrow an even better model drops, it's going to be able to take that prose and do even more with it.
- 15:44
And so an agent is an octopus, right? It can wriggle. It can squeeze into tight corners. It can maneuver itself around problems. You do not want to overconstrain the agent in its ability to get problems done aside from the shenanigans stuff as we talked about, right?
- 16:03
So instead of thinking about, like, "Man, how can I scaffold the hell out of the behavior of this agent?" It's about saying, "How do I step back? How do I give it enough information?
- 16:14
And how do I sequence the information that I give it so that it does the thing that I want it to do, and it makes people happy in the process?"
- 16:27
So this is what I know from the robot blooding my nose. I see on my clock here I got a couple minutes left. Does anyone have questions about the strange adventure of building this robot that makes people happy?
- 16:42
Shoot.
- 16:43
Uh, you had on the model airplane section-
- 16:46
Yeah
- 16:46
... you sort of talked through giving a sort of, like, exemplar for the model is really helpful for it to sort of have imagine and figure out what you want.
- 16:54
Is that distributed in part of the prompt? H-H-How... Basically, how is that structured and provided to the model?
- 16:59
Oh, sure. So the way that we drive context for the wizard is we use skill files that are generated from our context service. And so that context service is gonna take all of those model airplanes, flatten them into a single markdown file, and then include them as a reference in the skill file.
- 17:19
And so we always have access to the full model airplane which the model can grip and otherwise churn through.
- 17:30
Same, um, same thing about the, the airplane model.
- 17:33
Mm-hmm.
- 17:34
Uh, I just, um, how is this going to be different from using a regular skill? Why would you use a model rather than a skill to-
- 17:42
Oh, sure
- 17:42
... do the same thing?
- 17:44
So yeah. This is just part of the supplemental content that is included in the skill. And so what we found was there was a range of useful input that we can include as part of the skill file.
- 17:56
So we've got documentation, which is plain text prose, but then we also include the model airplane so that it can see the shape of a successful integration, and it references all of that as part of getting the job done.
- 18:08
Yeah. Makes sense.
- 18:09
Yeah. Shoot.
- 18:10
Is the structure building on top of coding agents like Code or is it, like, running independently of that coding agent?
- 18:16
Oh, sure. So this uses the Claude Agent SDK which we then wrap inside of a CLI. And so you just run a single command, and then we give you free inference by logging into PostHog.
- 18:28
So we've got this LLM gateway where we can cover all of the tokens on your behalf, um, which was a whole zoo because sometimes Claude Code would store auth information in a place that we weren't expecting, and then it would just break for people.
- 18:41
Uh, it's, it's early days for doing this as kind of a service. Yeah.
- 18:49
Anything else I can tell you? Well, then I'm gonna scoot out of the next speaker's way. Thank you for hanging out. It's great to see you. Have yourself a great rest of your day. [clapping] [outro music]