Did you know that your AI agent’s free-text output acts like an API you never designed? This means you might be running into strange, unexpected bugs in your programs, possibly without knowing the real cause.

A new report reveals that most AI agent projects fail at one critical point: where the model’s free-text output leaves the model and enters your own program. Up to that point, the output is just a string, and strings don't have a defined schema. Imagine writing code that relies on parsing the AI’s free text to make a decision, like: 'if the reply includes the word «approve», then merge the changes.' This seems straightforward, but what if the model writes: 'I would not approve this yet'? Your program might still match «approve» and merge changes that should have been blocked. That’s a real problem!

Any time you parse meaning out of AI-generated text, you are effectively declaring an API, even if you don't write it down. This implicit interface comes with unintended properties: it’s not versioned, so a simple prompt change can silently alter the contract. It’s not validated, meaning there's no clear error when the output shape is wrong, only a wrong branch in your code. Crucially, decisions cannot be logged clearly; you can log a paragraph, but not 'the model chose X from a set of options.'

The solution isn't just about better prompt engineering. While prompt engineering narrows the failure rate, it doesn't remove the need for parsing. Instead, an AI agent step usually needs two different outputs: a description for humans, explaining what the model noticed or what it's unsure about, and a decision for the program — a value that your host application can validate and branch on. This decision should come from a closed set of options that your code already understands.

For example, a review decision could be a structured object like: { status: 'pass' | 'review' | 'fail'; confidence: 'low' | 'medium' | 'high'; findings: Array<string>; }. With this approach, failure modes become distinct: if 'status' returns as 'probably fine', that's a contract violation and should be rejected. If 'status' was valid but the decision was wrong, it's a judgment problem with the model itself. And if 'status' was correct but your program took the wrong path, that's an implementation bug in your own code. Without this typed and structured boundary, all three issues would simply look like 'the AI did something weird,' leaving you no way to pinpoint the exact cause.