<?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: Haowen Huang</title>
    <description>The latest articles on DEV Community by Haowen Huang (@haowen_huang).</description>
    <link>https://dev.to/haowen_huang</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%2F1578798%2F23e6f9b0-33a5-48c2-9eb7-9936394625dd.png</url>
      <title>DEV Community: Haowen Huang</title>
      <link>https://dev.to/haowen_huang</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/haowen_huang"/>
    <language>en</language>
    <item>
      <title>Agent Toolkit for AWS in Practice (1) - Claude Code</title>
      <dc:creator>Haowen Huang</dc:creator>
      <pubDate>Sun, 06 Sep 2026 08:24:59 +0000</pubDate>
      <link>https://dev.to/haowen_huang/agent-toolkit-for-aws-in-practice-1-claude-code-pi8</link>
      <guid>https://dev.to/haowen_huang/agent-toolkit-for-aws-in-practice-1-claude-code-pi8</guid>
      <description>&lt;p&gt;&lt;em&gt;Part 1 of the series "Agent Toolkit for AWS in Practice."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Agent Toolkit for AWS gives your coding agent two things it normally lacks: curated knowledge of how AWS services are meant to be used, and a way to actually call them. Setup is one command.&lt;/p&gt;

&lt;p&gt;This walkthrough covers the install, two verification tasks against a real account, and three things worth knowing before you rely on it. Every command and output below is from an actual run on macOS with Claude Code.&lt;/p&gt;




&lt;h2&gt;
  
  
  What you're installing
&lt;/h2&gt;

&lt;p&gt;Two independent pieces. Knowing which is which saves time when something misbehaves.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Piece&lt;/th&gt;
&lt;th&gt;Role&lt;/th&gt;
&lt;th&gt;Where it lives&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Agent Skills&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;AWS knowledge — service selection, tested procedures, troubleshooting&lt;/td&gt;
&lt;td&gt;Files on your disk&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;AWS MCP Server&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Lets the agent call AWS APIs and search current docs&lt;/td&gt;
&lt;td&gt;AWS-managed, reached through a local proxy&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;They work independently. Skills don't require the MCP server, and the MCP server doesn't serve your locally installed skills.&lt;/p&gt;

&lt;p&gt;A skill is a directory with a &lt;code&gt;SKILL.md&lt;/code&gt; and often a &lt;code&gt;references/&lt;/code&gt; folder:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aws-storage/
├── SKILL.md
├── .aws-skill-metadata      # {"version": "v1"}
└── references/
    ├── s3-general-purpose-knowledge.md
    ├── ebs-knowledge.md
    └── ...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The front matter's &lt;code&gt;description&lt;/code&gt; is what the agent uses to decide whether a skill applies — and it spells out what the skill is &lt;em&gt;not&lt;/em&gt; for, which keeps irrelevant skills from loading:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;aws-storage&lt;/span&gt;
&lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;&amp;gt;-&lt;/span&gt;
  &lt;span class="s"&gt;Selects, investigates, and compares AWS object, file, and block storage&lt;/span&gt;
  &lt;span class="s"&gt;services... Not applicable for SQL query engines (Athena, Spark, Redshift,&lt;/span&gt;
  &lt;span class="s"&gt;EMR), ETL (Glue), streaming (Kafka, MSK, Kinesis), or managed database&lt;/span&gt;
  &lt;span class="s"&gt;services (RDS, Aurora, DynamoDB).&lt;/span&gt;
&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The body holds behavioural rules. One from &lt;code&gt;aws-storage&lt;/code&gt; explains why the toolkit is worth having: it requires the agent to verify current figures rather than recall them, to cite the pricing page for any cost claim, and to name a value it couldn't verify rather than guess. That pairs directly with the MCP server's documentation tools — the skill demands verification, the server provides the means.&lt;/p&gt;

&lt;p&gt;Skills are open source in &lt;a href="https://github.com/aws/agent-toolkit-for-aws" rel="noopener noreferrer"&gt;aws/agent-toolkit-for-aws&lt;/a&gt; (Apache-2.0), so you can read them before installing.&lt;/p&gt;




&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws &lt;span class="nt"&gt;--version&lt;/span&gt;    &lt;span class="c"&gt;# need 2.35.0 or later&lt;/span&gt;
uv &lt;span class="nt"&gt;--version&lt;/span&gt;     &lt;span class="c"&gt;# required — the MCP proxy runs through uvx&lt;/span&gt;
node &lt;span class="nt"&gt;--version&lt;/span&gt;   &lt;span class="c"&gt;# v22+ for Claude Code&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;uv&lt;/code&gt; is easy to miss. Nothing in the setup output mentions it, but the MCP server won't connect without it. See the &lt;a href="https://docs.astral.sh/uv/getting-started/installation/" rel="noopener noreferrer"&gt;uv install guide&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If your AWS CLI is older than 2.35, upgrade by reinstalling the package — there's no self-update:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="s2"&gt;"https://awscli.amazonaws.com/AWSCLIV2.pkg"&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="s2"&gt;"AWSCLIV2.pkg"&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;installer &lt;span class="nt"&gt;-pkg&lt;/span&gt; AWSCLIV2.pkg &lt;span class="nt"&gt;-target&lt;/span&gt; /
&lt;span class="nb"&gt;rm &lt;/span&gt;AWSCLIV2.pkg

aws &lt;span class="nt"&gt;--version&lt;/span&gt;
&lt;span class="c"&gt;# aws-cli/2.36.40 Python/3.14.6 Darwin/25.6.0 exe/arm64&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Install
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws configure agent-toolkit &lt;span class="nt"&gt;--region&lt;/span&gt; us-east-1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Why the region flag?&lt;/strong&gt; Agent Toolkit is served from us-east-1 only. Official examples omit it, which works if that's already your default. Mine is us-west-2, and without the flag the wizard completes agent detection and the selection screen, then fails at the fetch:&lt;/p&gt;


&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Fetching default AWS skills...
aws: [ERROR]: AgentToolkit is only available in us-east-1
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Check &lt;code&gt;aws configure get region&lt;/code&gt; first.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The wizard detects installed agents, offers a checklist (everything selected by default), installs skills, and configures the MCP server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;Detecting installed AI coding agents...
  ✓ Claude Code — ~/.claude/skills
  ✓ Codex — ~/.agents/skills/
  ✓ Cursor — ~/.cursor/skills
  ✓ Kiro — ~/.kiro/skills

Install 23 default AWS skills? [Y/n]: Y
Configure AWS MCP server connection? [Y/n]: Y
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Restart your agent afterwards to pick up the config — if Claude Code is already open, exit with &lt;code&gt;/exit&lt;/code&gt; and launch it again.&lt;/p&gt;

&lt;h3&gt;
  
  
  What you got
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-1&lt;/span&gt; ~/.claude/skills | &lt;span class="nb"&gt;wc&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt;
&lt;span class="c"&gt;# 23&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Those 23 are the catalog's &lt;code&gt;aws-core&lt;/code&gt; category — covering IaC, core services, databases, networking, storage, security, observability, messaging, SDKs and cost management. They're installed as &lt;strong&gt;a full copy per agent&lt;/strong&gt;, not symlinks.&lt;/p&gt;

&lt;p&gt;The catalog holds more, at finer granularity, which you add yourself:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws agent-toolkit search-skills &lt;span class="nt"&gt;--search-query&lt;/span&gt; &lt;span class="s2"&gt;"dynamodb"&lt;/span&gt; &lt;span class="nt"&gt;--region&lt;/span&gt; us-east-1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That surfaces single-service skills like &lt;code&gt;amazon-dynamodb&lt;/code&gt; — access-pattern enumeration, partition key and GSI selection, single- versus multi-table decisions, cost estimation — well past what the domain-level &lt;code&gt;aws-database&lt;/code&gt; covers.&lt;/p&gt;




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

&lt;h3&gt;
  
  
  Read path: query your bill
&lt;/h3&gt;

&lt;p&gt;Launch Claude Code from the directory you want to work in:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;claude
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On first run in a project it asks you to enable the MCP server. Press Enter to accept — pressing Esc rejects it, and the server stays silently disabled with no further prompting.&lt;/p&gt;

&lt;p&gt;Once you're at the prompt, check the connection by typing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/mcp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;aws-mcp · ✔ connected · 8 tools
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's success. Now ask for something real:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Get my AWS billing details for July 2026, grouped by service.
Do the sorting and totalling inside the script.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The agent reaches for &lt;code&gt;aws___run_script&lt;/code&gt; and shows you the whole script before running it:&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="n"&gt;resp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;call_boto3&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;service_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ce&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;operation_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;GetCostAndUsage&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;region_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;us-east-1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;TimePeriod&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Start&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;2026-07-01&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;End&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;2026-08-01&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Granularity&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;MONTHLY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Metrics&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;UnblendedCost&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;GroupBy&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;DIMENSION&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Key&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;SERVICE&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}],&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Confirm the API actually ran
&lt;/span&gt;&lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="nf"&gt;any&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;operation_name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;GetCostAndUsage&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;api_calls&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[])),&lt;/span&gt; &lt;span class="n"&gt;resp&lt;/span&gt;

&lt;span class="n"&gt;rv&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;return_value&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;rv&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ResultsByTime&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;groups&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Groups&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;unit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
&lt;span class="n"&gt;rows&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;g&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;groups&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;svc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Keys&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;amt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Metrics&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;UnblendedCost&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;unit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;amt&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Unit&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;svc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amt&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Amount&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])))&lt;/span&gt;

&lt;span class="c1"&gt;# Sort descending by cost, inside the script
&lt;/span&gt;&lt;span class="n"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;reverse&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;total&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;period&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;2026-07-01 to 2026-07-31&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;currency&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;unit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;estimated&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Estimated&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;service_count&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;total&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;total&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;services&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;service&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cost&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;pct&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;total&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;total&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;rows&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;result&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Reading it is worth the few seconds. One thing is visibly right: the sorting and totalling really do happen &lt;strong&gt;in the script&lt;/strong&gt;, as the prompt asked — those are the &lt;code&gt;rows.sort(...)&lt;/code&gt; and &lt;code&gt;sum(...)&lt;/code&gt; lines, not something the model does in its reply afterwards.&lt;/p&gt;

&lt;p&gt;Two things are wrong, and they share a cause. Both of these assume &lt;code&gt;call_boto3&lt;/code&gt; returns a wrapper around the API response:&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="k"&gt;assert&lt;/span&gt; &lt;span class="nf"&gt;any&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;operation_name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;GetCostAndUsage&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;api_calls&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[])),&lt;/span&gt; &lt;span class="n"&gt;resp&lt;/span&gt;
&lt;span class="n"&gt;rv&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;return_value&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;Neither &lt;code&gt;api_calls&lt;/code&gt; nor &lt;code&gt;return_value&lt;/code&gt; exists on what &lt;code&gt;call_boto3&lt;/code&gt; hands back, so the assert can never pass and the script fails on the spot. The agent worked it out immediately:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The response is the raw API dict directly. Let me fix that.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Here's the corrected script it submitted next — the version that actually works:&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="n"&gt;resp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;call_boto3&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;service_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ce&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;operation_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;GetCostAndUsage&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;region_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;us-east-1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;TimePeriod&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Start&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;2026-07-01&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;End&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;2026-08-01&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Granularity&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;MONTHLY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Metrics&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;UnblendedCost&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;GroupBy&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;DIMENSION&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Key&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;SERVICE&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}],&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ResultsByTime&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;groups&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Groups&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;unit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
&lt;span class="n"&gt;rows&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;g&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;groups&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;svc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Keys&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;amt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Metrics&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;UnblendedCost&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;unit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;amt&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Unit&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;svc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amt&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Amount&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])))&lt;/span&gt;

&lt;span class="c1"&gt;# Sort descending by cost, inside the script
&lt;/span&gt;&lt;span class="n"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;reverse&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;total&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;period&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;2026-07-01 to 2026-07-31&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;currency&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;unit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;estimated&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Estimated&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;service_count&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;total&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;total&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;services&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;service&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cost&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;pct&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;total&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;total&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;rows&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;result&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Both wrong assumptions are gone: &lt;code&gt;resp["ResultsByTime"]&lt;/code&gt; replaces &lt;code&gt;resp["return_value"]["ResultsByTime"]&lt;/code&gt;, and the &lt;code&gt;assert&lt;/code&gt; on &lt;code&gt;api_calls&lt;/code&gt; has been dropped entirely.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;call_boto3&lt;/code&gt; hands back the boto3 response directly. A &lt;code&gt;return_value&lt;/code&gt; envelope does exist, but one level up — it wraps your script's final value in the MCP &lt;em&gt;tool&lt;/em&gt; response, which is a different object. Inside the script, read the API response as-is.&lt;/p&gt;

&lt;p&gt;This is a good template to reuse. Take the raw response, aggregate and sort in the script, return a compact dict.&lt;/p&gt;

&lt;p&gt;Then it asks permission:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt; Do you want to proceed?
 ❯ 1. Yes
&lt;/span&gt;&lt;span class="gp"&gt;   2. Yes, and don't ask again for aws-mcp — Aws Run Script commands in &amp;lt;this directory&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="go"&gt;   3. No
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Choose &lt;code&gt;1&lt;/code&gt;, and this is what a working setup produces:&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%2Fam0i5pmig91e2eh0j9hd.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%2Fam0i5pmig91e2eh0j9hd.png" alt=" " width="800" height="1105"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Note what came back beyond the raw numbers: percentages per service, a count of how many services had zero spend, a note that the figures are finalized rather than estimated, and an unprompted takeaway pointing at the two services worth optimising. The skill's guidance is visible in the shape of that answer.&lt;/p&gt;

&lt;p&gt;Two things to notice about how it got there.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1 / It's Python in a sandbox, not the AWS CLI.&lt;/strong&gt; The tool executes code with AWS access through &lt;code&gt;call_boto3&lt;/code&gt; and no other network. &lt;code&gt;call_boto3&lt;/code&gt; takes a service name, a canonical API operation name and a parameter dict. Aggregation happens inside the script rather than by pulling raw data back into context, which keeps token use down.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2 / Ask for the maths to be done in the script.&lt;/strong&gt; That's why the prompt above says &lt;em&gt;"Do the sorting and totalling inside the script"&lt;/em&gt;. Left to itself, the model may pull the raw numbers back and add them up in its reply — which in one of my runs produced a total $48 too high, with nothing to indicate anything was wrong. Doing it in Python avoids that.&lt;/p&gt;

&lt;p&gt;To check the total the agent gives you, ask Cost Explorer for the same month &lt;strong&gt;without&lt;/strong&gt; grouping. Skip &lt;code&gt;--group-by&lt;/code&gt; and the API fills in &lt;code&gt;Total&lt;/code&gt; for you, so you get one number to compare against:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws ce get-cost-and-usage &lt;span class="nt"&gt;--time-period&lt;/span&gt; &lt;span class="nv"&gt;Start&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;2026-07-01,End&lt;span class="o"&gt;=&lt;/span&gt;2026-08-01 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--granularity&lt;/span&gt; MONTHLY &lt;span class="nt"&gt;--metrics&lt;/span&gt; UnblendedCost &lt;span class="nt"&gt;--region&lt;/span&gt; us-east-1 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--query&lt;/span&gt; &lt;span class="s1"&gt;'ResultsByTime[0].Total.UnblendedCost.Amount'&lt;/span&gt; &lt;span class="nt"&gt;--output&lt;/span&gt; text
&lt;span class="c"&gt;# 2116.6859001279&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add &lt;code&gt;--group-by&lt;/code&gt; and &lt;code&gt;Total&lt;/code&gt; comes back empty — you get per-service groups and have to sum them yourself. That's why the agent does the adding, and why you want it doing that in Python.&lt;/p&gt;

&lt;h3&gt;
  
  
  Write path: create and delete a bucket
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Create an S3 bucket named "example-toolkit-test" in us-east-1.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then verify from a normal terminal rather than trusting the summary:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws s3api head-bucket &lt;span class="nt"&gt;--bucket&lt;/span&gt; example-toolkit-test &lt;span class="nt"&gt;--region&lt;/span&gt; us-east-1
aws s3api get-bucket-encryption &lt;span class="nt"&gt;--bucket&lt;/span&gt; example-toolkit-test
aws s3api get-public-access-block &lt;span class="nt"&gt;--bucket&lt;/span&gt; example-toolkit-test
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Encryption came back SSE-S3 (&lt;code&gt;AES256&lt;/code&gt;) and all four public access blocks enabled — the secure defaults, nothing extra needed. Clean up:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Delete the S3 bucket "example-toolkit-test".
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws s3api head-bucket &lt;span class="nt"&gt;--bucket&lt;/span&gt; example-toolkit-test &lt;span class="nt"&gt;--region&lt;/span&gt; us-east-1
&lt;span class="c"&gt;# An error occurred (404) ... Not Found&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Read, write and delete all working end to end.&lt;/p&gt;




&lt;h2&gt;
  
  
  Three things worth knowing
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. The setup command doesn't update skills
&lt;/h3&gt;

&lt;p&gt;Re-running &lt;code&gt;aws configure agent-toolkit&lt;/code&gt; installs newly published skills and &lt;strong&gt;skips everything already on disk&lt;/strong&gt;. Not "checks and confirms current" — untouched. Mine sat a month behind without any indication:&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="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt; ~/.claude/skills/aws-cdk/SKILL.md
&lt;span class="c"&gt;# Aug  6 06:06     ← still the version installed a month earlier&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;add-skill&lt;/code&gt; states the rule outright:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;aws-cdk is already installed (v2) at /Users/you/.claude/skills/aws-cdk.
Run "aws agent-toolkit update-skill --skill-name aws-cdk" to update, or remove it first to reinstall.
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Updating is a separate verb, and it does compare versions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws agent-toolkit update-skill &lt;span class="nt"&gt;--skill-name&lt;/span&gt; aws-cdk &lt;span class="nt"&gt;--region&lt;/span&gt; us-east-1
&lt;span class="c"&gt;# Updated aws-cdk (v2) to Claude Code — ~/.claude/skills.&lt;/span&gt;
&lt;span class="c"&gt;# ... and to the other three agent directories&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One command covers every agent copy. To audit what's behind:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws agent-toolkit list-available-skills &lt;span class="nt"&gt;--category-filter&lt;/span&gt; aws-core &lt;span class="nt"&gt;--region&lt;/span&gt; us-east-1

&lt;span class="k"&gt;for &lt;/span&gt;s &lt;span class="k"&gt;in&lt;/span&gt; ~/.claude/skills/&lt;span class="k"&gt;*&lt;/span&gt;/&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
  &lt;/span&gt;&lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s2"&gt;"%-34s %s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;basename&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$s&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$s&lt;/span&gt;&lt;span class="s2"&gt;/.aws-skill-metadata"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Worth putting on a schedule. A stale skill doesn't error; it quietly supplies last month's guidance.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. The MCP server runs remotely
&lt;/h3&gt;

&lt;p&gt;Selecting the server in &lt;code&gt;/mcp&lt;/code&gt; shows how it's wired:&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%2Fflfabnbgu2du5jijn9xt.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%2Fflfabnbgu2du5jijn9xt.png" alt=" " width="800" height="283"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The two lines that matter, in text so you can compare them against your own:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;Command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;uvx&lt;/span&gt;
&lt;span class="na"&gt;Args&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;    &lt;span class="s"&gt;mcp-proxy-for-aws@latest https://aws-mcp.us-east-1.api.aws/mcp --metadata INSTALL_SOURCE=aws-cli&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There's no local server. It's an AWS-managed endpoint, and &lt;code&gt;uvx mcp-proxy-for-aws&lt;/code&gt; is a thin local proxy that signs requests with your AWS credential chain. Hence the &lt;code&gt;uv&lt;/code&gt; prerequisite and the region in the URL.&lt;/p&gt;

&lt;p&gt;This view is also where you go when something isn't working — &lt;strong&gt;Reconnect&lt;/strong&gt; and &lt;strong&gt;Disable&lt;/strong&gt; are right there, and &lt;code&gt;Status&lt;/code&gt; tells you whether the problem is the connection or something further along.&lt;/p&gt;

&lt;p&gt;Note the &lt;code&gt;@latest&lt;/code&gt;. The official examples pin a version and recommend doing so for reproducible behaviour; the CLI writes &lt;code&gt;@latest&lt;/code&gt;. Both are defensible — &lt;code&gt;@latest&lt;/code&gt; picks up fixes automatically, a pin keeps behaviour stable — so make the choice deliberately rather than inheriting it.&lt;/p&gt;

&lt;p&gt;Pick &lt;strong&gt;View tools&lt;/strong&gt; from that menu and Claude Code lists all eight with their annotations:&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%2Flo0t023xq11xx1cvyl3z.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%2Flo0t023xq11xx1cvyl3z.png" alt=" " width="800" height="484"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Six of the eight are read-only lookups, three of those being documentation search and retrieval. &lt;strong&gt;Exactly one — &lt;code&gt;aws___run_script&lt;/code&gt;, the only one marked &lt;code&gt;destructive&lt;/code&gt; — can change your account.&lt;/strong&gt; Every write goes through it.&lt;/p&gt;

&lt;p&gt;Worth scrolling this list once. It's the clearest picture you'll get of what the agent can actually do, and the &lt;code&gt;destructive&lt;/code&gt; label tells you which single tool to pay attention to when an approval dialog appears.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Approval is coarser than it looks
&lt;/h3&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%2Fmtz8n2dzi1ickacqp281.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%2Fmtz8n2dzi1ickacqp281.png" alt=" " width="800" height="386"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That's the dialog for a two-line script that returns the string &lt;code&gt;OK&lt;/code&gt;. The one for deleting an S3 bucket looks the same — same three options, no extra warning for destructive work. I compared it across five operations.&lt;/p&gt;

&lt;p&gt;Which makes option 2 more consequential than it reads. &lt;em&gt;"Don't ask again for aws-mcp — Aws Run Script commands in this directory"&lt;/em&gt; sounds narrow, but because reads, writes and deletes all travel through that single tool, it covers &lt;strong&gt;every&lt;/strong&gt; subsequent AWS operation there, deletions included. The grant can't be scoped per operation.&lt;/p&gt;

&lt;p&gt;Two practical follow-ups.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1 / Check &lt;code&gt;autoApprove&lt;/code&gt; in the configs the wizard touched.&lt;/strong&gt; On this machine it added &lt;code&gt;"autoApprove": ["aws___run_script"]&lt;/code&gt; to &lt;code&gt;~/.kiro/settings/mcp.json&lt;/code&gt; — the one tool that can change your account, pre-approved. Claude Code and Cursor got no such field, and the official example config doesn't include it. Remove it if you'd rather be asked.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2 / Read the code in the dialog, not the comments in it.&lt;/strong&gt; One delete script arrived with a &lt;code&gt;# Verify empty first&lt;/code&gt; comment, computed an object count, never branched on it, and deleted anyway — then reported that it had "verified the bucket was empty". The check the comment promised wasn't there.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where the real guardrails are
&lt;/h2&gt;

&lt;p&gt;The client is the wrong place to look for granularity. The toolkit's mechanism for this sits on the AWS side: the condition keys &lt;strong&gt;&lt;code&gt;aws:ViaAWSMCPService&lt;/code&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;code&gt;aws:CalledViaAWSMCP&lt;/code&gt;&lt;/strong&gt; distinguish requests made through the AWS-managed MCP server from direct API calls.&lt;/p&gt;

&lt;p&gt;You can use them in IAM policies and SCPs to write rules that apply only to agent-initiated actions — for example, permitting only read-only operations through MCP even where the underlying role can write. Every request also lands in CloudWatch metrics and CloudTrail.&lt;/p&gt;

&lt;p&gt;That's the control point worth investing in. Clicking through identical dialogs doesn't scale, and the tool annotation gates nothing on its own.&lt;/p&gt;




&lt;h2&gt;
  
  
  Command reference
&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;# install / reconfigure&lt;/span&gt;
aws configure agent-toolkit &lt;span class="nt"&gt;--region&lt;/span&gt; us-east-1

&lt;span class="c"&gt;# skills — add --region unless your default is us-east-1&lt;/span&gt;
aws agent-toolkit list-installed-skills
aws agent-toolkit list-available-skills &lt;span class="nt"&gt;--category-filter&lt;/span&gt; aws-core &lt;span class="nt"&gt;--region&lt;/span&gt; us-east-1
aws agent-toolkit search-skills &lt;span class="nt"&gt;--search-query&lt;/span&gt; &lt;span class="s2"&gt;"dynamodb"&lt;/span&gt; &lt;span class="nt"&gt;--region&lt;/span&gt; us-east-1
aws agent-toolkit update-skill &lt;span class="nt"&gt;--skill-name&lt;/span&gt; aws-cdk &lt;span class="nt"&gt;--region&lt;/span&gt; us-east-1
aws agent-toolkit update-skill &lt;span class="nt"&gt;--skill-name&lt;/span&gt; aws-cdk &lt;span class="nt"&gt;--agent&lt;/span&gt; kiro &lt;span class="nt"&gt;--region&lt;/span&gt; us-east-1
aws agent-toolkit add-skill &lt;span class="nt"&gt;--skill-name&lt;/span&gt; amazon-dynamodb &lt;span class="nt"&gt;--region&lt;/span&gt; us-east-1
aws agent-toolkit remove-skill &lt;span class="nt"&gt;--skill-name&lt;/span&gt; aws-cdk &lt;span class="nt"&gt;--region&lt;/span&gt; us-east-1
aws agent-toolkit get-skill-metadata &lt;span class="nt"&gt;--skill-name&lt;/span&gt; aws-serverless &lt;span class="nt"&gt;--region&lt;/span&gt; us-east-1

&lt;span class="c"&gt;# local versions at a glance&lt;/span&gt;
&lt;span class="k"&gt;for &lt;/span&gt;s &lt;span class="k"&gt;in&lt;/span&gt; ~/.claude/skills/&lt;span class="k"&gt;*&lt;/span&gt;/&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
  &lt;/span&gt;&lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s2"&gt;"%-34s %s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;basename&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$s&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$s&lt;/span&gt;&lt;span class="s2"&gt;/.aws-skill-metadata"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;list-installed-skills&lt;/code&gt; is the one subcommand that works without &lt;code&gt;--region&lt;/code&gt; — it only reads local disk.&lt;/p&gt;




&lt;h2&gt;
  
  
  Verified on
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Component&lt;/th&gt;
&lt;th&gt;Version&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;macOS&lt;/td&gt;
&lt;td&gt;Darwin 25.6.0 (arm64)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AWS CLI&lt;/td&gt;
&lt;td&gt;2.36.40&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Node.js&lt;/td&gt;
&lt;td&gt;v22.23.2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;uv&lt;/td&gt;
&lt;td&gt;0.8.18&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Claude Code&lt;/td&gt;
&lt;td&gt;2.1.261 (via Amazon Bedrock)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AWS skills&lt;/td&gt;
&lt;td&gt;23 (&lt;code&gt;aws-core&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Part 2 runs the same walkthrough on Codex — where the config format is TOML rather than JSON, the skills land in a directory shared with three other agents, and the approval model works differently. It also covers what the &lt;code&gt;aws-core&lt;/code&gt; plugin installs that the CLI path doesn't.&lt;/p&gt;

&lt;p&gt;Whatever your setup looks like, verify it the way this post did: one read, one write, both confirmed from a second terminal. An agent's account of what it did is not evidence that it did it.&lt;/p&gt;




&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Agent Toolkit for AWS&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;a href="https://aws.amazon.com/products/developer-tools/agent-toolkit-for-aws/?trk=7b33727f-f84b-453c-8f31-3d32f7b2a4e7&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;Product page&lt;/a&gt; — overview, features, per-agent getting started&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.aws.amazon.com/agent-toolkit/latest/userguide/?trk=7b33727f-f84b-453c-8f31-3d32f7b2a4e7&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;User guide&lt;/a&gt; — setup and reference documentation&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.aws.amazon.com/agent-toolkit/latest/userguide/aws-cli.html?trk=7b33727f-f84b-453c-8f31-3d32f7b2a4e7&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;AWS CLI integration guide&lt;/a&gt; — the &lt;code&gt;configure agent-toolkit&lt;/code&gt; wizard and every &lt;code&gt;agent-toolkit&lt;/code&gt; subcommand, including &lt;code&gt;update-skill&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.aws.amazon.com/agent-toolkit/latest/userguide/understanding-mcp-server-tools.html?trk=7b33727f-f84b-453c-8f31-3d32f7b2a4e7&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;AWS MCP Server tools reference&lt;/a&gt; — the eight tools, authentication, supported regions&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.aws.amazon.com/agent-toolkit/latest/userguide/getting-started-aws-mcp-server.html?trk=7b33727f-f84b-453c-8f31-3d32f7b2a4e7&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;Getting started with the AWS MCP Server&lt;/a&gt; — configuring the server with agents other than Claude Code, Codex and Cursor&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Source and skill contents (Apache-2.0)&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;a href="https://github.com/aws/agent-toolkit-for-aws" rel="noopener noreferrer"&gt;aws/agent-toolkit-for-aws&lt;/a&gt; — repository&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/aws/agent-toolkit-for-aws/tree/main/skills" rel="noopener noreferrer"&gt;&lt;code&gt;skills/&lt;/code&gt;&lt;/a&gt; — every skill's &lt;code&gt;SKILL.md&lt;/code&gt; and reference files, readable before you install&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/aws/agent-toolkit-for-aws/tree/main/rules" rel="noopener noreferrer"&gt;&lt;code&gt;rules/&lt;/code&gt;&lt;/a&gt; — the recommended project-level rules file, not covered in this post&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Prerequisites and related&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;a href="https://docs.astral.sh/uv/getting-started/installation/" rel="noopener noreferrer"&gt;uv installation&lt;/a&gt; — required; the MCP proxy runs through &lt;code&gt;uvx&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html?trk=7b33727f-f84b-453c-8f31-3d32f7b2a4e7&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;Installing or updating the AWS CLI&lt;/a&gt; — 2.35.0 or later needed&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://modelcontextprotocol.io" rel="noopener noreferrer"&gt;Model Context Protocol&lt;/a&gt; — the open standard behind the MCP server, including tool annotations&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://code.claude.com/docs/en/mcp" rel="noopener noreferrer"&gt;Claude Code MCP documentation&lt;/a&gt; — the &lt;code&gt;/mcp&lt;/code&gt; command and server management&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Referenced APIs&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;a href="https://docs.aws.amazon.com/aws-cost-management/latest/APIReference/API_GetCostAndUsage.html?trk=7b33727f-f84b-453c-8f31-3d32f7b2a4e7&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;&lt;code&gt;GetCostAndUsage&lt;/code&gt;&lt;/a&gt; — Cost Explorer; note the canonical PascalCase operation name expected by &lt;code&gt;call_boto3&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;&lt;em&gt;A note on method: official documentation and skill contents are paraphrased rather than quoted. Every command and output in this post is from a real run on the environment listed above, and the agent's actions were verified from a separate shell rather than taken from its own reporting.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>claude</category>
      <category>agentskills</category>
      <category>mcp</category>
      <category>claudecode</category>
    </item>
    <item>
      <title>Get Started with GPT-5.6 on Amazon Bedrock in 15 Minutes</title>
      <dc:creator>Haowen Huang</dc:creator>
      <pubDate>Sat, 01 Aug 2026 06:13:15 +0000</pubDate>
      <link>https://dev.to/haowen_huang/gpt-56-on-amazon-bedrock-in-15-minutes-gaf</link>
      <guid>https://dev.to/haowen_huang/gpt-56-on-amazon-bedrock-in-15-minutes-gaf</guid>
      <description>&lt;p&gt;OpenAI's GPT-5.6 comes in three tiers — Sol, Terra and Luna — and you can now call them on Amazon Bedrock through your own AWS account, with no OpenAI API key.&lt;/p&gt;

&lt;p&gt;This takes the shortest path: &lt;strong&gt;clone, run, understand the output.&lt;/strong&gt; Every command is copy-pasteable, every number below came from a real run, and you should see the same order of magnitude on your own account.&lt;/p&gt;

&lt;h2&gt;
  
  
  Background: two things worth knowing first
&lt;/h2&gt;

&lt;p&gt;GPT-5.6 became generally available on Amazon Bedrock in July 2026. Two things are worth understanding before you start.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;First, Sol / Terra / Luna are not version numbers.&lt;/strong&gt; The 5.6 identifies the generation; Sol, Terra and Luna are three capability tiers that can each advance on their own cadence. So the question when choosing is "how much reasoning does this task need", not "which one is newer". Per OpenAI's published evaluations, Sol is their strongest reasoning model to date, clearly ahead of the previous generation on coding-agent and security-research work while spending fewer output tokens; Terra beats the previous generation at lower cost; Luna targets high volume and low latency. Sol also gets one extra reasoning level, &lt;code&gt;max&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Second, why run this on Bedrock instead of calling OpenAI  directly.&lt;/strong&gt; All three&lt;br&gt;
points below come from the AWS GA announcement (linked in the appendix):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Inference stays in the AWS Region you specify, which helps with data residency&lt;/li&gt;
&lt;li&gt;Every call goes through your own IAM policies, inside your VPC, and lands in
CloudTrail&lt;/li&gt;
&lt;li&gt;Pricing matches OpenAI's first-party rates, and usage counts toward your existing
AWS commitments&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now let's build.&lt;/p&gt;
&lt;h2&gt;
  
  
  What you need
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Python 3.10 or newer&lt;/li&gt;
&lt;li&gt;An AWS account with working credentials (&lt;code&gt;~/.aws/credentials&lt;/code&gt; or &lt;code&gt;AWS_PROFILE&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;GPT-5.6 available in your target Region, and an IAM identity permitted to call
Bedrock&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Confirm your credentials resolve. If you have the AWS CLI:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws sts get-caller-identity
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If it prints your account and identity, you're good. &lt;strong&gt;The AWS CLI is not&lt;br&gt;
required&lt;/strong&gt; — the examples never call it, and credentials are read through the&lt;br&gt;
Python SDK. Without it, run this equivalent check after step 1 installs the&lt;br&gt;
dependencies:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s2"&gt;"import botocore.session as s; print('credentials found' if s.get_session().get_credentials() else 'NO credentials')"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 1: Set up
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/hanyun2019/openai-bedrock-samples.git
&lt;span class="nb"&gt;cd &lt;/span&gt;openai-bedrock-samples

python &lt;span class="nt"&gt;-m&lt;/span&gt; venv .venv
&lt;span class="nb"&gt;source&lt;/span&gt; .venv/bin/activate          &lt;span class="c"&gt;# Windows: .venv\Scripts\activate&lt;/span&gt;
pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; requirements.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;You don't set an API key.&lt;/strong&gt; That's the biggest difference from calling OpenAI&lt;br&gt;
directly: the code uses your AWS credentials to mint a short-lived Bedrock token&lt;br&gt;
before every request.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;openai&amp;gt;=2.45.0&lt;/code&gt; is a hard requirement, because that's where the &lt;code&gt;BedrockOpenAI&lt;/code&gt;&lt;br&gt;
client lives.&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 2: First call
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python &lt;span class="nt"&gt;-m&lt;/span&gt; src.gpt56.hello
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;============================================================
Tier      : terra
Model ID  : openai.gpt-5.6-terra
Region    : us-east-1
Usage     : in=20 out=36 total=56
            reasoning=0
============================================================
I'm best suited for understanding and generating text, answering
questions, summarizing and analyzing information, ...
============================================================
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Working. Only one thing here is worth memorizing: &lt;strong&gt;run with &lt;code&gt;-m&lt;/code&gt;, not a file&lt;br&gt;
path.&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python &lt;span class="nt"&gt;-m&lt;/span&gt; src.gpt56.hello              &lt;span class="c"&gt;# correct&lt;/span&gt;
python src/gpt56/hello.py              &lt;span class="c"&gt;# ImportError&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The example modules use relative imports, and running a file directly leaves Python&lt;br&gt;
with no idea which package it belongs to.&lt;/p&gt;

&lt;p&gt;The whole project has exactly one essential file, &lt;code&gt;src/gpt56/client.py&lt;/code&gt;. It does two&lt;br&gt;
things: validate the tier/Region combination, and build a client whose token renews&lt;br&gt;
itself. Everything else imports it.&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 3: Which tier?
&lt;/h2&gt;

&lt;p&gt;The short version:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tier&lt;/th&gt;
&lt;th&gt;Model ID&lt;/th&gt;
&lt;th&gt;When to use it&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Sol&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;openai.gpt-5.6-sol&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Complex refactoring, long reasoning chains, security research&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Terra&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;openai.gpt-5.6-terra&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Everyday production. &lt;strong&gt;Start here&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Luna&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;openai.gpt-5.6-luna&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Classification, summarization, routing — high volume, low latency&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Here's the problem it uses:&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%2Fsc0ew6xr16g6eksfc8uk.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%2Fsc0ew6xr16g6eksfc8uk.png" alt=" " width="799" height="395"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It deliberately splits the information in two: the vertex form hides "the maximum is&lt;br&gt;
at x=3", and g(3) has to be looked up in the table. The model has to combine both&lt;br&gt;
rather than pattern match its way to an answer. The answer is B.&lt;/p&gt;

&lt;p&gt;Same problem, all three tiers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python &lt;span class="nt"&gt;-m&lt;/span&gt; src.gpt56.compare_tiers
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;built-in text problem · effort=low · region=us-east-1
Correct answer: B (k=3, g(3)=6)
==============================================================================
tier         sec     in    out  reasoning  answer
sol          2.4    133     79          0       B
terra        1.5    133     67          0       B
luna         1.5    133     95         25       B
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All three got it right, and that's the point: &lt;strong&gt;on an easy task, the expensive tier&lt;br&gt;
does not buy you a better answer.&lt;/strong&gt; On this run Terra was also faster than Sol and&lt;br&gt;
spent fewer output tokens. Tier differences only show up on hard problems.&lt;/p&gt;

&lt;p&gt;The exact numbers drift run to run (a rerun gave me 87 output tokens for sol and 85&lt;br&gt;
for terra, with the timings reordered), so don't anchor on any single figure. The&lt;br&gt;
conclusion is what matters: &lt;strong&gt;all three got it right, so paying more bought nothing&lt;br&gt;
here.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;So work upward: start on Terra, move to Sol when Terra isn't enough — not the other&lt;br&gt;
way around.&lt;/p&gt;

&lt;p&gt;One gotcha that will actually raise an error: &lt;strong&gt;Sol exists only in &lt;code&gt;us-east-1&lt;/code&gt; and&lt;br&gt;
&lt;code&gt;us-east-2&lt;/code&gt;&lt;/strong&gt;, while Terra and Luna add &lt;code&gt;us-west-2&lt;/code&gt;. &lt;code&gt;client.py&lt;/code&gt; catches this before&lt;br&gt;
any request goes out:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ValueError: GPT-5.6 sol is not available in us-west-2.
Available Regions: us-east-1, us-east-2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 4: Reasoning effort
&lt;/h2&gt;

&lt;p&gt;GPT-5.6 reasons before it answers, and &lt;code&gt;reasoning.effort&lt;/code&gt; controls how hard. Six&lt;br&gt;
levels: &lt;code&gt;none&lt;/code&gt;, &lt;code&gt;low&lt;/code&gt;, &lt;code&gt;medium&lt;/code&gt;, &lt;code&gt;high&lt;/code&gt;, &lt;code&gt;xhigh&lt;/code&gt;, &lt;code&gt;max&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This step switches to an algebra problem:&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%2F7g3fxmybyy418f3jtgth.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%2F7g3fxmybyy418f3jtgth.png" alt=" " width="799" height="300"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It needs exactly one exponent-rule transformation (dividing powers subtracts the&lt;br&gt;
exponents, so 3x - y substitutes straight in). That looks trivial, but the single&lt;br&gt;
transformation &lt;em&gt;is&lt;/em&gt; the reasoning step — which makes it a good probe for whether&lt;br&gt;
&lt;code&gt;effort&lt;/code&gt; is doing anything. D is the trap: x and y really are individually&lt;br&gt;
undetermined, but the expression only depends on the combination 3x - y, so there is&lt;br&gt;
a unique answer. The correct answer is A.&lt;/p&gt;

&lt;p&gt;Sweep them:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python &lt;span class="nt"&gt;-m&lt;/span&gt; src.gpt56.effort_sweep terra
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Model: openai.gpt-5.6-terra @ us-east-1
Correct answer: A   1 run(s) per level

effort       sec     in    out  reasoning    answer
none         3.1     83     79          0      A OK
low          1.2     83     73          0      A OK
medium       2.9     83    115         30      A OK
high         1.1     83    116         32      A OK
xhigh        1.7     83    121         43      A OK
max          1.7     83    126         46      A OK
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two columns tell the story.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The &lt;code&gt;reasoning&lt;/code&gt; column&lt;/strong&gt; climbs from 0 to 46. That is what effort buys: an amount&lt;br&gt;
of thinking.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The &lt;code&gt;in&lt;/code&gt; column is flat at 83.&lt;/strong&gt; The prompt didn't change, so input doesn't&lt;br&gt;
either — effort only affects the output side. Which means &lt;strong&gt;raising effort only&lt;br&gt;
raises output cost&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Meanwhile &lt;code&gt;sec&lt;/code&gt; is all over the place (3.1 → 1.2 → 2.9 → 1.1). Don't read "higher&lt;br&gt;
effort is slower" out of a single run. Network jitter alone swamps the difference,&lt;br&gt;
and per the AWS docs the &lt;code&gt;bedrock-mantle&lt;/code&gt; endpoint &lt;strong&gt;may briefly queue a request&lt;/strong&gt;&lt;br&gt;
while in-flight work completes and throughput frees up. That's by design — it trades&lt;br&gt;
queueing for higher initial throughput limits — not a fault, but it makes a single&lt;br&gt;
timing measurement even less meaningful.&lt;/p&gt;

&lt;p&gt;⚠️ &lt;strong&gt;The &lt;code&gt;reasoning&lt;/code&gt; column also comes out unordered in a single run.&lt;/strong&gt; Another run&lt;br&gt;
gave me &lt;code&gt;0, 0, 33, 28, 31, 40&lt;/code&gt; — &lt;code&gt;high&lt;/code&gt; spent less than &lt;code&gt;medium&lt;/code&gt;. The upward trend&lt;br&gt;
is real, but one sample doesn't clear the noise. Average a few runs per level to see&lt;br&gt;
it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python &lt;span class="nt"&gt;-m&lt;/span&gt; src.gpt56.effort_sweep terra 3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;effort       sec     in    out  reasoning  accuracy  answers
none         1.5     83     80          0       3/3  A, A, A
low          1.3     83     77          0       3/3  A, A, A
medium       1.4     83    103         22       3/3  A, A, A
high         1.4     83    111         31       3/3  A, A, A
xhigh        1.5     83    117         33       3/3  A, A, A
max          1.6     83    121         49       3/3  A, A, A
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Averaged, it's monotonic: &lt;code&gt;0, 0, 22, 31, 33, 49&lt;/code&gt;. This problem isn't hard — 18 out&lt;br&gt;
of 18 correct — so what you're seeing is the cost gradient, not an accuracy&lt;br&gt;
difference.&lt;/p&gt;

&lt;p&gt;One thing you do need to know: &lt;strong&gt;reasoning tokens are billed as output tokens&lt;/strong&gt;, and&lt;br&gt;
they draw down your &lt;code&gt;max_output_tokens&lt;/code&gt; budget. Set that budget too low and&lt;br&gt;
reasoning can consume all of it, leaving you a &lt;code&gt;status="incomplete"&lt;/code&gt; response with&lt;br&gt;
empty text. The examples default to 32000 to stay clear of this.&lt;/p&gt;

&lt;p&gt;Practical advice: &lt;strong&gt;start at &lt;code&gt;low&lt;/code&gt;.&lt;/strong&gt; &lt;code&gt;none&lt;/code&gt; gets a reasoning budget of zero, which&lt;br&gt;
is fine for extraction and formatting, but anything needing even one inference step&lt;br&gt;
belongs at &lt;code&gt;low&lt;/code&gt; or above.&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 5: Saving money with prompt caching
&lt;/h2&gt;

&lt;p&gt;If you ask repeated questions against the same long document — the shape of RAG and&lt;br&gt;
document Q&amp;amp;A — caching pays off.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python &lt;span class="nt"&gt;-m&lt;/span&gt; src.gpt56.prompt_cache
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The script uses the opening of &lt;em&gt;Moby-Dick&lt;/em&gt; (1851, public domain) as a reference&lt;br&gt;
document and asks &lt;strong&gt;two different questions against the same prefix&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Q1: In two sentences, what is the narrator's stated reason for going to sea?
Q2: In two sentences, describe the mood of the opening chapter.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One asks for a fact, the other for atmosphere, but both are scoped to that document.&lt;br&gt;
This is exactly the shape where caching pays off most: &lt;strong&gt;the document stays fixed,&lt;br&gt;
the questions change.&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Reference doc: first 12000 chars of Moby-Dick (public domain)

[call 1 (cache write)] input=3002 cached=0    written=2980 hit_rate=0.0%
[call 2 (cache read) ] input=2998 cached=2980 written=0    hit_rate=99.4%
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The second call hit cache on &lt;strong&gt;99.4% of its input&lt;/strong&gt;. Cached input bills at &lt;strong&gt;10%&lt;/strong&gt; of&lt;br&gt;
the uncached rate (writes bill at 1.25x) and &lt;strong&gt;doesn't count against your input TPM&lt;br&gt;
quota&lt;/strong&gt; — that's where the savings come from, so write-once, read-many wins.&lt;/p&gt;

&lt;p&gt;(The first run downloads the full text from Project Gutenberg; a few &lt;code&gt;IncompleteRead&lt;/code&gt;&lt;br&gt;
retries are normal.)&lt;/p&gt;

&lt;p&gt;The trap that catches everyone: &lt;strong&gt;the cached prefix must be at least 1,024&lt;br&gt;
tokens.&lt;/strong&gt; Below that nothing is cached and &lt;strong&gt;no error is raised&lt;/strong&gt; — &lt;code&gt;cached&lt;/code&gt; just&lt;br&gt;
stays 0 forever. You'll assume your code is wrong when the prefix is simply too&lt;br&gt;
short.&lt;/p&gt;

&lt;p&gt;One more thing that looks wrong but isn't: &lt;strong&gt;run that same&lt;br&gt;
&lt;code&gt;python -m src.gpt56.prompt_cache&lt;/code&gt; again right away, and this time &lt;code&gt;call 1&lt;/code&gt; reports a&lt;br&gt;
hit too&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[call 1 (cache write)] input=3002 cached=2980 written=0 hit_rate=99.3%
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Labelled cache write, yet 99.3% cached. That's correct — the cache written by the&lt;br&gt;
previous run is still inside its retention window (at least 30 minutes), so this&lt;br&gt;
run's first call reads it. The label describes which call it is in the script, not a&lt;br&gt;
guarantee that this particular call writes the cache.&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 6 (optional): Function calling and MCP
&lt;/h2&gt;

&lt;p&gt;The first five steps are all ask-once, answer-once. This step lets the model &lt;strong&gt;call&lt;br&gt;
external tools&lt;/strong&gt;, which is where agents start. Skip it if you're not building one.&lt;/p&gt;

&lt;p&gt;The repo has two versions. The protocol is identical; only the source of the tools&lt;br&gt;
differs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Version one: a stub function, to see the protocol clearly&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python &lt;span class="nt"&gt;-m&lt;/span&gt; src.gpt56.tool_calling
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Model: openai.gpt-5.6-terra @ us-east-1

-&amp;gt; model requested get_weather({'location': 'Seattle, US', 'unit': 'fahrenheit'}) -&amp;gt; returned {'location': 'Seattle, US', 'temperature': 18, 'condition': 'Partly cloudy'}

Final answer:
Seattle is currently **18°F** and **partly cloudy**.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One full round trip is three steps: send your tool definitions in &lt;code&gt;tools=&lt;/code&gt; → the model&lt;br&gt;
replies with a &lt;code&gt;function_call&lt;/code&gt; naming the tool and its arguments → you execute it&lt;br&gt;
locally and send the result back as a &lt;code&gt;function_call_output&lt;/code&gt;, paired to that call via&lt;br&gt;
&lt;code&gt;call_id&lt;/code&gt;. &lt;strong&gt;Your code always executes the tool; the model only decides whether to&lt;br&gt;
call it and with what arguments.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Version two: a real MCP server, returning real data&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;MCP (Model Context Protocol) is an open protocol that connects AI models to external tools and data sources. This example uses AWS documentation MCP server:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Read-only access to public docs - no AWS permissions needed &lt;/li&gt;
&lt;li&gt;Requires uv/uvx (install first)&lt;/li&gt;
&lt;li&gt;First run downloads the server automatically
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python &lt;span class="nt"&gt;-m&lt;/span&gt; src.gpt56.mcp_tools
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Starting MCP server: awslabs.aws-documentation-mcp-server ...
MCP offers 5 tools; bridging 2 to the model: ['read_documentation', 'search_documentation']

Model: openai.gpt-5.6-terra @ us-east-1
Question: Using the AWS documentation tools, find the model ID and the AWS Regions for GPT-5.6 Sol on Amazon Bedrock. ...

[turn 1] model called MCP tool search_documentation
[turn 2] model called MCP tool read_documentation

Final answer (turn 3):
The Amazon Bedrock model ID for GPT-5.6 Sol is `openai.gpt-5.6-sol`.
It is available for in-Region inference in `us-east-1` (N. Virginia) and `us-east-2` (Ohio).
Source: [AWS documentation—GPT-5.6 Sol](https://docs.aws.amazon.com/bedrock/latest/userguide/model-card-openai-gpt-56-sol.html).
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The model planned two steps on its own: search first, then read the specific page,&lt;br&gt;
and only answered on turn 3 — with a citation to the official URL, genuinely read out&lt;br&gt;
of the docs rather than invented.&lt;/p&gt;

&lt;p&gt;In code, the only difference from version one is where the tools come from: instead of&lt;br&gt;
hand-written definitions, they're translated from the MCP server's &lt;code&gt;list_tools()&lt;/code&gt; into&lt;br&gt;
the Responses API function format, and execution forwards to &lt;code&gt;session.call_tool()&lt;/code&gt;&lt;br&gt;
instead of a local function. &lt;strong&gt;The protocol part is unchanged.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Two things worth knowing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Don't hand the model every tool an MCP server offers.&lt;/strong&gt; This one exposes 5; the
example allows 2. Tool definitions cost input tokens and raise the chance the model
picks the wrong one&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Set a turn limit.&lt;/strong&gt; My first attempt asked something too broad ("which reasoning
levels are supported") and the model kept searching without converging. Asking a
specific question and telling it to stop once it had the two facts got it done on
turn 3&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Error cheat sheet
&lt;/h2&gt;

&lt;p&gt;Errors you might hit at any of the steps above, listed by the message you see.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;What you see&lt;/th&gt;
&lt;th&gt;Why&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ImportError: attempted relative import...&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;You ran a file path; use &lt;code&gt;python -m&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ValueError: GPT-5.6 sol is not available in...&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Sol has no &lt;code&gt;us-west-2&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;status="incomplete"&lt;/code&gt; with empty text&lt;/td&gt;
&lt;td&gt;Reasoning ate &lt;code&gt;max_output_tokens&lt;/code&gt;; raise it or lower effort&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;cached&lt;/code&gt; stuck at 0&lt;/td&gt;
&lt;td&gt;Cached prefix is under 1,024 tokens&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HTTP 429&lt;/td&gt;
&lt;td&gt;Throttled. The client already sets &lt;code&gt;max_retries=6&lt;/code&gt;; or spread the work out&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;AccessDeniedException&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Missing permissions. Check that IAM allows calling Bedrock and that no SCP explicitly denies it&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;401 Unauthorized: Signature expired&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The short-lived Bedrock token expired (12 hours max). The examples renew it automatically; you'll normally only see this with Codex&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;command not found: aws&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;No AWS CLI. It's optional — use the &lt;code&gt;botocore&lt;/code&gt; check above instead&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Wrapping up
&lt;/h2&gt;

&lt;p&gt;At this point you've run GPT-5.6 end to end on your own AWS account: environment set&lt;br&gt;
up, first call out, all three tiers compared side by side, all six effort levels&lt;br&gt;
swept, caching cutting repeated input to a tenth of the price, and the model calling a&lt;br&gt;
real external tool. None of it is a mock-up — it's code you can lift into a project.&lt;/p&gt;

&lt;p&gt;Two directions from here. Point the Codex CLI at Bedrock so your coding agent's&lt;br&gt;
reasoning also runs through your own account — that works quite differently from the&lt;br&gt;
calls above, and the repo README covers it end to end. Or take the two examples from&lt;br&gt;
Step 6 as a skeleton and swap in your own tools to build an agent.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Full code&lt;/strong&gt; | &lt;a href="https://github.com/hanyun2019/openai-bedrock-samples" rel="noopener noreferrer"&gt;github.com/hanyun2019/openai-bedrock-samples&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Happy agentic AI coding!&lt;/p&gt;




&lt;h2&gt;
  
  
  Appendix: References
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;AWS documentation&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;a href="https://aws.amazon.com/blogs/machine-learning/openai-gpt-5-6-sol-terra-and-luna-are-now-generally-available-on-amazon-bedrock/?trk=7b33727f-f84b-453c-8f31-3d32f7b2a4e7&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;GPT-5.6 Sol, Terra, and Luna are now generally available on Amazon Bedrock&lt;/a&gt;
— the GA announcement and the source for the background section above: tier
positioning, benchmark results, the inference engine, and the security model&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.aws.amazon.com/bedrock/latest/userguide/model-card-openai-gpt-56-sol.html?trk=7b33727f-f84b-453c-8f31-3d32f7b2a4e7&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;GPT-5.6 Sol model card&lt;/a&gt;
— authoritative source for model IDs and Regions&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.aws.amazon.com/bedrock/latest/userguide/endpoints.html?trk=7b33727f-f84b-453c-8f31-3d32f7b2a4e7&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;Endpoints supported by Amazon Bedrock&lt;/a&gt;
— explains the split between the &lt;code&gt;bedrock-mantle&lt;/code&gt; and &lt;code&gt;bedrock-runtime&lt;/code&gt; endpoints,
and the different throughput and quota model each uses. This post uses the former
throughout (the OpenAI-compatible Responses API), which AWS also recommends for new
applications; the latter serves the native &lt;code&gt;InvokeModel&lt;/code&gt; / &lt;code&gt;Converse&lt;/code&gt; APIs. Worth
noting: because we're on mantle, none of this needs boto3 for inference&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://aws.amazon.com/bedrock/pricing/?trk=7b33727f-f84b-453c-8f31-3d32f7b2a4e7&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;Amazon Bedrock pricing&lt;/a&gt;
— current rates. GPT-5.6 Terra and Luna pricing changed in late July 2026, so treat
this page as the source of truth&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.aws.amazon.com/bedrock/latest/userguide/api-keys-permissions.html?trk=7b33727f-f84b-453c-8f31-3d32f7b2a4e7&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;Bedrock API keys permissions&lt;/a&gt;
— calling the Responses API needs the &lt;code&gt;bedrock-mantle:CallWithBearerToken&lt;/code&gt; action.
Note it is &lt;strong&gt;not&lt;/strong&gt; &lt;code&gt;bedrock:CallWithBearerToken&lt;/code&gt;; the names are close enough that
getting it wrong yields a confusing denial&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.aws.amazon.com/bedrock/latest/userguide/model-access.html?trk=7b33727f-f84b-453c-8f31-3d32f7b2a4e7&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;Request access to models&lt;/a&gt;
— how model access permissions work. One easy point of confusion: the Marketplace
subscription flow described there applies to third-party models that have a product
ID, and &lt;strong&gt;OpenAI models are not sold through AWS Marketplace and have no product
ID&lt;/strong&gt;, so that flow and the &lt;code&gt;aws-marketplace:*&lt;/code&gt; permissions don't apply to GPT-5.6&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;OpenAI documentation&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;a href="https://developers.openai.com/cookbook/examples/partners/aws/openai_models_with_amazon_bedrock" rel="noopener noreferrer"&gt;Getting Started with OpenAI Models on Amazon Bedrock&lt;/a&gt;
— the official OpenAI Cookbook guide. Covers the advanced surface this post skips:
structured outputs, JSON mode, server-side state, encrypted reasoning context,
background work, direct PDF input, custom tools, and compaction.
⚠️ It defaults to &lt;code&gt;us-west-2&lt;/code&gt;, where Sol is unavailable, so don't copy its model
and Region configuration&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://developers.openai.com/api/docs/guides/reasoning" rel="noopener noreferrer"&gt;Reasoning models&lt;/a&gt;
— the official reference for &lt;code&gt;reasoning.effort&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Tools and dependencies&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;a href="https://docs.astral.sh/uv/getting-started/installation/" rel="noopener noreferrer"&gt;Installing uv / uvx&lt;/a&gt;
— required by &lt;code&gt;mcp_tools.py&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/awslabs/mcp" rel="noopener noreferrer"&gt;awslabs/mcp&lt;/a&gt;
— AWS's collection of MCP servers; the AWS Documentation MCP Server used here
comes from it&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://developers.openai.com/codex/amazon-bedrock" rel="noopener noreferrer"&gt;Codex on Amazon Bedrock&lt;/a&gt;
— pointing Codex at Bedrock&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Material used in the examples&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;a href="https://www.gutenberg.org/files/2701/2701-0.txt" rel="noopener noreferrer"&gt;Moby-Dick, Project Gutenberg #2701&lt;/a&gt;
— the reference document in &lt;code&gt;prompt_cache.py&lt;/code&gt;; published 1851, public domain&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Code&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;a href="https://github.com/hanyun2019/openai-bedrock-samples" rel="noopener noreferrer"&gt;openai-bedrock-samples&lt;/a&gt;
— every example in this post&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>ai</category>
      <category>aws</category>
      <category>gpt</category>
      <category>bedrock</category>
    </item>
    <item>
      <title>Building a Multi-Agent Quant Backtesting System: Amazon Bedrock AgentCore + Strands Agents</title>
      <dc:creator>Haowen Huang</dc:creator>
      <pubDate>Sat, 18 Jul 2026 23:24:20 +0000</pubDate>
      <link>https://dev.to/haowen_huang/building-a-multi-agent-quant-backtesting-system-amazon-bedrock-agentcore-strands-agents-16dj</link>
      <guid>https://dev.to/haowen_huang/building-a-multi-agent-quant-backtesting-system-amazon-bedrock-agentcore-strands-agents-16dj</guid>
      <description>&lt;p&gt;A hands-on walkthrough of building a multi-agent quantitative backtesting system on &lt;a href="https://docs.aws.amazon.com/bedrock-agentcore/?trk=7b33727f-f84b-453c-8f31-3d32f7b2a4e7&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;Amazon Bedrock AgentCore&lt;/a&gt; and the &lt;a href="https://strandsagents.com/?trk=7b33727f-f84b-453c-8f31-3d32f7b2a4e7&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;Strands Agents SDK&lt;/a&gt;. Three specialized AI agents collaborate to turn a plain-English trading strategy into a full performance report. This post is the introduction to an &lt;a href="https://catalog.us-east-1.prod.workshops.aws/workshops/dcf31eb4-6479-48ed-acc5-e58fe1f53656/en-US?trk=7b33727f-f84b-453c-8f31-3d32f7b2a4e7&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;eight-lab, 90-minute workshop&lt;/a&gt; and the first in a multi-part series. It covers the architecture, the three foundation models, and the lab progression—and kicks off follow-up posts on collaboration (A2A), safe execution (sandboxing), governed actions (guardrails), and compounding memory.&lt;/p&gt;




&lt;h3&gt;
  
  
  The Problem
&lt;/h3&gt;

&lt;p&gt;The success or failure of quantitative trading depends, to a large degree, on &lt;strong&gt;backtesting&lt;/strong&gt;. Before any real money goes into the market, a strategy has to prove itself on historical data: Does it make money? What's the worst-case loss? Is this much return worth that much risk?&lt;/p&gt;

&lt;p&gt;The hard part is that going from a trading idea to a credible backtest report spans several domains at once: trading domain knowledge, data engineering, Python coding, and statistical analysis. That is precisely the kind of multi-step, multi-skill problem where AI agents shine. The hands-on workshop explored in this post builds exactly such a system: multiple specialized agents collaborating to go from a one-sentence strategy description to a full performance analysis—automatically.&lt;/p&gt;

&lt;p&gt;This post gives you a quick tour of what the workshop covers and why its design decisions are worth adopting in your own projects.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Disclaimer:&lt;/strong&gt; This content is for learning and discussion purposes only. It does not constitute investment advice, recommendations, or solicitation. Any investment decisions and resulting gains or losses are solely the responsibility of the individual.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  About This Series
&lt;/h2&gt;

&lt;p&gt;This post is the opener of a multi-part series. It gives you the big picture; the follow-up posts each zoom into one design decision that turns this system from a demo into something production-ready:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Part 1 (this post)&lt;/strong&gt; — The big picture: the architecture, the models, and the eight-lab progression.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Part 2 — Collaboration (A2A protocol):&lt;/strong&gt; how agents discover and invoke each other across accounts, clouds, and frameworks using an open standard rather than a proprietary API.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Part 3 — Safe execution (Code Interpreter sandbox):&lt;/strong&gt; why you should not run LLM-generated code directly, and how a sandbox contains it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Part 4 — Governed actions (Cedar guardrails):&lt;/strong&gt; how to impose a deterministic guardrail on a probabilistic agent—a boundary it can never cross, no matter what it decides.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Part 5 — Compounding memory:&lt;/strong&gt; how giving the agent memory turns one-off backtests into a research companion that accumulates context and converses.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The through-line: big picture → collaboration → safety → accumulation. If any of those resonate, follow along.&lt;/p&gt;




&lt;h2&gt;
  
  
  What You'll Build
&lt;/h2&gt;

&lt;p&gt;This is a hands-on workshop—roughly 90 minutes—at an intermediate (300) level. By the end you will have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Three specialized AI agents deployed to Amazon Bedrock AgentCore&lt;/li&gt;
&lt;li&gt;The ability to connect agents to external market data through an AgentCore MCP Gateway&lt;/li&gt;
&lt;li&gt;A full-stack backtesting application that runs all the way from strategy input to performance analysis&lt;/li&gt;
&lt;li&gt;An understanding of multi-agent orchestration patterns for complex financial workflows.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The bar is not high: basic Python and command-line familiarity, plus a general grasp of trading concepts such as buy, sell, and technical indicators. No prior experience with AI agents or backtesting frameworks is required. The workshop environment ships with a browser-based code editor (Code-OSS/VS Code Open Source), so there is nothing to install locally.&lt;/p&gt;




&lt;h2&gt;
  
  
  Three Foundation Models
&lt;/h2&gt;

&lt;p&gt;A core idea of the workshop is &lt;strong&gt;matching the right model to the task&lt;/strong&gt;. Rather than having one large model do everything, each agent uses the model best suited to its job:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Model&lt;/th&gt;
&lt;th&gt;Role&lt;/th&gt;
&lt;th&gt;Responsibility&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Amazon Nova Lite 2.0&lt;/td&gt;
&lt;td&gt;Result summarizer&lt;/td&gt;
&lt;td&gt;Analyze performance metrics and write a professional report&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Anthropic Claude Sonnet 4&lt;/td&gt;
&lt;td&gt;Quant agent (orchestrator)&lt;/td&gt;
&lt;td&gt;Coordinate the entire workflow and all sub-agents&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Anthropic Claude Opus 4&lt;/td&gt;
&lt;td&gt;Strategy generator&lt;/td&gt;
&lt;td&gt;Turn natural-language strategy into executable Backtrader Python code&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Using a powerful model for code generation and a lighter, faster model for summarization is, in itself, a practical lesson in cost-and-latency optimization.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Backtesting, and Why Agents
&lt;/h2&gt;

&lt;p&gt;Backtesting answers the questions that matter most before real capital is deployed: total and annualized return, maximum drawdown, Sharpe and Sortino ratios, win rate, profit/loss ratio, and how a strategy behaves in bull, bear, and sideways markets.&lt;/p&gt;

&lt;p&gt;The traditional flow has five steps: define the strategy, gather historical data (OHLCV), implement it in code, run the simulation, and analyze the results. The problem is that each step demands a different skill.&lt;/p&gt;

&lt;p&gt;The workshop uses &lt;strong&gt;Backtrader&lt;/strong&gt;, a popular open-source Python backtesting framework with an event-driven engine, built-in technical indicators (SMA, EMA, RSI, MACD), order management, and performance analytics. In this system, the strategy generator writes the Backtrader code and the quant agent runs it against real market data—leaving the human free to focus on the strategy itself.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Multiple Agents Instead of One Big Agent
&lt;/h2&gt;

&lt;p&gt;A single "do-everything" agent tends to struggle with complex, multi-step tasks. The workshop argues for a multi-agent architecture along four axes:&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%2Fk4lzkarq8ygli4p8i1kq.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%2Fk4lzkarq8ygli4p8i1kq.png" alt=" " width="800" height="441"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Specialization&lt;/strong&gt; — each agent has a single responsibility, improving accuracy&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scalability&lt;/strong&gt; — distributed processing scales elastically and independently&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cost efficiency&lt;/strong&gt; — provision resources per agent, on demand&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Maintainability&lt;/strong&gt; — fine-grained control, independent health monitoring, isolated testing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Strands Agents supports four collaboration patterns:&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%2Ftk6df78bl5ibcbrsqmbf.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%2Ftk6df78bl5ibcbrsqmbf.png" alt=" " width="799" height="367"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Agent-as-Tool&lt;/strong&gt; (the orchestrator invokes specialized agents as callable tools)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Swarm&lt;/strong&gt; (agents collaborate through shared memory)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Graph&lt;/strong&gt; (agents as nodes connected by explicit edges)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Workflow&lt;/strong&gt; (structured, sequential collaboration)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Use Cases:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Loan approval processes&lt;/strong&gt; — Sequential steps: identity verification → credit check → risk assessment → approval decision&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CI/CD pipelines&lt;/strong&gt; — Build → test → security scan → deploy, with defined dependencies between stages&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Insurance claims&lt;/strong&gt; — Document collection → damage assessment → policy validation → settlement calculation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The diagram below illustrates sample use cases for each pattern.&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%2Fbpkrs1mux56o7cbk4wts.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%2Fbpkrs1mux56o7cbk4wts.png" alt=" " width="800" height="365"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This workshop uses the &lt;strong&gt;Agent-as-Tool&lt;/strong&gt; pattern, because a backtesting flow is naturally hierarchical:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User Request
↓
Quant Agent (Orchestrator)
├── invoke → Strategy Generator Agent → Backtrader code
├── invoke → Market Data MCP Tool → Historical OHLCV data
├── execute → Backtest (Backtrader engine)
└── invoke → Result Summarizer Agent → Performance analysis
↓
Consolidated Response → User

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Because each specialized agent runs independently, it can use a different model and its own configuration, and it can be tested, scaled, and updated in isolation.&lt;/p&gt;




&lt;h2&gt;
  
  
  What AgentCore Brings
&lt;/h2&gt;

&lt;p&gt;Amazon Bedrock AgentCore provides managed infrastructure for deploying, running, and scaling agents in production. The workshop uses five of its services:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Runtime&lt;/strong&gt; — a serverless compute environment that hosts each agent. No servers or containers to manage; it auto-scales with invocation load, supports secure environment variables, and enables agent-to-agent invocation. All three agents are deployed here.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Gateway&lt;/strong&gt; — wraps a market-data Lambda function into a &lt;code&gt;get_market_data&lt;/code&gt; MCP tool that any agent can invoke, with semantic routing and Cognito-based OAuth.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Identity&lt;/strong&gt; — secure authentication integrated with an existing identity provider (in this case, Amazon Cognito), ensuring that only authorized agents can access the market-data tool.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Memory&lt;/strong&gt; — short-term and long-term context storage, enabling the quant agent to handle follow-ups and iterative strategy refinement.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Observability&lt;/strong&gt; — OpenTelemetry-compatible tracing of the full execution path—from orchestrator to sub-agents to Gateway tool calls—flowing into Amazon CloudWatch.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Deployment is straightforward: point the AgentCore CLI at your Python entry file, and it handles packaging, dependencies, container management, and scaling:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;agentcore configure &lt;span class="nt"&gt;--entrypoint&lt;/span&gt; quant_agent.py &lt;span class="nt"&gt;--name&lt;/span&gt; quant_agent &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--requirements-file&lt;/span&gt; requirements.txt &lt;span class="nt"&gt;--idle-timeout&lt;/span&gt; 900

agentcore launch &lt;span class="nt"&gt;--auto-update-on-conflict&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--env&lt;/span&gt; &lt;span class="nv"&gt;AWS_REGION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$WORKSHOP_REGION&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--env&lt;/span&gt; &lt;span class="nv"&gt;STRATEGY_GENERATOR_RUNTIME_ARN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;arn:... &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--env&lt;/span&gt; &lt;span class="nv"&gt;AGENTCORE_GATEWAY_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;https://...

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  System Architecture
&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frxb1st2bof3doxr4owxp.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%2Frxb1st2bof3doxr4owxp.png" alt=" " width="800" height="446"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Overall system architecture. Source: the "Agentic Backtesting for Quants" workshop (AWS).&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The system has three layers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Frontend (Next.js)&lt;/strong&gt; — a strategy-input form, real-time workflow progress indicators, and a results dashboard with metrics and AI-generated analysis.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Orchestration layer (Bedrock AgentCore)&lt;/strong&gt; — the quant agent receives the request, invokes the strategy generator for code, fetches data through the market-data Gateway, runs the Backtrader simulation locally, and then invokes the result summarizer.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data layer&lt;/strong&gt; — S3 Tables (in Apache Iceberg format) store historical daily OHLCV data sourced from Yahoo Finance (for educational use only); a Lambda function queries the data via PyIceberg; and the Gateway exposes that Lambda function as the &lt;code&gt;get_market_data&lt;/code&gt; tool.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  The Hands-On Labs
&lt;/h2&gt;

&lt;p&gt;The labs build progressively, each adding one new AgentCore capability on top of the last. You start with a prompt-only agent and evolve it, step by step, into a full multi-agent system with observability and guardrails:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Lab 1 — Deploy the strategy generator (AgentCore Runtime):&lt;/strong&gt; get a simple, prompt-only agent up and running.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lab 2 — Build the quant agent with market data (AgentCore Gateway &amp;amp; Identity):&lt;/strong&gt; connect the agent to external tools.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lab 3 — Multi-agent orchestration (Agent-as-Tool):&lt;/strong&gt; transition from a single agent to an "orchestrator + experts" structure.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lab 4 — Run your first backtest (AgentCore Observability):&lt;/strong&gt; make the black box transparent with traces and spans.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lab 5 — Backtest memory and chat (AgentCore Memory):&lt;/strong&gt; transition from stateless to stateful, enabling the agent to remember context.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lab 6 (bonus) — Add guardrails (AgentCore Policy):&lt;/strong&gt; transition from unconstrained to governed execution.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lab 7 (bonus) — Sandboxed execution (AgentCore Code Interpreter):&lt;/strong&gt; run code in a secure sandbox rather than locally.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lab 8 (bonus) — A2A protocol (Agent-to-Agent):&lt;/strong&gt; replace a proprietary API with an open, interoperable standard.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This evolution path is itself the payoff: each lab corresponds to a real capability gap you will encounter when pushing an agent from "toy" toward "production."&lt;/p&gt;




&lt;h2&gt;
  
  
  What You've Built
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Component&lt;/th&gt;
&lt;th&gt;Technology&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Strategy Generator&lt;/td&gt;
&lt;td&gt;Claude Opus 4 + AgentCore&lt;/td&gt;
&lt;td&gt;Converts natural language to Backtrader code&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Quant Agent&lt;/td&gt;
&lt;td&gt;Claude Sonnet 4 + AgentCore&lt;/td&gt;
&lt;td&gt;Orchestrates the four-step workflow&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Results Summarizer&lt;/td&gt;
&lt;td&gt;Nova Lite 2.0 + AgentCore&lt;/td&gt;
&lt;td&gt;Analyzes performance metrics&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Market Data MCP&lt;/td&gt;
&lt;td&gt;Lambda + S3 Tables + AgentCore Gateway&lt;/td&gt;
&lt;td&gt;Serves historical OHLCV data&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Frontend&lt;/td&gt;
&lt;td&gt;Next.js + TypeScript&lt;/td&gt;
&lt;td&gt;User interface for strategy input and results&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Who It's For
&lt;/h2&gt;

&lt;p&gt;This workshop is aimed at quant developers, data scientists, engineers, and engineering managers who are curious about how agentic AI can accelerate quantitative trading workflows. If you have been looking for a concrete demonstration of how multi-agent orchestration, MCP, and managed agent infrastructure fit together in an end-to-end project, this is a well-scoped place to start. It is free at AWS events; running it in your own account requires you to cover the cloud resource costs.&lt;/p&gt;

&lt;p&gt;Finally, to repeat a reminder from the workshop itself: the market data here comes from Yahoo Finance, for educational use only, and is not investment advice. What is truly worth taking away is the overall architecture of this quant backtesting system and the multi-agent design patterns you can internalize and apply to your own systems.&lt;/p&gt;




&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Agentic Backtesting for Quants with Bedrock AgentCore and Strands Agents: &lt;a href="https://catalog.us-east-1.prod.workshops.aws/workshops/dcf31eb4-6479-48ed-acc5-e58fe1f53656/en-US?trk=7b33727f-f84b-453c-8f31-3d32f7b2a4e7&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;https://catalog.us-east-1.prod.workshops.aws/workshops/dcf31eb4-6479-48ed-acc5-e58fe1f53656/en-US?trk=7b33727f-f84b-453c-8f31-3d32f7b2a4e7&amp;amp;sc_channel=el&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Backtrader open-source backtesting framework: &lt;a href="https://www.backtrader.com/" rel="noopener noreferrer"&gt;https://www.backtrader.com/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Amazon Bedrock AgentCore docs: &lt;a href="https://docs.aws.amazon.com/bedrock-agentcore/?trk=7b33727f-f84b-453c-8f31-3d32f7b2a4e7&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;https://docs.aws.amazon.com/bedrock-agentcore/?trk=7b33727f-f84b-453c-8f31-3d32f7b2a4e7&amp;amp;sc_channel=el&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Strands Agents docs: &lt;a href="https://strandsagents.com/?trk=7b33727f-f84b-453c-8f31-3d32f7b2a4e7&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;https://strandsagents.com/?trk=7b33727f-f84b-453c-8f31-3d32f7b2a4e7&amp;amp;sc_channel=el&lt;/a&gt;
&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>ai</category>
      <category>python</category>
      <category>opensource</category>
      <category>aws</category>
    </item>
    <item>
      <title>Running Claude Code and Claude Desktop on Amazon Bedrock</title>
      <dc:creator>Haowen Huang</dc:creator>
      <pubDate>Mon, 04 May 2026 06:35:23 +0000</pubDate>
      <link>https://dev.to/haowen_huang/running-claude-code-and-claude-desktop-on-amazon-bedrock-1ed2</link>
      <guid>https://dev.to/haowen_huang/running-claude-code-and-claude-desktop-on-amazon-bedrock-1ed2</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Abstract:&lt;/strong&gt; This article walks through configuring both Claude Code (terminal CLI) and Claude Desktop (Cowork) to use &lt;a href="https://aws.amazon.com/bedrock/?trk=7b33727f-f84b-453c-8f31-3d32f7b2a4e7&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;Amazon Bedrock&lt;/a&gt; as the inference backend — no Anthropic API key or subscription required. Claude Code needs two environment variables in &lt;code&gt;~/.claude/settings.json&lt;/code&gt;. Claude Desktop needs a few fields in the built-in Setup UI. Both share the same AWS credentials and Bedrock model access. The entire setup, including troubleshooting, was done through AI-assisted development with &lt;a href="https://kiro.dev/?trk=7b33727f-f84b-453c-8f31-3d32f7b2a4e7&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;Kiro&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In a &lt;a href="https://builder.aws.com/content/3AC38DtkrFlNL0p076gVNPzSHuw/running-claude-agent-sdk-with-skills-on-amazon-bedrock" rel="noopener noreferrer"&gt;previous post&lt;/a&gt;, we covered how to run the Claude Agent SDK (Python) on &lt;a href="https://aws.amazon.com/bedrock/?trk=7b33727f-f84b-453c-8f31-3d32f7b2a4e7&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;Amazon Bedrock&lt;/a&gt; with just two environment variables. This post continues the series, covering the other two main ways developers interact with Claude daily: the terminal CLI and the desktop app.&lt;/p&gt;

&lt;p&gt;If you're already in the AWS ecosystem, routing Claude through &lt;a href="https://aws.amazon.com/bedrock/?trk=7b33727f-f84b-453c-8f31-3d32f7b2a4e7&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;Amazon Bedrock&lt;/a&gt; keeps your data in your own account, bills through your existing AWS agreement, and eliminates the need for a separate Anthropic subscription. This post covers two scenarios:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Scenario A:&lt;/strong&gt; Claude Code CLI — the terminal-based coding tool&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scenario B:&lt;/strong&gt; Claude Desktop (Cowork 3P) — the GUI desktop app&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Both use the same AWS IAM user and Bedrock model access.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites (Shared)
&lt;/h2&gt;

&lt;p&gt;Before either scenario, make sure you have:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;AWS CLI installed and credentials configured&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws &lt;span class="nt"&gt;--version&lt;/span&gt;
aws sts get-caller-identity
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Bedrock model access enabled&lt;/strong&gt; — Serverless foundation models on &lt;a href="https://console.aws.amazon.com/bedrock/?trk=7b33727f-f84b-453c-8f31-3d32f7b2a4e7&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;Amazon Bedrock&lt;/a&gt; are now automatically enabled when first invoked. However, for Anthropic models, first-time users may need to submit use case details before access is granted. Simply select a model from the Model catalog and try invoking it — you'll be prompted if any additional steps are needed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;IAM permissions&lt;/strong&gt; — Your IAM user or role needs:&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&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;"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="w"&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="s2"&gt;"bedrock:ListInferenceProfiles"&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:GetInferenceProfile"&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;"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:*:*:inference-profile/*"&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:*:*:application-inference-profile/*"&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="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;ol&gt;
&lt;li&gt;
&lt;strong&gt;Know your inference profile IDs&lt;/strong&gt; — Bedrock requires cross-region inference profile IDs (with a region prefix like &lt;code&gt;us.&lt;/code&gt;), not bare model IDs. The ones used in this post:&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Model&lt;/th&gt;
&lt;th&gt;Inference Profile ID&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Claude Opus 4.7&lt;/td&gt;
&lt;td&gt;&lt;code&gt;us.anthropic.claude-opus-4-7&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Claude Opus 4.6&lt;/td&gt;
&lt;td&gt;&lt;code&gt;us.anthropic.claude-opus-4-6-v1&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Scenario A: Claude Code CLI
&lt;/h2&gt;

&lt;p&gt;Claude Code is Anthropic's terminal-based AI coding tool. Install it via npm:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; @anthropic-ai/claude-code
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 1: Edit settings.json
&lt;/h3&gt;

&lt;p&gt;The cleanest approach is writing the Bedrock configuration into Claude Code's settings file, so you don't need to export environment variables every time.&lt;/p&gt;

&lt;p&gt;Edit &lt;code&gt;~/.claude/settings.json&lt;/code&gt;:&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;"model"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"us.anthropic.claude-opus-4-6-v1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"env"&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;"CLAUDE_CODE_USE_BEDROCK"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1"&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_REGION"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"us-east-1"&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 key fields:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;CLAUDE_CODE_USE_BEDROCK&lt;/code&gt;: Tells Claude Code to use Bedrock instead of the Anthropic API.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;AWS_REGION&lt;/code&gt;: Required. Claude Code does not read this from &lt;code&gt;~/.aws/config&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;code&gt;model&lt;/code&gt; field uses the Bedrock inference profile ID. Without it, Claude Code picks its own default.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Run and Verify
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;claude
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inside Claude Code, run &lt;code&gt;/status&lt;/code&gt;. You should see:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;API provider&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Amazon Bedrock&lt;/span&gt;
&lt;span class="na"&gt;AWS region&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;us-east-1&lt;/span&gt;
&lt;span class="na"&gt;Model&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;us.anthropic.claude-opus-4-6-v1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it. Claude Code picks up your AWS credentials through the standard SDK credential chain (&lt;code&gt;~/.aws/credentials&lt;/code&gt;, environment variables, IAM role, SSO profile).&lt;/p&gt;

&lt;h3&gt;
  
  
  Switching Models
&lt;/h3&gt;

&lt;p&gt;There are two ways to switch models:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;At runtime&lt;/strong&gt; — Inside Claude Code, use the &lt;code&gt;/model&lt;/code&gt; command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;/model us.anthropic.claude-opus-4-7
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This switches immediately without restarting. Use &lt;code&gt;/model us.anthropic.claude-opus-4-6-v1&lt;/code&gt; to switch back.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Permanently&lt;/strong&gt; — Change the &lt;code&gt;model&lt;/code&gt; field in &lt;code&gt;~/.claude/settings.json&lt;/code&gt;:&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;"model"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"us.anthropic.claude-opus-4-7"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"env"&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;"CLAUDE_CODE_USE_BEDROCK"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1"&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_REGION"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"us-east-1"&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;Restart Claude Code (&lt;code&gt;/exit&lt;/code&gt;, then &lt;code&gt;claude&lt;/code&gt;) for the change to take effect.&lt;/p&gt;

&lt;h3&gt;
  
  
  Optional: Install Skills
&lt;/h3&gt;

&lt;p&gt;Claude Code supports Skills — packaged instructions that extend Claude's capabilities. Anthropic publishes an official set at &lt;a href="https://github.com/anthropics/skills" rel="noopener noreferrer"&gt;github.com/anthropics/skills&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;To install them, run inside Claude Code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;/plugin marketplace add anthropics/skills
/plugin &lt;span class="nb"&gt;install &lt;/span&gt;document-skills@anthropic-agent-skills
/plugin &lt;span class="nb"&gt;install &lt;/span&gt;example-skills@anthropic-agent-skills
/reload-plugins
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This gives you skills like &lt;code&gt;mcp-builder&lt;/code&gt;, &lt;code&gt;webapp-testing&lt;/code&gt;, &lt;code&gt;claude-api&lt;/code&gt;, document generation (docx/pdf/pptx/xlsx), and more.&lt;/p&gt;

&lt;p&gt;After installation, your &lt;code&gt;~/.claude/settings.json&lt;/code&gt; will be updated automatically with the new plugin entries:&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;"model"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"us.anthropic.claude-opus-4-6-v1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"env"&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;"CLAUDE_CODE_USE_BEDROCK"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1"&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_REGION"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"us-east-1"&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;"enabledPlugins"&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;"document-skills@anthropic-agent-skills"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"example-skills@anthropic-agent-skills"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&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;"extraKnownMarketplaces"&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;"anthropic-agent-skills"&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;"source"&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;"source"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"github"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"repo"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"anthropics/skills"&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;Compared to the base configuration in Step 1, two new sections are added:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;enabledPlugins&lt;/code&gt;: Tracks which Skills are active.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;extraKnownMarketplaces&lt;/code&gt;: Records the GitHub source for the Skills marketplace.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Example: Turning a Blog Post into a Slide Deck
&lt;/h4&gt;

&lt;p&gt;Once Skills are installed, you can use them directly in Claude Code. For example, I previously wrote a blog post &lt;a href="https://builder.aws.com/content/3CQFzc91nM9sGkfHRbpjo4eXojf/deploying-openclaw-on-amazon-ec2-a-developers-perspective" rel="noopener noreferrer"&gt;"Deploying OpenClaw on Amazon EC2 - A Developer's Perspective"&lt;/a&gt;, covering one-click CloudFormation deployment, VPC Endpoints security architecture, and multi-region inference profile configuration. It's a detailed post. If I needed to present this topic at a developer conference the next day, building slides manually would take too long. With the &lt;code&gt;pptx&lt;/code&gt; skill, it takes one command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;❯ /example-skills:pptx
⏺ PPTX skill loaded. What presentation would you like me to create?

❯ Turn the following blog post into a slide deck:
  https://builder.aws.com/content/3CQFzc91nM9sGkfHRbpjo4eXojf/deploying-openclaw-on-amazon-ec2-a-developers-perspective
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Claude Code reads the blog, extracts the architecture descriptions, deployment steps, and key configurations, organizes them into well-structured slides, and generates a &lt;code&gt;.pptx&lt;/code&gt; file — all within the terminal, powered by &lt;a href="https://aws.amazon.com/bedrock/?trk=7b33727f-f84b-453c-8f31-3d32f7b2a4e7&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;Amazon Bedrock&lt;/a&gt;. From blog post to presentation-ready slides in a single command.&lt;/p&gt;

&lt;h2&gt;
  
  
  Scenario B: Claude Desktop (Cowork 3P)
&lt;/h2&gt;

&lt;p&gt;Claude Desktop can run in "third-party platform" mode, using Bedrock for inference instead of Anthropic's own servers. This is called Cowork 3P.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Open the Setup UI
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Open Claude Desktop (you don't need to log in)&lt;/li&gt;
&lt;li&gt;Go to &lt;strong&gt;Help → Troubleshooting → Enable Developer mode&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Go to &lt;strong&gt;Developer → Configure third-party inference&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This opens the built-in configuration UI.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Configure Bedrock
&lt;/h3&gt;

&lt;p&gt;Fill in the following fields:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Field&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Inference provider&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Bedrock&lt;/strong&gt; (select the radio button)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AWS region&lt;/td&gt;
&lt;td&gt;&lt;code&gt;us-east-1&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AWS bearer token&lt;/td&gt;
&lt;td&gt;Leave empty&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Bedrock base URL&lt;/td&gt;
&lt;td&gt;Leave empty&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AWS profile name&lt;/td&gt;
&lt;td&gt;&lt;code&gt;default&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AWS config directory&lt;/td&gt;
&lt;td&gt;Leave empty (uses &lt;code&gt;~/.aws&lt;/code&gt; by default)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Under &lt;strong&gt;IDENTITY &amp;amp; MODELS&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;Field&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Model list&lt;/td&gt;
&lt;td&gt;&lt;code&gt;us.anthropic.claude-opus-4-6-v1&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The model list uses Bedrock inference profile IDs. You can add multiple models — click &lt;strong&gt;+ Add&lt;/strong&gt; for each one. The first entry becomes the default.&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%2Fr4bcp9u5cau8tmrkdpq9.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%2Fr4bcp9u5cau8tmrkdpq9.png" alt=" " width="800" height="643"&gt;&lt;/a&gt;&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%2F7i6f52d3cv6mwnh4sk4m.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%2F7i6f52d3cv6mwnh4sk4m.png" alt=" " width="800" height="638"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: Apply and Relaunch
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Click &lt;strong&gt;Apply locally&lt;/strong&gt; at the bottom of the Setup UI&lt;/li&gt;
&lt;li&gt;Fully quit Claude Desktop (&lt;strong&gt;Cmd+Q&lt;/strong&gt; on macOS)&lt;/li&gt;
&lt;li&gt;Reopen Claude Desktop&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;After relaunch, Claude Desktop shows the Bedrock login screen — no Anthropic account needed, just your AWS credentials:&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%2Fg1bbaie9ttlvxppho8g4.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%2Fg1bbaie9ttlvxppho8g4.png" alt=" " width="800" height="796"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 4: Verify
&lt;/h3&gt;

&lt;p&gt;After relaunch, you should see:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Bottom-left corner shows &lt;strong&gt;Cowork 3P | Bedrock&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;The model picker shows &lt;code&gt;us.anthropic.claude-opus-4-6-v1&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Claude responds and identifies itself as running on the Bedrock model&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Send a test message like "What version of the model are you currently using?" — Claude should confirm it's powered by &lt;code&gt;claude-opus-4-6-v1&lt;/code&gt; in Cowork mode.&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%2Fmul2k7xl70javjr8z24p.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%2Fmul2k7xl70javjr8z24p.png" alt=" " width="800" height="525"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Adding More Models Later
&lt;/h3&gt;

&lt;p&gt;To add models (e.g., Opus 4.7) after initial setup:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;In the macOS menu bar, go to &lt;strong&gt;Help → Troubleshooting → Enable Developer mode&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;Developer&lt;/strong&gt; menu appears in the menu bar — click &lt;strong&gt;Developer → Configure third-party inference&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Under Model list, click &lt;strong&gt;+ Add&lt;/strong&gt; and enter &lt;code&gt;us.anthropic.claude-opus-4-7&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Apply locally&lt;/strong&gt;, then &lt;strong&gt;Cmd+Q&lt;/strong&gt; and reopen Claude Desktop&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The model picker at the bottom of the chat window will now show all configured models.&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%2Fsfrfbgc8du3tipa9muc6.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%2Fsfrfbgc8du3tipa9muc6.png" alt=" " width="800" height="520"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  How It Works Under the Hood
&lt;/h3&gt;

&lt;p&gt;When you set &lt;strong&gt;AWS profile name&lt;/strong&gt; to &lt;code&gt;default&lt;/code&gt;, Claude Desktop reads your &lt;code&gt;~/.aws/credentials&lt;/code&gt; and &lt;code&gt;~/.aws/config&lt;/code&gt; files to authenticate with Bedrock. The three authentication methods are:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Method&lt;/th&gt;
&lt;th&gt;When to use&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;AWS bearer token&lt;/td&gt;
&lt;td&gt;If you have a Bedrock API key&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AWS profile name&lt;/td&gt;
&lt;td&gt;If you have standard AWS credentials (this is what we used)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Credential helper&lt;/td&gt;
&lt;td&gt;For enterprise SSO setups with rotating credentials&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;You only need one of the three. The Setup UI validates the configuration and writes it to &lt;code&gt;~/Library/Application Support/Claude-3p/claude_desktop_config.json&lt;/code&gt; on macOS.&lt;/p&gt;

&lt;h3&gt;
  
  
  Important: Use the Setup UI
&lt;/h3&gt;

&lt;p&gt;During this setup, I first tried manually editing the &lt;code&gt;claude_desktop_config.json&lt;/code&gt; file. This resulted in a persistent "Your provider setup needs a fix" error. The Setup UI handles the correct format and field validation automatically — use it instead of hand-editing the JSON.&lt;/p&gt;

&lt;h2&gt;
  
  
  Troubleshooting
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;"on-demand throughput isn't supported"&lt;/strong&gt; — You're using a bare model ID instead of an inference profile ID. Use the &lt;code&gt;us.&lt;/code&gt; prefixed IDs (e.g., &lt;code&gt;us.anthropic.claude-opus-4-6-v1&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;"Your provider setup needs a fix" in Claude Desktop&lt;/strong&gt; — Don't hand-edit the config JSON. Use the Setup UI (Developer → Configure third-party inference) and click Apply locally.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Claude Code &lt;code&gt;/status&lt;/code&gt; doesn't show Bedrock&lt;/strong&gt; — Make sure &lt;code&gt;CLAUDE_CODE_USE_BEDROCK&lt;/code&gt; is set to &lt;code&gt;"1"&lt;/code&gt; in &lt;code&gt;~/.claude/settings.json&lt;/code&gt; under the &lt;code&gt;env&lt;/code&gt; key. Restart Claude Code after changing settings.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;AWS credentials not found&lt;/strong&gt; — Claude Code uses the standard AWS SDK credential chain. Verify with &lt;code&gt;aws sts get-caller-identity&lt;/code&gt;. For Claude Desktop, make sure the AWS profile name matches a profile in &lt;code&gt;~/.aws/credentials&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Claude Code CLI&lt;/th&gt;
&lt;th&gt;Claude Desktop (Cowork 3P)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Config location&lt;/td&gt;
&lt;td&gt;&lt;code&gt;~/.claude/settings.json&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Setup UI → Apply locally&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Key setting&lt;/td&gt;
&lt;td&gt;&lt;code&gt;CLAUDE_CODE_USE_BEDROCK=1&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;inferenceProvider: bedrock&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Auth method&lt;/td&gt;
&lt;td&gt;AWS SDK credential chain&lt;/td&gt;
&lt;td&gt;AWS profile name&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Model format&lt;/td&gt;
&lt;td&gt;Inference profile ID&lt;/td&gt;
&lt;td&gt;Inference profile ID&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Verify&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;/status&lt;/code&gt; in Claude Code&lt;/td&gt;
&lt;td&gt;Bottom-left shows "Cowork 3P | Bedrock"&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Both scenarios use the same AWS credentials and Bedrock model access. Once you have one working, the other is straightforward.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Note on the Setup Process
&lt;/h2&gt;

&lt;p&gt;This entire configuration — both scenarios, including troubleshooting the Claude Desktop JSON format issue — was completed through conversation with &lt;a href="https://kiro.dev/?trk=7b33727f-f84b-453c-8f31-3d32f7b2a4e7&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;Kiro&lt;/a&gt;, an AI-powered IDE. &lt;a href="https://kiro.dev/?trk=7b33727f-f84b-453c-8f31-3d32f7b2a4e7&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;Kiro&lt;/a&gt; checked the AWS environment, verified IAM permissions, wrote the settings files, researched the official documentation, and diagnosed the Setup UI requirement for Claude Desktop — all without leaving the IDE.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Tested with Claude Code 2.1.123, Claude Desktop (Cowork 3P), Claude Opus 4.6 &amp;amp; 4.7 on &lt;a href="https://aws.amazon.com/bedrock/?trk=7b33727f-f84b-453c-8f31-3d32f7b2a4e7&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;Amazon Bedrock&lt;/a&gt;, us-east-1&lt;/em&gt;&lt;/p&gt;

</description>
      <category>claude</category>
      <category>agents</category>
      <category>claudecode</category>
      <category>claudedesktop</category>
    </item>
    <item>
      <title>Deploying OpenClaw on Amazon EC2 - A Developer's Perspective</title>
      <dc:creator>Haowen Huang</dc:creator>
      <pubDate>Thu, 16 Apr 2026 04:10:44 +0000</pubDate>
      <link>https://dev.to/haowen_huang/deploying-openclaw-on-aws-ec2-a-developers-perspective-4d3i</link>
      <guid>https://dev.to/haowen_huang/deploying-openclaw-on-aws-ec2-a-developers-perspective-4d3i</guid>
      <description>&lt;h2&gt;
  
  
  What is OpenClaw?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/openclaw/openclaw" rel="noopener noreferrer"&gt;OpenClaw&lt;/a&gt; is a personal AI assistant that you can deploy on your own infrastructure. It can respond to you through channels you already use — WhatsApp, Telegram, Slack, Discord, Google Chat, Signal, iMessage, WeChat, Lark, and 20+ other platforms. It can have voice conversations on macOS/iOS/Android, and render a real-time Canvas you can control. The Gateway is just the control plane — the product itself is the assistant.&lt;/p&gt;

&lt;p&gt;If you want a self-hosted, fast, always-on single-user personal assistant, OpenClaw is it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Run Your Own AI Assistant on AWS?
&lt;/h2&gt;

&lt;p&gt;Most people interact with AI through hosted services. That works — until you care about:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Privacy&lt;/strong&gt;: Your conversations, code, and data stay in your AWS account&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cost control&lt;/strong&gt;: Pay only for Bedrock API usage, no per-seat SaaS fees&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Customization&lt;/strong&gt;: Full control over models, plugins, and integrations&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security&lt;/strong&gt;: No open ports, no public endpoints, SSM-only access&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By deploying OpenClaw on AWS with Amazon Bedrock, you can use the latest Claude models (Opus 4.6, Sonnet 4.6) as your personal AI assistant — not just for coding, but for automation, messaging, device control, and more.&lt;/p&gt;

&lt;p&gt;I decided to try it out myself. Here's how it went.&lt;/p&gt;

&lt;h2&gt;
  
  
  Architecture: What You're Deploying
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;🚀 Quick Start&lt;/strong&gt;: If you're an experienced developer, you can use the deployment template directly:&lt;/p&gt;


&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-O&lt;/span&gt; https://raw.githubusercontent.com/hanyun2019/openclaw-on-aws/main/openclaw-deployment.yaml

aws cloudformation create-stack &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--stack-name&lt;/span&gt; openclaw &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--template-body&lt;/span&gt; file://openclaw-deployment.yaml &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--capabilities&lt;/span&gt; CAPABILITY_IAM &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--region&lt;/span&gt; us-east-1
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;📦 &lt;strong&gt;Template URL&lt;/strong&gt;: &lt;a href="https://github.com/hanyun2019/openclaw-on-aws" rel="noopener noreferrer"&gt;github.com/hanyun2019/openclaw-on-aws&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;⚠️ &lt;strong&gt;Non-US Region Users&lt;/strong&gt;: Additional configuration is required after deployment. See the &lt;em&gt;Non-US Region Deployment Guide&lt;/em&gt; below.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Before we dive in, here's what the CloudFormation template sets up:&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%2Fxutnx9qq9mvwrzdly8x2.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%2Fxutnx9qq9mvwrzdly8x2.png" alt="OpenClaw on AWS Architecture" width="800" height="556"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;User Access&lt;/strong&gt;: Connect via SSM Session Manager to establish a secure tunnel, forwarding local &lt;code&gt;localhost:18789&lt;/code&gt; to the EC2 instance — no inbound ports required.&lt;/p&gt;

&lt;p&gt;Key design decisions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;EC2 in the public subnet&lt;/strong&gt; — for initial setup (package downloads via Internet Gateway)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;VPC Endpoints in the private subnet&lt;/strong&gt; — ensures Bedrock API calls never leave the AWS network&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No inbound ports open&lt;/strong&gt; — all access through SSM port forwarding&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Graviton (ARM) instances&lt;/strong&gt; — better price-performance ratio&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;Before you start, make sure you have:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;An AWS account&lt;/strong&gt; with billing enabled&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;IAM permissions&lt;/strong&gt;: Ability to create CloudFormation, EC2, IAM, and VPC resources&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Local tools installed&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html?trk=7b33727f-f84b-453c-8f31-3d32f7b2a4e7&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;AWS CLI v2&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.aws.amazon.com/systems-manager/latest/userguide/session-manager-working-with-install-plugin.html?trk=7b33727f-f84b-453c-8f31-3d32f7b2a4e7&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;SSM Session Manager Plugin&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  US Region Deployment Guide
&lt;/h2&gt;

&lt;p&gt;If you're deploying in &lt;code&gt;us-east-1&lt;/code&gt; or &lt;code&gt;us-west-2&lt;/code&gt;, it's genuinely a one-click experience.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Download the Template
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-O&lt;/span&gt; https://raw.githubusercontent.com/hanyun2019/openclaw-on-aws/main/openclaw-deployment.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 2: Deploy the Stack
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws cloudformation create-stack &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--stack-name&lt;/span&gt; openclaw &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--template-body&lt;/span&gt; file://openclaw-deployment.yaml &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--capabilities&lt;/span&gt; CAPABILITY_IAM &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--region&lt;/span&gt; us-east-1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Optional parameters&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;Parameter&lt;/th&gt;
&lt;th&gt;Default&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;InstanceType&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;t4g.large&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Graviton instance type (2 vCPU, 8GB RAM)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;KeyPairName&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;em&gt;(none)&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;EC2 key pair for SSH access (optional)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;CreateVPCEndpoints&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;true&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Create VPC endpoints for private Bedrock access&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;AllowedSSHCIDR&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;em&gt;(empty)&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;CIDR block for SSH access (optional)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;For example, to use a larger instance:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws cloudformation create-stack &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--stack-name&lt;/span&gt; openclaw &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--template-body&lt;/span&gt; file://openclaw-deployment.yaml &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--capabilities&lt;/span&gt; CAPABILITY_IAM &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--region&lt;/span&gt; us-east-1 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--parameters&lt;/span&gt; &lt;span class="nv"&gt;ParameterKey&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;InstanceType,ParameterValue&lt;span class="o"&gt;=&lt;/span&gt;t4g.xlarge
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 3: Wait (~10-15 minutes)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws cloudformation &lt;span class="nb"&gt;wait &lt;/span&gt;stack-create-complete &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--stack-name&lt;/span&gt; openclaw &lt;span class="nt"&gt;--region&lt;/span&gt; us-east-1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Go grab a coffee. ☕&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 4: Get Your Access Info
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws cloudformation describe-stacks &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--stack-name&lt;/span&gt; openclaw &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--query&lt;/span&gt; &lt;span class="s1"&gt;'Stacks[0].Outputs'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--region&lt;/span&gt; us-east-1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This gives you the instance ID and access URL.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 5: Connect via SSM Port Forwarding
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Get Instance ID&lt;/span&gt;
&lt;span class="nv"&gt;INSTANCE_ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;aws cloudformation describe-stacks &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--stack-name&lt;/span&gt; openclaw &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--query&lt;/span&gt; &lt;span class="s1"&gt;'Stacks[0].Outputs[?OutputKey==`InstanceId`].OutputValue'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--output&lt;/span&gt; text &lt;span class="nt"&gt;--region&lt;/span&gt; us-east-1&lt;span class="si"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;# Start the tunnel&lt;/span&gt;
aws ssm start-session &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--target&lt;/span&gt; &lt;span class="nv"&gt;$INSTANCE_ID&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--region&lt;/span&gt; us-east-1 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--document-name&lt;/span&gt; AWS-StartPortForwardingSession &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--parameters&lt;/span&gt; &lt;span class="s1"&gt;'{"portNumber":["18789"],"localPortNumber":["18789"]}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 6: Open OpenClaw
&lt;/h3&gt;

&lt;p&gt;Navigate to the &lt;code&gt;Step3AccessURL&lt;/code&gt; from the stack outputs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;http://localhost:18789/?token=&amp;lt;your-token&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it. You're in. 🎉&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%2Fh2o59kmucgvk1qjv936b.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%2Fh2o59kmucgvk1qjv936b.png" alt="OpenClaw Admin Page" width="800" height="521"&gt;&lt;/a&gt;&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%2F9vzj9hvlk4sadgsm1xon.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%2F9vzj9hvlk4sadgsm1xon.png" alt="OpenClaw Chat Interface" width="800" height="472"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Non-US Region Deployment Guide
&lt;/h2&gt;

&lt;p&gt;If you're deploying outside the US (e.g., Sydney &lt;code&gt;ap-southeast-2&lt;/code&gt;), you need to modify the model IDs.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: If you're deploying in &lt;strong&gt;us-east-1&lt;/strong&gt; or &lt;strong&gt;us-west-2&lt;/strong&gt;, you can skip this section. The template's default &lt;code&gt;us.&lt;/code&gt; prefixed model IDs work out of the box in US regions.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  The Issue
&lt;/h3&gt;

&lt;p&gt;The template defaults to &lt;code&gt;us.anthropic.claude-opus-4-6-v1&lt;/code&gt; — this is the US region Inference Profile. In other regions, you need to use the corresponding regional prefix.&lt;/p&gt;

&lt;h3&gt;
  
  
  Solution Steps
&lt;/h3&gt;

&lt;h4&gt;
  
  
  1. Connect to the Instance via SSM
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws ssm start-session &lt;span class="nt"&gt;--target&lt;/span&gt; &amp;lt;instance-id&amp;gt; &lt;span class="nt"&gt;--region&lt;/span&gt; ap-southeast-2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  2. Query Available Inference Profiles (Optional)
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws bedrock list-inference-profiles &lt;span class="nt"&gt;--region&lt;/span&gt; ap-southeast-2 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--query&lt;/span&gt; &lt;span class="s1"&gt;'inferenceProfileSummaries[*].inferenceProfileId'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--output&lt;/span&gt; table
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  3. Update OpenClaw Configuration
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nano /home/ubuntu/.openclaw/openclaw.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Replace the &lt;code&gt;us.&lt;/code&gt; prefix in model IDs with your region's prefix:&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;"models"&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;"providers"&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;"amazon-bedrock"&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;"models"&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;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"au.anthropic.claude-opus-4-6-v1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Claude Opus 4.6"&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;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"au.anthropic.claude-sonnet-4-6"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Claude Sonnet 4.6"&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;span class="nl"&gt;"agents"&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;"defaults"&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;"model"&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;"primary"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"amazon-bedrock/au.anthropic.claude-opus-4-6-v1"&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;blockquote&gt;
&lt;p&gt;&lt;strong&gt;nano save&lt;/strong&gt;: &lt;code&gt;Ctrl+O&lt;/code&gt; → Enter to confirm → &lt;code&gt;Ctrl+X&lt;/code&gt; to exit&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  4. Restart the Gateway
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;systemctl &lt;span class="nt"&gt;--user&lt;/span&gt; restart openclaw-gateway.service
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Done! 🎉&lt;/p&gt;




&lt;h2&gt;
  
  
  Understanding Inference Profile Prefixes
&lt;/h2&gt;

&lt;p&gt;Here's a quick reference:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Prefix&lt;/th&gt;
&lt;th&gt;Scope&lt;/th&gt;
&lt;th&gt;Example Regions&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;us.&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;US cross-region&lt;/td&gt;
&lt;td&gt;us-east-1, us-east-2, us-west-2, ca-central-1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;eu.&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Europe cross-region&lt;/td&gt;
&lt;td&gt;eu-central-1, eu-west-1, eu-west-3, eu-north-1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;apac.&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Asia-Pacific cross-region&lt;/td&gt;
&lt;td&gt;ap-northeast-1, ap-southeast-1, ap-southeast-2, ap-south-1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;au.&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Australia&lt;/td&gt;
&lt;td&gt;ap-southeast-2, ap-southeast-4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;jp.&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Japan&lt;/td&gt;
&lt;td&gt;ap-northeast-1, ap-northeast-3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;global.&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Global cross-region (routes to optimal commercial region)&lt;/td&gt;
&lt;td&gt;Can be called from all commercial regions&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Rule of thumb&lt;/strong&gt;: Use the most specific prefix for your deployment region.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Deploying in &lt;strong&gt;us-east-1&lt;/strong&gt; or &lt;strong&gt;us-west-2&lt;/strong&gt;? The default &lt;code&gt;us.anthropic.claude-opus-4-6-v1&lt;/code&gt; just works. No changes needed.&lt;/li&gt;
&lt;li&gt;Deploying in &lt;strong&gt;ap-southeast-2&lt;/strong&gt; (Sydney)? Use &lt;code&gt;au.anthropic.claude-opus-4-6-v1&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Deploying in &lt;strong&gt;ap-northeast-1&lt;/strong&gt; (Tokyo)? Use &lt;code&gt;jp.anthropic.claude-sonnet-4-6&lt;/code&gt; or &lt;code&gt;apac.&lt;/code&gt; prefix.&lt;/li&gt;
&lt;li&gt;Deploying in &lt;strong&gt;eu-west-1&lt;/strong&gt; (Ireland)? Use &lt;code&gt;eu.anthropic.claude-opus-4-6-v1&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Not sure? Query &lt;code&gt;aws bedrock list-inference-profiles&lt;/code&gt; in your region to see what's available.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: Model availability varies by region. For example, Claude Opus 4.6 in Japan may only be available with the &lt;code&gt;global.&lt;/code&gt; prefix, while Sonnet 4.6 has a &lt;code&gt;jp.&lt;/code&gt; prefix. Use &lt;code&gt;aws bedrock list-inference-profiles&lt;/code&gt; to check actual available profiles in your region.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Cost Estimate
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Resource&lt;/th&gt;
&lt;th&gt;Spec&lt;/th&gt;
&lt;th&gt;Est. Monthly Cost&lt;/th&gt;
&lt;th&gt;Calculation&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;EC2 (&lt;code&gt;t4g.large&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;2 vCPU, 8GB RAM&lt;/td&gt;
&lt;td&gt;~$49&lt;/td&gt;
&lt;td&gt;$0.0672/hr × 730 hrs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;EBS (&lt;code&gt;gp3&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;50GB&lt;/td&gt;
&lt;td&gt;~$4&lt;/td&gt;
&lt;td&gt;$0.08/GB-mo × 50GB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;VPC Endpoints (×4)&lt;/td&gt;
&lt;td&gt;Interface type&lt;/td&gt;
&lt;td&gt;~$29&lt;/td&gt;
&lt;td&gt;$0.01/hr × 730 hrs × 4 endpoints&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Bedrock API&lt;/td&gt;
&lt;td&gt;Usage-based&lt;/td&gt;
&lt;td&gt;Variable&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Total (excl. API)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;~$82&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Pricing References&lt;/strong&gt; (us-east-1 region, 2024):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;EC2 pricing: &lt;a href="https://aws.amazon.com/ec2/instance-types/t4/?trk=7b33727f-f84b-453c-8f31-3d32f7b2a4e7&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;AWS EC2 T4g Instances&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;EBS pricing: &lt;a href="https://aws.amazon.com/ebs/pricing/?trk=7b33727f-f84b-453c-8f31-3d32f7b2a4e7&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;AWS EBS Pricing&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;VPC Endpoint pricing: &lt;a href="https://aws.amazon.com/privatelink/pricing/?trk=7b33727f-f84b-453c-8f31-3d32f7b2a4e7&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;AWS PrivateLink Pricing&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Note: Actual prices may vary by region and time. Please refer to official AWS pricing pages for current rates.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Cost-saving tip&lt;/strong&gt;: Set &lt;code&gt;CreateVPCEndpoints=false&lt;/code&gt; to save ~$29/month. In this case, Bedrock API calls will route through the Internet Gateway to Bedrock's public endpoints. Traffic is still encrypted via TLS, but traverses the public internet rather than staying within the AWS backbone. For scenarios with strict security or compliance requirements, keep VPC endpoints enabled to ensure traffic never leaves the AWS network.&lt;/p&gt;




&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;h3&gt;
  
  
  How do I access EC2 via SSM and use OpenClaw TUI?
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Option 1: Via AWS Console&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open the &lt;a href="https://console.aws.amazon.com/ec2/?trk=7b33727f-f84b-453c-8f31-3d32f7b2a4e7&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;EC2 Console&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Select your OpenClaw instance&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Connect&lt;/strong&gt; → Select &lt;strong&gt;Session Manager&lt;/strong&gt; → Click &lt;strong&gt;Connect&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&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%2Fnvyo1k8vgetgu7s29lwd.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%2Fnvyo1k8vgetgu7s29lwd.png" alt="Connect to EC2 via AWS Console SSM" width="800" height="253"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Option 2: Via AWS CLI&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws ssm start-session &lt;span class="nt"&gt;--target&lt;/span&gt; &amp;lt;instance-id&amp;gt; &lt;span class="nt"&gt;--region&lt;/span&gt; &amp;lt;your-region&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After connecting, switch to the ubuntu user and launch TUI:&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="nb"&gt;sudo &lt;/span&gt;su - ubuntu
openclaw tui
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  How do I configure OpenClaw and switch Bedrock models?
&lt;/h3&gt;

&lt;p&gt;Use the &lt;code&gt;openclaw config&lt;/code&gt; command for configuration management, including switching models on Amazon Bedrock:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;openclaw config
&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.amazonaws.com%2Fuploads%2Farticles%2F5pfpiwdfq8wpgqte17pl.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%2F5pfpiwdfq8wpgqte17pl.png" alt="OpenClaw Config - Switch Bedrock Models" width="800" height="911"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Stack deployment timed out (WaitCondition failure)?
&lt;/h3&gt;

&lt;p&gt;Connect to the instance via SSM and check the setup log:&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="nb"&gt;cat&lt;/span&gt; /var/log/openclaw-setup.log
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Common causes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Network issues during package downloads&lt;/li&gt;
&lt;li&gt;Bedrock model access not yet approved (it can take a few minutes after requesting)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  How do I retrieve my Gateway token?
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Replace &amp;lt;stack-name&amp;gt; with your stack name&lt;/span&gt;
aws ssm get-parameter &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--name&lt;/span&gt; &lt;span class="s2"&gt;"/openclaw/&amp;lt;stack-name&amp;gt;/gateway-token"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--with-decryption&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--query&lt;/span&gt; &lt;span class="s1"&gt;'Parameter.Value'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--output&lt;/span&gt; text
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  How do I switch models?
&lt;/h3&gt;

&lt;p&gt;Edit &lt;code&gt;agents.defaults.model.primary&lt;/code&gt; in &lt;code&gt;/home/ubuntu/.openclaw/openclaw.json&lt;/code&gt;, then restart:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;systemctl &lt;span class="nt"&gt;--user&lt;/span&gt; restart openclaw-gateway.service
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  How do I update OpenClaw?
&lt;/h3&gt;

&lt;p&gt;SSH or SSM into the instance and run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm update &lt;span class="nt"&gt;-g&lt;/span&gt; openclaw
systemctl &lt;span class="nt"&gt;--user&lt;/span&gt; restart openclaw-gateway.service
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  How do I tear it all down?
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws cloudformation delete-stack &lt;span class="nt"&gt;--stack-name&lt;/span&gt; openclaw &lt;span class="nt"&gt;--region&lt;/span&gt; us-east-1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This removes everything — EC2 instance, VPC, IAM roles, all of it. Clean.&lt;/p&gt;




&lt;h2&gt;
  
  
  Wrapping Up
&lt;/h2&gt;

&lt;p&gt;Deploying OpenClaw on AWS is straightforward — with one note about region selection:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;US regions (us-east-1, us-west-2)&lt;/strong&gt;: Truly one-click. The template works out of the box.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Other regions&lt;/strong&gt;: You need to replace the model IDs with the corresponding regional inference profiles.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Either way, the CloudFormation template handles 90% of the work. What you get at the end is a private, secure AI assistant running on your own infrastructure — no data leaving your AWS account, no third-party services in the loop, and the full power of Claude at your fingertips.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Resources&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;📦 &lt;a href="https://github.com/hanyun2019/openclaw-on-aws/blob/main/openclaw-deployment.yaml" rel="noopener noreferrer"&gt;Deployment Template (GitHub)&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Series Preview: Four Ways to Deploy OpenClaw on AWS
&lt;/h2&gt;

&lt;p&gt;This post is the first in the &lt;strong&gt;OpenClaw on AWS&lt;/strong&gt; series. There are four ways to deploy OpenClaw on AWS, each suited for different scenarios:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Deployment Method&lt;/th&gt;
&lt;th&gt;Use Case&lt;/th&gt;
&lt;th&gt;Status&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;EC2 Deployment&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Full control, custom configuration, persistent runtime&lt;/td&gt;
&lt;td&gt;✅ This post&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Lightsail Deployment&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Simple and fast, fixed monthly cost, beginner-friendly&lt;/td&gt;
&lt;td&gt;📝 Coming soon&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;AgentCore Deployment&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Managed service, no infrastructure management&lt;/td&gt;
&lt;td&gt;📝 Coming soon&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;EKS Deployment&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Containerized, scalable, enterprise-grade&lt;/td&gt;
&lt;td&gt;📝 Coming soon&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Stay tuned for upcoming posts!&lt;/p&gt;




&lt;h2&gt;
  
  
  Industry Trends: The Rise of AI Agents
&lt;/h2&gt;

&lt;p&gt;Beyond OpenClaw, the AI Agent space is evolving rapidly. More developers are exploring how to build autonomous, controllable AI agent systems.&lt;/p&gt;

&lt;p&gt;One project worth watching is &lt;a href="https://github.com/nousresearch/hermes-agent" rel="noopener noreferrer"&gt;Hermes Agent&lt;/a&gt; — an open-source AI Agent framework developed by Nous Research that has been gaining increasing attention in the developer community. It offers a different approach to building and deploying AI agents.&lt;/p&gt;

&lt;p&gt;I'll share hands-on experience with Hermes Agent in upcoming blog posts — stay tuned.&lt;/p&gt;

&lt;p&gt;Happy Deploying! 🦞&lt;/p&gt;




&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.aws.amazon.com/bedrock/latest/userguide/inference-profiles-support.html?trk=7b33727f-f84b-453c-8f31-3d32f7b2a4e7&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;AWS Bedrock - Supported Regions and models for inference profiles&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.aws.amazon.com/bedrock/latest/userguide/geographic-cross-region-inference.html?trk=7b33727f-f84b-453c-8f31-3d32f7b2a4e7&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;AWS Bedrock - Geographic cross-Region inference&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://aws.amazon.com/blogs/machine-learning/global-cross-region-inference-for-latest-anthropic-claude-opus-sonnet-and-haiku-models-on-amazon-bedrock-in-thailand-malaysia-singapore-indonesia-and-taiwan/?trk=7b33727f-f84b-453c-8f31-3d32f7b2a4e7&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;AWS Blog - Global cross-Region inference for Anthropic Claude models&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://aws.amazon.com/blogs/machine-learning/introducing-amazon-bedrock-cross-region-inference-for-claude-sonnet-4-5-and-haiku-4-5-in-japan-and-australia/?trk=7b33727f-f84b-453c-8f31-3d32f7b2a4e7&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;AWS Blog - Cross-Region inference for Claude in Japan and Australia&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://aws.amazon.com/blogs/machine-learning/unlock-global-ai-inference-scalability-using-new-global-cross-region-inference-on-amazon-bedrock-with-anthropics-claude-sonnet-4-5/?trk=7b33727f-f84b-453c-8f31-3d32f7b2a4e7&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;AWS Blog - Global cross-Region inference with Claude Sonnet 4.5&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/openclaw/openclaw" rel="noopener noreferrer"&gt;OpenClaw GitHub Repository&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>openclaw</category>
      <category>agents</category>
      <category>bedrock</category>
      <category>ai</category>
    </item>
    <item>
      <title>Running Claude Agent SDK with Skills on Amazon Bedrock</title>
      <dc:creator>Haowen Huang</dc:creator>
      <pubDate>Wed, 11 Mar 2026 08:56:47 +0000</pubDate>
      <link>https://dev.to/haowen_huang/running-claude-agent-sdk-with-skills-on-amazon-bedrock-el6</link>
      <guid>https://dev.to/haowen_huang/running-claude-agent-sdk-with-skills-on-amazon-bedrock-el6</guid>
      <description>&lt;p&gt;by Haowen Huang (&lt;a href="https://www.linkedin.com/in/haowenhuang/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://github.com/anthropics/claude-agent-sdk" rel="noopener noreferrer"&gt;Claude Agent SDK&lt;/a&gt; enables building multi-agent systems with Skills, MCP servers, and subagents. By default, it requires an Anthropic API key. This post shows how to run it entirely on &lt;a href="https://aws.amazon.com/bedrock/?trk=7b33727f-f84b-453c-8f31-3d32f7b2a4e7&amp;amp;sc_channel=el/" rel="noopener noreferrer"&gt;Amazon Bedrock&lt;/a&gt; instead—no Anthropic API key needed.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;The DeepLearning.AI course &lt;a href="https://github.com/https-deeplearning-ai/sc-agent-skills-files/tree/main/L7" rel="noopener noreferrer"&gt;"Agent Skills with Anthropic"&lt;/a&gt; assumes you have an &lt;code&gt;ANTHROPIC_API_KEY&lt;/code&gt;. But what if you're already using AWS and want to leverage your existing &lt;a href="https://aws.amazon.com/bedrock/?trk=7b33727f-f84b-453c-8f31-3d32f7b2a4e7&amp;amp;sc_channel=el/" rel="noopener noreferrer"&gt;Amazon Bedrock&lt;/a&gt; access?&lt;/p&gt;

&lt;h2&gt;
  
  
  The Solution: Two Lines of Code
&lt;/h2&gt;

&lt;p&gt;The Claude Agent SDK uses Claude Code under the hood, which supports &lt;a href="https://aws.amazon.com/bedrock/?trk=7b33727f-f84b-453c-8f31-3d32f7b2a4e7&amp;amp;sc_channel=el/" rel="noopener noreferrer"&gt;Amazon Bedrock&lt;/a&gt; via environment variables. The key configuration is surprisingly simple:&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="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;

&lt;span class="c1"&gt;# Configure Claude Code to use Amazon Bedrock
&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;CLAUDE_CODE_USE_BEDROCK&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;AWS_REGION&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;us-west-2&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;  &lt;span class="c1"&gt;# Your preferred region
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it. Set these before creating &lt;code&gt;ClaudeSDKClient&lt;/code&gt;, and the SDK will use your AWS credentials instead of an Anthropic API key.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;Before running, verify your AWS setup:&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;# Check AWS CLI&lt;/span&gt;
aws &lt;span class="nt"&gt;--version&lt;/span&gt;

&lt;span class="c"&gt;# Verify credentials&lt;/span&gt;
aws configure get aws_access_key_id

&lt;span class="c"&gt;# Test Bedrock access&lt;/span&gt;
aws bedrock list-foundation-models &lt;span class="nt"&gt;--query&lt;/span&gt; &lt;span class="s2"&gt;"modelSummaries[?contains(modelId, 'claude')]"&lt;/span&gt; &lt;span class="nt"&gt;--output&lt;/span&gt; table
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AWS credentials configured (&lt;code&gt;~/.aws/credentials&lt;/code&gt; or environment variables)&lt;/li&gt;
&lt;li&gt;Amazon Bedrock model access enabled in your AWS console&lt;/li&gt;
&lt;li&gt;IAM permissions for &lt;code&gt;bedrock:InvokeModel&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Complete Example
&lt;/h2&gt;

&lt;p&gt;Here's the modified &lt;code&gt;agent.py&lt;/code&gt; for Amazon Bedrock:&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="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;dotenv&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;load_dotenv&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;claude_agent_sdk&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;AgentDefinition&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ClaudeSDKClient&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ClaudeAgentOptions&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;AssistantMessage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;load_dotenv&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;AWS_REGION&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;AWS_REGION&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;us-west-2&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Key configuration for Bedrock
&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;CLAUDE_CODE_USE_BEDROCK&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;AWS_REGION&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;AWS_REGION&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;agents&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;docs_researcher&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;AgentDefinition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Finds information from official documentation.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;You research official docs.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;WebSearch&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;WebFetch&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;haiku&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;options&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ClaudeAgentOptions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;system_prompt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;You are a helpful assistant.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;allowed_tools&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Skill&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Task&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Write&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Bash&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;WebSearch&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;WebFetch&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sonnet&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;agents&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;agents&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nc"&gt;ClaudeSDKClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hello!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;receive_response&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;isinstance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;AssistantMessage&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="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Adding MCP Servers (Optional)
&lt;/h2&gt;

&lt;p&gt;MCP servers like Notion work the same way. Just ensure the token exists before adding the config:&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="n"&gt;NOTION_TOKEN&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;NOTION_TOKEN&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;mcp_servers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;NOTION_TOKEN&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;mcp_servers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;notion&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;command&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;npx&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;args&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;-y&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;@notionhq/notion-mcp-server&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;env&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;NOTION_TOKEN&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;NOTION_TOKEN&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;options&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ClaudeAgentOptions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;mcp_servers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;mcp_servers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="c1"&gt;# ... other options
&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What Works on Amazon Bedrock
&lt;/h2&gt;

&lt;p&gt;Everything from the original SDK works:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Skills (e.g., &lt;code&gt;learning-a-tool&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Subagents with parallel execution&lt;/li&gt;
&lt;li&gt;MCP servers (Notion, etc.)&lt;/li&gt;
&lt;li&gt;All built-in tools (WebSearch, Bash, Write, etc.)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  A Note on the Debugging Process
&lt;/h2&gt;

&lt;p&gt;This entire migration—from identifying the Bedrock configuration, fixing MCP server issues, to successfully running Skills with subagents—was completed through conversation with &lt;a href="https://kiro.dev/?trk=7b33727f-f84b-453c-8f31-3d32f7b2a4e7&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;Kiro&lt;/a&gt;, an AI-powered IDE. No external documentation was consulted. &lt;a href="https://kiro.dev/?trk=7b33727f-f84b-453c-8f31-3d32f7b2a4e7&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;Kiro&lt;/a&gt; diagnosed issues in real-time, suggested fixes, and validated the setup by running test scripts directly.&lt;/p&gt;

&lt;p&gt;The workflow:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Asked &lt;a href="https://kiro.dev/?trk=7b33727f-f84b-453c-8f31-3d32f7b2a4e7&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;Kiro&lt;/a&gt; how to use Bedrock instead of Anthropic API&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://kiro.dev/?trk=7b33727f-f84b-453c-8f31-3d32f7b2a4e7&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;Kiro&lt;/a&gt; checked the environment, identified missing dependencies&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://kiro.dev/?trk=7b33727f-f84b-453c-8f31-3d32f7b2a4e7&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;Kiro&lt;/a&gt; found the correct configuration (environment variables, not client parameters)&lt;/li&gt;
&lt;li&gt;Fixed runtime errors (MCP config validation when token was missing)&lt;/li&gt;
&lt;li&gt;Verified everything worked end-to-end&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This demonstrates how AI-assisted development can accelerate debugging unfamiliar SDKs without documentation diving.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Running Claude Agent SDK on Amazon Bedrock requires just two environment variables. Your existing AWS credentials handle authentication, and all SDK features—Skills, subagents, MCP servers—work unchanged.&lt;/p&gt;

&lt;p&gt;If you're already in the AWS ecosystem, this is the simplest path to using Claude Agent SDK without managing a separate Anthropic API key.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agentaichallenge</category>
      <category>awschallenge</category>
      <category>mcp</category>
    </item>
  </channel>
</rss>
