Skip to content
allsrc.dev
Go back

The Two Layers That Decide Whether Your Agent Survives

I have read a lot of agent architecture content over the last two years, and almost all of it is about the same layer: how the agent thinks. Prompt chaining, routing, orchestrator-workers, evaluator-optimizer, ReAct, plan-and- execute. That layer is genuinely well served, and I am not going to add to it.

Here is the uncomfortable thing I keep running into instead. The incidents I have seen and reviewed did not come from picking the wrong orchestration pattern. They came from an agent that was allowed to do something nobody had decided it could do.

A support agent with read access to the orders database escalating from SELECT to DELETE, because a customer wrote “I was double-charged, sort it out.” A contractor asking a policy chatbot about executive severance and getting a correct, well-cited answer from a document they were never permitted to see. An accounts-payable agent paying a $4,200 invoice, getting killed mid-run by a pod eviction, and paying it again on the retry.

None of those is a reasoning failure. In every case the model did something defensible. They are architecture failures, and they all live in the two layers underneath the framework.

TL;DR

An AI agent has three layers, and most content covers only the first:

LayerDecidesExamplesWell covered?
Frameworkhow the agent thinksLangGraph, CrewAI, Agent FrameworkYes — go read Anthropic and Gulli
Harnesshow the agent actsthe loop, budgets, sandboxing, compaction, retriesBarely
Governancewhat the agent is allowed to dopolicy, identity, approval, audit, redactionBarely, and usually as vendor marketing

Agent = Model + Harness. The model proposes; the harness disposes. A tool call is a request, not an action, and everything that makes it safe to honour lives outside the model. This series is 18 patterns for those two layers, each one backed by code that runs, with the failure it prevents included as a program you can execute.

The code is at github.com/shashikanth-gs/agent-harness-patterns — 314 tests, runs offline with no API keys.

The framework layer is not the problem

I want to be specific about what I am not claiming, because “frameworks don’t matter” is the kind of statement that gets quoted without its qualifier.

The framework layer is well covered, and you should read that work. Anthropic’s Building Effective Agents is the best short treatment of the workflow patterns — prompt chaining, routing, parallelisation, orchestrator-workers, evaluator-optimizer — and its central advice (“use the simplest thing that works, add agentic behaviour only when it pays”) is correct and widely ignored. Antonio Gulli’s Agentic Design Patterns catalogues 21 patterns with runnable code across LangChain, CrewAI, and Google ADK. Between them, that layer has a canon.

What I am claiming is narrower and, I think, harder to argue with: your choice between LangGraph and CrewAI will not determine whether you have an incident. Your answer to “who decided this agent could issue refunds, and what stops it issuing one it shouldn’t?” will.

I tested this claim rather than asserting it. Every pattern in this series is written as a plain-Python hook, then mounted — unchanged — on both LangGraph and Microsoft Agent Framework, with tests asserting the denial messages come out byte-for-byte identical because they come from the same code. That is in the adapters article. The patterns port. The framework is plumbing.

What a harness actually is

The LLM is a reasoning engine. It reads text and produces text, including text that says “call issue_refund with these arguments.” It cannot execute anything. Everything between that proposal and a refund actually reaching a customer’s card is the harness:

 user goal ──▶ ┌────────────────────── HARNESS ──────────────────────┐
               │                                                     │
               │   before_model ─▶ ┌───────┐ ─▶ after_model          │
               │                   │ MODEL │                         │
               │                   └───────┘                         │
               │                       │ tool call (a request!)      │
               │                       ▼                             │
               │   before_tool ──▶ allow / deny / pause              │
               │                       │                             │
               │                       ▼                             │
               │   execute ──▶ after_tool ──▶ result back to model   │
               │                                                     │
               │   on_event ◀── every step, narrated                 │
               └─────────────────────────────────────────────────────┘

Those five seams are the whole architecture. Every pattern in this series mounts on one or two of them:

SeamWhat mounts there
before_modelcontext compaction, memory injection, budget checks
after_modeloutput guardrails, citation verification
before_toolprivilege broker, approval gate, identity, budgets, sandboxing — returns ALLOW / DENY / PAUSE
after_toolredaction, untrusted-content quarantine
on_eventaudit trail, cost metering, circuit breakers

And these are not my invention. They are what production frameworks already expose under different names: Microsoft Agent Framework calls them middleware, LangGraph exposes node wrappers and interrupt, Claude Code calls them hooks. If your harness has these seams, every pattern here ports to it. If it doesn’t, that is the finding.

Five design rules that do most of the work

These come out of building all 18 patterns, and they matter more than any individual pattern:

  1. A tool call is a request, not an action. The model never executes anything. If your framework’s tool decorator calls the function directly, you do not have a governance boundary — you have a hope.

  2. Fail closed. An unregistered tool, a missing policy, an unknown token, an exhausted budget: all resolve to denial. Registration is not authorization.

  3. Denials must be visible to the model. A denied call returns DENIED by policy: <reason> as a tool result, so the agent re-plans — escalates to a human, tries a permitted route, or reports honestly. A silent refusal produces an agent that stalls or hallucinates success.

  4. Policy in code, never in the prompt. “You must never modify customer data” in a system prompt is advisory. Models under pressure ignore it, and models under prompt injection are instructed to ignore it. A deterministic check cannot be argued with.

  5. Most restrictive wins, and order is about cost, not safety. When several controls disagree, DENY beats PAUSE beats ALLOW regardless of ordering. Order determines how much you spend before refusing and how good the error message is. Getting the order wrong should cost you a worse message, not a breach.

The 18 patterns

Governance — what the agent is allowed to do

PatternPreventsOWASP
Identity PropagationThe confused deputy: one service account with everyone’s permissionsASI03, ASI07
Tool Privilege BrokerAn authorized tool used in an unauthorized wayASI02, ASI03
Goal IntegrityIndirect prompt injection rewriting the agent’s objectiveASI01, ASI06
HITL Approval GateIrreversible actions taken without judgmentASI02, ASI05, ASI09
Redaction BoundarySensitive data crossing the wrong boundaryASI02, ASI06
RAG Access ControlRetrieval that ignores who is askingASI03, ASI06
Memory IsolationAn injection that persists into tomorrow’s sessionASI01, ASI06
Decision Trace & AuditBeing unable to answer “what did it do, and on whose authority?”ASI10
Agent EvaluationsScoring the answer instead of the trajectorycross-cutting
CI/CD Evaluation GatesShipping a config change that removes a controlcross-cutting
Agent Lifecycle ProfileAgents accumulating with no owner and no expiryASI04, ASI10

Harness — how the agent acts

PatternPreventsOWASP
Cost & Tool BudgetingThe runaway loop you find out about from the invoiceASI08
Failure ContainmentAn agent hammering a dead dependency, or retrying its own bad planASI08
Sandboxed ExecutionAgent-written code reaching outside its workspaceASI05, ASI02
Context CompactionContext rot: forgetting the goal, the constraint, and the denialASI06
Durable ExecutionA retry that pays the invoice twiceASI08
Verification LoopsBelieving the agent when it says “done”ASI09
Tool DesignTools that make the agent guess, retry, and overspendASI02, ASI04

Then the capstone: all of them on one agent, and the gap that composing them revealed.

Scope, stated honestly

Real enterprise governance spans API management, network policy, cloud IAM, secrets management, and a security operations centre. None of that fits in a repository, and I am not going to pretend otherwise. If someone sells you “complete AI governance” as a library, they are selling you a subset with confident branding.

What this series covers is the part that belongs in the agent’s own design — the seams where policy meets the loop, the decisions you make in code review rather than in Terraform. Where a pattern needs infrastructure to be real, I say so: the sandboxing article is explicit that a Python function is not isolation and a container is, and the audit article is explicit that tamper-evidence only becomes proof when the chain head is published somewhere the agent cannot reach.

That boundary is the most useful thing I can offer. Most agent governance content is vague about it, which is how teams end up believing a regex is a sandbox.

Frequently asked questions

Is the “agent harness” a real term or industry jargon?

It has become standard over the past year. Databricks, Fiddler AI, and Firecrawl all published on agent harnesses in 2026, and Microsoft’s Agent Framework and Agent Governance Toolkit implement the concept under the names “middleware” and “Agent OS.” The underlying idea — that the runtime around the model is a distinct architectural layer with its own concerns — is older than the label.

Do I need all 18 patterns?

No, and adopting all of them on a low-stakes agent would be a mistake. Every article has a “when NOT to use it” section that is as long as the “when to use” section, because the honest answer for a read-only documentation bot is “you need about two of these.” Start with identity propagation and the privilege broker if your agent touches a system of record; start with cost budgeting if it has an unbounded loop.

Does this replace my framework?

No. The reference harness in the repository exists so the patterns can be read and tested in isolation — about 150 lines. In production you mount the same patterns on whatever framework you already run, which is what the adapters demonstrate on LangGraph and Microsoft Agent Framework.

Why OWASP ASI identifiers rather than general security language?

Because “ASI01” is checkable and “follows security best practices” is not. The OWASP Top 10 for Agentic Applications 2026 went through peer review with more than a hundred practitioners, and citing it by ID means a reader can verify whether my claim about a risk matches the standard’s. That is a habit worth adopting generally: prefer claims someone can check.

References


Next in this series: the confused deputy — the most common architectural flaw in enterprise agent deployments, and the one that looks like good engineering the entire time you are building it.



Next Post
The Confused Deputy Is In Your Agent Right Now