<?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: Matheus Guimaraes</title>
    <description>The latest articles on DEV Community by Matheus Guimaraes (@techwithmatheus).</description>
    <link>https://dev.to/techwithmatheus</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%2F990373%2Fc3282166-8fbe-4de0-ae95-edb54e59fc04.png</url>
      <title>DEV Community: Matheus Guimaraes</title>
      <link>https://dev.to/techwithmatheus</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/techwithmatheus"/>
    <language>en</language>
    <item>
      <title>Switching Between Your Personal ChatGPT Account and Amazon Bedrock</title>
      <dc:creator>Matheus Guimaraes</dc:creator>
      <pubDate>Thu, 01 Oct 2026 10:33:52 +0000</pubDate>
      <link>https://dev.to/aws/switching-between-your-personal-chatgpt-account-and-amazon-bedrock-4h08</link>
      <guid>https://dev.to/aws/switching-between-your-personal-chatgpt-account-and-amazon-bedrock-4h08</guid>
      <description>&lt;p&gt;In the &lt;a href="https://dev.to/aws/how-to-set-up-the-chatgpt-desktop-app-with-amazon-bedrock-ggp"&gt;previous post in this series&lt;/a&gt;, I walked through how to configure the ChatGPT desktop app to use OpenAI models through Amazon Bedrock.&lt;/p&gt;

&lt;p&gt;That works great if Bedrock is the only environment you want to use. But what if you want to use both your personal ChatGPT account and Amazon Bedrock?&lt;/p&gt;

&lt;p&gt;That's when it gets awkward.&lt;/p&gt;

&lt;p&gt;I found that out the hard way after setting up my Bedrock configuration, because my intention was always to keep using my personal ChatGPT account as well and switch between the two on demand to help me manage my token limits.&lt;/p&gt;

&lt;p&gt;I also didn't want two completely separate Codex environments. I wanted to keep the same local conversations, files and working state, and simply change which provider was handling the model requests.&lt;/p&gt;

&lt;p&gt;So I built a small account switcher to make that easier.&lt;/p&gt;

&lt;p&gt;If you just want the solution, you can grab it here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/techwithmatheus/codex-account-switcher" rel="noopener noreferrer"&gt;&lt;strong&gt;techwithmatheus/codex-account-switcher&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It includes an installer, uninstaller and two simple commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;codex-personal
codex-bedrock
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you'd rather understand what it's doing before installing it, keep reading. That's what the rest of this post is about.&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem with simply switching accounts
&lt;/h2&gt;

&lt;p&gt;When you're using the normal ChatGPT experience, switching accounts is something you generally think about at the application level.&lt;/p&gt;

&lt;p&gt;Bedrock is different.&lt;/p&gt;

&lt;p&gt;In the setup from the previous post, Codex is configured locally with something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="py"&gt;model&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"openai.gpt-6-astra"&lt;/span&gt;
&lt;span class="py"&gt;model_provider&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"amazon-bedrock"&lt;/span&gt;

&lt;span class="nn"&gt;[model_providers.amazon-bedrock.aws]&lt;/span&gt;
&lt;span class="py"&gt;profile&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"codex-bedrock"&lt;/span&gt;
&lt;span class="py"&gt;region&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"us-west-2"&lt;/span&gt;
&lt;span class="py"&gt;wire_api&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"responses"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That tells Codex to send model requests through Amazon Bedrock using the AWS profile and Region you've configured.&lt;/p&gt;

&lt;p&gt;So Bedrock isn't another ChatGPT account that can simply appear in the normal account switcher. It's a different model-provider configuration.&lt;/p&gt;

&lt;p&gt;My first thought was therefore to maintain two separate Codex environments: one for my personal account and another for Bedrock.&lt;/p&gt;

&lt;p&gt;That would work, but there's a downside.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I decided not to separate the whole Codex environment
&lt;/h2&gt;

&lt;p&gt;Codex stores its local state under:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;~/.codex
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And there's considerably more in there than &lt;code&gt;config.toml&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;On my machine, that directory contains authentication state, sessions, thread history, memories, plugins, skills, model caches, trusted-project settings and several local databases used by the desktop experience.&lt;/p&gt;

&lt;p&gt;If I gave my personal and Bedrock setups completely separate Codex homes, I would also be separating much of that useful state.&lt;/p&gt;

&lt;p&gt;That wasn't really what I wanted.&lt;/p&gt;

&lt;p&gt;My use case was closer to this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;same Codex workspace
same conversations
same local state
different model provider
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So I tried something simpler.&lt;/p&gt;

&lt;p&gt;I completely quit the ChatGPT app, removed only the Bedrock-specific configuration from &lt;code&gt;~/.codex/config.toml&lt;/code&gt;, and launched it again.&lt;/p&gt;

&lt;p&gt;The desktop app returned to my personal ChatGPT-backed Codex environment.&lt;/p&gt;

&lt;p&gt;More importantly, a test conversation that I had originally created while using Bedrock was still there. It contained a small .NET console application, and I could still open the generated files in the desktop preview.&lt;/p&gt;

&lt;p&gt;I then quit the app, restored the Bedrock configuration and launched it again.&lt;/p&gt;

&lt;p&gt;The same conversation and files were still there.&lt;/p&gt;

&lt;p&gt;So that's the model we'll use here: &lt;strong&gt;keep the Codex state shared and switch only the part of the configuration that selects Amazon Bedrock.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;There was another nice surprise when I later tested the full uninstall flow. When I switched back to my personal ChatGPT environment, I expected to have to sign in again. I didn't.&lt;/p&gt;

&lt;p&gt;My existing personal authentication was still part of the shared Codex state. Bedrock had changed which provider handled the model requests, but it hadn't logged me out of my personal ChatGPT account.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This is behaviour I've personally verified on macOS with the ChatGPT desktop app. I haven't tested every piece of desktop state, so I'm deliberately not claiming that every feature behaves identically across providers.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Back up your configuration first
&lt;/h2&gt;

&lt;p&gt;Before changing anything, make a backup of your existing Codex configuration.&lt;/p&gt;

&lt;p&gt;I like using the date and time in the filename so old backups remain meaningful:&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;cp&lt;/span&gt; ~/.codex/config.toml ~/.codex/config.toml.backup.&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;date&lt;/span&gt; +%F-%H%M%S&lt;span class="si"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I'd also back up your &lt;code&gt;.zshrc&lt;/code&gt;, since the installer will add a small block to it:&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;cp&lt;/span&gt; ~/.zshrc ~/.zshrc.backup.&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;date&lt;/span&gt; +%F-%H%M%S&lt;span class="si"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You don't need to copy the whole &lt;code&gt;~/.codex&lt;/code&gt; directory for this. The switcher doesn't touch your sessions, memories, authentication databases or other Codex state.&lt;/p&gt;

&lt;p&gt;We'll also make the switcher maintain a rolling safety backup before it modifies &lt;code&gt;config.toml&lt;/code&gt;, but that's different from this manual checkpoint.&lt;/p&gt;

&lt;h2&gt;
  
  
  Install the switcher
&lt;/h2&gt;

&lt;p&gt;I've put the maintained version of the switcher on GitHub:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/techwithmatheus/codex-account-switcher" rel="noopener noreferrer"&gt;&lt;strong&gt;techwithmatheus/codex-account-switcher&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Clone the repository:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/techwithmatheus/codex-account-switcher.git
&lt;span class="nb"&gt;cd &lt;/span&gt;codex-account-switcher
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then run the installer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bash install.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I'm deliberately using &lt;code&gt;bash install.sh&lt;/code&gt; rather than &lt;code&gt;./install.sh&lt;/code&gt;. That means you don't have to change executable permissions on the downloaded script first.&lt;/p&gt;

&lt;p&gt;The installer puts the switcher under:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;~/.config/codex-switcher/
├── codex-switcher.zsh
└── config
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and adds a small marked block to &lt;code&gt;~/.zshrc&lt;/code&gt; so zsh loads it whenever you open a shell.&lt;/p&gt;

&lt;p&gt;The actual switching code lives in its own file rather than dumping a large shell function directly into your &lt;code&gt;.zshrc&lt;/code&gt;. That makes it much easier to inspect, maintain or replace later.&lt;/p&gt;

&lt;p&gt;After installation, reload your shell:&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;source&lt;/span&gt; ~/.zshrc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Configure your Bedrock settings
&lt;/h2&gt;

&lt;p&gt;The switcher's Bedrock-specific settings live in:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;~/.config/codex-switcher/config
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The defaults used throughout this series are:&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="nv"&gt;CODEX_BEDROCK_MODEL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"openai.gpt-6-astra"&lt;/span&gt;
&lt;span class="nv"&gt;CODEX_BEDROCK_PROFILE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"codex-bedrock"&lt;/span&gt;
&lt;span class="nv"&gt;CODEX_BEDROCK_REGION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"us-west-2"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fy46pd2mvmq4ke7jduos1.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%2Fy46pd2mvmq4ke7jduos1.png" alt="Finder window showing the codex-switcher configuration folder and the config file containing the Amazon Bedrock model, AWS profile and Region settings." width="739" height="416"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you used different values when configuring Bedrock, update them there.&lt;/p&gt;

&lt;p&gt;For example, if your AWS profile is called &lt;code&gt;work-bedrock&lt;/code&gt;:&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="nv"&gt;CODEX_BEDROCK_PROFILE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"work-bedrock"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The model and Region should likewise match the Bedrock setup you've already verified.&lt;/p&gt;

&lt;h3&gt;
  
  
  What if Bedrock is already configured?
&lt;/h3&gt;

&lt;p&gt;If you've just followed the first article, you may already have Amazon Bedrock active when you install the switcher.&lt;/p&gt;

&lt;p&gt;The installer handles that case too.&lt;/p&gt;

&lt;p&gt;If it finds the standard Bedrock configuration already active, it shows the values it discovered:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Existing Amazon Bedrock configuration found.

Model:       openai.gpt-6-astra
AWS profile: codex-bedrock
Region:      us-west-2

These provider settings will be adopted by the switcher and will not be replaced.

Continue? [Y/n]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It then adopts the existing settings rather than creating a duplicate Bedrock provider configuration.&lt;/p&gt;

&lt;p&gt;If you're starting from your normal personal ChatGPT environment instead, your current Codex configuration is left alone and the switcher starts from there.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the switcher actually changes
&lt;/h2&gt;

&lt;p&gt;When Bedrock is active, the tool owns one clearly marked block inside &lt;code&gt;~/.codex/config.toml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="c"&gt;# &amp;gt;&amp;gt;&amp;gt; codex-bedrock-switcher &amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;
&lt;span class="py"&gt;model&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"openai.gpt-6-astra"&lt;/span&gt;
&lt;span class="py"&gt;model_provider&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"amazon-bedrock"&lt;/span&gt;

&lt;span class="nn"&gt;[model_providers.amazon-bedrock.aws]&lt;/span&gt;
&lt;span class="py"&gt;profile&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"codex-bedrock"&lt;/span&gt;
&lt;span class="py"&gt;region&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"us-west-2"&lt;/span&gt;
&lt;span class="py"&gt;wire_api&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"responses"&lt;/span&gt;
&lt;span class="c"&gt;# &amp;lt;&amp;lt;&amp;lt; codex-bedrock-switcher &amp;lt;&amp;lt;&amp;lt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The values come from the separate switcher configuration file we just looked at.&lt;/p&gt;

&lt;p&gt;Everything outside those markers belongs to Codex, or to you, and the switcher leaves it alone.&lt;/p&gt;

&lt;p&gt;That's important because the desktop-generated &lt;code&gt;config.toml&lt;/code&gt; can contain much more than provider configuration: desktop preferences, plugins, MCP servers, trusted projects and other settings may all live in the same file.&lt;/p&gt;

&lt;p&gt;Replacing the entire file whenever you switch would be unnecessarily risky.&lt;/p&gt;

&lt;p&gt;Before each automated change, the current configuration is also copied to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;~/.codex/config.toml.switcher-backup
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's a rolling safety backup. It contains the state immediately before the most recent switch and is intentionally overwritten on later switches.&lt;/p&gt;

&lt;h2&gt;
  
  
  Switch to Amazon Bedrock
&lt;/h2&gt;

&lt;p&gt;Once everything is installed and your configuration looks right, run:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;The switcher will:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;make a safety backup of your current &lt;code&gt;config.toml&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;add the managed Bedrock block;&lt;/li&gt;
&lt;li&gt;launch the ChatGPT desktop app.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The rest of your Codex state remains where it was.&lt;/p&gt;

&lt;h2&gt;
  
  
  Switch back to your personal ChatGPT account
&lt;/h2&gt;

&lt;p&gt;To go back:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;The switcher removes only the Bedrock block it owns.&lt;/p&gt;

&lt;p&gt;It does &lt;strong&gt;not&lt;/strong&gt; insert some handcrafted OpenAI provider configuration in its place.&lt;/p&gt;

&lt;p&gt;That's deliberate.&lt;/p&gt;

&lt;p&gt;During testing, removing the Bedrock override was enough for the desktop app to return naturally to my personal ChatGPT-backed environment using its existing authentication and defaults.&lt;/p&gt;

&lt;p&gt;So rather than trying to reproduce configuration that Codex already knows how to manage, the switcher simply gets out of the way.&lt;/p&gt;

&lt;p&gt;In my tests, I didn't need to authenticate again either. My personal ChatGPT login was still available because we had never replaced or deleted the shared Codex authentication state.&lt;/p&gt;

&lt;h2&gt;
  
  
  What if ChatGPT is still running?
&lt;/h2&gt;

&lt;p&gt;I didn't want the switcher modifying &lt;code&gt;config.toml&lt;/code&gt; underneath a running desktop application.&lt;/p&gt;

&lt;p&gt;So if ChatGPT is still open when you run either command, you'll get:&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%2F41i69lxcy7a0hic04bch.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%2F41i69lxcy7a0hic04bch.png" alt="Terminal showing the codex-bedrock command detecting that the ChatGPT desktop app is still running and asking whether it should close the app and continue." width="800" height="141"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Answer &lt;code&gt;y&lt;/code&gt; and the switcher asks macOS to quit ChatGPT normally, waits until the application has exited, performs the switch and launches it again.&lt;/p&gt;

&lt;p&gt;Anything else cancels the operation.&lt;/p&gt;

&lt;p&gt;The important part here is that it uses the application's normal quit behaviour rather than abruptly killing the process.&lt;/p&gt;

&lt;h3&gt;
  
  
  Skip the question
&lt;/h3&gt;

&lt;p&gt;If you already know you want it to close ChatGPT, use &lt;code&gt;-f&lt;/code&gt; or &lt;code&gt;--force&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;codex-bedrock &lt;span class="nt"&gt;-f&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;codex-personal &lt;span class="nt"&gt;--force&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That closes the app automatically and continues with the switch.&lt;/p&gt;

&lt;h2&gt;
  
  
  Do the conversations actually carry across?
&lt;/h2&gt;

&lt;p&gt;This was the part I cared about most.&lt;/p&gt;

&lt;p&gt;I created a test conversation while Codex was configured through Amazon Bedrock. In that conversation I had it create a small .NET console application that displayed the date.&lt;/p&gt;

&lt;p&gt;I then switched the desktop app back to my personal ChatGPT environment.&lt;/p&gt;

&lt;p&gt;The conversation was still in the app. I could open it and inspect the generated files in the preview panel.&lt;/p&gt;

&lt;p&gt;I switched back to Bedrock and it remained there as well.&lt;/p&gt;

&lt;p&gt;So at least for the local conversation and generated-file workflow I tested, this gives me what I wanted:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Personal ChatGPT
        │
        ▼
same local Codex workspace
        ▲
        │
Amazon Bedrock
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The conversations aren't being recreated each time you switch providers. We're keeping the same local Codex state and changing which provider handles model requests.&lt;/p&gt;

&lt;p&gt;That doesn't mean the underlying services suddenly share billing, authentication or infrastructure. They don't.&lt;/p&gt;

&lt;p&gt;What we're preserving is the local working environment around them.&lt;/p&gt;

&lt;h2&gt;
  
  
  What if I already use another custom provider?
&lt;/h2&gt;

&lt;p&gt;Codex can contain definitions for multiple model providers in the same configuration, and the switcher leaves unrelated provider definitions alone.&lt;/p&gt;

&lt;p&gt;However, this utility is &lt;strong&gt;not intended to be a universal provider manager&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;It specifically manages:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Personal ChatGPT / OpenAI
            ⇅
       Amazon Bedrock
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you also use another custom provider, you can continue switching to it using whatever method you already use.&lt;/p&gt;

&lt;p&gt;There is one important behaviour to understand.&lt;/p&gt;

&lt;p&gt;Running:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;deliberately makes Bedrock active.&lt;/p&gt;

&lt;p&gt;Running:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;removes the Bedrock override and returns Codex to its normal personal ChatGPT/OpenAI behaviour.&lt;/p&gt;

&lt;p&gt;It does not remember that you previously happened to be using some third provider and restore that provider instead.&lt;/p&gt;

&lt;p&gt;Because of that, if the automatic installer finds an unrelated custom provider currently active, it stops instead of trying to guess what your configuration means.&lt;/p&gt;

&lt;p&gt;You can still install the switcher manually alongside a more complex provider setup. The repository README contains the manual installation steps.&lt;/p&gt;

&lt;p&gt;And if there's another provider you'd like the switcher to support directly, feel free to &lt;a href="https://github.com/techwithmatheus/codex-account-switcher/issues" rel="noopener noreferrer"&gt;open an issue&lt;/a&gt;. Pull requests are welcome too.&lt;/p&gt;

&lt;h2&gt;
  
  
  Uninstalling the switcher
&lt;/h2&gt;

&lt;p&gt;Run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bash uninstall.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The slightly interesting part of uninstalling isn't removing the shell files. It's deciding which provider should remain configured afterward.&lt;/p&gt;

&lt;p&gt;The uninstaller therefore asks:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Removing the switcher means ChatGPT will be left configured for a single provider.

Which provider would you like to keep?

1) Personal ChatGPT / OpenAI
2) Amazon Bedrock
3) Cancel
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you choose &lt;strong&gt;Personal ChatGPT / OpenAI&lt;/strong&gt;, the switcher-managed Bedrock block is removed.&lt;/p&gt;

&lt;p&gt;If you choose &lt;strong&gt;Amazon Bedrock&lt;/strong&gt;, the Bedrock settings stay in &lt;code&gt;config.toml&lt;/code&gt;, but the switcher's marker comments are removed. What remains is simply a normal Codex Bedrock configuration like the one from the first article.&lt;/p&gt;

&lt;p&gt;And if you choose &lt;strong&gt;Cancel&lt;/strong&gt;, nothing changes.&lt;/p&gt;

&lt;p&gt;One thing the uninstaller deliberately does &lt;strong&gt;not&lt;/strong&gt; do is restore some snapshot of &lt;code&gt;config.toml&lt;/code&gt; from the day you installed the switcher.&lt;/p&gt;

&lt;p&gt;Your Codex configuration may have legitimately evolved since then with new desktop settings, project permissions, plugins or other configuration. Restoring an old snapshot could wipe changes that have nothing to do with this tool.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why &lt;code&gt;~/.config&lt;/code&gt;?
&lt;/h2&gt;

&lt;p&gt;You'll notice the utility lives under:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;~/.config/codex-switcher/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;rather than inside the Codex directory itself.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;~/.config&lt;/code&gt; is a common convention in Unix-style command-line environments for user-specific configuration. macOS doesn't guarantee that the directory already exists, so the installer creates it when necessary.&lt;/p&gt;

&lt;p&gt;I also deliberately keep the utility outside &lt;code&gt;~/.codex&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The switcher isn't part of Codex. It's a small shell tool that modifies one well-defined part of Codex configuration, and keeping its own code and settings separate makes that boundary clearer.&lt;/p&gt;

&lt;h2&gt;
  
  
  A provider switch, not a second account system
&lt;/h2&gt;

&lt;p&gt;There's one distinction worth finishing on.&lt;/p&gt;

&lt;p&gt;This doesn't turn Amazon Bedrock into another ChatGPT account.&lt;/p&gt;

&lt;p&gt;Your personal ChatGPT environment and your Bedrock environment are still separate in the ways that matter: authentication, billing and the infrastructure processing the model requests are different.&lt;/p&gt;

&lt;p&gt;What we've done is take advantage of the fact that Codex's local workspace doesn't need to be discarded just because the active model provider changes.&lt;/p&gt;

&lt;p&gt;For my workflow, that's considerably more useful than maintaining two completely isolated desktop environments.&lt;/p&gt;

&lt;p&gt;I can keep working in the same Codex setup and choose whether the next part of that work should run through my personal ChatGPT environment or through Amazon Bedrock.&lt;/p&gt;

&lt;p&gt;Until the desktop app has a first-class way to handle that scenario, two shell commands are doing the job nicely.&lt;/p&gt;

&lt;h2&gt;
  
  
  Source code
&lt;/h2&gt;

&lt;p&gt;The switcher, installer and uninstaller used in this article are available here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/techwithmatheus/codex-account-switcher" rel="noopener noreferrer"&gt;&lt;strong&gt;techwithmatheus/codex-account-switcher&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The repository also contains manual installation instructions, configuration details and notes for people already using other custom providers.&lt;/p&gt;

&lt;p&gt;If Codex changes in a way that affects the switching mechanism, I'll maintain the implementation there rather than expecting readers to keep copying an old shell snippet.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>chatgpt</category>
      <category>ai</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>How to Set Up the ChatGPT Desktop App with Amazon Bedrock</title>
      <dc:creator>Matheus Guimaraes</dc:creator>
      <pubDate>Sun, 20 Sep 2026 06:40:10 +0000</pubDate>
      <link>https://dev.to/aws/how-to-set-up-the-chatgpt-desktop-app-with-amazon-bedrock-ggp</link>
      <guid>https://dev.to/aws/how-to-set-up-the-chatgpt-desktop-app-with-amazon-bedrock-ggp</guid>
      <description>&lt;p&gt;A while ago, I tried setting up the ChatGPT desktop app with Amazon Bedrock on another laptop and, while I eventually got it working, it wasn't without a few snags.&lt;/p&gt;

&lt;p&gt;Fast-forward to last week, when I got a brand-new, shiny, beautiful MacBook Pro (yes, not a very humble brag! 😆) and realised I regretted not writing a blog about the setup the first time around. It would have been pretty handy to have my own instructions when I needed to do it all again. So here we are.&lt;/p&gt;

&lt;p&gt;What I want is fairly simple: to use Codex in the desktop app while sending its model requests through Amazon Bedrock, using my AWS identity, permissions and billing.&lt;/p&gt;

&lt;p&gt;There is an important detail to call out here. This configuration works with &lt;strong&gt;Codex and Work&lt;/strong&gt;, not the regular ChatGPT experience. When the app loads with the Bedrock configuration, the ChatGPT option in the dropdown becomes unavailable and is replaced by Work. It also doesn't change the provider behind normal conversations on &lt;code&gt;chatgpt.com&lt;/code&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkt0no92xdvd99zn55v1b.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%2Fkt0no92xdvd99zn55v1b.png" alt="ChatGPT desktop app dropdown showing Work and Codex as the only available options." width="280" height="269"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;With the Bedrock configuration loaded, the desktop app offers Work and Codex but not regular ChatGPT.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Getting everything in place isn't that difficult, really. Some bits can be a little confusing, though, and I don't think the official documentation out there does a particularly good job of covering them all or explaining how the pieces fit together.&lt;/p&gt;

&lt;h2&gt;
  
  
  Before getting started
&lt;/h2&gt;

&lt;p&gt;For this setup, you need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a current version of the Codex desktop app;&lt;/li&gt;
&lt;li&gt;access to an AWS account with Amazon Bedrock enabled;&lt;/li&gt;
&lt;li&gt;permission to invoke the OpenAI model you want to use;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html" rel="noopener noreferrer"&gt;AWS CLI v2&lt;/a&gt; because you are authenticating through AWS SSO; and&lt;/li&gt;
&lt;li&gt;an AWS Region where the selected model is available.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I'm using &lt;code&gt;openai.gpt-6-astra&lt;/code&gt; as the model. Supported models and minimum app versions can change, so it is worth checking the &lt;a href="https://help.openai.com/en/articles/20001253-configure-codex-with-amazon-bedrock" rel="noopener noreferrer"&gt;OpenAI Bedrock configuration guide&lt;/a&gt; before following the same setup.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Giving Bedrock its own AWS profile
&lt;/h2&gt;

&lt;p&gt;I don't want Codex quietly depending on whichever AWS profile happens to be the default on my machine, so I create a named profile specifically for this setup. This keeps the configuration explicit, makes it easier to maintain and reduces the risk of a future change to the default profile breaking the Codex integration.&lt;/p&gt;

&lt;p&gt;First, I start the AWS SSO configuration wizard with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws configure sso
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The wizard asks for several values:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;an SSO session name;&lt;/li&gt;
&lt;li&gt;your SSO start URL;&lt;/li&gt;
&lt;li&gt;the AWS Region that hosts IAM Identity Center;&lt;/li&gt;
&lt;li&gt;the AWS account and role you want to use;&lt;/li&gt;
&lt;li&gt;the default AWS Region for the profile; and&lt;/li&gt;
&lt;li&gt;a profile name.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you're not familiar with it, the &lt;strong&gt;SSO session name&lt;/strong&gt; can sound a little confusing. It is simply a local name for the IAM Identity Center session used to authenticate. Multiple AWS profiles can reuse the same SSO session while pointing to different accounts, roles or default Regions.&lt;/p&gt;

&lt;p&gt;Let's call the SSO session:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;And the AWS profile:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;For the default client Region, I'm going to choose a Region where the OpenAI model is available. I use &lt;code&gt;us-west-2&lt;/code&gt; in the examples below, but this is one of those values you shouldn't copy blindly if your AWS environment uses a different Region.&lt;/p&gt;

&lt;p&gt;I follow the steps and, once the profile is created, I sign in with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws sso login &lt;span class="nt"&gt;--profile&lt;/span&gt; codex-bedrock
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This opens the browser so I can complete the login. I then check which AWS identity the new profile resolves to:&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;span class="nt"&gt;--profile&lt;/span&gt; codex-bedrock
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If everything is working, the command returns a JSON response containing the account, user ID and ARN for the selected identity. If it cannot use the profile, you will see a credentials, profile or SSO-related error instead. A successful response confirms that the profile points where I expect it to before I involve Bedrock or Codex.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Checking the model is available in the right Region
&lt;/h2&gt;

&lt;p&gt;Before touching the Codex configuration, you should check whether the model you want to use is available in the same Region you configured in your profile. The model I want is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;openai.gpt-6-astra
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And the Region in the &lt;code&gt;codex-bedrock&lt;/code&gt; profile I just set up is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;us-west-2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I could use the Amazon Bedrock console to check, or I can just run the following command from Terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws bedrock list-foundation-models &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--by-provider&lt;/span&gt; OpenAI &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--region&lt;/span&gt; us-west-2 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--profile&lt;/span&gt; codex-bedrock
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This shows me the OpenAI models available through my SSO profile in &lt;code&gt;us-west-2&lt;/code&gt;, based on the permissions attached to the role I selected. I can see that &lt;code&gt;openai.gpt-6-astra&lt;/code&gt; is available, so I'm good to proceed.&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%2F91aw9fp9uat3aon31mul.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%2F91aw9fp9uat3aon31mul.png" alt="Terminal output listing GPT-6 Astra as an available OpenAI model in Amazon Bedrock." width="799" height="478"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Confirming that GPT-6 Astra is available through the SSO profile in us-west-2.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Foundation models should be available in Bedrock by default when the required permissions are in place. With third-party models, however, Bedrock may start the subscription process in the background the first time you invoke one, and that can take a few minutes. In a centrally managed AWS account, an administrator may also need to enable the model or grant the required Marketplace and Bedrock permissions.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Editing the Codex configuration without losing what's already there
&lt;/h2&gt;

&lt;p&gt;Here is where we need to be a bit more careful. The desktop app has already populated its configuration with desktop settings, plugins and local tooling, so replacing the whole file with a minimal example would throw away configuration we want to keep.&lt;/p&gt;

&lt;p&gt;Codex reads its local configuration from:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;~/.codex/config.toml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the directory does not exist yet, create it with:&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;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; ~/.codex
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Because my &lt;code&gt;config.toml&lt;/code&gt; already exists, I make a backup before changing anything:&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;cp&lt;/span&gt; ~/.codex/config.toml ~/.codex/config.toml.backup
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Codex loads the file named &lt;code&gt;config.toml&lt;/code&gt;, so the &lt;code&gt;.backup&lt;/code&gt; copy is there if I need it without being treated as the active configuration.&lt;/p&gt;

&lt;p&gt;I then open the configuration in Kiro:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;open &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="s2"&gt;"Kiro"&lt;/span&gt; ~/.codex/config.toml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you would rather stay in Terminal, &lt;code&gt;nano&lt;/code&gt; works too, of course:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nano ~/.codex/config.toml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The code that we need to add it the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="py"&gt;model&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"openai.gpt-6-astra"&lt;/span&gt;
&lt;span class="py"&gt;model_provider&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"amazon-bedrock"&lt;/span&gt;

&lt;span class="nn"&gt;[model_providers.amazon-bedrock.aws]&lt;/span&gt;
&lt;span class="py"&gt;profile&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"codex-bedrock"&lt;/span&gt;
&lt;span class="py"&gt;region&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"us-west-2"&lt;/span&gt;
&lt;span class="py"&gt;wire_api&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"responses"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If your file already contains &lt;code&gt;model&lt;/code&gt; or &lt;code&gt;model_provider&lt;/code&gt;, update those values rather than adding the same keys twice.&lt;/p&gt;

&lt;p&gt;There are three values worth checking before saving:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;model&lt;/code&gt; is an exact model ID supported by the current Codex and Bedrock integration. In my case, I'm using astra but you pick what you prefer, of course;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;profile&lt;/code&gt; matches the named AWS profile you created earlier; and&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;region&lt;/code&gt; matches the Region in which that model is available.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I choose to set the AWS profile directly in &lt;code&gt;config.toml&lt;/code&gt;. That makes the dependency explicit and avoids relying on the desktop app to inherit environment variables from my shell, which desktop applications do not always do.&lt;/p&gt;

&lt;p&gt;By the way, be careful where you add the snippet on config.toml because placement matters. Not because Codex requires the sections in a particular visual order, but because TOML uses section headings to determine which settings belong together.&lt;/p&gt;

&lt;p&gt;In the configuration created by my desktop app, the file begins with a &lt;code&gt;notify&lt;/code&gt; setting followed by the &lt;code&gt;[desktop]&lt;/code&gt; section. I keep the existing &lt;code&gt;notify&lt;/code&gt; line unchanged and insert the Bedrock block &lt;strong&gt;immediately before &lt;code&gt;[desktop]&lt;/code&gt;&lt;/strong&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F4e9sa1rcni15xnwgo7w0.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%2F4e9sa1rcni15xnwgo7w0.png" alt="Codex config.toml with the Amazon Bedrock settings inserted before the desktop section." width="800" height="580"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The Bedrock settings go after the existing top-level values and immediately before &lt;code&gt;[desktop]&lt;/code&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Restarting the desktop app
&lt;/h2&gt;

&lt;p&gt;This is an easy step to overlook. After saving the file, I quit the desktop app completely and open it again. Editing &lt;code&gt;config.toml&lt;/code&gt; while the app is running does not force the current process to reload the provider configuration.&lt;/p&gt;

&lt;p&gt;Once the app reopens, I start a new Codex session.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Proving that Codex is actually using Bedrock
&lt;/h2&gt;

&lt;p&gt;I don't want to treat “Codex answered me” as proof that the setup works. A successful response only proves that &lt;em&gt;some&lt;/em&gt; provider handled the request.&lt;/p&gt;

&lt;p&gt;To check the provider directly, I start a Codex CLI session and open:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;The model provider should be:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;I also confirm that Astra is the selected model.&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%2Fkdskeme4eu5abb8q7aix.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%2Fkdskeme4eu5abb8q7aix.png" alt="Codex status showing amazon-bedrock as the model provider and GPT-6 Astra as the selected model." width="800" height="524"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The status output provides a direct check that Codex is using Amazon Bedrock.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Finally, I send a small test prompt through the desktop app. I deliberately use something that exercises Codex without involving one of my real codebases yet:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Create a small C# console application that prints the current UTC time, and explain each file you create.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once that completes and &lt;code&gt;/status&lt;/code&gt; shows &lt;code&gt;amazon-bedrock&lt;/code&gt;, I know the local Codex setup is genuinely sending its requests through Bedrock.&lt;/p&gt;

&lt;h2&gt;
  
  
  If it doesn't work...
&lt;/h2&gt;

&lt;p&gt;Once you split the setup into AWS authentication, Bedrock model access and the local Codex configuration, most failures become much easier to narrow down. These are the checks I would make first.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;aws&lt;/code&gt; is not found
&lt;/h3&gt;

&lt;p&gt;AWS CLI is either not installed or is not available on your shell’s &lt;code&gt;PATH&lt;/code&gt;. Install AWS CLI v2, open a new Terminal window and run &lt;code&gt;aws --version&lt;/code&gt; again.&lt;/p&gt;

&lt;h3&gt;
  
  
  The SSO session has expired
&lt;/h3&gt;

&lt;p&gt;Authenticate again:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws sso login &lt;span class="nt"&gt;--profile&lt;/span&gt; codex-bedrock
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then restart the desktop app if the current session does not recover.&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%2Fghnzbvbn5uryp3qhdyb1.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%2Fghnzbvbn5uryp3qhdyb1.png" alt="The ChatGPT desktop app error shown when the AWS SSO session has expired." width="800" height="594"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;An expired AWS SSO session may appear as a less obvious provider error in the desktop app.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Codex cannot find the AWS profile
&lt;/h3&gt;

&lt;p&gt;Check that the profile exists:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws configure list-profiles
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then make sure the spelling in &lt;code&gt;config.toml&lt;/code&gt; matches it exactly.&lt;/p&gt;

&lt;h3&gt;
  
  
  The model ID is rejected
&lt;/h3&gt;

&lt;p&gt;Model IDs must match one of the values currently supported by the Codex and Bedrock integration. Do not assume that every model visible in the Bedrock catalog is supported by Codex, and do not shorten the model ID.&lt;/p&gt;

&lt;h3&gt;
  
  
  You receive &lt;code&gt;AccessDeniedException&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Check all three layers:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;the AWS profile resolves to the identity you expected;&lt;/li&gt;
&lt;li&gt;that identity has permission to invoke the model in Amazon Bedrock; and&lt;/li&gt;
&lt;li&gt;the model is available to the account in the selected Region.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;On first use of a third-party model, Bedrock may still be completing its subscription process. If permissions are correct, wait a few minutes and try again. In an organisation-managed AWS account, you may need the account administrator to enable the model or update your permissions.&lt;/p&gt;

&lt;h3&gt;
  
  
  The desktop app still uses the previous provider
&lt;/h3&gt;

&lt;p&gt;Check that you edited &lt;code&gt;~/.codex/config.toml&lt;/code&gt;, saved the file and completely restarted the app. If you are using environment-variable-based AWS authentication instead of a named profile, remember that the desktop app may not inherit variables exported only in Terminal; OpenAI recommends putting required desktop-app variables in &lt;code&gt;~/.codex/.env&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  An unexpected Bedrock API key is being used
&lt;/h3&gt;

&lt;p&gt;Codex checks &lt;code&gt;AWS_BEARER_TOKEN_BEDROCK&lt;/code&gt; before the AWS SDK credential chain. If that variable contains an old or unintended key, it takes precedence over your named AWS profile. Remove or correct it, then restart Codex.&lt;/p&gt;

&lt;h2&gt;
  
  
  What actually changes?
&lt;/h2&gt;

&lt;p&gt;With &lt;code&gt;model_provider = "amazon-bedrock"&lt;/code&gt;, my local Codex setup authenticates with AWS and sends model requests through Amazon Bedrock’s implementation of the Responses API. The OpenAI-hosted API is not in that request path.&lt;/p&gt;

&lt;h2&gt;
  
  
  Not every feature is supported
&lt;/h2&gt;

&lt;p&gt;The unavailable ChatGPT option is the most immediately visible difference, but it isn't the only one. The Bedrock-backed experience does not necessarily include every feature available when Codex is backed by ChatGPT. OpenAI’s documentation lists limitations including image generation, voice transcription, the cloud plugin store, cloud configuration and policies, and cloud agents. Feature support can change, so I would check the documentation rather than treating that as a permanent list.&lt;/p&gt;

&lt;p&gt;There is another limitation I wasn't expecting. Even with &lt;code&gt;amazon-bedrock&lt;/code&gt; shown as the active provider, I still reached the ChatGPT desktop app's standard usage limit. In other words, using Bedrock changes where the model request goes and where that usage is billed, but it does not necessarily make the desktop experience unlimited, which is surprising, but a topic for another day.&lt;/p&gt;

&lt;h2&gt;
  
  
  Switching between different accounts
&lt;/h2&gt;

&lt;p&gt;At this point, I have Bedrock working on the new Mac. But I have also replaced the configuration used by my personal ChatGPT-backed setup, which brings me straight to the next practical problem: how do I use both without manually editing &lt;code&gt;config.toml&lt;/code&gt; every time?&lt;/p&gt;

&lt;p&gt;That is what I'll cover in the second post in this series, where I'll show how I keep the two environments separate and use simple shell commands to switch between them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Further reading
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://help.openai.com/en/articles/20001253-configure-codex-with-amazon-bedrock" rel="noopener noreferrer"&gt;Configure Codex with Amazon Bedrock: OpenAI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.aws.amazon.com/bedrock/latest/userguide/getting-started.html" rel="noopener noreferrer"&gt;Amazon Bedrock quickstart: AWS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-sso.html" rel="noopener noreferrer"&gt;Configure IAM Identity Center authentication with AWS CLI: AWS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.aws.amazon.com/bedrock/latest/userguide/model-access.html" rel="noopener noreferrer"&gt;Request access to Amazon Bedrock models: AWS&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ai</category>
      <category>chatgpt</category>
      <category>aws</category>
      <category>bedrock</category>
    </item>
    <item>
      <title>AI in Games: Are We Drawing the Line in the Wrong Place?</title>
      <dc:creator>Matheus Guimaraes</dc:creator>
      <pubDate>Wed, 02 Sep 2026 14:10:01 +0000</pubDate>
      <link>https://dev.to/techwithmatheus/ai-in-games-are-we-drawing-the-line-in-the-wrong-place-706</link>
      <guid>https://dev.to/techwithmatheus/ai-in-games-are-we-drawing-the-line-in-the-wrong-place-706</guid>
      <description>&lt;p&gt;The games industry is going through an uncomfortable transition. Studios see the productivity gains AI may offer, while many players see almost any use of it as inherently bad. As a lifelong gamer who started his career as a game developer, I see that divide from both sides.&lt;/p&gt;

&lt;p&gt;I understand the reaction. People are worried about artists losing work, creative jobs being devalued and models being trained on work without permission. Those concerns certainly deserve careful consideration, but I also think the conversation has become far too binary with outright rejection often treated as the only acceptable position.&lt;/p&gt;

&lt;h2&gt;
  
  
  When any use becomes unacceptable
&lt;/h2&gt;

&lt;p&gt;The example that crystallised this for me was &lt;em&gt;Clair Obscur: Expedition 33&lt;/em&gt;. The &lt;a href="https://uk.pcmag.com/ai/162208/clair-obscur-expedition-33-stripped-of-a-game-of-the-year-award-because-of-ai" rel="noopener noreferrer"&gt;Indie Game Awards withdrew its Game of the Year and Debut Game awards&lt;/a&gt; after it emerged that generative AI had been used during production. The material appears to have been placeholder artwork that accidentally shipped and was later patched out.&lt;/p&gt;

&lt;p&gt;There is a disclosure issue. The awards had a clear rule, and the submission reportedly stated that no generative AI had been used so, ok, I understand it from the perspective of enforcing that rule.&lt;/p&gt;

&lt;p&gt;What I disagree with is the rule itself. Declaring a game ineligible because generative AI touched any part of production, regardless of how it was used, feels very extreme and, dare I say, very naive and counterproductive to me. It turns “AI was involved” into the entire judgement and ignores context, scale and impact.&lt;/p&gt;

&lt;h2&gt;
  
  
  We have seen this pattern before
&lt;/h2&gt;

&lt;p&gt;When Disney blended computer-generated environments with hand-drawn characters in &lt;em&gt;Beauty and the Beast&lt;/em&gt;, audiences marvelled. CGI transformed visual effects, and computer animation became an art form of its own. We did not judge those works by how many people might have recreated every frame by hand. In fact, &lt;em&gt;Toy Story&lt;/em&gt;, released in 1995 as the first fully computer-animated feature film, continues to be celebrated today.&lt;/p&gt;

&lt;p&gt;To me, AI is just another step in that long history of automation. Game development already depends on IDEs, automated testing, procedural generation, motion capture, physics engines and infrastructure that scales itself. All allow teams to do more. If replacing manual effort is the line we object to, where does that line begin?&lt;/p&gt;

&lt;p&gt;That is not to say that every use of AI is ethical, of course. Replacing an actor’s performance without consent is not the same as generating an environmental texture. Eliminating a creative team is not the same as helping one automate repetitive work. Training data, consent, attribution, disclosure and the treatment of workers matter.&lt;/p&gt;

&lt;p&gt;That is why I find blanket rejection, at the very least, unhelpful. It removes the nuance needed to tell responsible use from exploitative use.&lt;/p&gt;

&lt;h2&gt;
  
  
  Judge the outcome, and ask better questions
&lt;/h2&gt;

&lt;p&gt;As a gamer, I care most about the game: Is it good? Is it original? Does it move me?&lt;/p&gt;

&lt;p&gt;If we want to examine how it was made then we should go deeper than just “AI was used.” What was it used for? Did it replace credited work? Was source material used with permission? Did the studio mislead anyone? Did the tool help creators realise their vision, or flatten it?&lt;/p&gt;

&lt;p&gt;I know this is a topic that probably deserves a whole post in itself, but I also feel similarly about AI-generated art.&lt;/p&gt;

&lt;p&gt;Art communicates, provokes or makes us feel.&lt;/p&gt;

&lt;p&gt;The creation process can affect how we value a work. I personally struggle to appreciate works created by simply throwing paint at a canvas, for example, but my reaction to that process does not necessarily mean the result isn’t art. Similarly, I do not believe that using a prompt automatically prevents the result from being art, any more than using a camera, graphics tablet, image editor, particle system or CGI package does.&lt;/p&gt;

&lt;p&gt;My bet is that AI will become another ordinary part of how games are made and the current backlash is just a transitional state of mind while society works out the boundaries of a disruptive technology and adjusts to a new world.&lt;/p&gt;

&lt;p&gt;We should absolutely shape those boundaries, but I hope we shape them around consent, transparency and harm, not fear of the technology itself.&lt;/p&gt;

&lt;p&gt;Of course, that's just my perspective, not a universal answer. Where would you draw the line? Which uses of AI in game development do you consider acceptable, and which do you not? I would genuinely like to hear how players and developers see it.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>gamedev</category>
      <category>ethics</category>
      <category>discuss</category>
    </item>
    <item>
      <title>Agent Creation vs. Agent Engineering</title>
      <dc:creator>Matheus Guimaraes</dc:creator>
      <pubDate>Tue, 18 Aug 2026 16:36:11 +0000</pubDate>
      <link>https://dev.to/aws/why-cant-we-just-use-claude-for-everything-agent-creation-vs-agent-engineering-5aaa</link>
      <guid>https://dev.to/aws/why-cant-we-just-use-claude-for-everything-agent-creation-vs-agent-engineering-5aaa</guid>
      <description>&lt;p&gt;Recently, I was talking to a friend who, much like the rest of the world, has started using AI extensively at work to create agents even though she's not a software developer or from a technical background.&lt;/p&gt;

&lt;p&gt;She has been experimenting with Claude a lot, building useful workflows for herself and her team, and getting increasingly excited about what these systems can do.&lt;/p&gt;

&lt;p&gt;At some point, our conversation moved onto the work I've been doing around agentic systems: agent architectures, context engineering, memory, orchestration, sub-agents and frameworks such as Strands Agents.&lt;/p&gt;

&lt;p&gt;And her reaction was:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Why do you need all of that? I'm already creating agents.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;"Great question", I thought to myself.&lt;/p&gt;

&lt;p&gt;And what made it particularly interesting was that I'd heard almost the same question from the opposite direction.&lt;/p&gt;

&lt;p&gt;After giving a talk about agentic architecture and building harnesses with Strands Agents SDK, a junior developer came up to me and asked:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;What's the point of all of this? Why can't we just use Claude for everything?&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Two people approaching the subject from completely different directions had arrived at the same question.&lt;/p&gt;

&lt;p&gt;And I think that question exposes something important about where we are with agents today. We are using the same word &lt;strong&gt;"agent"&lt;/strong&gt; to describe two very different activities with very different use cases.&lt;/p&gt;

&lt;p&gt;The way I see it, there is a big difference between &lt;strong&gt;creating agents&lt;/strong&gt; and &lt;strong&gt;engineering agents&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Agent Creation vs. Agent Engineering
&lt;/h2&gt;

&lt;p&gt;Applications such as Claude, ChatGPT, Amazon Quick and others increasingly allow people to create surprisingly sophisticated agentic workflows without building the underlying infrastructure themselves.&lt;/p&gt;

&lt;p&gt;There is still a learning curve, though. You need to provide instructions and give the system knowledge and context in a way that produces results that are within expectation (and, hopefully, without hallucinations!). You may also need to learn about tools, set up integrations, schedule work or even create subagents so multiple pieces of functionality can work together.&lt;/p&gt;

&lt;p&gt;From the user's perspective, they have created an agent. And indeed they have! But when a software engineer looks at the same system... they see something different.&lt;/p&gt;

&lt;p&gt;They see an application providing a highly abstracted, opinionated agent runtime operating as a black box. You have little control over how execution happens, how context is assembled and maintained, how the system scales, or even where memory lives, among other architectural concerns.&lt;/p&gt;

&lt;p&gt;As an application user, you are creating an agent &lt;strong&gt;inside somebody else's agentic architecture&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;And that's not a problem. In fact, this could be exactly what you need!&lt;/p&gt;

&lt;p&gt;Developers and software architects make trade-offs between abstraction and control all the time. We don't choose the lowest-level technology simply because it gives us the most control; we use abstractions because they remove decisions we don't want to make and complexity we don't need to own.&lt;/p&gt;

&lt;p&gt;The same principle applies here. If Claude gives you everything you need to create an agent, why &lt;em&gt;wouldn't&lt;/em&gt; you use it?&lt;/p&gt;

&lt;p&gt;As usual with system design, the important thing is understanding the trade-offs. The abstraction works because somebody else has made a set of architectural decisions for you. If those decisions suit your requirements, then awesome. If they don't, you may need to take ownership of some of them yourself.&lt;/p&gt;

&lt;p&gt;That's where I find the distinction between &lt;strong&gt;Agent Creation&lt;/strong&gt; and &lt;strong&gt;Agent Engineering&lt;/strong&gt; useful.&lt;/p&gt;

&lt;p&gt;For me, three things make that distinction particularly clear.&lt;/p&gt;




&lt;h2&gt;
  
  
  Is the agent a feature or a component?
&lt;/h2&gt;

&lt;p&gt;This is perhaps my favourite way of thinking about the distinction.&lt;/p&gt;

&lt;p&gt;Let's say I create an agent in Claude to research holidays for me. It knows my preferences, researches destinations, compares options and perhaps uses tools to build an itinerary. It could be incredibly sophisticated... but Claude is still the application. I go to Claude, interact through Claude's interface and rely on Claude's infrastructure to make everything work.&lt;/p&gt;

&lt;p&gt;My agent is a &lt;strong&gt;feature of an application I'm using&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Now imagine I want to offer that same experience through my own travel website. A customer comes to my application and asks for a holiday; somewhere behind the scenes an agent researches flights and hotels, applies their preferences, interacts with booking systems and returns the result.&lt;/p&gt;

&lt;p&gt;The capability sounds almost identical, but architecturally something fundamental has changed. The agent is now a &lt;strong&gt;component of a system I'm building&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Suddenly I need to decide where it runs, how my application communicates with it, how it scales, how it authenticates against other systems, what happens when it fails, how it fits into traditional application flows, and how I observe what it's doing. The AI is no longer the destination; it's now part of the system I'm responsible for.&lt;/p&gt;

&lt;p&gt;That's very clearly Agent Engineering.&lt;/p&gt;

&lt;p&gt;The point is really about ownership. If an agent is a feature of Claude or another application, you're limited, quite deliberately, to what that application allows you to do. If your requirements fit inside those boundaries, great. When they don't... you need another abstraction.&lt;/p&gt;




&lt;h2&gt;
  
  
  Do you need control over the economics?
&lt;/h2&gt;

&lt;p&gt;Another reason you might choose to engineer the agent is cost.&lt;/p&gt;

&lt;p&gt;There is a lot of conversation right now about just how many tokens agentic systems can consume, particularly as we build long-running workflows with large context windows, tool calls and multiple agents.&lt;/p&gt;

&lt;p&gt;Moving from Agent Creation to Agent Engineering doesn't automatically make any of this cheaper, by the way. Engineering has its own cost, and it would be rather ironic to spend £100,000 in developer time to save £500 in tokens.&lt;/p&gt;

&lt;p&gt;What engineering gives you is &lt;strong&gt;control&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;If you own the harness around your agents, architectural decisions become available that simply aren't exposed when you're operating inside somebody else's application.&lt;/p&gt;

&lt;p&gt;You can decide that one task doesn't need the full conversation history, cache an expensive result, retrieve memory only when it's relevant, summarize context between steps, or route simpler tasks to cheaper models.&lt;/p&gt;

&lt;p&gt;You can start treating context and tokens as resources that you deliberately engineer.&lt;/p&gt;

&lt;p&gt;There's a much larger conversation here around context engineering, but that's a story for another post. For now, the important point is that &lt;strong&gt;the abstraction determines which levers are available to you&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;If you don't need those levers, there's little value in taking responsibility for them. If the economics of your system mean you do, Agent Engineering gives you that control.&lt;/p&gt;




&lt;h2&gt;
  
  
  Do you need to own where your data goes?
&lt;/h2&gt;

&lt;p&gt;Then there is a question that tends to become important very quickly in enterprise environments: where does everything actually live?&lt;/p&gt;

&lt;p&gt;When I create an agent inside an application, I'm accepting that application's architecture and its mechanisms for handling context, state, memory, integrations and data. Again, that may be completely acceptable.&lt;/p&gt;

&lt;p&gt;But what if particular data cannot leave a certain environment? What if I need to know exactly where long-term memory is persisted, control which model receives which information, maintain my own audit trail, or guarantee that certain data never crosses a particular boundary?&lt;/p&gt;

&lt;p&gt;Now the black box really matters.&lt;/p&gt;

&lt;p&gt;This is partly a compliance question, partly a data ownership question and, yes, partly a vendor lock-in question. The more behaviour, knowledge and state I build around one application's abstractions, the more dependent I become on that platform's capabilities and constraints.&lt;/p&gt;

&lt;p&gt;But vendor lock-in isn't, by itself, a reason to engineer everything from scratch. We accept varying degrees of lock-in throughout modern software architecture because managed abstractions can provide enormous value.&lt;/p&gt;

&lt;p&gt;The question is simply whether that trade-off is acceptable &lt;strong&gt;for the requirements in front of you&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  So... Can't We Just Use Claude For Everything?
&lt;/h2&gt;

&lt;p&gt;A useful spreadsheet can eventually become an application, but that doesn't mean the spreadsheet was a mistake. It may have been exactly the right abstraction for the problem at the time, and it may even have helped us understand the problem well enough to know what was worth engineering later.&lt;/p&gt;

&lt;p&gt;I think Agent Creation and Agent Engineering should be seen in much the same way: not as levels on a maturity ladder, and certainly not as a journey where every agent should eventually become an engineered one, but as different architectural choices about how much of the underlying system we need to own. We might happily create an agent inside Claude for one task while engineering another from the ground up, perhaps even within the same system.&lt;/p&gt;

&lt;p&gt;Sometimes an agent created inside Claude, ChatGPT, Amazon Quick or another application will remain there because it does everything we need. Sometimes our requirements will mean taking ownership of the architecture ourselves and we'll find ourselves reaching for Strands Agents SDK or another agent harness.&lt;/p&gt;

&lt;p&gt;And perhaps the next time someone asks me, &lt;em&gt;"Why can't we just use Claude for everything?"&lt;/em&gt;, my answer will simply be...&lt;/p&gt;

&lt;p&gt;You can! For as long as its decisions are compatible with yours.**&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
      <category>architecture</category>
      <category>programming</category>
    </item>
    <item>
      <title>Understanding Async Programming</title>
      <dc:creator>Matheus Guimaraes</dc:creator>
      <pubDate>Mon, 17 Aug 2026 16:01:25 +0000</pubDate>
      <link>https://dev.to/aws/understanding-async-programming-4mei</link>
      <guid>https://dev.to/aws/understanding-async-programming-4mei</guid>
      <description>&lt;p&gt;Async programming, short for asynchronous programming, is one of those concepts that might sound intimidating at first but becomes surprisingly intuitive once you understand the problem it is trying to solve.&lt;/p&gt;

&lt;p&gt;And that problem is mostly waiting.&lt;/p&gt;

&lt;p&gt;Modern applications spend a lot of time waiting for things to happen. They wait for APIs to respond, databases to return queries, files to be read or written, and data to travel across a network. Async programming gives us a way to avoid blocking while that happens, allowing other useful work to make progress instead.&lt;/p&gt;

&lt;p&gt;In this post, I’ll cover the basic concepts behind async programming rather than focusing on a particular language. The exact implementation differs between languages and runtimes, but the underlying ideas are largely the same. So if you’re new to async, or have used async and await without ever being completely sure what they’re doing, this is a good place to start.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Async Programming?
&lt;/h2&gt;

&lt;p&gt;At its core, async programming allows your program to start an operation that may take some time and avoid blocking while it waits for that operation to complete.&lt;/p&gt;

&lt;p&gt;This contrasts with synchronous programming, where execution waits for an operation to finish before continuing past that point.&lt;/p&gt;

&lt;p&gt;Imagine you’re making an API call, a very common task in modern applications. Your application sends a request across the network and then has to wait for a response. Even if that response takes only a fraction of a second, that's a long time in computer terms.&lt;/p&gt;

&lt;p&gt;The important thing is that your application isn't necessarily doing useful computation during all that time. A lot of it is simply waiting for something external to happen.&lt;/p&gt;

&lt;p&gt;This is where async programming shines. Rather than blocking an execution resource while waiting for the API call to complete, asynchronous execution can allow other work to make progress and then continue the original operation when its result becomes available.&lt;/p&gt;

&lt;h2&gt;
  
  
  Async Doesn't Necessarily Mean Faster
&lt;/h2&gt;

&lt;p&gt;One of the most common misconceptions about async programming is that it's about improving performance. A lot of people think that using async makes their code run faster. However...&lt;/p&gt;

&lt;p&gt;Async does not necessarily make the operation itself any faster.&lt;/p&gt;

&lt;p&gt;Your API call might take exactly the same amount of time to complete whether you call it synchronously or asynchronously. What async changes is what your application can do while it waits. Instead of being blocked by that wait, it can potentially make progress on other work.&lt;/p&gt;

&lt;h2&gt;
  
  
  When is Async Programming Useful?
&lt;/h2&gt;

&lt;p&gt;There are three main benefits to using async programming:&lt;/p&gt;

&lt;p&gt;Improved throughput: Because your application doesn't have to block on one operation before making progress on other work, it can often handle more work over the same period of time. This is particularly valuable in applications such as web servers that may be handling many requests concurrently.&lt;br&gt;
Better resource utilization: Waiting for I/O doesn't necessarily require a thread to sit blocked until the operation completes. With asynchronous I/O, execution resources can potentially be used for other work while the application waits for the database, network, filesystem or another external resource.&lt;br&gt;
Better responsiveness: Async programming can also help applications remain responsive while longer-running operations are taking place. In a user interface, for example, you generally don't want the entire application to freeze while it waits for a network request or file operation to complete.&lt;/p&gt;

&lt;p&gt;The common thread between all three is the same: making better use of time that would otherwise be spent waiting.&lt;/p&gt;
&lt;h2&gt;
  
  
  Sync vs. Async: When to Use Each
&lt;/h2&gt;

&lt;p&gt;Async programming sounds great, but that doesn't mean everything should be asynchronous.&lt;/p&gt;

&lt;p&gt;The distinction becomes clearer when we think about I/O-bound and CPU-bound work.&lt;/p&gt;

&lt;p&gt;I/O-bound operations spend a significant amount of their time waiting for something outside the CPU: network requests, database calls, file operations and similar tasks. These are often excellent candidates for async programming because there is useful time to reclaim while the application waits.&lt;/p&gt;

&lt;p&gt;CPU-bound operations are different. If you're performing a heavy calculation, for example, the CPU is actively doing the work rather than waiting for something else to happen. Making that code asynchronous doesn't suddenly make the computation faster.&lt;/p&gt;

&lt;p&gt;CPU-bound work may instead benefit from parallelism, where computation is divided so that multiple pieces of work can execute at the same time, potentially across multiple CPU cores.&lt;/p&gt;

&lt;p&gt;Async programming can also introduce additional complexity and some runtime overhead, so there's little benefit in making code asynchronous simply for the sake of it. It is most useful when your application would otherwise spend meaningful time blocked waiting for I/O.&lt;/p&gt;

&lt;p&gt;Async Isn't the Same as Parallelism&lt;/p&gt;

&lt;p&gt;The distinction between async and parallelism is an important one. Async is primarily about allowing other work to make progress while something is waiting. Parallelism is about performing multiple pieces of work at the same time.&lt;/p&gt;

&lt;p&gt;And async doesn't necessarily mean multithreaded either. Different languages and runtimes implement asynchronous execution in different ways, so you shouldn't assume that an async operation means another thread is somewhere doing the work.&lt;/p&gt;

&lt;p&gt;This is why async can provide concurrency without necessarily providing parallelism: multiple operations can make progress over the same period of time without their code actually executing at the exact same moment.&lt;/p&gt;
&lt;h2&gt;
  
  
  How Does Async Work in Code?
&lt;/h2&gt;

&lt;p&gt;The exact mechanics vary between programming languages, but many modern languages provide the familiar async and await keywords to make asynchronous code easier to write and reason about.&lt;/p&gt;

&lt;p&gt;At a conceptual level, async identifies code that participates in asynchronous execution, while await marks a point where that code depends on the result of an asynchronous operation.&lt;/p&gt;

&lt;p&gt;If that result is already available, execution may simply continue. If it isn't, the function can yield rather than blocking there, allowing other work to make progress. Once the awaited operation completes, execution can continue from that point.&lt;/p&gt;

&lt;p&gt;You can think of await as saying: "I need the result of this operation before I can continue from here, but there's no reason to block everything else while I'm waiting for it."&lt;/p&gt;

&lt;p&gt;The precise details of what happens underneath, whether that involves an event loop, tasks, promises, futures, state machines or something else, depend on the language and runtime. But you don't need to understand all of those implementation details to understand the basic async mental model.&lt;/p&gt;
&lt;h2&gt;
  
  
  Ready to Dive Deeper?
&lt;/h2&gt;

&lt;p&gt;If async still feels a little abstract, I also explain the same ideas visually in the companion video below. Sometimes seeing the synchronous and asynchronous flows side by side is what finally makes the concept click.&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/_Fgu2ZVNo2c" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

</description>
      <category>programming</category>
      <category>softwaredevelopment</category>
      <category>beginners</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Running Kiro Crew in Docker on Windows</title>
      <dc:creator>Matheus Guimaraes</dc:creator>
      <pubDate>Wed, 12 Aug 2026 20:12:47 +0000</pubDate>
      <link>https://dev.to/aws/running-kiro-crew-in-docker-on-windows-19j6</link>
      <guid>https://dev.to/aws/running-kiro-crew-in-docker-on-windows-19j6</guid>
      <description>&lt;p&gt;I've been playing with &lt;a href="https://kiro.dev/docs/crew/installation/" rel="noopener noreferrer"&gt;Kiro Crew&lt;/a&gt; recently, and when I went to get it running on my Windows machine I had a decision to make.&lt;/p&gt;

&lt;p&gt;Kiro Crew doesn't currently have a Windows desktop app. You can still run it natively on Windows, but the documented route involves installing and running the Gateway from source.&lt;/p&gt;

&lt;p&gt;But then, while looking through the &lt;a href="https://github.com/kirodotdev/KiroCrew" rel="noopener noreferrer"&gt;Kiro Crew GitHub repository&lt;/a&gt;, I noticed another option that immediately caught my attention: &lt;strong&gt;there's an official Docker image!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Docker is already a familiar part of the development workflow for many of us, and a container felt like a nice, clean way to get Kiro Crew running without installing it from source.&lt;/p&gt;

&lt;p&gt;So that's the route I took.&lt;/p&gt;

&lt;p&gt;It worked, but along the way I ran into an interesting security detail that made the setup slightly less straightforward than simply running a container.&lt;/p&gt;

&lt;p&gt;And, as it turns out, that's actually a good thing.&lt;/p&gt;

&lt;h2&gt;
  
  
  What we're going to do
&lt;/h2&gt;

&lt;p&gt;By the end of this post, we'll have Kiro Crew running in Docker on Windows, with its agent sandbox enabled and without giving the container more privileges than it actually needs.&lt;/p&gt;

&lt;p&gt;I'm using Docker Desktop with WSL 2, so you'll want to have those installed before following along.&lt;/p&gt;

&lt;p&gt;You can check your WSL installation with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;wsl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;--version&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With that out of the way, let's get Kiro Crew running.&lt;/p&gt;

&lt;h2&gt;
  
  
  Starting with the official container image
&lt;/h2&gt;

&lt;p&gt;The Kiro Crew team publishes a public container image, so we don't need to build anything ourselves or even authenticate with a container registry. Nice and easy.&lt;/p&gt;

&lt;p&gt;Before doing anything else, I created a directory to keep the files for this setup together:&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;mkdir &lt;/span&gt;kiro-crew
&lt;span class="nb"&gt;cd &lt;/span&gt;kiro-crew
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, at first glance, running Kiro Crew looks like it should be as simple as starting the official image.&lt;/p&gt;

&lt;p&gt;And technically, the Gateway itself will run.&lt;/p&gt;

&lt;p&gt;But there's another security boundary inside that container that we need to understand before we can start it properly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wait... a sandbox inside a container?
&lt;/h2&gt;

&lt;p&gt;This was the interesting part for me.&lt;/p&gt;

&lt;p&gt;We're already putting Kiro Crew inside a Docker container, which gives us an isolation boundary between Kiro Crew and our Windows host.&lt;/p&gt;

&lt;p&gt;But Kiro Crew adds another boundary of its own.&lt;/p&gt;

&lt;p&gt;Agent commands aren't simply executed with access to everything available to the main Kiro Crew process. On Linux, Kiro Crew creates an internal user-namespace sandbox for those commands.&lt;/p&gt;

&lt;p&gt;Conceptually, our setup looks something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Windows
└── Docker container
    └── Kiro Crew
        └── Agent sandbox
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Why sandbox an agent that's already inside a container?&lt;/p&gt;

&lt;p&gt;Because the two boundaries are protecting different things.&lt;/p&gt;

&lt;p&gt;The container isolates Kiro Crew from our host. The inner sandbox isolates &lt;strong&gt;agent commands from sensitive state available to Kiro Crew itself&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For example, Kiro Crew's sandbox hides credential directories such as &lt;code&gt;~/.aws&lt;/code&gt; and &lt;code&gt;~/.ssh&lt;/code&gt; from agent subprocesses by bind-mounting empty directories over them. So if an agent-executed command tries to access one of those directories, it simply sees an empty directory rather than our AWS credentials or SSH keys.&lt;/p&gt;

&lt;p&gt;That means the Gateway can have the credentials it needs to do its job without automatically making those credentials readable by commands executed by an agent.&lt;/p&gt;

&lt;p&gt;That's a pretty important distinction when we're giving an AI agent the ability to execute commands.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where Docker gets in the way
&lt;/h2&gt;

&lt;p&gt;There's one complication.&lt;/p&gt;

&lt;p&gt;To create that inner sandbox, Kiro Crew needs Linux system calls including:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;unshare(CLONE_NEWUSER)
unshare(CLONE_NEWNS)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Docker's default seccomp security policy blocks those operations.&lt;/p&gt;

&lt;p&gt;So if the Kiro Crew container can't create its inner sandbox, it doesn't quietly shrug its shoulders and run agent commands without one.&lt;/p&gt;

&lt;p&gt;It &lt;strong&gt;fails closed&lt;/strong&gt;, meaning that when the security mechanism can't be established, access is denied rather than silently falling back to a less secure mode.&lt;/p&gt;

&lt;p&gt;The Gateway and dashboard can still run, but agent command execution remains disabled.&lt;/p&gt;

&lt;p&gt;I actually really like this design! What initially looks like an extra hurdle in getting the container running is Kiro Crew refusing to silently weaken its security model.&lt;/p&gt;

&lt;p&gt;So how do we fix it?&lt;/p&gt;

&lt;h2&gt;
  
  
  The tempting solution and the better solution
&lt;/h2&gt;

&lt;p&gt;There are a few ways we could approach this.&lt;/p&gt;

&lt;p&gt;One option is to simply tell Kiro Crew that we accept running agent commands without the inner sandbox. Kiro Crew provides an environment variable for exactly that:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;We could pass that into our container and Kiro Crew would allow agent execution, leaving Docker itself as our only isolation boundary.&lt;/p&gt;

&lt;p&gt;We could also reach for the rather large hammer:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;That would make the sandbox work, but it does so by granting the container extremely broad privileges and removing many of Docker's normal isolation restrictions.&lt;/p&gt;

&lt;p&gt;That's a much bigger security concession than we actually need.&lt;/p&gt;

&lt;p&gt;What we really want is much narrower:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Allow the operations Kiro Crew needs to create its sandbox while keeping the rest of Docker's security restrictions in place.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;And this is another nice detail about the Kiro Crew implementation: the team already provides a seccomp profile specifically for this!&lt;/p&gt;

&lt;p&gt;So we don't have to create one ourselves.&lt;/p&gt;

&lt;h2&gt;
  
  
  Downloading the Kiro Crew seccomp profile
&lt;/h2&gt;

&lt;p&gt;From the &lt;code&gt;kiro-crew&lt;/code&gt; directory we created earlier, download the &lt;a href="https://github.com/kirodotdev/KiroCrew/blob/main/docker/seccomp/kirocrew-seccomp.json" rel="noopener noreferrer"&gt;official Kiro Crew seccomp profile&lt;/a&gt;:&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="nt"&gt;-fsSL&lt;/span&gt; https://raw.githubusercontent.com/kirodotdev/KiroCrew/main/docker/seccomp/kirocrew-seccomp.json &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-o&lt;/span&gt; kirocrew-seccomp.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should now have:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kiro-crew/
└── kirocrew-seccomp.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Having trouble downloading it from WSL?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I happened to be dealing with a DNS issue in my WSL environment when I did this, so &lt;code&gt;curl&lt;/code&gt; couldn't resolve GitHub. If you happen to run into the same thing, there's nothing special about downloading the file through &lt;code&gt;curl&lt;/code&gt;: you can download &lt;code&gt;kirocrew-seccomp.json&lt;/code&gt; directly from the Kiro Crew GitHub repository in your browser and place it in this directory manually, which is what I did.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now we can start the container using that profile.&lt;/p&gt;

&lt;h2&gt;
  
  
  Running Kiro Crew
&lt;/h2&gt;

&lt;p&gt;Run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;--name&lt;/span&gt; kirocrew &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-p&lt;/span&gt; 127.0.0.1:5476:5476 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-v&lt;/span&gt; kirocrew-home:/home/kirocrew &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--security-opt&lt;/span&gt; &lt;span class="nv"&gt;seccomp&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;kirocrew-seccomp.json &lt;span class="se"&gt;\&lt;/span&gt;
  ghcr.io/kirodotdev/kirocrew:stable
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are a couple of things worth noticing here.&lt;/p&gt;

&lt;p&gt;We're only publishing port &lt;code&gt;5476&lt;/code&gt; on the host's loopback interface, so the dashboard isn't being exposed to the rest of our network.&lt;/p&gt;

&lt;p&gt;We're also creating a named Docker volume:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Kiro Crew keeps its persistent state under &lt;code&gt;/home/kirocrew&lt;/code&gt;, including its configuration and Kiro CLI credentials. That means our state can survive replacing or upgrading the container.&lt;/p&gt;

&lt;p&gt;And, most importantly for what we've just discussed, we're passing the Kiro Crew seccomp profile with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;--security-opt seccomp=kirocrew-seccomp.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The container can now create the inner namespace sandbox while Docker's other default security restrictions remain in place.&lt;/p&gt;

&lt;h2&gt;
  
  
  Let's open it
&lt;/h2&gt;

&lt;p&gt;At this point I did what I imagine most developers would do.&lt;/p&gt;

&lt;p&gt;I opened:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http://localhost:5476
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And instead of the Kiro Crew dashboard, I was greeted by a message telling me I was missing a token.&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%2Fibs1dbiy2gnkertdm7o2.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%2Fibs1dbiy2gnkertdm7o2.png" alt="Kiro Crew dashboard showing that an access token is required" width="800" height="706"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Another security measure!&lt;/p&gt;

&lt;p&gt;Simply being able to reach port &lt;code&gt;5476&lt;/code&gt; isn't enough to get access to the dashboard. Kiro Crew also requires a bearer token, so someone who can reach the Gateway still needs to authenticate before they can use it.&lt;/p&gt;

&lt;p&gt;So, there's one more part of the setup we need to do.&lt;/p&gt;

&lt;p&gt;Actually, two.&lt;/p&gt;

&lt;h2&gt;
  
  
  Authenticating Kiro CLI
&lt;/h2&gt;

&lt;p&gt;Kiro Crew's agent runtime uses &lt;code&gt;kiro-cli&lt;/code&gt;, so first we need to authenticate the CLI running inside our container.&lt;/p&gt;

&lt;p&gt;We can do that without opening an interactive shell ourselves:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nt"&gt;-it&lt;/span&gt; kirocrew kiro-cli login
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Follow the authentication flow and log in with the identity you use for Kiro.&lt;/p&gt;

&lt;p&gt;Once authentication succeeds, those credentials are stored in the &lt;code&gt;kirocrew-home&lt;/code&gt; volume we created earlier, so they survive container upgrades.&lt;/p&gt;

&lt;p&gt;But that authenticates the agent runtime.&lt;/p&gt;

&lt;p&gt;We still need access to the dashboard.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting our dashboard token
&lt;/h2&gt;

&lt;p&gt;Every request to the Kiro Crew dashboard requires a token.&lt;/p&gt;

&lt;p&gt;We can mint a temporary login link from the running container:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker &lt;span class="nb"&gt;exec &lt;/span&gt;kirocrew kirocrew token &lt;span class="nt"&gt;--ttl&lt;/span&gt; 2h
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Kiro Crew will print a URL containing the token.&lt;/p&gt;

&lt;p&gt;It will look roughly like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http://localhost:5476/?token=...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open that URL in your browser and...&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%2Fugtlxga5vgxv3hj4i2f8.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%2Fugtlxga5vgxv3hj4i2f8.png" alt="Kiro Crew running successfully in Docker on Windows" width="800" height="469"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;We're in!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;And with that, we have Kiro Crew running nicely inside Docker on Windows, without having to build it from source and without unnecessarily weakening either of its isolation boundaries.&lt;/p&gt;

&lt;p&gt;Now I just need someone to explain why the Solarized theme is green instead of yellow. 😄&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://kiro.dev/docs/crew/installation/" rel="noopener noreferrer"&gt;Kiro Crew installation documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/kirodotdev/KiroCrew" rel="noopener noreferrer"&gt;Kiro Crew GitHub repository&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/kirodotdev/KiroCrew/blob/main/docs/guides/docker.md" rel="noopener noreferrer"&gt;Kiro Crew Docker guide&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>docker</category>
      <category>ai</category>
      <category>security</category>
      <category>devops</category>
    </item>
  </channel>
</rss>
