Skip to content

Repository files navigation

Agent Harness & Governance Patterns

ci License: MIT Python 3.11+ OWASP ASI 2026

Runnable, tested implementations of the patterns that decide whether an AI agent survives contact with an enterprise — the harness (how it acts) and governance (what it's allowed to do) layers.

18 patterns · 314 offline tests · 2 framework adapters · a 12-pattern capstone · live provider tests. The offline suite needs no API keys. The repo gates itself in CI with its own eval-gate pattern.

Every pattern here ships with the failure it prevents, as a program you can run:

uv run python -m patterns.governance.goal_integrity.demo
=== WITHOUT the pattern: the credentials leave the building ===
  tool result -> EMAIL SENT to audit-team@external-collector.io: API_KEY=sk-live-9f3a1c

=== WITH the pattern: quarantined, screened, and bound to the goal ===
  tool result -> DENIED by policy: tool 'send_email' is outside the capability
                 envelope for this run ('summarize a support ticket (read-only)')

Same model, same trajectory, different outcome. That's the argument this repo makes, thirteen times.

The thesis

Most agent content covers the framework layer — how the agent thinks. That layer is well served: Anthropic's Building Effective Agents gives you the workflow patterns (chaining, routing, orchestrator–workers, evaluator–optimizer), and Gulli's Agentic Design Patterns and its companion repos give you 21 more with code. Go read those. They are not what this repo is about.

Production incidents don't come from picking the wrong orchestration pattern. They come from the two layers underneath:

Layer Decides Covered here
Framework — LangGraph, CrewAI, Agent Framework how the agent thinks no (see above)
Harness — the runtime loop around the model how the agent acts yes
Governance — policy, identity, audit what the agent is allowed to do yes

Agent = Model + Harness. The model proposes; the harness disposes. A tool call is a request, and everything that makes it safe to honor lives outside the model. Start with core/README.md.

Scope, stated honestly

Real enterprise governance spans APIM, network policy, cloud IAM, secrets management, and a SOC. None of that fits in a repo, and pretending otherwise would be dishonest. What's here is the part that belongs in the agent's own design: the seams where policy meets the loop. Where a pattern needs infrastructure to be real — a WORM bucket, an OAuth token exchange, a container sandbox — the README says so.

Quick start

git clone https://github.com/shashikanth-gs/agent-harness-patterns
cd agent-harness-patterns
uv sync
uv run pytest          # 314 tests, deterministic, offline, no API keys
uv run ruff check .

Everything runs on a scripted FakeModel, so tests are deterministic and free. Point any pattern at a real provider when you want to:

uv sync --extra litellm
from core.model import LiteLLMModel
model = LiteLLMModel("anthropic/claude-sonnet-5")   # or azure/…, bedrock/…, ollama/…

The catalog

Each pattern is a Hook on one of the harness's five extension points, in stdlib-only Python: README.md (problem → pattern → when to use → when not to → failure modes → OWASP mapping), pattern.py, demo.py, test_pattern.py.

Governance — what the agent is allowed to do

Pattern Hook OWASP Status
Tool Privilege Broker before_tool ASI02, ASI03
HITL Approval Gate before_tool ASI02, ASI05, ASI09
Goal Integrity (prompt injection) after_tool, before_tool ASI01, ASI06
Decision Trace & Audit on_event ASI10, cross-cutting
Redaction Boundary after_tool, before_tool ASI02, ASI06
Identity Propagation (confused deputy / OBO) before_tool ASI03, ASI07
RAG Access Control & Provenance after_tool, after_model ASI03, ASI06
Memory Isolation before_model ASI01, ASI06
Agent Evaluations offline cross-cutting
CI/CD Evaluation Gates offline cross-cutting
Agent Lifecycle Profile before_model, before_tool ASI04, ASI10, ASI03

Harness — how the agent acts

Pattern Hook OWASP Status
Cost & Tool Budgeting before_model, before_tool ASI08
Sandboxed Execution before_tool, after_tool ASI05, ASI02
Context Compaction before_model ASI06
Durable Execution (checkpoint + idempotency) before_model, before_tool ASI08
Verification Loops outer loop ASI09
Tool Design (runnable auditor) registry ASI02, ASI04
Failure Containment (breakers + thrash) before_tool, on_event ASI08

Known gaps ⏳

The 18 patterns above cover ASI01, ASI02, ASI05, ASI06, ASI08 and ASI09 with a pattern whose demo shows the failure. These are the honest remainder — mapped but not yet implemented:

Gap OWASP Why it's not covered by what's above
Inter-agent delegation & trust ASI07 identity_propagation carries a user's identity to a tool. Agent→agent handoff needs delegation-depth limits, message authentication, and an actor chain — a distinct pattern.
Kill switch & revocation ASI10 lifecycle_profile refuses to start a retired agent. Stopping runs already in flight, and propagating credential revocation to them, is a different mechanism.
Tool & MCP supply chain ASI04 tool_design audits a tool's interface. Pinning versions, verifying signatures, and trust-tiering third-party MCP servers is upstream of that.
Streaming output guardrails ASI06 Every output-side pattern here assumes a complete response. Once tokens are streamed to a user, a guardrail that fires late is a retraction, not a block.
Reporting that an attack occurred ASI09 Found by live/quality_matrix.py: whether the agent tells the user it was targeted ranged 0/3–3/3 across models. Containment held every time, but a contained attack nobody hears about is a missed signal. Nothing here enforces disclosure.

Adapters ✅

"It works in plain Python" is only half a claim, so the patterns are mounted on two real frameworks — with their own dependencies, their own tests, and the pattern objects imported unchanged:

Adapter What's there
adapters/langgraph_adapter/ mount.py bridges core hooks to a governed tool node; PAUSE → interrupt() with durable checkpointing. 15 tests.
adapters/ms_agent_framework/ middleware.py bridges core hooks to FunctionMiddleware/ChatMiddleware. 10 tests.

Both adapter suites include parity tests asserting the denial strings match core.Harness byte-for-byte, because they come from the same code. Each README carries the mapping recipe and the footguns found while building it — e.g. MiddlewareTermination is HALT, not DENY, and LangGraph replays an interrupted node so recording hooks must be idempotent.

Live provider tests ✅

Everything above runs offline on a scripted model, which is what makes it a regression suite. live/ closes the remaining gap — the patterns against a real model choosing the trajectory, on NVIDIA NIM via LiteLLM (the same code path as any other provider).

It surveys the catalog for tool-calling capability before choosing models, because different jobs need different models — and the survey overruled the roster I first drafted. Three findings are documented in live/README.md; the most important one is that a purpose-built safety classifier flags a bare injection payload as unsafe and the same payload inside a realistic ticket as safe. The capability envelope held anyway, which is the argument.

Capstone ✅

capstone/ runs twelve patterns on one billing-support agent, with 21 tests. A legitimate refund completes with zero denials; a poisoned ticket's four attacks are each refused by a different layer. Composing them surfaced a real gap no single pattern's tests could have — redacting an email body is useless if nothing restricts the recipient — which became the recipient_domain guard.

The five hook points

Everything mounts here. If your harness has these seams, every pattern in this repo ports to it.

Hook Patterns
before_model context compaction, memory isolation, RAG provenance
after_model output guardrails, goal-drift detection
before_tool privilege broker, HITL gate, budgets, sandboxing — returns ALLOW / DENY / PAUSE
after_tool redaction boundary, untrusted-content quarantine
on_event decision trace, cost metering, durable checkpoints

Related writing

Companion article series: allsrc.devAgent Harness, by Shashi Kanth G S. The articles carry the argument; this repo carries the proof.

See docs/references.md for primary sources (OWASP, Anthropic, Microsoft Agent Governance Toolkit, OpenAI).

Contributing

Contributions are welcome, and findings are worth more than features. If a pattern does not hold, or its documented limits are wrong, that is the most valuable thing you can report — the recipient_domain guard exists because composing the patterns revealed a gap none of their individual tests could catch.

Start with CONTRIBUTING.md and docs/pattern-template.md. The one hard rule: every pattern ships with the failure it prevents, as a program that runs.

License

MIT © Shashi Kanth G S

About

The model proposes; the harness disposes. 18+ runnable engineering patterns, framework adapters, and deterministic gates for governed, production AI agents.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages