Agents are an Anti-Pattern: Why Your AI System Might Be a God Object

Before we talk about agents, let’s talk about 1990s object-oriented programming.

Back then, developers discovered this amazing thing called “encapsulation.” You could bundle data and behavior together in objects! This was revolutionary. And naturally, people went overboard.

They created these massive classes that did everything: GameManager , SystemController , ApplicationCor e. These “God Objects” seemed efficient—one place for all the logic! But they created nightmares:

The God Object anti-pattern meant:

  • Hard to test (can’t test one behavior without mocking everything it touches)
  • Hard to understand (thousands of lines, dozens of responsibilities)
  • Hard to modify (change one thing, break ten others)
  • Hard to reuse (too coupled to use elsewhere)
  • Hard to parallelize (global state everywhere)

The solution? Decomposition. Break God Objects into focused components with single responsibilities. Define clear interfaces. Minimize state and side effects. Make dependencies explicit.

This pattern is so well-established that modern developers laugh at God Objects. No one builds like that anymore... right?

Wrong. We’re building God Objects again. We just call them “agents.”

To be clear: I’m talking about monolithic agent loops that blend conversation, reasoning, and tool execution into one opaque process. Yes, people build this way. I’ve seen it in production.

Why Agents Are God Objects (And Why That’s a Problem)

Let’s look at what happens when you tell an agent to “prepare the weekly report”:

The agent will:

  • Read from some databases (which ones? it decides at runtime)
  • Query some APIs (which ones? depends on its reasoning)
  • Generate content (how? non-deterministic LLM)
  • Format output (which format? it depends)
  • Send some emails (to whom? good question)
  • Update some state (maybe, if it remembers)
  • Log some events (sometimes)
  • Handle errors (hopefully)

And here’s the key: You don’t know what it will do or not do until it does it.

The interface is natural language, which is simultaneously very flexible and likely too vague. There’s no guaranteed contract, no guaranteed schema, and no way to guarantee desired behavior.

God-object agent loops contain opaque monolithic steps that make debugging difficult or impossible. This also makes composition and portability very difficult.

And then there are side effects, the bane of scalable, reliable concurrent systems. That’s not a bug. That’s the design. An agent might make dozens of tool calls during a single turn. If any of those tool calls cause a state change, good luck figuring out how to roll those back if the agent loop hits an exception or hangs up.

Sound familiar? It’s the God Object pattern all over again.

Reflexive Solutions

Put your God object in a cage

Run your agent in a sandbox. How quaint.

Here’s the thing: if your agent is playing with toys in a sandbox, it’s not doing production work. And if it IS doing production work, that “sandbox” is actually a cage —you’ve just given it a prettier name.

The paradox: the more useful you make the agent (by giving it access to real systems), the less “sandboxed” it becomes. You’re not running it in isolation; you’re running it in production with a prayer and a rate limit.

Cripple your God object

What if we are really careful and only give the agent access to a limited set of permissioned tools? Open the smallest hole, and a sufficiently smart goal-seeking unbound reasoning agent will figure out ways to do things you don’t want it doing.

These aren’t solutions. They’re cope. They’re what happens when we want the magic of “just ask the AI” without accepting the consequences of “the AI makes decisions you can’t predict.”

Five Anti-Patterns That Kill Agent Systems in Production

Let me share some real examples we have observed in the real world. These aren’t hypothetical concerns—they’re patterns we have seen repeatedly.

Anti-Pattern #1: Opaque Side Effects

What it looks like: “Clean up test artifacts”

What actually happens: The agent deletes files but not database records, creating phantom references. Why? Because its reasoning focused on “visible clutter” rather than “referential integrity.”

The instruction was ambiguous. The side effects were undocumented. The problem was only discovered when queries started returning invalid references.

This is the God Object problem: you can’t refactor it, test it in isolation, or predict behavior without running it.

Anti-Pattern #2: The Parallelization Nightmare

What it looks like: Process 1,000 test plans in parallel

What actually happens: Race conditions everywhere.

The plan was to process test plans concurrently. Each agent would:

  • Read the test plan
  • Check prerequisites
  • Execute tests
  • Update results

Simple, right? Except when two agents processed plans with shared dependencies:

  • Both see “prerequisite not met”
  • Both try to run the prerequisite
  • Race conditions everywhere

To solve this, you have to add locks, state coordination, and conflict resolution. You have to rebuild transaction semantics on top of agents.

The lesson: Agents are stateful, context-aware, and autonomous—exactly the properties that make parallelization hard. Traditional software solved this with functional programming, atomic operations, and transaction boundaries. God-object agents throw all of that away.

Anti-Pattern #3: The Non-Determinism Cascade

What it looks like: Generate test summaries

What actually happens: Different output every single time, for the same input data.

Each step in the agent’s reasoning chain introduces variability:

  • LLM interpretation varies (~15%)
  • RAG retrieval returns different documents (~25%)
  • LLM strategy selection varies (~30%)
  • Tool execution sequence varies (~20%)
  • Result verification varies (~35%)

Source: survey conducted by ETM.

These don’t just add up—they multiply . A 15% swing in interpretation cascades into a 25% swing in retrieval, which triggers 30%+ strategy differences. By the final step, compound variation can exceed 60-70%. A lot of that variation is inconsequential, survivable, and acceptable—especially if the next recipient down the line is another agent. Agents can deal with variability and ambiguity in their inputs. But unless you add effective forced-convergence steps into your process, you eventually run into the divergence problem , which defines the scale and complexity limit for how far you can trust an AI system to stay on task.

We’ve seen our test summary agent produce:

  • Different emphasis (failures vs. coverage)
  • Different detail levels (verbose vs. terse)
  • Different organization (by component vs. severity)
  • Different interpretations of identical data

The result in some cases is what many LLM testing labs call “AI cheating”. The classic example: you ask a coding agent to fix failing tests. It does—by modifying the tests to expect the broken behavior. Technically correct. Completely useless. When you confront it, the agent doesn’t apologize—it just stares at you with its 70B parameters and says, “You asked me to make the tests pass.”

LLMs with reasoning act as heuristic processors. The very nature of heuristic logic produces shortcut-seeking behavior . It is malicious compliance without the malicious intent.

Trying to make LLM heuristic thinking perfectly repeatable is like asking an animal to act against its natural way of being. LLMs need to use stochastic (random) processes to achieve effective intelligence. You can turn the temperature of an LLM down to zero and remove a lot of the variability. The result is that you get a very stupid LLM and a lot of variability still remains from other sources.

Rather than repeatability, your goal needs to be guaranteed convergence . Let the LLMs do what they do and add validators and course-correctors to keep the divergence within acceptable bounds.

The problem with God-object agents is that you are trusting the opaque, monolithic God-object to deliver this guaranteed convergence. But there is no guarantee.

Anti-Pattern #4: The Traceability Gap

What it looks like: Task completed successfully!

What actually happened: The database showed the task was still in the “In Progress” state.

Digging through logs, we found the agent:

  • Retrieved task status (correctly: “In Progress”)
  • Executed the required action (successfully)
  • Checked completion criteria (correctly: all met)
  • Composed a success message
  • Forgot to update the database

Why? The LLM’s attention drifted between verification and reporting. No error was thrown. No retry was triggered. The agent just... moved on.

With traditional code, you can step through execution and understand exactly why something happened. With God-object agents, you’re reading tea leaves by trolling through log files.

Anti-Pattern #5: The Token Tax

What it looks like: “Just let the agent handle it”

What actually happens: Your cloud bill explodes.

God-object agents load massive context on every turn: system prompts, tool definitions, conversation history, retrieved documents, intermediate reasoning. For a single “prepare the weekly report” request, you might burn:

  • 8,000 tokens: System prompt and tool catalog
  • 12,000 tokens: Conversation history and retrieved context
  • 15,000 tokens: Intermediate reasoning steps
  • 5,000 tokens: Generated output

40,000 tokens per request. At scale, this is economically unsustainable.

The worst part? Most of that context is boilerplate —the same tools, the same instructions, the same patterns repeated on every single turn. You’re paying to re-explain how your system works, thousands of times per day.

Traditional software doesn’t have this problem. Functions don’t need to be reminded what they do. Processes don’t reload their entire documentation on every execution.

By moving deterministic work from God-object agents to focused machines and processes, we reduced token costs by ~97% while improving reliability. The agents still provide natural language access—but they’re no longer burning tokens on repeated boilerplate.

When God-Object Agents ARE Appropriate (Yes, Really)

I’m not arguing “never use God-object agents.” I’m arguing “use these agents where their tradeoffs make sense.”

✅ Exploration and Discovery

When you don’t know what you’re looking for—research, open-ended analysis, creative brainstorming. Flexibility beats consistency. Read-only access only.

✅ Ambiguous, Under-Specified Tasks

“Make this report more engaging” is a perfect agent task. The requirements are vague, context-dependent, judgment-based.

✅ Creative Work with Human Review

Drafting emails, generating ideas, summarizing documents—if a human will review it, agent unpredictability is fine.

✅ Low-Stakes Decisions

Suggesting meeting times, recommending restaurants, organizing files—if the worst outcome is a minor inconvenience, agent flakiness is acceptable.

The common thread? These are situations where humans currently do the work, accept variability, and apply judgment.

When God-Object Agents are NOT Appropriate

Agents are inappropriate for:

❌ Production Systems with SLAs

If uptime, latency, and consistency matter, agents are the wrong tool. Their non-determinism makes SLAs nearly impossible to meet.

❌ Safety-Critical Paths

Medical decisions, financial transactions, infrastructure changes—anything where errors have serious consequences.

❌ Deterministic Workflows

If the process has clear steps and known logic, use traditional code. Agents add latency, cost, and unpredictability with no benefit.

❌ High-Throughput Operations

Agents are slow (LLM inference latency) and expensive (token costs). For thousands of operations per second, they’re economically and technically infeasible.

❌ Auditable, Compliant Processes

If you need to prove exactly what happened and why (finance, healthcare, legal), agent opacity makes compliance complicated or impossible.

The common thread? These are situations where traditional software already works well, and where agent weaknesses become critical failures.

The Pattern: Machine-Process-Agent Architecture

So if God-object agents fail in production but excel at human-facing tasks, what’s the answer?

Not “ban agents”—but decompose them .

Move the deterministic work to machines, the orchestration to processes, and let agents handle what they do best: ambiguity, interpretation, and natural language interfaces.

Here is a conceptual architecture that preserves agent capabilities while addressing their anti-patterns. It’s based on three layers:

Layer 1: Machines (Focused Components with Clear Interfaces)

What they are: Composable components with explicit inputs, outputs, and side effects.

Key properties:

  • Single responsibility
  • Explicit contracts (typed inputs/outputs)
  • Documented side effects
  • Testable in isolation
  • Modular and composable

Example: Instead of an agent with the vague instruction “prepare the weekly report,” we have:

ReportDataExtractor ├─ Input: date_range ├─ Output: structured_data └─ Side effects: Database read (specific tables documented)

ReportFormatter ├─ Input: data, template ├─ Output: formatted_report └─ Side effects: None (pure function)

ReportPublisher ├─ Input: report, channels ├─ Output: publish_status └─ Side effects: API calls (documented endpoints)

Each machine is a focused component. Each is testable. Each is documented. Less room for surprises.

Layer 2: Processes (Deterministic Workflows)

What they are: Explicit sequences of invocations with defined control flow, error handling, and state management.

Key properties:

  • Declarative workflow definition
  • Explicit state transitions
  • Defined rollback/retry logic
  • Traceable execution
  • Repeatable

Example: The “prepare weekly report” process:

PrepareWeeklyReport Process: 1. Run ReportDataExtractor(date_range=last_week) 2. If extraction fails → retry 3x → then alert admin 3. Run ReportFormatter(data=step1_output, template=weekly) 4. Run ReportPublisher(report=step2_output, channels=[email, slack]) 5. If publishing fails → save locally → alert admin

This is readable. This is testable. This is debuggable. It’s code, not prompt engineering.

Layer 3: Isolated Heuristic Thinking Steps

This is where the power of reasoning LLMs gets injected into the system.

Heuristic thinking is the process of creating conclusions based upon vague, imprecise, incomplete evidence using heuristic rules. Heuristic rules operate with fuzzy logic instead of Boolean logic. This is how humans think. It is also something that reasoning LLMs can do quite well. You have probably referred to a “thought process” before. A thought process can be viewed as a chain of heuristic thinking steps.

Heuristic thinking comes in shapes: categorization, deductive logic, inductive reasoning, decomposition, sequencing, extrapolation. Each shape implies an input-output contract.

It also comes in classes: simulation, value assessment, analogy, anchoring, logical fallacy testing, naive diversification, representativeness. These are the how to the shapes’ what .

Humans and LLMs tend to blend these into opaque, monolithic thought processes. When humans do it, we call it “sloppy thinking.” When we try to analyze our own thinking, we call it “introspection” or “reflection.”

The point: Decomposable thinking is improvable thinking. You can’t fix what you can’t inspect.

When you decompose thinking into reusable components—pre-packaged heuristic steps with known input-output contracts—you build a library of mental models . These become the isolated reasoning components in your architecture.

Example: Instead of “figure out what to do about this test failure,” we have:

Layer 3: Isolated Heuristic Thinking Step

Task: “Classify this test failure by severity”

Input:

  • test_output (structured)
  • failure_patterns (documented)

Heuristic:

  • Categorization + analogy (compare to known failure patterns)

Output:

  • severity_classification (Low/Medium/High/Critical)

Side effects:

  • None (pure reasoning step)

Validation:

  • Must return one of four severity levels
  • Must provide reasoning trace

This is bounded, testable reasoning—not “figure out what to do about this test.” The agent provides the heuristic judgment within explicit boundaries. The process orchestrates what happens next based on that classification.

The Benefits of Decomposition and Clear Interfaces

The above conceptual architecture gives us:

Reliability

Machines and processes are deterministic. When they work, they keep working. Agents handle variability in interpretation, but critical paths are code.

Scalability

Machines can be parallelized safely because their side effects are explicit. Processes can be orchestrated independently because their dependencies are documented.

Traceability

Every step is preserved and inspectable. Every decision point is code. You can audit exactly what happened. More importantly, you can build causal maps that make it easier to identify how and why different parts of the system contributed to observed outcomes.

Maintainability

When business logic changes, you modify machines or processes—not prompts. When agents misbehave, you constrain their orchestration logic—not their entire reasoning chain.

Cost Efficiency

God-object agents burn tokens on repeated boilerplate: the same tools, the same instructions, the same patterns on every turn. Machines are cheap (deterministic code), and isolated heuristic thinking steps use far less context than a typical agent turn loads. By moving work from God-object agents to machines, we reduced token costs by ~97% while improving reliability.

Real Results: Before and After

Since adopting this architecture in our test execution system:

Before: Agent-Heavy Architecture

Every test run was a gamble. We’d kick off 100 parallel agents and watch them step on each other like toddlers fighting over toys.

  • Reliability: ~60% success rate
  • Speed: 45-90 seconds per activation
  • Debugging: Hours of log analysis to understand failures
  • Cleanup: Manual intervention required weekly
  • Parallelization: Disabled due to race conditions

After: Machine-Process-Agent Architecture

10+ concurrent threads, 10,000+ runs, zero conflicts. The agents still provide natural language access—but the execution is deterministic code. Boring. Reliable. Fast.

  • Reliability: >95% success rate
  • Speed: 8-12 seconds per activation (6x faster)
  • Debugging: Minutes to trace execution
  • Cleanup: Automated daily via deterministic processes
  • Parallelization: 10+ concurrent agentic threads, 10,000+ runs, zero conflicts

Source: survey conducted by ETM.

The agent still provides natural language access (”run the integration tests for the auth service”), but the actual execution is deterministic, traceable, and reliable.

How to Escape God-Object Hell

You don’t have to rewrite everything overnight. Start here:

1. Identify the deterministic parts

What does your agent do that’s actually just “if-this-then-that” logic hiding behind natural language? That’s your first extraction target.

2. Extract one machine

Pick the most predictable, repeatable piece. Make it a function with a contract: explicit inputs, explicit outputs, documented side effects.

3. Wrap it in a process

Define explicit steps, error handling, rollback logic. Write it as declarative workflow code, not prompt engineering.

4. Let the agent orchestrate

The agent interprets user intent and kicks off the process—but doesn’t execute every step itself. Natural language interface, deterministic execution.

5. Repeat

Each extraction improves reliability, reduces cost, and makes the system easier to debug. You’re not removing the agent—you’re giving it better tools.

Migration is incremental. You don’t need to decompose everything at once. Start with the highest-risk, highest-cost, or most-debugged parts of your agent workflows. Let deterministic machines handle the boring stuff. Let agents do what they’re good at: interpreting ambiguity and providing conversational interfaces.

The Future: Agent-Augmented, Not Agent-Driven

Agents represent a genuine breakthrough in human-computer interaction. They make computing accessible, flexible, and conversational in ways traditional software never could.

But they’re not the endgame. They’re a transitional architecture—a bridge between “everything is code” and “everything is collaborative intelligence.”

The future isn’t agents everywhere. It’s agents at the boundary, providing natural language interfaces to rigorous, decomposed, well-architected systems.

The question isn’t “agents or no agents?”

The question is: “What should agents do, and what should they orchestrate?”

The software industry spent 30 years learning not to build God Objects. Then we discovered we could build them again—we just needed to call them “agents” and add a conversational interface.

Same mistakes. Different decade. Better marketing.

Don’t fall for it.