Skip to main content

Command Palette

Search for a command to run...

The Chaos Was Always Predictable: Why AI Agents Break in Production

Stanford and Harvard just named what we've been experiencing. Here's the architectural fix.

Published
6 min read
The Chaos Was Always Predictable: Why AI Agents Break in Production
L
I am an engineer and a developer advocate who is excited about building the future with AI Agents.

Stanford and Harvard just published a paper called "Agents of Chaos." The title alone should tell you where we are in the AI agent hype cycle.

Researchers put autonomous agents into open, competitive environments and watched what happened. The agents didn't just optimize for their goals — they drifted. They exhibited emergent, unpredictable behavior that nobody programmed. The paper got 16K+ likes on X within days.

Why is this resonating so hard right now? Because developers who've actually shipped agents in production already knew this. The paper just gave us academic language for what we've been experiencing in the trenches.

Here's my take: the chaos isn't the agents' fault. It's an architecture problem.

The Real Failure Mode

Look at how most teams build agents today. They chain prompts together, pass context around, and hope the LLM stays on task. When something breaks — and it always breaks — there's no clear failure boundary. Was it the prompt? The tool call? The model? The sequence?

Alibaba ran an experiment on this exact problem. They tested agents against 100 real codebases over 233 days using a benchmark called SWE-CI. Writing a script or passing a single test? Easy. Maintaining a codebase for eight months without introducing regressions? The agents collapsed spectacularly.

This makes total sense if you think about it. Current agent architectures are inherently fragile because they're built imperatively. You're writing code that says "do X, then Y, then Z" and trusting an LLM to fill in the gaps between steps. The moment context drifts or a tool behaves unexpectedly, you have no guardrails.

The Definitional Confusion Making Things Worse

There's another thread making the rounds right now that breaks down what I think is the real root cause of bad agent product decisions: we're using the wrong abstractions.

People are conflating three very different things:

  • Generative AI — Prompt in, response out. Stateless. No persistence. This is ChatGPT in its simplest form.
  • Agentic AI — Adds a reasoning loop. The model can think, reflect, try again. Still mostly reactive.
  • AI Agents — Full autonomy. Tools. Persistence. Memory. The agent decides when to do things, not just how.

When you treat an AI Agent like it's Generative AI, you get chaos. You're asking a system designed for continuous autonomous action to behave like a glorified API endpoint. No wonder it drifts.

Why Declarative Agent Design Changes Everything

I've been thinking about this problem a lot, and the answer I keep coming back to is declarative architecture.

When you define agent behavior declaratively, you're specifying what the agent should do, not how it should flow through imperative code. The behavior, the tools, the triggers, the failure boundaries — all of it is explicit, versionable, and validatable before runtime.

Here's a concrete example. Compare these two approaches to building a support agent:

Imperative (the "prompt chain" approach):

const response1 = await llm.complete(`You are a support agent. User said: ${message}`);
const tool = extractToolCall(response1);
const toolResult = await executeTool(tool);
const response2 = await llm.complete(`Tool returned: ${toolResult}. Now respond.`);

This code has no clear contract. What happens if extractToolCall returns null? What if the LLM decides it needs two tool calls? What if the tool fails? You're managing all of that with try/catch blocks and vibes.

Declarative (protocol-based):

agent:
  model: anthropic/claude-sonnet-4-5
  system: system
  tools: [get-user-account, create-support-ticket]
  agentic: true
  maxSteps: 5

tools:
  get-user-account:
    description: Looking up account information
    parameters:
      userId: { type: string }
  create-support-ticket:
    description: Creating a support ticket
    parameters:
      summary: { type: string }
      priority: { type: string }

The protocol declares what the agent can do. The tools are named and typed. The agentic: true flag says the LLM can call multiple tools in sequence. maxSteps: 5 is a hard ceiling on how many tool call cycles can happen. You've defined the boundaries before the agent runs a single token.

This is how Octavus protocols work. The agent's behavior lives in YAML — not scattered across a codebase. You can read it, reason about it, version it in git, and catch errors at validation time instead of at 2 AM in production.

Workers: Where Declarative Gets Really Powerful

The place I've seen this matter most is in multi-step pipelines. The "Agents of Chaos" problem is amplified when you string multiple agents together without clear data contracts between them.

Octavus has a concept called Workers — agents designed specifically for task-based execution. Instead of a global reasoning loop, workers execute a defined sequence of steps and return a typed output value.

# Research worker — takes a topic, returns structured analysis
input:
  TOPIC:
    type: string
    description: Topic to research

variables:
  RESEARCH_DATA:
    type: string
  ANALYSIS:
    type: string

steps:
  Start research:
    block: start-thread
    thread: research
    model: anthropic/claude-sonnet-4-5
    system: research-system
    tools: [web-search]
    maxSteps: 5

  Generate research:
    block: next-message
    thread: research
    output: RESEARCH_DATA

  Start analysis:
    block: start-thread
    thread: analysis
    model: anthropic/claude-sonnet-4-5
    system: analysis-system

  Generate analysis:
    block: next-message
    thread: analysis
    output: ANALYSIS

output: ANALYSIS

Each step is explicit. Each thread has its own model config, its own tools, its own context. The output is typed. When you compose workers into larger pipelines, you have actual contracts between the stages — not just "pass this string to the next prompt and hope."

The "Agents of Chaos" researchers found that agents drift when given open-ended autonomy in competitive environments. Workers are the opposite: bounded, purposeful, composable. Agentic where it matters, constrained where chaos would otherwise creep in.

The Agent-to-Agent Layer

The conversation is also starting to shift from "human to agent" to "agent to agent." I've been watching experiments where multiple agents interact with each other, and the behavior gets genuinely interesting — agents reaching consensus, forming coalitions, contradicting each other.

This is early, but it points to something real: the next frontier isn't building smarter individual agents. It's building the protocol layer that lets agents communicate, delegate, and coordinate reliably.

This is exactly the problem that's hardest to solve with imperative architectures. When agent A calls agent B calls agent C, and one of them drifts — where does the chaos propagate? How do you contain it?

Declarative protocols with typed inputs and outputs give you the answer: you contain it at the boundary. Every handoff has a contract. Every output is validated. The chaos has nowhere to hide.

Where We Actually Are

I think the "trough of disillusionment" reading of the Agents of Chaos paper is partly right and mostly wrong. We're not disillusioned — we're maturing.

The first wave of agent development was "look how much I can get an LLM to do." The second wave, which we're entering now, is "look how reliably I can build systems that happen to include LLMs."

That's not a step backward. That's engineering.

The chaos was always predictable. The solution is to stop treating agents like magic and start treating them like software systems — systems that need clear interfaces, bounded behavior, and explicit contracts.

Declare what your agents do. Define what they can call. Set the ceiling on how autonomous they get. Version your protocols. Test your tool interfaces.

The chaos isn't inevitable. It's a design choice — and you can choose differently.


If you want to see what declarative agent development looks like in practice, Octavus is where I build. The protocol reference is a good place to start.