<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Amar Tinawi</title>
    <description>The latest articles on DEV Community by Amar Tinawi (@amartinawi).</description>
    <link>https://dev.to/amartinawi</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3835350%2F9a38aad8-4304-49b0-8ded-8b6c774cabf6.jpg</url>
      <title>DEV Community: Amar Tinawi</title>
      <link>https://dev.to/amartinawi</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/amartinawi"/>
    <language>en</language>
    <item>
      <title>ZOdyssey: making the plan-review gate a hard hook, not a prompt convention</title>
      <dc:creator>Amar Tinawi</dc:creator>
      <pubDate>Mon, 10 Aug 2026 12:57:01 +0000</pubDate>
      <link>https://dev.to/amartinawi/zodyssey-making-the-plan-review-gate-a-hard-hook-not-a-prompt-convention-3g9c</link>
      <guid>https://dev.to/amartinawi/zodyssey-making-the-plan-review-gate-a-hard-hook-not-a-prompt-convention-3g9c</guid>
      <description>&lt;h1&gt;
  
  
  ZOdyssey: making the plan-review gate a hard hook, not a prompt convention
&lt;/h1&gt;

&lt;p&gt;What if the "review the plan before executing" step in your agent pipeline was a hard gate, not a suggestion?&lt;/p&gt;

&lt;p&gt;That is the question I kept coming back to after another session of watching an agent do the thing. You know the thing. The plan looked fine. The review step was in the prompt. The model nodded, said "looks good," and then immediately started editing files before anyone had actually approved anything — because nothing was actually stopping it. The review was a convention. Conventions are suggestions. Suggestions are not physics.&lt;/p&gt;

&lt;p&gt;This post is about a small open-source project I just shipped called &lt;a href="https://github.com/amartinawi/zodyssey" rel="noopener noreferrer"&gt;&lt;strong&gt;ZOdyssey&lt;/strong&gt;&lt;/a&gt;. It is a multi-agent orchestration pipeline whose one architectural commitment is that the load-bearing invariants are enforced with code, not with prompts. I want to tell you why I built it, how it works, and — because I have read too many launch posts that hand-wave the limitations — exactly what it is not.&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem, in four failure modes
&lt;/h2&gt;

&lt;p&gt;If you have spent any real time driving coding agents on non-trivial tasks, you have hit all four of these. They are not exotic. They are the boring, recurring ways agent runs go sideways:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;The model edits code before the plan is reviewed.&lt;/strong&gt; You wrote "consult, then plan, then review, then execute" into the prompt. The model agreed to the order. Then a sub-task got exciting and an edit landed before the review step had actually returned a verdict. The plan was a draft; the code is now real.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The model over-engineers.&lt;/strong&gt; You asked for a one-line fix. You got 50 spawned subagents, three refactors, a new abstraction, and a changelog. Parallelism is a superpower until it is a tax.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The model drifts off-scope.&lt;/strong&gt; The plan said "edit &lt;code&gt;auth.ts&lt;/code&gt;." The executor helpfully also touched &lt;code&gt;session.ts&lt;/code&gt;, &lt;code&gt;middleware.ts&lt;/code&gt;, and the README, because they were "related." Now your diff review is the scope review, after the fact.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A crashed run starts over from scratch.&lt;/strong&gt; The agent got 40 minutes into a six-todo plan, hit a transient failure, and there is no checkpoint. You re-run. It re-plans. It re-edits. State is gone.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;All four of these are deterministic. They are not about model intelligence. They are about invariants — properties of the run that should hold regardless of how clever or compliant the model feels today. And the dirty secret of most orchestrators (including ones I admire) is that they enforce these invariants the same way: by putting a sentence in the system prompt and hoping.&lt;/p&gt;

&lt;p&gt;Prompts catch these failures &lt;em&gt;most of the time&lt;/em&gt;. The model is usually cooperative. "Most of the time" is a rough profile when the failure is "unreviewed code landed in main."&lt;/p&gt;

&lt;h2&gt;
  
  
  The aha
&lt;/h2&gt;

&lt;p&gt;The shift is embarrassingly small once you see it: &lt;strong&gt;enforce the gate with a &lt;code&gt;PreToolUse&lt;/code&gt; hook, not a prompt convention.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A hook is not advice. It is a function that runs before a tool call is allowed to proceed, and it can return &lt;code&gt;block&lt;/code&gt;. The model cannot argue with it, cannot "decide" to skip it, cannot get clever and route around it between tool calls in a single turn. If the hook says "no edit until &lt;code&gt;state.review.verdict === "OKAY"&lt;/code&gt;," then no edit happens until that field is set. The model can write a brilliant argument for why it should be allowed to edit early. The hook does not read arguments. It reads state.&lt;/p&gt;

&lt;p&gt;That is the entire delta. The pipeline shape — prime, triage, consult, plan, review, execute, verify, final wave — is the same shape &lt;a href="https://github.com/code-yeongyu/oh-my-openagent" rel="noopener noreferrer"&gt;omo&lt;/a&gt; and others already use, and ZOdyssey is openly built on that lineage. The cast of sub-agents (a consult agent, a planner, a reviewer, executors) is borrowed too. What ZOdyssey adds is the enforcement layer: the four invariants below are checked in code, on every relevant tool call, for the entire duration of a run.&lt;/p&gt;

&lt;p&gt;The framing I keep coming back to is this: &lt;strong&gt;prompts guide choices; code enforces invariants.&lt;/strong&gt; Use prompts for the stuff that is genuinely a judgment call (which skill to reach for, how to phrase the plan, when to ask the user). Use hooks for the stuff that must never be a judgment call (did the plan pass review, is this file in scope, are we over the parallel cap).&lt;/p&gt;

&lt;h2&gt;
  
  
  How it works
&lt;/h2&gt;

&lt;p&gt;ZOdyssey runs an eight-phase state machine. The conductor (your main agent) drives it; sub-agents do the work; the hooks guard the invariants. Every phase transition checkpoints to a &lt;code&gt;state.json&lt;/code&gt; file so a crashed run resumes instead of restarting.&lt;/p&gt;

&lt;h3&gt;
  
  
  The pipeline
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Phase&lt;/th&gt;
&lt;th&gt;Name&lt;/th&gt;
&lt;th&gt;One-line job&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;−1&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;PRIME&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;A &lt;code&gt;prompt-master&lt;/code&gt; pass refines your raw task into a sharp brief: intent, success criteria, surfaced constraints, ambiguities (ask up to 3, then commit), and a rewritten prompt that &lt;em&gt;replaces&lt;/em&gt; the original. Runs first, before triage.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;TRIAGE&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;The conductor does this directly. Trivial task → just answer and stop. Standard → single-track. Architecture-changing → full pipeline.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;CONSULT&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;A &lt;code&gt;metis&lt;/code&gt; agent reads prior learnings from a memory store, then returns intent classification, risks, questions, and directives. If it has user-facing questions, it surfaces them and waits.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;PLAN&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;A &lt;code&gt;prometheus&lt;/code&gt; agent writes the plan to &lt;code&gt;&amp;lt;repo&amp;gt;/.zcode/plans/&amp;lt;slug&amp;gt;.md&lt;/code&gt;, one todo per block, each with &lt;code&gt;Files:&lt;/code&gt;, &lt;code&gt;References:&lt;/code&gt;, and executable acceptance criteria. It cannot edit product code — the hook blocks it.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;REVIEW&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;A &lt;code&gt;momus&lt;/code&gt; agent returns &lt;code&gt;OKAY&lt;/code&gt; or &lt;code&gt;REJECT&lt;/code&gt; with up to three blockers. &lt;strong&gt;This is the enforced gate.&lt;/strong&gt; REJECT below the round cap (3) → re-plan and re-review. At the cap → stop and surface to the user. No unbounded loop.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;EXECUTE&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;The conductor dispatches a &lt;code&gt;sisyphus-junior&lt;/code&gt; per todo, parallel-by-default, scope-locked to that todo's declared &lt;code&gt;Files:&lt;/code&gt;. On each return: tick the checkbox, write a checkpoint, update state.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;VERIFY&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;The conductor runs each todo's acceptance commands itself. On failure, it re-dispatches with the error output attached.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;FINAL WAVE&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Independent passes against the full diff: F1 plan-compliance, F2 code-quality, F3 manual-QA, F4 scope-fidelity. All four must pass before the run is "done."&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  The four enforced invariants
&lt;/h3&gt;

&lt;p&gt;These are the delta. They are all implemented as &lt;code&gt;PreToolUse&lt;/code&gt; hooks in &lt;code&gt;~/.zcode/cli/config.json&lt;/code&gt;, and they are all &lt;strong&gt;no-ops unless an orchestration run is active&lt;/strong&gt; — normal editing in your repo is never affected.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Review gate (the big one).&lt;/strong&gt; Every edit-class tool call is intercepted. Is a run active? Is this path bookkeeping (&lt;code&gt;.zcode/&lt;/code&gt;)? Has review returned &lt;code&gt;OKAY&lt;/code&gt;? If not, block: &lt;em&gt;"edits blocked until plan passes review."&lt;/em&gt; There is no override flag the model can set.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scope-isolation boundary.&lt;/strong&gt; The target file must be in the union of &lt;code&gt;Files:&lt;/code&gt; declared in the plan. It &lt;strong&gt;fails closed&lt;/strong&gt; if the plan is unreadable or empty — which is the fix for the real-world scope-creep failure where an executor widens its own scope by editing the plan after review. (The hook re-hashes the plan against the sha bound to the OKAY verdict, so post-review tampering does not silently widen scope.)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;File-lock ledger.&lt;/strong&gt; A per-file lock map. If another in-flight todo holds the lock for a path, the second edit blocks. Locks release when the todo is marked done (or get reaped by TTL). This is what makes parallel execution safe without the orchestrator having to reason about it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Parallel cap.&lt;/strong&gt; The dispatch tool (&lt;code&gt;Task&lt;/code&gt;/&lt;code&gt;Agent&lt;/code&gt;) is gated. The hook counts in-flight dispatches and blocks at the cap — default four. The model cannot bump state between tool calls in one turn, so the hook owns this counter; the orchestrator literally cannot over-spawn past the cap even if it tries.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;There is a fifth, optional hook — a Bash write-gate that treats write-capable shell invocations (&lt;code&gt;sed -i&lt;/code&gt;, redirects, &lt;code&gt;git apply&lt;/code&gt;, …) the same way as direct edits. It is on by default and can be disabled with &lt;code&gt;ZODYSSEY_UNGATE_BASH=1&lt;/code&gt; when you want lower friction. The four above are the core delta.&lt;/p&gt;

&lt;h3&gt;
  
  
  The cast, and why the conductor matters
&lt;/h3&gt;

&lt;p&gt;The sub-agents are narrow on purpose. &lt;code&gt;metis&lt;/code&gt; consults. &lt;code&gt;prometheus&lt;/code&gt; plans (and is one of only two agents that can write anything). &lt;code&gt;momus&lt;/code&gt; reviews. &lt;code&gt;sisyphus-junior&lt;/code&gt; executes — the only other writer. &lt;code&gt;explore&lt;/code&gt;, &lt;code&gt;librarian&lt;/code&gt;, and &lt;code&gt;oracle&lt;/code&gt; are read-only research and advice. Each does one thing, returns a structured verdict, and gets out of the way.&lt;/p&gt;

&lt;p&gt;The interesting part is not the cast, though — it is the &lt;strong&gt;capability routing&lt;/strong&gt;. The orchestrator is the thing that &lt;em&gt;knows&lt;/em&gt; to reach for the right tool before doing the activity the generic way. Logic implementation gets routed to a test-driven-development skill (non-negotiable for code todos). Hard multi-step reasoning gets sequential thinking. Codebase questions get &lt;code&gt;codegraph_explore&lt;/code&gt; if there is a &lt;code&gt;.codegraph/&lt;/code&gt; index, else a dispatched explore agent. Library questions get Context7 plus a librarian. After two failed debugging attempts, the orchestrator asks an oracle for a fresh diagnosis instead of flailing. The point is that the conductor tells every dispatched agent &lt;em&gt;which&lt;/em&gt; capability to use, rather than assuming a fresh sub-agent will reach for the right one on its own.&lt;/p&gt;

&lt;h3&gt;
  
  
  Two more things worth knowing
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Checkpoint and resume.&lt;/strong&gt; Every phase transition and every completed todo writes a checkpoint. &lt;code&gt;/orchestrate resume &amp;lt;slug&amp;gt;&lt;/code&gt; reads the last checkpoint and picks up there, not from scratch. Durable execution was a hard requirement — a six-todo plan that dies on todo four should not cost you the first three.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;An optional independent audit.&lt;/strong&gt; After a run reaches &lt;code&gt;done&lt;/code&gt;, &lt;code&gt;/orchestrate-consult &amp;lt;slug&amp;gt;&lt;/code&gt; hands the plan plus the full git diff to a &lt;em&gt;separate&lt;/em&gt; CLI process — fresh context, independent model — for an ACCEPT/REJECT audit. Because that auditor cannot inherit the run's assumptions, it catches things in-session reviewers miss. On REJECT, ZOdyssey re-arms the gates and loops until ACCEPT. (Honest caveat: the remediation loop runs after a terminal phase, so the gates are only re-armed because ZOdyssey explicitly flips state back to a remediate phase — the doc-vs-code gap here is itself a tracked item, and I would rather tell you that than pretend the cap is magic.)&lt;/p&gt;

&lt;h2&gt;
  
  
  Quick start
&lt;/h2&gt;

&lt;p&gt;The reference implementation targets &lt;a href="https://z.ai" rel="noopener noreferrer"&gt;ZCode&lt;/a&gt;. If you are on ZCode, this is the whole install — zero npm dependencies, all scripts are ESM &lt;code&gt;.mjs&lt;/code&gt; using only Node built-ins:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/amartinawi/zodyssey.git
&lt;span class="nb"&gt;cd &lt;/span&gt;zodyssey
node scripts/install.mjs            &lt;span class="c"&gt;# copies into ~/.zcode/, registers hooks + MCPs&lt;/span&gt;
node scripts/install.mjs &lt;span class="nt"&gt;--verify&lt;/span&gt;   &lt;span class="c"&gt;# health-check: hooks parse, MCP backends resolvable&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then start a new session and, in any repo, run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;/orchestrate &amp;lt;your task&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is it. The installer also registers the pipeline MCPs (memory, sequential-thinking, codegraph, chrome-devtools, the model server) — each gated on its backend being on PATH, skipped with a hint if not. Full install, troubleshooting, and config live in &lt;a href="https://github.com/amartinawi/zodyssey/blob/main/docs/INSTALL.md" rel="noopener noreferrer"&gt;&lt;code&gt;docs/INSTALL.md&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Not on ZCode?&lt;/strong&gt; The pattern is portable. Read &lt;a href="https://github.com/amartinawi/zodyssey/blob/main/docs/ADAPT.md" rel="noopener noreferrer"&gt;&lt;code&gt;docs/ADAPT.md&lt;/code&gt;&lt;/a&gt; — it is a concrete guide to bolting the four enforcement hooks onto omo, Claude Code, Cursor, or any harness that can run a &lt;code&gt;PreToolUse&lt;/code&gt; hook. If you are already an omo user, start there: omo gives you the full pipeline and ergonomics, and you layer on the four hooks. That is the highest-leverage path for most people.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it is NOT
&lt;/h2&gt;

&lt;p&gt;I want this section to read as engineering integrity, not as an apology. The honest scope of v1 is narrower than the architecture implies, and you should know that before you install it.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;It is not a replacement for normal agent operation.&lt;/strong&gt; ZOdyssey is an &lt;em&gt;opt-in&lt;/em&gt; mode you enter with &lt;code&gt;/orchestrate&lt;/code&gt;. Everything else — quick questions, one-shot edits, the 95% of interactions that do not need a pipeline — is handled directly, the way you already work. The hooks are no-ops unless a run is active.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It is not multi-model in v1.&lt;/strong&gt; There is a &lt;code&gt;category&lt;/code&gt; routing field designed into the state machine (see &lt;a href="https://github.com/amartinawi/zodyssey/blob/main/docs/DESIGN.md" rel="noopener noreferrer"&gt;&lt;code&gt;docs/DESIGN.md&lt;/code&gt;&lt;/a&gt;), but in v1 routing reduces to effort and variant selection within one connected model. Wiring a second provider is on the roadmap, not in the binary.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It is not harness-agnostic in v1.&lt;/strong&gt; The reference implementation targets ZCode; that is where the hooks, commands, and sub-agents are native. The &lt;em&gt;pattern&lt;/em&gt; is portable — that is what &lt;code&gt;docs/ADAPT.md&lt;/code&gt; is for — but I am not going to claim it drops into Claude Code or Cursor unchanged, because it does not.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It is not a team-mode orchestrator yet.&lt;/strong&gt; Parallel multi-executor with mailboxes and git worktrees is designed but deferred to v2. v1 is single-executor-per-todo, dispatched in parallel waves under the cap. If you wanted multiple human collaborators in one run, that is not this version.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If any of those four are disqualifying for your use case, that is a perfectly good reason not to use it yet. I would rather you know now than find out mid-run.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is next
&lt;/h2&gt;

&lt;p&gt;The roadmap is the parts of the architecture that are &lt;em&gt;designed for, not yet wired&lt;/em&gt;: multi-model routing (the &lt;code&gt;category&lt;/code&gt; field becomes a real provider switch), team mode (parallel executors across mailboxes and worktrees), and broader harness support so the ADAPT path gets shorter. The enforcement pattern itself is stable — the four hooks are the load-bearing idea, and they are done. What changes next is what runs &lt;em&gt;inside&lt;/em&gt; the gate, not the gate.&lt;/p&gt;

&lt;h2&gt;
  
  
  Provenance
&lt;/h2&gt;

&lt;p&gt;ZOdyssey is a synthesis, not an invention, and I want the lineage visible because it is the honest framing. The pipeline shape and the sub-agent cast are modeled on &lt;a href="https://github.com/code-yeongyu/oh-my-openagent" rel="noopener noreferrer"&gt;&lt;strong&gt;omo&lt;/strong&gt;&lt;/a&gt; — if you are not familiar, go read it; it is the cleaner expression of the orchestration pattern. The enforcement layer (the four hooks) is the differentiator, not a derivative. The thinking on multi-agent systems is grounded in &lt;a href="https://www.anthropic.com/engineering/multi-agent-research-system" rel="noopener noreferrer"&gt;Anthropic's multi-agent research post&lt;/a&gt; and the &lt;a href="https://www.anthropic.com/engineering/building-effective-agents" rel="noopener noreferrer"&gt;Building Effective Agents&lt;/a&gt; essay, with additional citations to LangChain's multi-agent architecture analysis and an arXiv context-engineering paper in &lt;a href="https://github.com/amartinawi/zodyssey/blob/main/docs/DESIGN.md" rel="noopener noreferrer"&gt;&lt;code&gt;docs/DESIGN.md&lt;/code&gt;&lt;/a&gt;. The routed skills (TDD, systematic debugging, brainstorming) come from &lt;a href="https://github.com/obra/superpowers" rel="noopener noreferrer"&gt;obra/superpowers&lt;/a&gt;; the impact-analysis step uses &lt;a href="https://github.com/colbymchenry/codegraph" rel="noopener noreferrer"&gt;codegraph&lt;/a&gt;. Full citations are in DESIGN.md §0 and §15.&lt;/p&gt;

&lt;p&gt;It is MIT licensed. Take it, adapt it, use it. If the enforcement-gate pattern makes your orchestrator more reliable, that is the whole point.&lt;/p&gt;

&lt;p&gt;The repo is &lt;a href="https://github.com/amartinawi/zodyssey" rel="noopener noreferrer"&gt;github.com/amartinawi/zodyssey&lt;/a&gt;. The two things to read first are &lt;a href="https://github.com/amartinawi/zodyssey/blob/main/docs/DESIGN.md" rel="noopener noreferrer"&gt;&lt;code&gt;docs/DESIGN.md&lt;/code&gt;&lt;/a&gt; (the principle, load-bearing decisions, and research) and &lt;a href="https://github.com/amartinawi/zodyssey/blob/main/docs/ADAPT.md" rel="noopener noreferrer"&gt;&lt;code&gt;docs/ADAPT.md&lt;/code&gt;&lt;/a&gt; (how to bolt the delta onto whatever you are already running).&lt;/p&gt;

</description>
      <category>ai</category>
      <category>automation</category>
      <category>opensource</category>
      <category>devtools</category>
    </item>
    <item>
      <title>Multi-Tenant Agentic AI on AWS: Isolation and Cost Architecture</title>
      <dc:creator>Amar Tinawi</dc:creator>
      <pubDate>Fri, 07 Aug 2026 14:10:24 +0000</pubDate>
      <link>https://dev.to/amartinawi/multi-tenant-agentic-ai-on-aws-isolation-and-cost-architecture-34i2</link>
      <guid>https://dev.to/amartinawi/multi-tenant-agentic-ai-on-aws-isolation-and-cost-architecture-34i2</guid>
      <description>&lt;p&gt;&lt;em&gt;Cross-posted from &lt;a href="https://iqraa.tech/aws-cloud/aws-multi-tenant-agentic-ai/?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=aws-agentic-ai" rel="noopener noreferrer"&gt;iqraa.tech&lt;/a&gt; — the &lt;a href="https://iqraa.tech/aws-cloud/aws-multi-tenant-agentic-ai/?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=aws-agentic-ai" rel="noopener noreferrer"&gt;full guide&lt;/a&gt; covers siloed vs pooled vs hybrid deployment, per-tenant cost attribution on Bedrock, and the noisy-neighbor problem for agent workloads.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Multi-tenant agents&lt;/strong&gt; turn one agentic AI system into a SaaS serving many customers from shared infrastructure. Siloed, pooled, or hybrid deployment determines your unit economics and security.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqaf2ojfwqy36ya4yr95n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqaf2ojfwqy36ya4yr95n.png" alt="04 - AWS Multi-Tenant Agentic AI: Isolation and Cost Architecture, title card" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Multi-Tenant Agents: What You’ll Learn
&lt;/h2&gt;

&lt;p&gt;This guide maps the AWS-recommended deployment models, tenant-context propagation patterns, and isolation primitives across siloed, pooled, and hybrid topologies on Bedrock AgentCore.&lt;/p&gt;

&lt;p&gt;By the end you should be able to justify a siloed, pooled, or hybrid topology for a given tenant mix, and trace a tenant identifier through every hop of a request from JWT to memory write.&lt;/p&gt;

&lt;p&gt;You should also be able to explain the layered isolation controls (IAM, KMS, microVM, MCP credentials) that a security review will ask about. The goal is a mental checklist for any new tenant-facing agent feature, not one fixed blueprint.&lt;/p&gt;

&lt;h2&gt;
  
  
  Multi-Tenant Agents: The Core Challenge
&lt;/h2&gt;

&lt;p&gt;Unlike a stateless web request, an agent invocation carries tenant-specific memory, tenant-scoped tools, and tenant-aware prompts. Every layer (API entry, LLM call, tool execution) must know which tenant it serves.&lt;/p&gt;

&lt;p&gt;Three forces shape every architecture: &lt;strong&gt;isolation&lt;/strong&gt; (tenant A never sees tenant B’s data), &lt;strong&gt;context&lt;/strong&gt; (the agent knows which tenant is requesting), and &lt;strong&gt;attribution&lt;/strong&gt; (every token is billable to the triggering tenant). No universally best pattern, only the best fit for your workload and regulatory environment.&lt;/p&gt;

&lt;p&gt;The reason agents are harder to isolate than plain web apps is that an LLM call is not a single, auditable database query. It is a chain of tool invocations, memory reads, and prompt assemblies, and any one of those hops can silently pull in the wrong tenant’s data if the identifier is dropped.&lt;/p&gt;

&lt;p&gt;A missing tenant_id at the tool layer does not throw an error; it just returns whatever the tool finds, which makes these bugs more dangerous because they fail silently instead of loudly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Siloed vs Pooled Agent Deployment
&lt;/h2&gt;

&lt;p&gt;The first and most consequential decision: a separate agent instance per tenant (&lt;strong&gt;siloed&lt;/strong&gt;), or one shared instance with tenant context injected at runtime (&lt;strong&gt;pooled&lt;/strong&gt;)?&lt;/p&gt;

&lt;p&gt;This decision cascades into almost every later architecture choice: how you provision infrastructure, how you bill, how you patch, and how a security auditor will scope their review. Getting it wrong early is expensive to reverse because migrating live tenants between topologies means rebuilding the isolation boundary underneath production traffic, so it deserves more upfront analysis than most teams give it.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Dimension&lt;/th&gt;
&lt;th&gt;Siloed&lt;/th&gt;
&lt;th&gt;Pooled&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Isolation&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Strong (no shared state)&lt;/td&gt;
&lt;td&gt;Weak (relies on context scoping)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Per-tenant cost&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;td&gt;Low&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Scaling&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Linear (N = N instances)&lt;/td&gt;
&lt;td&gt;Sublinear (1 serves all)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Customization&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Trivial&lt;/td&gt;
&lt;td&gt;Needs conditional logic&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Upgrade velocity&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Slow&lt;/td&gt;
&lt;td&gt;Fast&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Operational toil&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;td&gt;Low&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Best fit&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Enterprise, regulated&lt;/td&gt;
&lt;td&gt;Consumer, PLG&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;A &lt;strong&gt;hybrid model&lt;/strong&gt; bridges them: most tenants share a pooled agent, but high-tier or regulated tenants get dedicated siloed instances, routed at API Gateway by the JWT &lt;code&gt;tier&lt;/code&gt; claim.&lt;/p&gt;

&lt;h3&gt;
  
  
  When siloed wins
&lt;/h3&gt;

&lt;p&gt;Siloed is right for regulated industries requiring per-tenant compute isolation, enterprise contracts with per-tenant fine-tuning or knowledge bases, and B2B SaaS with few high-value tenants where the cost premium is trivial relative to revenue.&lt;/p&gt;

&lt;p&gt;The tell-tale sign you need siloed is a customer contract clause that names a specific isolation guarantee (dedicated compute, a named encryption key, or a right to audit the runtime) because those clauses are much easier to satisfy with a physically separate agent instance than with logical scoping inside a shared one.&lt;/p&gt;

&lt;h3&gt;
  
  
  When pooled wins
&lt;/h3&gt;

&lt;p&gt;Pooled dominates consumer and PLG segments where a dedicated instance per tenant would sink the idle-cost baseline. It also wins when tenant customization is uniform. A new tenant is just a registry row, not a provisioning project.&lt;/p&gt;

&lt;p&gt;Idle cost is the deciding variable: a siloed agent instance still consumes baseline compute even when a tenant sends zero requests overnight, and at thousands of low-usage tenants that idle cost dwarfs the actual inference spend. Pooled collapses that baseline to near zero because the shared instance is already running for other tenants’ traffic.&lt;/p&gt;

&lt;h3&gt;
  
  
  When hybrid wins
&lt;/h3&gt;

&lt;p&gt;Hybrid is the 2026 default for enterprise SaaS: free tiers pooled, enterprise tiers siloed. The cost is running two topologies in parallel; the upside is matching isolation to willingness-to-pay. Most Bedrock AgentCore agents ship hybrid from day one.&lt;/p&gt;

&lt;p&gt;Running two topologies means maintaining two deployment pipelines, two sets of IAM policies, and two on-call runbooks, which is real operational overhead. Teams that pick hybrid successfully treat the pooled and siloed paths as the same codebase with a routing decision at the edge, not two forked implementations that drift apart over time.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fn6g5c8qxk0uesrh4gbyd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fn6g5c8qxk0uesrh4gbyd.png" alt="multi-tenant agents siloed pooled deployment models" width="798" height="195"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Three deployment models: siloed, pooled, hybrid.&lt;/p&gt;

&lt;h2&gt;
  
  
  Injecting Tenant Context into Agents
&lt;/h2&gt;

&lt;p&gt;How does a pooled agent know which tenant is requesting? &lt;strong&gt;Tenant context injection&lt;/strong&gt; attaches a tenant identifier to every step of execution. Done right, the agent behaves as if per-tenant. Done wrong, you ship a data leak. The canonical AWS pattern:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1. Caller authenticates → Cognito / OIDC issues a JWT
2. JWT carries a custom claim: { "tenant_id": "acme-corp" }
3. API Gateway authorizer validates JWT, extracts tenant_id
4. API Gateway forwards request to Lambda with tenant_id in header
5. Lambda reads tenant_id, scopes all DynamoDB queries with it
6. Lambda invokes Bedrock Agent with tenant_id in sessionMetadata
7. Bedrock Agent's tools receive tenant_id, scope their own queries
8. Memory store (Bedrock AgentCore Memory) keys sessions by tenant_id
9. Response returns to caller; no cross-tenant state leaked
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The most common mistake is stopping at the API layer: validating tenant at API Gateway but forgetting to scope the DynamoDB query, S3 prefix, or Knowledge Base retrieval. Bedrock AgentCore exposes &lt;strong&gt;session metadata&lt;/strong&gt; as a first-class concept: attach &lt;code&gt;tenant_id&lt;/code&gt; once and it propagates to every tool call, memory write, and observability event. The Lambda authorizer that extracts tenant_id from the JWT:&lt;/p&gt;

&lt;p&gt;Session metadata matters because it removes the temptation to pass tenant_id as an ordinary function argument that a future refactor could quietly drop. Once tenant_id lives on the session object, every downstream component (the tool executor, the memory writer, the trace exporter) reads it from the same place, so there is exactly one code path to audit instead of dozens of call sites that each need to remember to forward the value correctly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import json, jwt  # PyJWT
TENANT_CLAIM = "custom:tenant_id"
JWT_AUDIENCE = "agent-api"
def lambda_handler(event, context):
    auth_header = event["headers"].get("authorization", "")
    token = auth_header.replace("Bearer ", "")
    try:
        # Verify signature + audience against Cognito JWKS
        decoded = jwt.decode(
            token,
            algorithms=["RS256"],
            audience=JWT_AUDIENCE,
            jwks_url="https://cognito-idp.us-east-1.amazonaws.com/"
                     + os.environ["USER_POOL_ID"] + "/.well-known/jwks.json",
        )
        tenant_id = decoded[TENANT_CLAIM]
        tier = decoded.get("custom:tier", "free")
    except jwt.PyJWTError as e:
        return {"principalId": "denied", "policyDocument": deny_policy()}
    # Allow + propagate tenant_id / tier to integration via context
    return {
        "principalId": tenant_id,
        "policyDocument": allow_policy(event["methodArn"]),
        "context": {"tenant_id": tenant_id, "tier": tier},
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fszjwuzmqlko8tjy1vtwz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fszjwuzmqlko8tjy1vtwz.png" alt="multi-tenant agents tenant context injection flow API Gateway Lambda Bedrock" width="800" height="576"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Tenant context resolved at the perimeter, enforced at each interaction.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tenant Onboarding and Lifecycle Management
&lt;/h2&gt;

&lt;p&gt;Multi-tenant agents need a &lt;strong&gt;control plane&lt;/strong&gt; separate from the application plane: the control plane handles onboarding, tiering changes, and offboarding; the application plane serves real-time requests. They communicate through a shared tenant registry (typically DynamoDB global tables) and use different IAM roles so a control-plane bug cannot serve tenant traffic.&lt;/p&gt;

&lt;p&gt;A reference onboarding flow on Bedrock AgentCore:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import boto3
control_plane = boto3.client('events')  # EventBridge for lifecycle events
agentcore = boto3.client('bedrock-agentcore')
def onboard_tenant(tenant_id: str, tier: str, admin_email: str):
    # 1. Create tenant-scoped IAM role
    role_arn = iam.create_role(
        RoleName=f"agent-tenant-{tenant_id}",
        AssumeRolePolicyDocument=trust_policy_for_agentcore(),
        Description=f"Tenant {tenant_id} ({tier})",
    )['Role']['Arn']
    # 2. Provision tenant-scoped memory in AgentCore
    memory_id = agentcore.create_memory(
        name=f"mem-{tenant_id}",
        strategy='semantic',
        encryptionKeyArn=tenant_kms_key(tenant_id),
    )['memoryId']
    # 3. Register tenant in control-plane registry
    dynamodb.put_item(
        TableName='Tenants',
        Item={'tenant_id': {'S': tenant_id},
              'tier': {'S': tier},
              'role_arn': {'S': role_arn},
              'memory_id': {'S': memory_id},
              'status': {'S': 'ACTIVE'}},
    )
    # 4. Emit lifecycle event for downstream systems (billing, analytics)
    control_plane.put_events(Entries=[{
        'Source': 'agent.control-plane',
        'DetailType': 'TenantOnboarded',
        'Detail': json.dumps({'tenant_id': tenant_id, 'tier': tier}),
    }])
    return {'tenant_id': tenant_id, 'role_arn': role_arn, 'memory_id': memory_id}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every resource is &lt;strong&gt;tenant-scoped by name&lt;/strong&gt; (IAM role, memory ID, registry record), so cost attribution, audit, and offboarding become trivial prefix-matching operations.&lt;/p&gt;

&lt;p&gt;The onboarding function above also illustrates why the control plane and application plane need separate IAM roles: the control plane needs &lt;code&gt;iam:CreateRole&lt;/code&gt; and &lt;code&gt;bedrock-agentcore:CreateMemory&lt;/code&gt; permissions to provision new tenants, but the application plane that actually serves chat requests should never hold those permissions. A compromised or buggy request handler with IAM-creation rights is a far bigger blast radius than one that can only read a tenant’s own memory and DynamoDB rows.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fohu1i54ejjmssnd6vcll.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fohu1i54ejjmssnd6vcll.png" alt="multi-tenant agents onboarding lifecycle control plane" width="800" height="286"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The control plane orchestrates tenant onboarding atomically.&lt;/p&gt;

&lt;h2&gt;
  
  
  Isolation, Security, and Data Ownership
&lt;/h2&gt;

&lt;p&gt;A single cross-tenant leak is market-ending. AWS recommends a layered model. &lt;strong&gt;Identity&lt;/strong&gt;: every tenant gets its own IAM role. &lt;a href="https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/what-is-bedrock-agentcore.html" rel="noopener noreferrer"&gt;Bedrock AgentCore&lt;/a&gt;‘s per-tenant session tokens stop even a misconfigured tool at the IAM boundary. &lt;strong&gt;Data&lt;/strong&gt;: DynamoDB composite keys with tenant_id, S3 prefixes include tenant_id, Knowledge Bases per-tenant or partitioned. &lt;strong&gt;Compute&lt;/strong&gt;: AgentCore’s microVM runtime gives each session a hardened, ephemeral environment.&lt;/p&gt;

&lt;p&gt;Regulated workloads add &lt;strong&gt;per-tenant KMS customer-managed keys&lt;/strong&gt;: each tenant’s data is encrypted with a key only that tenant can authorize. The MCP protocol adds another surface. A pooled agent calling an MCP server must pass tenant-scoped IAM credentials explicitly, never trusted to defaults.&lt;/p&gt;

&lt;p&gt;Per-tenant KMS keys also give you a clean offboarding lever: scheduling a key for deletion cryptographically shreds every object encrypted under it, even if a stray copy of the data survives somewhere in a backup or log you forgot to purge. That is a much stronger guarantee than relying on a delete script to find and remove every row, because the guarantee holds even against your own mistakes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fosg0m71vqmeutrq4h7m1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fosg0m71vqmeutrq4h7m1.png" alt="multi-tenant agents tenant isolation MCP IAM scoped credentials" width="799" height="474"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;An MCP client passes tenant-scoped IAM credentials to the MCP server.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cost Attribution and Resource Management
&lt;/h2&gt;

&lt;p&gt;Every Bedrock inference, AgentCore session minute, Lambda invocation, and DynamoDB read must attribute to a tenant. The cleanest pattern is &lt;strong&gt;tag-based attribution&lt;/strong&gt;: tag every control-plane resource with &lt;code&gt;Tenant={tenant_id}&lt;/code&gt; at creation, and Cost Explorer breaks spend per tenant automatically. For per-request costs (tokens, session minutes), the agent emits a telemetry event with tenant_id.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;noisy neighbor&lt;/strong&gt; problem, one tenant’s burst saturating model concurrency or DynamoDB capacity, is the dark side of pooled. The fix is per-tenant token-bucket throttling at API Gateway or AgentCore Gateway. Tiered resource allocation (smaller model and shorter memory retention for free tier; larger model and dedicated capacity for premium) is config in the control-plane registry.&lt;/p&gt;

&lt;p&gt;Token-bucket throttling works well here because it tolerates short bursts, a tenant running a legitimate batch job for a few seconds, while still capping the sustained rate that would otherwise starve every other tenant sharing the same model endpoint. Setting the bucket size and refill rate per tier, rather than globally, means a premium tenant’s burst allowance does not have to be sized down to protect free-tier capacity.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tenant Tiering and Pricing Strategy
&lt;/h2&gt;

&lt;p&gt;Three pricing models dominate multi-tenant agents in 2026. &lt;strong&gt;Subscription&lt;/strong&gt; (flat fee with tiered feature gates) is simplest but risks heavy users eroding margin. &lt;strong&gt;Usage-based&lt;/strong&gt; (per invocation, per thousand tokens, per task) aligns revenue to cost but risks bill shock. Mitigate with per-tenant spending ceilings.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Outcome-based&lt;/strong&gt; (pay only when the agent delivers a measurable result) is boldest and most aligned with the agent’s value, but requires strong attribution connecting agent actions to business metrics. Most products start with subscription or usage-based and migrate to outcome-based once attribution matures.&lt;/p&gt;

&lt;p&gt;The practical reason most teams delay outcome-based pricing is that it needs a causal link between a specific agent action and a business result (a resolved support ticket, a closed deal) and that link is often ambiguous when a human also touched the workflow. Usage-based pricing sidesteps the ambiguity by billing on a countable signal (tokens, invocations) that the agent platform already measures precisely.&lt;/p&gt;

&lt;h2&gt;
  
  
  Observability for Multi-Tenant Agents
&lt;/h2&gt;

&lt;p&gt;Aggregate metrics hide problems: p95 looks fine while one tenant suffers a 10x regression. Tag every observability event with &lt;code&gt;tenant_id&lt;/code&gt;. AWS X-Ray supports annotation-based filtering; Bedrock AgentCore emits per-session traces with tenant metadata automatically. Three metrics matter: error rate (signals data issues), token efficiency (drops signal prompt drift), and guardrail intervention rate (high rates suggest tier upgrade or policy review).&lt;/p&gt;

&lt;p&gt;Annotation-based filtering in X-Ray means you can slice a trace query down to a single tenant_id and replay exactly what that tenant experienced, which turns a vague support ticket like “the agent is slow for us” into a concrete trace you can inspect end to end. Without tenant tagging on every span, the same investigation means grepping through shared logs hoping the right request stands out.&lt;/p&gt;

&lt;h2&gt;
  
  
  Migrating Between Deployment Models
&lt;/h2&gt;

&lt;p&gt;Most systems do not start in their final topology. A common trajectory: siloed for the first 10 enterprise customers, hit a cost ceiling around 50 tenants, migrate to hybrid, then consolidate to pooled-with-strong-isolation once per-tenant memory primitives mature.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Siloed to pooled&lt;/strong&gt; is highest-risk because isolation shifts from physical to logical. Audit every tool for tenant scoping, every IAM role for least privilege, and write regression tests that attempt cross-tenant access. Ramp behind a feature flag (5% → two weeks → 100%).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pooled to siloed&lt;/strong&gt; is mechanically simple but expensive if frequent. Automate it. &lt;strong&gt;Siloed to hybrid&lt;/strong&gt; requires the control plane to track each tenant’s deployment model. Pick the topology you expect at 24 months and build toward it; stability beats theoretical optimality.&lt;/p&gt;

&lt;p&gt;The feature-flag ramp matters more than it sounds: migrating a tenant from siloed to pooled at 100% on day one means any isolation gap surfaces in production against a real customer immediately. Ramping through 5%, then a subset of low-risk tenants for two weeks, then everyone, gives the chaos tests and monitoring dashboards time to catch a leak before it reaches a tenant who would notice and escalate.&lt;/p&gt;

&lt;h2&gt;
  
  
  Compliance and Audit for Multi-Tenant Agents
&lt;/h2&gt;

&lt;p&gt;SOC 2, HIPAA, ISO 27001, FedRAMP: the answer depends on the audit trail. Three artifacts matter: &lt;strong&gt;tenant-scoped access logs&lt;/strong&gt; (CloudTrail and AgentCore traces tagged with tenant_id), &lt;strong&gt;isolation test reports&lt;/strong&gt; (weekly chaos tests attempting cross-tenant access), and &lt;strong&gt;tenant offboarding certificates&lt;/strong&gt; (signed records of memory deletion, IAM revocation, KMS destruction).&lt;/p&gt;

&lt;p&gt;CloudTrail inherits tenant tags; AgentCore emits per-session traces with tenant metadata; Bedrock Guardrails records every intervention. Build the audit pipeline as part of the control plane from day one. Produce artifacts continuously, not on demand.&lt;/p&gt;

&lt;p&gt;Building the audit pipeline early also avoids a familiar failure mode: an auditor asks for six months of tenant-scoped access logs, and the team discovers CloudTrail tagging was only turned on three weeks ago. Continuous artifact generation costs almost nothing at write time (it is a tag and a log line) but retrofitting it after the fact means the gap in history simply cannot be recovered.&lt;/p&gt;

&lt;h2&gt;
  
  
  Multi-Tenant Agents in Practice: A Worked Example
&lt;/h2&gt;

&lt;p&gt;A SaaS “AI Customer Success Agent” for mid-market B2B. Each tenant has its own CRM, churn playbook, and chat branding. The company chooses &lt;strong&gt;hybrid&lt;/strong&gt;: free-tier tenants share a pooled Bedrock AgentCore agent (Strands supervisor + three MCP tools); premium tenants get a siloed agent with Claude Sonnet, per-tenant memory, and tighter IAM. API Gateway routes by JWT &lt;code&gt;tier&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from strands import Agent
from strands_tools import http_request
import boto3, os
# Bedrock AgentCore session carries tenant_id implicitly via session metadata
def build_agent(tenant_id: str, tier: str) -&amp;gt; Agent:
    model = "anthropic.claude-3-5-sonnet" if tier == "premium" else "anthropic.claude-3-5-haiku"
    system_prompt = f"""You are the Customer Success Agent for tenant {tenant_id}. Always scope CRM queries with tenant_id='{tenant_id}'. Never reveal data from other tenants.
Cite CRM record IDs in every answer."""
    return Agent(
        model=model,
        tools=[http_request, crm_lookup_tool(tenant_id), playbook_search_tool(tenant_id)],
        system_prompt=system_prompt,
    )
# Pooled mode: build once per request from cached agent instances by (tenant_id, tier)
# Siloed mode: long-running dedicated instance per tenant
agent = agent_pool.get_or_build(tenant_id, tier)
result = agent(customer_question)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The system prompt carries the tenant identifier; the CRM lookup tool receives &lt;code&gt;tenant_id&lt;/code&gt; as a closure so it cannot query another tenant’s data. Success is measured by per-tenant margin, p95 latency by tier, cross-tenant leak incidents (target: zero), and onboarding time (under 5 minutes).&lt;/p&gt;

&lt;p&gt;Closing over tenant_id in the tool constructor rather than reading it from the prompt text is the important design detail here: even if a malicious or careless prompt tried to ask the agent to look up a different tenant’s account, the tool itself has no code path to honor that request because the identifier it queries with was fixed when the tool was built, not parsed from the model’s output.&lt;/p&gt;

&lt;h2&gt;
  
  
  Multi-Tenant Agents: Common Mistakes to Avoid
&lt;/h2&gt;

&lt;p&gt;Most cross-tenant incidents trace back to one of a handful of repeatable mistakes rather than an exotic new failure mode. Reviewing a pooled agent design against this list before launch catches the majority of isolation gaps a chaos test would otherwise have to find the hard way.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Stopping tenant scoping at the API layer&lt;/strong&gt;: forgetting to scope the DynamoDB query, S3 prefix, or Knowledge Base retrieval.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Single shared memory store&lt;/strong&gt;: works until prompt injection retrieves another tenant’s session. Use per-tenant memory for regulated workloads.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No per-tenant rate limiting&lt;/strong&gt;: one noisy tenant saturates model concurrency. Enforce token buckets at API Gateway.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Shared IAM role&lt;/strong&gt;: one misconfigured tool reaches every tenant’s data. Use tenant-scoped roles, even in pooled mode.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9c3owk5l6l9l8au66zxy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9c3owk5l6l9l8au66zxy.png" alt="agentic AI, multi-tenant agents key concepts siloed pooled isolation" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Multi-Tenant Agents: Best Practices
&lt;/h2&gt;

&lt;p&gt;These practices are the operational checklist that follows from everything above: they are not new ideas so much as the concrete, repeatable version of the isolation, context-propagation, and attribution principles this guide has walked through. Treat them as the minimum bar for a production multi-tenant agent, not an aspirational list.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Default to hybrid (pooled free + siloed premium).&lt;/li&gt;
&lt;li&gt;Propagate tenant_id via session metadata, not spoofable request fields.&lt;/li&gt;
&lt;li&gt;Use per-tenant AgentCore Memory for regulated workloads; share only for low-stakes consumer products.&lt;/li&gt;
&lt;li&gt;Enforce per-tenant token-bucket limits at API Gateway keyed on JWT tenant_id.&lt;/li&gt;
&lt;li&gt;Tag every AWS resource with &lt;code&gt;Tenant={tenant_id}&lt;/code&gt; at provisioning time.&lt;/li&gt;
&lt;li&gt;Run weekly chaos tests attempting cross-tenant access from staging.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F1mzxo8oh716sdxgr1jb6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F1mzxo8oh716sdxgr1jb6.png" alt="agentic AI, multi-tenant agents best practices architecture" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Multi-Tenant Agents: Frequently Asked Questions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  When should I choose siloed over pooled?
&lt;/h3&gt;

&lt;p&gt;Choose siloed for enterprise or regulated tenants, when customization is a differentiator, or when tenant count is small (under 50). Pooled wins above a few hundred tenants and for free tiers. If you are unsure, default to pooled and carve out siloed exceptions for the specific tenants whose contracts demand it, rather than starting siloed for everyone and paying the operational cost of migrating later.&lt;/p&gt;

&lt;h3&gt;
  
  
  How does Bedrock AgentCore support multi-tenancy?
&lt;/h3&gt;

&lt;p&gt;Per-tenant session metadata, per-tenant memory, a gateway enforcing per-tenant rate limits, and MCP tool credentials passing tenant-scoped IAM roles. One deployment serves many tenants with strong isolation. The session metadata is the connective piece, because it travels with the invocation automatically, memory, tools, and observability all inherit the same tenant scope without extra plumbing in application code.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is the noisy neighbor problem in multi-tenant agents?
&lt;/h3&gt;

&lt;p&gt;One tenant’s bursty requests saturate shared capacity (model concurrency, DynamoDB read units, AgentCore session limits), degrading latency for others. Fix: per-tenant throttling at API Gateway or AgentCore Gateway. The problem is specific to pooled deployments; a siloed tenant can only ever exhaust their own dedicated capacity, which is exactly why regulated or usage-spiky tenants often justify the siloed cost premium.&lt;/p&gt;

&lt;h3&gt;
  
  
  Can multi-tenant agents be HIPAA-compliant?
&lt;/h3&gt;

&lt;p&gt;Yes, with per-tenant KMS keys, per-tenant AgentCore Memory, tenant-scoped IAM roles, and BAAs with AWS for HIPAA-eligible services (Bedrock, AgentCore, S3, DynamoDB). The isolation and audit-trail requirements described throughout this guide are not extra work bolted on for HIPAA. They are the same controls a well-run multi-tenant agent needs regardless of vertical, just enforced without exception.&lt;/p&gt;

&lt;h3&gt;
  
  
  How do I attribute Bedrock token cost to a specific tenant?
&lt;/h3&gt;

&lt;p&gt;Tag Bedrock invocations at the API layer with tenant_id (as request metadata), then aggregate per-request token counts in CloudWatch or a billing pipeline. Cost Explorer shows tag breakdowns natively. For usage-based billing, emit the token count and tenant_id as a structured event at invocation time rather than trying to reconstruct cost later from aggregate logs, since per-request granularity is what a billing dispute ultimately requires.&lt;/p&gt;

&lt;p&gt;[ays_quiz id=65]&lt;/p&gt;

&lt;h2&gt;
  
  
  Multi-Tenant Agents: Key Takeaways
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;SaaS with extra dimensions&lt;/strong&gt;: inherits SaaS challenges (isolation, attribution) and adds agent-specific ones (non-determinism, memory partitioning, MCP isolation).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Siloed vs pooled vs hybrid&lt;/strong&gt; is the first architecture decision; hybrid is the canonical enterprise pattern.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tenant context injection&lt;/strong&gt; propagates through every layer: JWT, API Gateway, Lambda, AgentCore, MCP tool, memory.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Control plane vs application plane&lt;/strong&gt; separation is mandatory.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Isolation is layered&lt;/strong&gt;: IAM, KMS, per-tenant Memory, microVM runtime, MCP credentials.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cost attribution is first-class&lt;/strong&gt;: tag every resource with &lt;code&gt;Tenant={tenant_id}&lt;/code&gt; and emit per-request telemetry.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Multi-tenant agents&lt;/strong&gt; on AWS give SaaS unit economics with per-tenant isolation. Choose hybrid by default, propagate tenant context through every layer, lean on AgentCore’s per-tenant primitives. Multi-tenant agentic AI on AWS succeeds when tenant isolation is enforced at IAM, AgentCore Memory, and KMS, not only at the application layer. Every multi-tenant design choice (pooled or siloed, shared or dedicated AgentCore) flows from the compliance tier and cost ceiling the tenant contract demands.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>aiagents</category>
      <category>saas</category>
      <category>bedrock</category>
    </item>
    <item>
      <title>What Agentic AI on AWS Actually Costs: A Unit-Economics Breakdown</title>
      <dc:creator>Amar Tinawi</dc:creator>
      <pubDate>Fri, 07 Aug 2026 14:09:20 +0000</pubDate>
      <link>https://dev.to/amartinawi/what-agentic-ai-on-aws-actually-costs-a-unit-economics-breakdown-200j</link>
      <guid>https://dev.to/amartinawi/what-agentic-ai-on-aws-actually-costs-a-unit-economics-breakdown-200j</guid>
      <description>&lt;p&gt;&lt;em&gt;Cross-posted from &lt;a href="https://iqraa.tech/aws-cloud/aws-agentic-ai-economics/?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=aws-agentic-ai" rel="noopener noreferrer"&gt;iqraa.tech&lt;/a&gt; — the &lt;a href="https://iqraa.tech/aws-cloud/aws-agentic-ai-economics/?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=aws-agentic-ai" rel="noopener noreferrer"&gt;full guide&lt;/a&gt; includes the worked ROI calculation, the Lambda/Step Functions cost model, and the risk-economics framework.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Agentic AI economics&lt;/strong&gt; compares total human costs against agent costs, introduces pay-per-outcome pricing, and gives you the ROI models to scale automation sustainably on AWS, answering when replacing human labor with agentic AI actually pays off, and where agentic AI economics tips in favor of automating.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9qtjt1yf1xz2a4m5np6z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9qtjt1yf1xz2a4m5np6z.png" alt="Agentic AI economics on AWS: human vs agent cost comparison and ROI"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Agentic AI Economics: What You’ll Learn
&lt;/h2&gt;

&lt;p&gt;Agentic AI economics is the structured comparison of what human labor really costs against what an agentic AI system really costs, across the full task lifecycle. The &lt;a href="https://docs.aws.amazon.com/prescriptive-guidance/latest/agentic-ai-economics/introduction.html" rel="noopener noreferrer"&gt;AWS Prescriptive Guidance&lt;/a&gt; frames this as a shift away from simplistic “human cost minus AI cost” arithmetic toward a model weighing total economic impact, risk, decision quality, and long-term strategic value.&lt;/p&gt;

&lt;p&gt;This guide covers both cost models, pay-per-outcome pricing, automation candidate criteria, and ROI metrics, then walks through a document-review worked example mapping Bedrock token pricing, Lambda per-invocation billing, and Step Functions state-transition costs onto real unit economics.&lt;/p&gt;

&lt;p&gt;Treat economics as a continuous practice: measure before, after, and as prices shift. Retire what stops paying off; double down on what compounds.&lt;/p&gt;

&lt;h2&gt;
  
  
  Agentic AI Economics: The Core Question
&lt;/h2&gt;

&lt;p&gt;The AWS guide opens with a line worth memorizing: &lt;em&gt;no system is 100% right.&lt;/em&gt; The core question is not “is the agent cheaper?” but “given that both humans and agents err, which mix delivers the best outcome-adjusted return?”&lt;/p&gt;

&lt;p&gt;A naive comparison fails fast. A human reviewer at $60/hour fully loaded handles eight documents per hour; a Bedrock agent costs $0.04/document in inference. On raw unit cost the agent wins by three orders of magnitude, until you account for the agent’s 3% hallucination rate at $2,000 per remediation.&lt;/p&gt;

&lt;p&gt;Once error cost enters the equation, the cheaper system is not always the agent.&lt;/p&gt;

&lt;p&gt;The question changes with volume. At ten documents a day the human’s fixed overhead dominates; at ten thousand, the agent’s near-zero marginal cost dominates. The model answers “when” and “where” as much as “whether,” and captures strategic value: the second automation costs far less once platform, guardrails, and observability exist.&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding Total Human Labor Costs
&lt;/h2&gt;

&lt;p&gt;Most teams undercount human costs, biasing the comparison against automation before it begins. Fully loaded cost is not salary; it is salary plus benefits, payroll taxes, facilities, management overhead, hiring, onboarding, training, and turnover, typically 1.4 to 1.8 times base salary.&lt;/p&gt;

&lt;p&gt;Two hidden costs dominate. &lt;strong&gt;Latency&lt;/strong&gt;: humans work eight to ten hours a day and handle one task at a time, so backlogs wait and surges create overtime. &lt;strong&gt;Error rate&lt;/strong&gt;: fatigue and consistency errors whose rework and compliance costs are real but rarely attributed.&lt;/p&gt;

&lt;p&gt;Training recurs on every policy or product change, and when a tenured reviewer leaves their judgment leaves with them. And scaling human cost is linear and slow: doubling throughput doubles overhead and takes months. That linearity is the lever agentic AI economics exploits.&lt;/p&gt;

&lt;h2&gt;
  
  
  Agentic AI System Costs on AWS
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Inference&lt;/strong&gt; is the dominant variable cost. Bedrock prices per million tokens; Nova Micro or Claude Haiku cost fractions of a cent per thousand tokens, Sonnet or Nova Pro several times more, favoring tiered selection (route easy 80% to the cheap model, hard 20% to the expensive one).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Infrastructure&lt;/strong&gt;: Lambda bills per invocation plus GB-second; Step Functions per state transition (a four-tool workflow costs four transitions); Bedrock AgentCore, OpenSearch, and S3 each add their own line. &lt;strong&gt;Prompt engineering&lt;/strong&gt; is skilled labor but amortizes: one versioned prompt serves a million requests. &lt;strong&gt;Monitoring&lt;/strong&gt; (CloudWatch, X-Ray, eval suites, sampled human review) typically adds 10 to 20% to operating cost.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Cost Factor&lt;/th&gt;
&lt;th&gt;Human Worker&lt;/th&gt;
&lt;th&gt;Agentic AI System&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Per-task cost&lt;/td&gt;
&lt;td&gt;$5 to $50 (fully loaded)&lt;/td&gt;
&lt;td&gt;$0.001 to $0.10 (inference)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Throughput&lt;/td&gt;
&lt;td&gt;8 to 10 hrs/day, 1 at a time&lt;/td&gt;
&lt;td&gt;24/7, 1000s in parallel&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Scaling cost&lt;/td&gt;
&lt;td&gt;Linear (hire more)&lt;/td&gt;
&lt;td&gt;Near-zero marginal&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Training cost&lt;/td&gt;
&lt;td&gt;Weeks, recurring&lt;/td&gt;
&lt;td&gt;Prompt updates, hours&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Error cost&lt;/td&gt;
&lt;td&gt;Variable, recoverable&lt;/td&gt;
&lt;td&gt;Variable, needs guardrails&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Oversight needed&lt;/td&gt;
&lt;td&gt;Low (self-monitoring)&lt;/td&gt;
&lt;td&gt;Required (trust builds over time)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The comparison that matters is per completed task, not per hour. Re-baseline quarterly using Cost Explorer and CloudWatch telemetry. Token prices fall, and a table accurate in January can mislead by July.&lt;/p&gt;

&lt;p&gt;Put a number on it: a customer-support triage agent that sends 600 input tokens and returns 80 output tokens per ticket, orchestrated through two Step Functions transitions and one Lambda invocation, lands near $0.003 per ticket on a mid-tier Bedrock model, before oversight sampling and error cost.&lt;/p&gt;

&lt;p&gt;Multiply that by ticket volume and the agentic AI economics of the workload are visible in minutes, which is the entire point of building the per-task table before debating the automation decision in a meeting.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pay-Per-Outcome: The New Pricing Paradigm
&lt;/h2&gt;

&lt;p&gt;Customers are shifting toward pay-per-outcome models, where you pay only when the agent delivers a measurable business result (a resolved ticket, an approved claim, a classified document), not for the compute that attempted it.&lt;/p&gt;

&lt;p&gt;The appeal is risk alignment: under upfront pricing the customer bears underperformance risk; under pay-per-outcome the vendor shares it. ROI becomes self-evident: if each outcome is priced below the human cost of producing it, every transaction is accretive.&lt;/p&gt;

&lt;p&gt;The model demands strong attribution, which is why it pairs naturally with AgentOps (Part 9). The catch is outcome definition: “resolved ticket” is clear until you define “resolved” across ten segments. Pay-per-outcome fits high-volume structured tasks long before ambiguous knowledge work.&lt;/p&gt;

&lt;h2&gt;
  
  
  Which Jobs Are Good Candidates for Automation?
&lt;/h2&gt;

&lt;p&gt;The strongest candidates are high-volume, structured, repetitive tasks with clear success criteria and bounded ambiguity: document classification, invoice extraction, first-line triage, log anomaly detection, form validation. They repeat enough to amortize integration cost, prompt reliably, and measure accuracy cleanly.&lt;/p&gt;

&lt;p&gt;Weak candidates are creative strategy, high-stakes empathy decisions, one-off annual tasks, ambiguous edge cases. High-stakes tasks like medical diagnosis or legal advice belong in a third category: human oversight, where the agent drafts and a human approves: ROI comes from productivity gain (e.g. 70% review-time reduction), not headcount reduction.&lt;/p&gt;

&lt;p&gt;Plot tasks on a 2×2 of volume vs ambiguity: high-vol/low-amb = automate-now; high-vol/high-amb = automate-with-overhead; low-vol/low-amb = automate-if-cheap; low-vol/high-amb = leave-alone. Revisit quarterly. Tasks become automatable as models improve.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Calculate Agentic AI ROI
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Cost per task&lt;/strong&gt;: fully loaded human vs fully loaded agent. &lt;strong&gt;Throughput multiplier&lt;/strong&gt;: how much more the agent produces, which reframes “can we afford the agent?” as “can we afford not to?” &lt;strong&gt;Error rate + rework cost&lt;/strong&gt;: the most-skipped, most-decisive metric: error rate × per-error remediation cost for both sides, treated as a first-class line item. &lt;strong&gt;Time-to-value&lt;/strong&gt;: how fast integration cost is repaid.&lt;/p&gt;

&lt;p&gt;Net annual value = (human cost per task − agent cost per task) × annual volume − one-time integration cost − annual error-cost delta. Benchmark against your own historical data, not vendor case studies.&lt;/p&gt;

&lt;p&gt;Run the formula both ways before committing budget. If agentic AI economics only clear the bar at optimistic error rates, the program is under-priced for risk; if they clear it even at pessimistic error rates and volume, integration is the safe next step. The teams that get agentic AI economics right treat this formula as a living spreadsheet updated monthly, not a one-time slide built to win a budget approval.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffe3w4pzeq3kmnqewfxn6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffe3w4pzeq3kmnqewfxn6.png" alt="agentic AI economics: Cumulative cost trajectory showing agentic AI break-even within the first month and 96000 dollars net savings by month six"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Six-month cumulative cost trajectory: break-even within the first month, widening savings as volume grows. Adapted from AWS Prescriptive Guidance.&lt;/p&gt;

&lt;h2&gt;
  
  
  Scaling What Works: From Pilot to Production
&lt;/h2&gt;

&lt;p&gt;The pattern: start with high-volume structured tasks, measure everything, scale winners, retire failures. Pilots look promising; production surfaces what pilots hid.&lt;/p&gt;

&lt;p&gt;Run a 30-day pilot on one task for one team. Treat it as an investment in data, not savings. When it clears its ROI bar, ramp volume in stages (10%, 50%, 100%) watching unit cost (should fall) and error cost (rises if task mix drifts harder). Retire failures honestly: a retired pilot is a successful experiment.&lt;/p&gt;

&lt;p&gt;Set the ROI threshold before the pilot and act on “stop.”&lt;/p&gt;

&lt;p&gt;The portfolio view: a mature program runs dozens of agents on one dashboard and reallocates investment from declining to rising agents quarterly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Risk Economics: The Cost of Agent Errors
&lt;/h2&gt;

&lt;p&gt;Finance respects this part most; engineering underweights it most. An agent that hallucinates a plausible-but-wrong action can be cheaper per task than a human until you account for catching and reworking the error. Weigh agent errors against equivalent human errors honestly.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7a5faqjeui1vq9c2x22i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7a5faqjeui1vq9c2x22i.png" alt="agentic AI economics: Four agentic AI deployment approaches from fully autonomous to human-led mapped to error tolerance and required oversight"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Four deployment approaches mapped to error tolerance. Adapted from AWS Prescriptive Guidance.&lt;/p&gt;

&lt;p&gt;Treat hallucination as expected error cost: error rate × per-error cost. Humans also hallucinate: they misremember policy, apply yesterday’s rule, get tired at hour seven. Measure both sides; do not assume the human baseline is zero.&lt;/p&gt;

&lt;p&gt;Bedrock Guardrails tilt risk economics in the agent’s favor: blocking harmful content, masking PII, denying out-of-scope topics, filtering hallucinations through contextual grounding checks before they reach a user. Treat guardrail config as an investment: reduction in expected error cost ÷ build cost. Human-in-the-loop is the other lever: find the sampling rate that catches errors that matter without erasing the throughput advantage.&lt;/p&gt;

&lt;p&gt;Risk compounds with scale: a rate tolerable at one thousand tasks a day can be catastrophic at one million. Stress-test at projected scale.&lt;/p&gt;

&lt;p&gt;This is where agentic AI economics and reliability engineering merge into one job. A guardrail that costs $0.002 per call but cuts the error rate in half is worth adding at almost any volume once you have priced the error it prevents; a guardrail that adds latency without moving the error rate is a cost with no return. Price every guardrail the same way you price the agent itself.&lt;/p&gt;

&lt;h2&gt;
  
  
  Agentic AI Economics in Practice: Automating Document Review with ROI Analysis
&lt;/h2&gt;

&lt;p&gt;A financial services firm reviews 8,000 loan applications/month with twelve reviewers at $48/hour fully loaded. Average review time 20 minutes, error rate 4%, each error $1,200 to remediate. They build a Bedrock agent that extracts fields, checks policy, and recommends: inference $0.06/app, Lambda + Step Functions $0.01, human oversight samples 15% at $4 each.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Agentic AI economics — document review ROI model
&lt;/span&gt;&lt;span class="n"&gt;monthly_volume&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;8000&lt;/span&gt;

&lt;span class="c1"&gt;# Human baseline (fully loaded)
&lt;/span&gt;&lt;span class="n"&gt;human_hourly&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;48&lt;/span&gt;
&lt;span class="n"&gt;apps_per_hour&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;                      &lt;span class="c1"&gt;# 20 min each
&lt;/span&gt;&lt;span class="n"&gt;human_cost_per_task&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;human_hourly&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;apps_per_hour&lt;/span&gt;   &lt;span class="c1"&gt;# $16.00
&lt;/span&gt;&lt;span class="n"&gt;human_error_rate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.04&lt;/span&gt;
&lt;span class="n"&gt;human_error_cost_per_task&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;human_error_rate&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1200&lt;/span&gt;  &lt;span class="c1"&gt;# $48.00
&lt;/span&gt;&lt;span class="n"&gt;human_total_per_task&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;human_cost_per_task&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;human_error_cost_per_task&lt;/span&gt;  &lt;span class="c1"&gt;# $64.00
&lt;/span&gt;&lt;span class="n"&gt;human_monthly&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;human_total_per_task&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;monthly_volume&lt;/span&gt;                &lt;span class="c1"&gt;# $512,000
&lt;/span&gt;
&lt;span class="c1"&gt;# Agent baseline
&lt;/span&gt;&lt;span class="n"&gt;inference&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.06&lt;/span&gt;
&lt;span class="n"&gt;infra&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.01&lt;/span&gt;
&lt;span class="n"&gt;oversight&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.15&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;                   &lt;span class="c1"&gt;# sample 15% at $4 each
&lt;/span&gt;&lt;span class="n"&gt;agent_cost_per_task&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;inference&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;infra&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;oversight&lt;/span&gt;  &lt;span class="c1"&gt;# $0.67
&lt;/span&gt;&lt;span class="n"&gt;agent_error_rate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.025&lt;/span&gt;               &lt;span class="c1"&gt;# measured in pilot
&lt;/span&gt;&lt;span class="n"&gt;agent_error_cost_per_task&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;agent_error_rate&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1200&lt;/span&gt;  &lt;span class="c1"&gt;# $30.00
&lt;/span&gt;&lt;span class="n"&gt;agent_total_per_task&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;agent_cost_per_task&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;agent_error_cost_per_task&lt;/span&gt;  &lt;span class="c1"&gt;# $30.67
&lt;/span&gt;&lt;span class="n"&gt;agent_monthly&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;agent_total_per_task&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;monthly_volume&lt;/span&gt;                   &lt;span class="c1"&gt;# $245,360
&lt;/span&gt;
&lt;span class="c1"&gt;# ROI
&lt;/span&gt;&lt;span class="n"&gt;monthly_saving&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;human_monthly&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;agent_monthly&lt;/span&gt;         &lt;span class="c1"&gt;# $266,640
&lt;/span&gt;&lt;span class="n"&gt;integration_cost&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;180_000&lt;/span&gt;                            &lt;span class="c1"&gt;# one-time build
&lt;/span&gt;&lt;span class="n"&gt;break_even_months&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;integration_cost&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;monthly_saving&lt;/span&gt;  &lt;span class="c1"&gt;# ~0.7 months
&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Human per task:  $&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;human_total_per_task&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Agent per task:  $&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;agent_total_per_task&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Monthly saving:  $&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;monthly_saving&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;,.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Break-even:      &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;break_even_months&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; months&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agent: $30.67/task vs human $64.00, which is $33.33 saved per application, ~$266,000/month. Integration cost ($180K) is repaid in under a month.&lt;/p&gt;

&lt;p&gt;But this only holds because error cost was modeled honestly. If agent error rate were 6% instead of 2.5%, error cost would rise to $72/task and the agent would lose.&lt;/p&gt;

&lt;p&gt;Guardrails and eval suites hold error rate in the profitable range, which is why economics and engineering must build the model together.&lt;/p&gt;

&lt;h3&gt;
  
  
  Token Economics: From Price-Per-Million-Tokens to Cost-Per-Task
&lt;/h3&gt;

&lt;p&gt;Bedrock bills separately for input and output tokens, and the two rarely cost the same: output tokens on most foundation models run three to five times the input rate, because generation is the expensive half of inference. A production agentic AI economics model has to price a task by its full token profile, not by a single blended rate pulled from a pricing page.&lt;/p&gt;

&lt;p&gt;A document-review call that sends 1,800 input tokens of policy context and returns 220 output tokens of structured JSON is a fundamentally different cost shape than a chat turn that sends 200 tokens and returns 900.&lt;/p&gt;

&lt;p&gt;Three levers move the token bill more than model choice alone. &lt;strong&gt;Prompt caching&lt;/strong&gt; on Bedrock lets a repeated system prompt or a large policy document be cached across calls, cutting the input-token charge on every call after the first by roughly 90 percent for the cached portion, decisive for RAG-heavy agentic workloads where the same 2,000-token context accompanies every request.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Output-length discipline&lt;/strong&gt;, constraining the agent to structured, schema-bound output instead of free-form prose, shrinks the more expensive half of the bill directly; a JSON-only response mode routinely cuts output tokens by half against an unconstrained one. &lt;strong&gt;Context trimming&lt;/strong&gt;, summarizing or windowing conversation history instead of resending the full transcript every turn, keeps input tokens from growing quadratically across a long agent session.&lt;/p&gt;

&lt;p&gt;None of this shows up in the sticker price of a model. Two teams running the same Claude or Nova model on the same workload can see per-task inference cost differ by 3 to 4x purely on prompt engineering discipline, which is why agentic AI economics treats token shape, not model choice, as the primary cost lever engineers actually control.&lt;/p&gt;

&lt;h3&gt;
  
  
  Orchestration and Hosting: Step Functions and SageMaker in the Same Model
&lt;/h3&gt;

&lt;p&gt;Inference is rarely the whole bill. A four-step agentic workflow (retrieve, reason, call a tool, verify) orchestrated on Step Functions Standard costs one state transition per step at a fraction of a cent each; the same workflow on Step Functions Express, priced by request duration and memory rather than per-transition, is usually cheaper at high volume and short execution times, and more expensive at low volume with long-running steps.&lt;/p&gt;

&lt;p&gt;Modeling both and picking per workload, not defaulting to one, is worth real money at scale, and belongs in the same agentic AI economics spreadsheet as the inference line, not a separate infrastructure budget nobody reconciles against it.&lt;/p&gt;

&lt;p&gt;When an agent calls a custom fine-tuned model instead of a foundation model on Bedrock, the cost model shifts from per-token to per-instance-hour: a SageMaker real-time endpoint bills for the instance whether or not it is handling traffic, so a lightly used endpoint can cost more per task than a heavily used Bedrock on-demand call.&lt;/p&gt;

&lt;p&gt;SageMaker Serverless Inference or Bedrock Provisioned Throughput close that gap for spiky or highly predictable traffic respectively. Provisioned Throughput trades a flat hourly commitment for a much lower per-token rate once volume clears the break-even point, typically in the tens of millions of tokens per month.&lt;/p&gt;

&lt;p&gt;Include instance-hour or reserved-throughput cost in the per-task model exactly like Bedrock on-demand pricing; treating hosting as a fixed sunk cost outside the ROI calculation is how pilots that look profitable in a spreadsheet lose money in production.&lt;/p&gt;

&lt;h2&gt;
  
  
  Agentic AI Economics: Common Mistakes to Avoid
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Comparing agent cost to salary, not fully loaded cost&lt;/strong&gt;: biases the comparison either way.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Skipping error cost&lt;/strong&gt;: the most-decisive line item; omitting it inflates every pilot.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automating the hardest task first&lt;/strong&gt;: start with high-volume structured tasks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scaling on enthusiasm without telemetry&lt;/strong&gt;: hidden costs surface at full volume.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Flat pricing where pay-per-outcome fits&lt;/strong&gt;: match pricing to outcome measurement maturity.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Retiring pilots into permanent production&lt;/strong&gt;: set the ROI threshold before the pilot and act on “stop.”&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ignoring idle hosting cost&lt;/strong&gt;: a SageMaker real-time endpoint or a Bedrock Provisioned Throughput commitment bills by the hour whether or not it is handling traffic; size it to measured pilot traffic, not a guess, or the fixed cost erases the savings.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Treating token price as the whole inference bill&lt;/strong&gt;: output tokens, uncached context, and unconstrained response length routinely double or triple the per-task cost implied by a model's headline price-per-million-tokens.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each of these mistakes shares a root cause: modeling the sticker price instead of the delivered cost. Agentic AI economics done well prices a task the way finance prices a product: fully loaded, including the hosting commitment, the token shape, the oversight sampling rate, and the error-remediation cost, not the number on a pricing page.&lt;/p&gt;

&lt;p&gt;Teams that skip this step consistently overstate ROI in the pilot deck and understate it in the first monthly AWS bill, which is the single most common reason a promising pilot gets killed after month two instead of scaled.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffe2q1b4ynqtkkna5es1n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffe2q1b4ynqtkkna5es1n.png" alt="Agentic AI economics key concepts human vs agent cost pay-per-outcome ROI risk"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Human vs agent cost models and the pay-per-outcome shift. Adapted from AWS Prescriptive Guidance.&lt;/p&gt;

&lt;h2&gt;
  
  
  Agentic AI Economics: Best Practices
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Model fully loaded human cost before any automation decision.&lt;/li&gt;
&lt;li&gt;Track an ROI dashboard: cost per task, throughput multiplier, error + rework cost, time-to-value.&lt;/li&gt;
&lt;li&gt;Start with high-volume structured tasks; defer ambiguous, high-stakes, or low-volume work.&lt;/li&gt;
&lt;li&gt;Price error cost as a first-class line item.&lt;/li&gt;
&lt;li&gt;Use tiered model selection on Bedrock: cheap models for easy cases, larger for hard.&lt;/li&gt;
&lt;li&gt;Instrument the attribution pipeline early to enable pay-per-outcome later.&lt;/li&gt;
&lt;li&gt;Scale in stages (10%, 50%, 100%) watching unit cost and error cost.&lt;/li&gt;
&lt;li&gt;Run the portfolio like an asset book: rebalance quarterly.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cost governance turns these practices from good intentions into an enforced discipline. Tag every Bedrock, Lambda, Step Functions, and SageMaker resource by agent and by task type, then pull a Cost Explorer report grouped by tag monthly. Without tagging, agentic AI economics collapses into one opaque AWS bill line that nobody can attribute to a specific automation's ROI.&lt;/p&gt;

&lt;p&gt;Set an AWS Budgets alert per agent so a runaway retry loop or a prompt regression that balloons token usage surfaces in hours, not at the end of the billing cycle.&lt;/p&gt;

&lt;p&gt;Quantify the caching and batching levers instead of assuming they help. Bedrock prompt caching, batch inference for non-real-time workloads, and SageMaker Savings Plans for steady-state hosting each independently cut 20 to 60 percent off their respective cost lines when applicable, layered together across a mature agentic AI economics program, they are usually the difference between a pilot that clears its ROI bar and one that does not.&lt;/p&gt;

&lt;p&gt;Re-run the model whenever AWS changes a price, a new model tier ships, or task volume moves by more than 20 percent; a cost table is a snapshot, not a constant.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffvalkbcarmv5h5qd6rgh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffvalkbcarmv5h5qd6rgh.png" alt="Agentic AI economics ROI best practices tiered models guardrails pay-per-outcome"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;ROI best practices: tiered models, honest error cost, staged scaling. Adapted from AWS Prescriptive Guidance.&lt;/p&gt;

&lt;h2&gt;
  
  
  Agentic AI Economics: Frequently Asked Questions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What is agentic AI economics and why does it matter?
&lt;/h3&gt;

&lt;p&gt;The structured comparison of human labor cost against agentic AI system cost, accounting for total economic impact, risk, and strategic value. It matters because naive comparisons mislead: an agent can look cheaper per task and cost more once error is counted.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is pay-per-outcome pricing?
&lt;/h3&gt;

&lt;p&gt;You pay only when the agent delivers a measurable business result. It aligns vendor and customer risk, makes ROI self-evident, and is self-funding as volume grows. It demands strong attribution.&lt;/p&gt;

&lt;h3&gt;
  
  
  When does automation not make economic sense?
&lt;/h3&gt;

&lt;p&gt;When volume is too low to amortize integration cost, ambiguity too high to measure success, or error cost overwhelms the per-task saving.&lt;/p&gt;

&lt;h3&gt;
  
  
  How do I calculate the ROI of an agentic AI workload on AWS?
&lt;/h3&gt;

&lt;p&gt;Start with fully loaded human cost: salary, overhead, latency, error rate, recurring training. Compare against agent cost: Bedrock inference per million tokens, Lambda per invocation, Step Functions per state transition, AgentCore per session, plus monitoring overhead. Agentic AI economics rewards teams that measure outcome-adjusted return: a deflected support contact is worth more than a successful API call.&lt;/p&gt;

&lt;p&gt;Net annual value equals per-task saving times volume, minus integration cost, minus annual error-cost delta. Run the dashboard monthly; retire agents whose ROI declines for two quarters.&lt;/p&gt;

&lt;h3&gt;
  
  
  What AWS services drive the biggest unit-cost savings for agentic AI?
&lt;/h3&gt;

&lt;p&gt;Three levers dominate. Tiered model selection routes the easy 80 percent of traffic to Claude Haiku or Amazon Nova Micro at fractions of a cent per thousand tokens, reserving Claude Sonnet or Nova Pro for the hard 20 percent. Bedrock prompt caching cuts input token cost for RAG-heavy pipelines. Bedrock model invocation jobs handle batch workloads at reduced pricing.&lt;/p&gt;

&lt;p&gt;Layered together, these agentic AI economics levers typically produce a 60 to 80 percent cost reduction versus a single-model baseline. Agentic AI economics on AWS rewards teams that measure cost-per-task monthly, retire agents whose agentic AI economics deteriorate, and double down on agents whose pay-per-outcome is rising.&lt;/p&gt;

&lt;p&gt;The agentic AI economics stack (Bedrock per-token, Lambda per-invocation, Step Functions per-transition, AgentCore per-session) turns abstract AI cost into auditable line items.&lt;/p&gt;

&lt;p&gt;[ays_quiz id=73]&lt;/p&gt;

&lt;h2&gt;
  
  
  Agentic AI Economics: Key Takeaways
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Core question is outcome-adjusted return&lt;/strong&gt;, not raw unit cost: weigh human and agent error honestly.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Count fully loaded human cost&lt;/strong&gt;: salary, overhead, latency, error, recurring training.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Agent cost&lt;/strong&gt; = inference + infra + prompts + monitoring, mapped to AWS primitives.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pay-per-outcome aligns cost with result&lt;/strong&gt;: shifts risk to vendor, makes ROI self-evident.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automate high-volume structured tasks first&lt;/strong&gt;; defer ambiguous or high-stakes work.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Measure ROI with a dashboard&lt;/strong&gt;, never a single number.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scale winners, retire failures&lt;/strong&gt;: rebalance quarterly.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Risk economics is the deciding line item&lt;/strong&gt;: invest in guardrails that hold error rate in the profitable range.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Agentic AI economics comes down to one discipline: price the fully loaded human alternative, price the fully loaded agent (inference, hosting, and error cost together) and let the honest gap decide what gets automated and when it scales. Get the token shape and the error-cost line right, and the agentic AI economics of a well-run program compound quarter over quarter.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>ai</category>
      <category>economics</category>
      <category>bedrock</category>
    </item>
    <item>
      <title>Running Claude Code on AWS Bedrock: IAM, SCPs, and the Governance Model Most Teams Get Wrong</title>
      <dc:creator>Amar Tinawi</dc:creator>
      <pubDate>Mon, 03 Aug 2026 12:00:00 +0000</pubDate>
      <link>https://dev.to/amartinawi/running-claude-code-on-aws-bedrock-iam-scps-and-the-governance-model-most-teams-get-wrong-3ojm</link>
      <guid>https://dev.to/amartinawi/running-claude-code-on-aws-bedrock-iam-scps-and-the-governance-model-most-teams-get-wrong-3ojm</guid>
      <description>&lt;p&gt;&lt;em&gt;Cross-posted with permission from &lt;a href="https://iqraa.tech?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=claude-code" rel="noopener noreferrer"&gt;iqraa.tech&lt;/a&gt; — the &lt;a href="https://iqraa.tech/ai-genai/claude/claude-code-aws-bedrock/?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=claude-code" rel="noopener noreferrer"&gt;full guide&lt;/a&gt; has the complete IAM policy, SCP examples, and a 300-engineer rollout case study.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Claude Code has a Bedrock mode. Most people find out about it from a single environment variable — &lt;code&gt;CLAUDE_CODE_USE_BEDROCK=1&lt;/code&gt; — and assume that's the whole story. It isn't. The env var is the on-switch; the IAM policy, region strategy, and governance layer around it are where almost every enterprise rollout actually gets stuck.&lt;/p&gt;

&lt;p&gt;I run through the deployment end to end below — the parts that matter for a platform team, not just "here's a flag."&lt;/p&gt;

&lt;h2&gt;
  
  
  Why route through Bedrock at all
&lt;/h2&gt;

&lt;p&gt;The models are identical either way. What changes is procurement, governance, and audit:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Consolidated billing.&lt;/strong&gt; An AWS spend commitment absorbs Bedrock usage instead of opening a separate Anthropic contract.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data residency.&lt;/strong&gt; Bedrock lets you pin inference to a region — direct Anthropic API gives you far less control over where a request lands.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SCP-level guardrails.&lt;/strong&gt; You can restrict &lt;em&gt;which&lt;/em&gt; IAM principals, accounts, or regions may invoke Bedrock at all. That control doesn't exist on the direct API.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CloudTrail auditability.&lt;/strong&gt; Every invocation lands in CloudTrail with caller identity, source IP, region, and model ID — append-only and SIEM-ready.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The environment variables
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;CLAUDE_CODE_USE_BEDROCK&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;AWS_REGION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;us-east-1
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;ANTHROPIC_MODEL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;us.anthropic.claude-sonnet-4-6-20250610-v1:0
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;AWS_PROFILE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;claude-code-prod
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note the model ID format difference — direct Anthropic uses &lt;code&gt;claude-sonnet-4-6&lt;/code&gt;; Bedrock uses inference-profile IDs like &lt;code&gt;us.anthropic.claude-sonnet-4-6-20250610-v1:0&lt;/code&gt;. The &lt;code&gt;us.&lt;/code&gt; prefix means AWS load-balances the request across US regions for resilience. Drop the prefix and you're pinned to one region only. Mixing the two ID formats is the single most common "model not found" error teams hit on day one.&lt;/p&gt;

&lt;h2&gt;
  
  
  The IAM policy (minimum viable, not &lt;code&gt;bedrock:*&lt;/code&gt;)
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2012-10-17"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Statement"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Sid"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"InvokeClaudeModels"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Effect"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Allow"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"bedrock:InvokeModel"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"bedrock:InvokeModelWithResponseStream"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Resource"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"arn:aws:bedrock:us-east-1::foundation-model/anthropic.claude-sonnet-*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"arn:aws:bedrock:us-east-1::foundation-model/anthropic.claude-opus-*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"arn:aws:bedrock:us-east-1::foundation-model/anthropic.claude-haiku-*"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Sid"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"UseCrossRegionInferenceProfiles"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Effect"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Allow"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"bedrock:InvokeModel"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"bedrock:InvokeModelWithResponseStream"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Resource"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"arn:aws:bedrock:us-east-1:*:inference-profile/us.anthropic.claude-*"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Sid"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ListFoundationModels"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Effect"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Allow"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"bedrock:ListFoundationModels"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Resource"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"*"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two details that trip people up:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;InvokeModelWithResponseStream&lt;/code&gt; is a &lt;em&gt;separate&lt;/em&gt; permission from &lt;code&gt;InvokeModel&lt;/code&gt;. Miss it and Claude Code falls back to one-shot invocation — it still works, but feels sluggish and streaming sessions fail.&lt;/li&gt;
&lt;li&gt;Never grant &lt;code&gt;Resource: "*"&lt;/code&gt; on Bedrock invoke actions. Bedrock also hosts Llama, Mistral, Nova, and marketplace models with their own cost/security profile. Scope to &lt;code&gt;anthropic.claude-*&lt;/code&gt; ARNs only, so a leaked credential's blast radius stays limited to Anthropic models.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The gotcha nobody expects: model access provisioning
&lt;/h2&gt;

&lt;p&gt;New AWS accounts don't have Claude models enabled by default. You have to explicitly request access per model per region in the Bedrock console, and approval can take anywhere from minutes to several hours — not instant, despite what the console implies. Request access to Haiku, Sonnet, &lt;em&gt;and&lt;/em&gt; Opus up front, even if you're only using Sonnet today, so a future model switch doesn't get blocked by a multi-hour provisioning delay mid-rollout.&lt;/p&gt;

&lt;h2&gt;
  
  
  SCPs: the actual governance layer
&lt;/h2&gt;

&lt;p&gt;IAM controls what a role &lt;em&gt;can&lt;/em&gt; do; SCPs control what an entire AWS account can do, org-wide:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2012-10-17"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Statement"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Sid"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"DenyBedrockOutsideApprovedRegions"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Effect"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Deny"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"bedrock:*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Resource"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Condition"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"StringNotEquals"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"aws:RequestedRegion"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"us-east-1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"eu-west-1"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Sid"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"DenyNonAnthropicBedrockModels"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Effect"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Deny"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"bedrock:InvokeModel"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"bedrock:InvokeModelWithResponseStream"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Resource"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"arn:aws:bedrock:*:*:foundation-model/*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Condition"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"StringNotLike"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"bedrock:FoundationModelArn"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"arn:aws:bedrock:*:*:foundation-model/anthropic.claude-*"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Layer this with an IAM permission boundary and the inline invoke policy above, and you get the same three-layer model mature shops already use for IAM and KMS: SCP governs the org, permission boundary governs what roles developers can create, inline policy governs what Claude Code itself can invoke.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cost levers that actually move the number
&lt;/h2&gt;

&lt;p&gt;The headline per-token rate is the ceiling, not what you'll actually pay:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Prompt caching&lt;/strong&gt; — cached tokens bill at ~10% of normal input rate. A stable &lt;code&gt;CLAUDE.md&lt;/code&gt; (no dynamic timestamps/build IDs) keeps cache hits high; that alone routinely cuts effective input cost 80-90% on long sessions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Model routing&lt;/strong&gt; — Haiku input is $0.80/M tokens vs. Opus at $15/M. Review your actual model mix after 30 days; Opus dominating usually means either a &lt;code&gt;CLAUDE.md&lt;/code&gt; that isn't giving Sonnet enough structure, or developers manually overriding the default.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;--max-budget-usd&lt;/code&gt; in CI&lt;/strong&gt; — without a hard cap, a runaway agent loop in a failed pipeline is the most common cost-overrun story in early adoption. $5/pipeline is a reasonable default for routine tasks.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Auth: use the credential chain you already have
&lt;/h2&gt;

&lt;p&gt;Claude Code on Bedrock rides the standard AWS SDK credential chain — no custom auth to build. AWS SSO for developer workstations (&lt;code&gt;aws sso login&lt;/code&gt;, short-lived creds, single point of revocation), OIDC federation for CI/CD (GitHub Actions/GitLab/Jenkins all support it — no static secrets), instance/task roles for EC2/ECS. If you're stuck on long-lived access keys, rotate quarterly via Secrets Manager + a rotator Lambda, not manually.&lt;/p&gt;

&lt;h2&gt;
  
  
  The five failure modes that generate the most support tickets
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Skipping the model-access request (blocks launch for hours)&lt;/li&gt;
&lt;li&gt;Wrong model ID format — direct vs. cross-region vs. single-region Bedrock IDs&lt;/li&gt;
&lt;li&gt;Missing &lt;code&gt;InvokeModelWithResponseStream&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Wildcard IAM resources on Bedrock invoke actions&lt;/li&gt;
&lt;li&gt;No SCP region pinning — developers &lt;em&gt;will&lt;/em&gt; invoke from unintended regions if nothing stops them&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;Full write-up (including a worked 300-engineer financial-services rollout, VPC endpoint config, and provisioned-throughput break-even math) is here: &lt;strong&gt;&lt;a href="https://iqraa.tech/ai-genai/claude/claude-code-aws-bedrock/?utm_source=devto&amp;amp;utm_medium=referral&amp;amp;utm_campaign=claude-code" rel="noopener noreferrer"&gt;Claude Code AWS Bedrock: Enterprise Setup Guide&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Happy to answer questions on IAM/SCP specifics in the comments — I set up a few of these rollouts and the model-access delay catches everyone the first time.&lt;br&gt;
``&lt;/p&gt;

</description>
      <category>aws</category>
      <category>claudecode</category>
      <category>devops</category>
      <category>bedrock</category>
    </item>
    <item>
      <title>EKS Diagnoses: The Swiss Knife</title>
      <dc:creator>Amar Tinawi</dc:creator>
      <pubDate>Fri, 20 Mar 2026 22:40:35 +0000</pubDate>
      <link>https://dev.to/aws-builders/eks-diagnoses-the-swiss-knife-1no9</link>
      <guid>https://dev.to/aws-builders/eks-diagnoses-the-swiss-knife-1no9</guid>
      <description>&lt;h2&gt;
  
  
  The 2 AM wake-up call every Kubernetes engineer dreads — and the tool I built to make it less painful
&lt;/h2&gt;

&lt;p&gt;It's 2 AM. PagerDuty fires. Pods are crashing across your EKS cluster. You SSH in, bleary-eyed, and start the ritual:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl get pods &lt;span class="nt"&gt;--all-namespaces&lt;/span&gt; | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-v&lt;/span&gt; Running
kubectl describe pod &amp;lt;that-one-pod&amp;gt;
kubectl get events &lt;span class="nt"&gt;--sort-by&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;.lastTimestamp
kubectl logs &amp;lt;pod&amp;gt; &lt;span class="nt"&gt;--previous&lt;/span&gt;
kubectl top nodes
kubectl describe node &amp;lt;node&amp;gt;
aws eks describe-cluster ...
aws logs filter-log-events ...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Twenty minutes in, you're staring at a wall of YAML. You've checked six things. You still don't know the &lt;em&gt;root cause&lt;/em&gt;. You don't even know if the node pressure caused the evictions, or if the evictions caused the node pressure.&lt;/p&gt;

&lt;p&gt;After living this loop for two years across dozens of EKS clusters, I built a tool to automate the entire diagnostic process. It runs &lt;strong&gt;73 analysis methods in parallel&lt;/strong&gt;, correlates findings across data sources, identifies the root cause with a confidence score, and hands you a single interactive report — in about 60 seconds.&lt;/p&gt;

&lt;p&gt;This is the &lt;strong&gt;EKS Comprehensive Debugger&lt;/strong&gt;, and here's why it exists and how it works.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhnlzbl04div4x7zqyym7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhnlzbl04div4x7zqyym7.png" alt=" " width="720" height="215"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  The Problem: EKS Troubleshooting Is a Scavenger Hunt
&lt;/h2&gt;

&lt;p&gt;Kubernetes failures are rarely isolated. A single root cause — say, a node running out of memory — cascades into a chain of symptoms: pod evictions, rescheduling failures, service endpoint gaps, and eventually user-facing 5xx errors. By the time you're paged, you're looking at the &lt;em&gt;end&lt;/em&gt; of that chain.&lt;/p&gt;

&lt;p&gt;The diagnostic challenge isn't running &lt;code&gt;kubectl&lt;/code&gt;. It's knowing &lt;strong&gt;which&lt;/strong&gt; of the 50+ things to check, &lt;strong&gt;in what order&lt;/strong&gt;, and then &lt;strong&gt;correlating&lt;/strong&gt; findings across completely different data sources — Kubernetes events, pod status, node conditions, CloudWatch metrics, control plane logs, VPC networking, IAM roles, and AWS service quotas — to find the one thing that started it all.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2dqndr4x9z31xue4kpt3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2dqndr4x9z31xue4kpt3.png" alt=" " width="720" height="463"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Most teams solve this in one of three ways:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Tribal knowledge.&lt;/strong&gt; The senior engineer who's "seen this before" runs their mental playbook. Works great until they're on vacation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Runbooks.&lt;/strong&gt; Documented checklists. Better, but they go stale, they can't correlate across data sources, and nobody reads a 40-step runbook at 2 AM.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Observability platforms.&lt;/strong&gt; Datadog, Grafana, New Relic. Excellent for monitoring, but they show you dashboards — they don't &lt;em&gt;diagnose&lt;/em&gt;. You still need to interpret the data and connect the dots yourself.&lt;/p&gt;

&lt;p&gt;None of these answer the question an on-call engineer actually needs answered: &lt;strong&gt;"What broke, why, and what do I do about it?"&lt;/strong&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  What the Tool Does
&lt;/h2&gt;

&lt;p&gt;The EKS Comprehensive Debugger is a single Python script that connects to your cluster and systematically checks everything. It pulls data from four sources simultaneously:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Kubernetes API (via &lt;code&gt;kubectl&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;AWS EKS API&lt;/li&gt;
&lt;li&gt;CloudWatch Logs&lt;/li&gt;
&lt;li&gt;CloudWatch Metrics&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It runs 73 analysis methods in parallel, correlates findings to identify root causes, and generates two output files:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;An &lt;strong&gt;interactive HTML dashboard&lt;/strong&gt; for humans&lt;/li&gt;
&lt;li&gt;An &lt;strong&gt;LLM-ready JSON file&lt;/strong&gt; for AI analysis&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One command, one minute, complete picture.&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/amartinawi" rel="noopener noreferrer"&gt;
        amartinawi
      &lt;/a&gt; / &lt;a href="https://github.com/amartinawi/EKS_Dubugger" rel="noopener noreferrer"&gt;
        EKS_Dubugger
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Production-grade Python diagnostic tool for Amazon EKS cluster troubleshooting
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;EKS Health Check Dashboard&lt;/h1&gt;
&lt;/div&gt;

&lt;p&gt;&lt;a href="https://www.python.org/downloads/" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/bd7bcdc70784bad7073b66850c51f4fed5dc3b2fc782277551b9013c7d27f043/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f707974686f6e2d332e382b2d626c75652e737667" alt="Python 3.8+"&gt;&lt;/a&gt;
&lt;a href="https://opensource.org/licenses/MIT" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/fdf2982b9f5d7489dcf44570e714e3a15fce6253e0cc6b5aa61a075aac2ff71b/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c6963656e73652d4d49542d79656c6c6f772e737667" alt="License: MIT"&gt;&lt;/a&gt;
&lt;a href="https://aws.amazon.com/eks/" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/c4b298e68a1680baa3694e791a271783162df364b877f02d48d0ec1a5b326ca2/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4157532d454b532d6f72616e67652e737667" alt="AWS EKS"&gt;&lt;/a&gt;
&lt;a href="https://github.com/amartinawi/EKS_Dubugger#catalog-coverage" rel="noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/e80ec49eb622898f05ee5c727595462f0589a67f2698768570a297ccbe27338e/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f636174616c6f67253230636f7665726167652d3130302532352d677265656e2e737667" alt="Catalog Coverage"&gt;&lt;/a&gt;
&lt;a href="https://github.com/amartinawi/EKS_Dubugger#unit-tests" rel="noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/7369760a50cc4d73be94a0d51d51e6598ecd95b198ed0d29a8eeba608af9b151/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f74657374732d3338342d627269676874677265656e2e737667" alt="Tests"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;A production-grade Python diagnostic tool for Amazon EKS cluster troubleshooting. Analyzes pod evictions, node conditions, OOM kills, CloudWatch metrics, control plane logs, and generates interactive HTML reports with LLM-ready JSON for AI analysis.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Version:&lt;/strong&gt; 5.0.0 | &lt;strong&gt;Analysis Methods:&lt;/strong&gt; 84 | &lt;strong&gt;Catalog Coverage:&lt;/strong&gt; 100% | &lt;strong&gt;Tests:&lt;/strong&gt; 384&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Features&lt;/h2&gt;
&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Comprehensive Issue Detection (84 Analysis Methods)&lt;/h3&gt;
&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h4 class="heading-element"&gt;Pod &amp;amp; Workload Issues&lt;/h4&gt;

&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;CrashLoopBackOff&lt;/strong&gt; - Container crash detection with exit code analysis&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ImagePullBackOff&lt;/strong&gt; - Registry authentication, rate limits, network issues&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;OOMKilled&lt;/strong&gt; - Memory limit exceeded detection&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pod Evictions&lt;/strong&gt; - Memory, disk, PID pressure analysis&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Probe Failures&lt;/strong&gt; - Liveness/readiness probe failures&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Init Container Failures&lt;/strong&gt; - Init container crash, timeout, dependency issues (v3.6.0)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sidecar Health&lt;/strong&gt; - Istio, Envoy, Fluentd sidecar failures (v3.6.0)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stuck Terminating&lt;/strong&gt; - Finalizer and volume detach issues&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deployment Rollouts&lt;/strong&gt; - ProgressDeadlineExceeded detection&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Jobs/CronJobs&lt;/strong&gt; - BackoffLimitExceeded, missed schedules&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;StatefulSets&lt;/strong&gt; - PVC issues, ordinal failures&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;PDB Violations&lt;/strong&gt; - Pod Disruption Budget blocking drains…&lt;/li&gt;
&lt;/ul&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/amartinawi/EKS_Dubugger" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;





&lt;h2&gt;
  
  
  The 73 Checks: What It Actually Analyzes
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu6t21bmxo8mw1izipiyv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu6t21bmxo8mw1izipiyv.png" alt=" " width="720" height="463"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The tool covers the full EKS stack in categories that map to how failures actually cascade:&lt;/p&gt;

&lt;h3&gt;
  
  
  Pod &amp;amp; Workload Issues
&lt;/h3&gt;

&lt;p&gt;CrashLoopBackOff, OOMKilled, ImagePullBackOff, stuck terminating pods, failed init containers, broken sidecar proxies, deployment rollout failures, StatefulSet issues, PDB violations.&lt;/p&gt;

&lt;h3&gt;
  
  
  Node Health
&lt;/h3&gt;

&lt;p&gt;NotReady nodes, disk/memory/PID pressure, resource saturation &lt;em&gt;(a leading indicator at 90% allocation, before kubelet pressure triggers)&lt;/em&gt;, PLEG issues, container runtime health, kubelet version skew, outdated AMIs.&lt;/p&gt;

&lt;h3&gt;
  
  
  Networking
&lt;/h3&gt;

&lt;p&gt;VPC CNI IP exhaustion, CoreDNS failures, DNS ndots:5 amplification, services with no endpoints, missing Ingress backends, ALB health, conntrack table exhaustion, security group misconfigurations.&lt;/p&gt;

&lt;h3&gt;
  
  
  Control Plane
&lt;/h3&gt;

&lt;p&gt;API server latency and rate limiting, etcd health, controller manager reconciliation failures, admission webhook timeouts, scheduler issues.&lt;/p&gt;

&lt;h3&gt;
  
  
  Storage
&lt;/h3&gt;

&lt;p&gt;Pending PVCs, EBS CSI attachment failures, EFS mount issues, failed volume snapshots.&lt;/p&gt;

&lt;h3&gt;
  
  
  IAM &amp;amp; Security
&lt;/h3&gt;

&lt;p&gt;RBAC errors, IRSA/Pod Identity credential failures, privileged containers, sensitive host path mounts, PSA violations.&lt;/p&gt;

&lt;h3&gt;
  
  
  Autoscaling
&lt;/h3&gt;

&lt;p&gt;Cluster Autoscaler issues, Karpenter provisioning and drift, HPA metrics source health, topology spread constraint violations.&lt;/p&gt;

&lt;p&gt;Each finding is classified as either:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Historical Event&lt;/strong&gt; — something that happened during your scan window&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Current State&lt;/strong&gt; — what the cluster looks like right now&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This distinction separates "what's happening now" from "what happened during the incident window."&lt;/p&gt;




&lt;h2&gt;
  
  
  The Part That Actually Matters: Root Cause Detection
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjaxdxv3h8303ypnjrzj8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjaxdxv3h8303ypnjrzj8.png" alt=" " width="720" height="463"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Listing problems is easy. Any monitoring tool can tell you "5 pods crashed." The hard part is answering &lt;em&gt;why&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;The debugger's correlation engine connects findings across data sources using a &lt;strong&gt;5-dimensional confidence scoring system&lt;/strong&gt;:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Dimension&lt;/th&gt;
&lt;th&gt;Weight&lt;/th&gt;
&lt;th&gt;What It Measures&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Temporal&lt;/td&gt;
&lt;td&gt;30%&lt;/td&gt;
&lt;td&gt;Did the cause happen &lt;em&gt;before&lt;/em&gt; the effect?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Spatial&lt;/td&gt;
&lt;td&gt;20%&lt;/td&gt;
&lt;td&gt;Same node, namespace, or pod?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mechanism&lt;/td&gt;
&lt;td&gt;25%&lt;/td&gt;
&lt;td&gt;Known causal relationship?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Exclusivity&lt;/td&gt;
&lt;td&gt;15%&lt;/td&gt;
&lt;td&gt;Only plausible explanation?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Reproducibility&lt;/td&gt;
&lt;td&gt;10%&lt;/td&gt;
&lt;td&gt;Pattern occurred multiple times?&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;These combine into a composite confidence score mapped to a tier: &lt;strong&gt;high&lt;/strong&gt; (≥75%), &lt;strong&gt;medium&lt;/strong&gt; (≥50%), or &lt;strong&gt;low&lt;/strong&gt; (&amp;lt;50%).&lt;/p&gt;

&lt;p&gt;Here's what a real detection looks like in the JSON output — a cluster upgrade identified as root cause with 92% confidence:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"potential_root_causes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"correlation_type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"cluster_upgrade"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"root_cause"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Cluster version upgrade in progress or recently completed"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"confidence_tier"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"high"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"composite_confidence"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.92&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"confidence_5d"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"temporal"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"spatial"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"mechanism"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"exclusivity"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"reproducibility"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;temporal: 1.0&lt;/code&gt; — the AWS API confirmed the upgrade timestamp preceded all other findings.&lt;br&gt;
&lt;code&gt;mechanism: 1.0&lt;/code&gt; — "cluster upgrade causes transient failures" is a well-established causal relationship.&lt;br&gt;
&lt;code&gt;reproducibility: 0.0&lt;/code&gt; — upgrades are one-time events. The other four dimensions still provide strong evidence.&lt;/p&gt;

&lt;p&gt;This is the reasoning a senior SRE does intuitively. The tool makes it systematic, consistent, and available at 2 AM without waking anyone up.&lt;/p&gt;


&lt;h2&gt;
  
  
  Actionable Output: Not Just What's Wrong — What to Do
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx6dytn8zd69b0dn18m5r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx6dytn8zd69b0dn18m5r.png" alt=" " width="720" height="463"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Every finding includes contextual remediation with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Diagnostic commands to investigate further&lt;/li&gt;
&lt;li&gt;Fix commands to resolve the issue&lt;/li&gt;
&lt;li&gt;Both &lt;strong&gt;pre-populated with actual resource names&lt;/strong&gt; from your cluster&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The commands aren't generic templates — that's &lt;code&gt;sg-0af46ef489f81f6d0&lt;/code&gt;, the actual security group from the cluster. Copy, paste, run.&lt;/p&gt;


&lt;h2&gt;
  
  
  The LLM-Ready JSON: Built for AI Analysis
&lt;/h2&gt;

&lt;p&gt;The HTML report is for humans. The JSON is for AI.&lt;/p&gt;

&lt;p&gt;Every run produces a structured JSON file optimized for feeding into an LLM. The schema includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Full analysis context (cluster, region, time range)&lt;/li&gt;
&lt;li&gt;Findings with severity classifications&lt;/li&gt;
&lt;li&gt;5D confidence-scored correlations&lt;/li&gt;
&lt;li&gt;Prioritized recommendations&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Practical workflow: paste the JSON into Claude or GPT and ask, &lt;em&gt;"What's the most important thing to fix first and why?"&lt;/em&gt; The confidence tiers and spatial evidence give the model enough context to prioritize correctly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Run the analysis&lt;/span&gt;
python eks_comprehensive_debugger.py &lt;span class="nt"&gt;--profile&lt;/span&gt; prod &lt;span class="nt"&gt;--region&lt;/span&gt; eu-west-1 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--cluster-name&lt;/span&gt; production &lt;span class="nt"&gt;--days&lt;/span&gt; 1

&lt;span class="c"&gt;# Two files generated:&lt;/span&gt;
&lt;span class="c"&gt;# production-eks-report-20260301-035821.html    ← for humans&lt;/span&gt;
&lt;span class="c"&gt;# production-eks-findings-20260301-035821.json   ← for AI&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  How to Run It
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Clone and install&lt;/span&gt;
git clone https://github.com/amartinawi/EKS_Dubugger
&lt;span class="nb"&gt;cd &lt;/span&gt;eks-debugger
pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; requirements.txt

&lt;span class="c"&gt;# Basic usage (auto-detects cluster)&lt;/span&gt;
python eks_comprehensive_debugger.py &lt;span class="nt"&gt;--profile&lt;/span&gt; prod &lt;span class="nt"&gt;--region&lt;/span&gt; eu-west-1

&lt;span class="c"&gt;# Incident investigation: last 2 hours&lt;/span&gt;
python eks_comprehensive_debugger.py &lt;span class="nt"&gt;--profile&lt;/span&gt; prod &lt;span class="nt"&gt;--region&lt;/span&gt; eu-west-1 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--cluster-name&lt;/span&gt; my-cluster &lt;span class="nt"&gt;--hours&lt;/span&gt; 2

&lt;span class="c"&gt;# Post-mortem: specific time window&lt;/span&gt;
python eks_comprehensive_debugger.py &lt;span class="nt"&gt;--profile&lt;/span&gt; prod &lt;span class="nt"&gt;--region&lt;/span&gt; eu-west-1 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--cluster-name&lt;/span&gt; my-cluster &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--start-date&lt;/span&gt; &lt;span class="s2"&gt;"2026-01-26T08:00:00"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--end-date&lt;/span&gt; &lt;span class="s2"&gt;"2026-01-27T18:00:00"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--timezone&lt;/span&gt; &lt;span class="s2"&gt;"America/New_York"&lt;/span&gt;

&lt;span class="c"&gt;# Private cluster via SSM tunnel&lt;/span&gt;
python eks_comprehensive_debugger.py &lt;span class="nt"&gt;--profile&lt;/span&gt; prod &lt;span class="nt"&gt;--region&lt;/span&gt; eu-west-1 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--cluster-name&lt;/span&gt; my-cluster &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--kube-context&lt;/span&gt; my-cluster-ssm-tunnel
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Prerequisites:&lt;/strong&gt; Python 3.8+, &lt;code&gt;kubectl&lt;/code&gt; configured, AWS CLI with credentials. Read-only access to EKS, CloudWatch, EC2 — no write permissions required.&lt;/p&gt;




&lt;h2&gt;
  
  
  What I Learned Building This
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Most EKS issues are knowable from existing data.&lt;/strong&gt; The Kubernetes API and CloudWatch already have the information to diagnose 90% of problems. The bottleneck isn't data collection — it's knowing what to look for and how to connect the dots.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Root cause detection is about correlation, not classification.&lt;/strong&gt; Classifying a finding as "critical" is easy. Determining that &lt;em&gt;this&lt;/em&gt; node pressure caused &lt;em&gt;those&lt;/em&gt; pod evictions on &lt;em&gt;that&lt;/em&gt; node during &lt;em&gt;this&lt;/em&gt; time window requires reasoning across multiple dimensions. Spatial correlation — matching cause and effect by node/pod/namespace identity — was the single biggest accuracy improvement.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The tool is most valuable when nothing is wrong.&lt;/strong&gt; Running it proactively — after an upgrade, after a config change, as part of a weekly health check — catches issues before they page you. Version skew detection, deprecated API scanning, and resource saturation warnings are all leading indicators.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;AI-ready output changes the workflow.&lt;/strong&gt; Structured JSON with confidence-scored root causes means you can ask an AI assistant to explain findings, draft an incident report, or suggest an architecture change — and it has enough structured evidence to do it well.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffa8h40vtj7nx24rty1r8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffa8h40vtj7nx24rty1r8.png" alt=" " width="720" height="463"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  What's Next
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;CI/CD integration&lt;/strong&gt; — Run as a post-deployment check; fail the deployment if critical issues are detected.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scheduled health reports&lt;/strong&gt; — Weekly automated runs with delta reporting.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multi-cluster support&lt;/strong&gt; — Aggregate findings across clusters for fleet-wide visibility.&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;If you're managing EKS clusters and spending too much time on diagnostics, give it a try. The tool is open source, a single Python file, no infrastructure dependencies — just point it at your cluster and run.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GitHub:&lt;/strong&gt; &lt;a href="https://github.com/amartinawi/EKS_Dubugger" rel="noopener noreferrer"&gt;https://github.com/amartinawi/EKS_Dubugger&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Issues, PRs, and feature ideas welcome.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>aws</category>
      <category>eks</category>
      <category>kubernetes</category>
      <category>k8s</category>
    </item>
  </channel>
</rss>
