<?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: Saurabh "Rob" Dahal</title>
    <description>The latest articles on DEV Community by Saurabh "Rob" Dahal (@raabdahl).</description>
    <link>https://dev.to/raabdahl</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%2F3709480%2F8d520395-4d17-449e-a5db-9dd63f9c5f62.jpeg</url>
      <title>DEV Community: Saurabh "Rob" Dahal</title>
      <link>https://dev.to/raabdahl</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/raabdahl"/>
    <language>en</language>
    <item>
      <title>Help Your Coding Assistant Find the Right Code in Large Repos</title>
      <dc:creator>Saurabh "Rob" Dahal</dc:creator>
      <pubDate>Fri, 16 Oct 2026 16:53:48 +0000</pubDate>
      <link>https://dev.to/raabdahl/help-your-coding-assistant-find-the-right-code-in-large-repos-20e3</link>
      <guid>https://dev.to/raabdahl/help-your-coding-assistant-find-the-right-code-in-large-repos-20e3</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Get the starter:&lt;/strong&gt; &lt;a href="https://github.com/sdahal1/repo-search-workshop" rel="noopener noreferrer"&gt;sdahal1/repo-search-workshop on GitHub&lt;/a&gt;. Rehearsed with Node.js 24.10.0, npm 11.6.0, ripgrep 15.2.0, and ast-grep 0.51.0.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Author:&lt;/strong&gt; Saurabh Rob Dahal, Developer Advocate, AWS&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Description:&lt;/strong&gt; Find and fix a bug in an unfamiliar repository by having your coding assistant search instead of read: map the repository, search by text and by code shape, follow symbols, then fix with evidence.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Level:&lt;/strong&gt; Beginner · &lt;strong&gt;Time:&lt;/strong&gt; 45 minutes of hands-on work plus 15 minutes of Q&amp;amp;A, after setup&lt;/p&gt;

&lt;p&gt;A coding assistant can suggest a plausible fix before it understands a repository. On a large codebase, it often gets there by reading file after file until something looks wrong. That fills its context with code that doesn't matter, and you can't see how it reached its answer.&lt;/p&gt;

&lt;p&gt;This workshop practices the opposite habit: &lt;strong&gt;map first, read less.&lt;/strong&gt; You narrow the problem to one package, use targeted searches to find the few lines that matter, and give the assistant only that evidence before it changes anything.&lt;/p&gt;

&lt;p&gt;You'll investigate one prepared bug. A client configured with &lt;code&gt;maxRetries: 0&lt;/code&gt; should give up after one failed request, but it sends three. The bug is small on purpose. The method is what carries over to your own code.&lt;/p&gt;

&lt;p&gt;You can use Kiro, Claude Code, Codex, or another assistant that can read files, run shell commands, and edit code. No AWS account is required.&lt;/p&gt;
&lt;h2&gt;
  
  
  How this workshop works
&lt;/h2&gt;

&lt;p&gt;There are &lt;strong&gt;9 tasks&lt;/strong&gt; across 6 steps. Each one is a &lt;code&gt;Task&lt;/code&gt; heading with a short prompt or command, followed by &lt;strong&gt;You should see&lt;/strong&gt;, describing a correct result. Everything else explains why the step matters, and you can read it later.&lt;/p&gt;

&lt;p&gt;You won't type search commands yourself. Each prompt tells the assistant what to find, where, and which tool to use, and it writes and runs the command. The ground rules you set at the start make it show you each command and its raw output.&lt;/p&gt;

&lt;p&gt;After each assistant prompt, an &lt;strong&gt;Expected commands&lt;/strong&gt; section shows what the assistant should have run, what each command does for you, and why it matters. During the live session, glance at it to confirm the assistant did the right kind of work: searched instead of reading, used the tool you asked for, and stayed in scope. Read the full explanations afterward. If the commands don't match, that's a sign the prompt didn't steer the assistant, and you can ask it to redo the step.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Time&lt;/th&gt;
&lt;th&gt;Step&lt;/th&gt;
&lt;th&gt;Tasks&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;0–3 min&lt;/td&gt;
&lt;td&gt;Start: set the ground rules&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3–6 min&lt;/td&gt;
&lt;td&gt;1. Reproduce the bug&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6–11 min&lt;/td&gt;
&lt;td&gt;2. Map the repository&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;11–21 min&lt;/td&gt;
&lt;td&gt;3. Search by text, then by shape&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;21–26 min&lt;/td&gt;
&lt;td&gt;4. Follow the symbols&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;26–35 min&lt;/td&gt;
&lt;td&gt;5. Write the evidence and get an explanation&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;35–43 min&lt;/td&gt;
&lt;td&gt;6. Make the fix and verify it&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;43–45 min&lt;/td&gt;
&lt;td&gt;Wrap up&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;45–60 min&lt;/td&gt;
&lt;td&gt;Q&amp;amp;A&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&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%2Fvgid48fk2lj6i4616ygq.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%2Fvgid48fk2lj6i4616ygq.png" alt=" " width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Before the session
&lt;/h2&gt;

&lt;p&gt;Do this ahead of time. It isn't part of the 45 minutes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Install the tools:&lt;/strong&gt; Git, Node.js 24 with npm, &lt;a href="https://github.com/BurntSushi/ripgrep#installation" rel="noopener noreferrer"&gt;ripgrep&lt;/a&gt;, an editor with TypeScript &lt;strong&gt;Go to Definition&lt;/strong&gt;, and a coding assistant you've signed in to. On a Mac with Homebrew, run &lt;code&gt;brew install ripgrep&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Clone the starter and install its dependencies:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/sdahal1/repo-search-workshop.git
&lt;span class="nb"&gt;cd &lt;/span&gt;repo-search-workshop
git switch &lt;span class="nt"&gt;-c&lt;/span&gt; workshop/my-investigation
npm ci
npx &lt;span class="nt"&gt;--no-install&lt;/span&gt; ast-grep &lt;span class="nt"&gt;--version&lt;/span&gt;
git status &lt;span class="nt"&gt;--short&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;You should see:&lt;/strong&gt; ast-grep reports 0.51.0, and &lt;code&gt;git status --short&lt;/code&gt; prints nothing. &lt;code&gt;npm ci&lt;/code&gt; installs the exact dependency versions in the lockfile, including ast-grep, so everyone has the same tools. The empty status is your starting baseline: in step 6, anything that shows up in &lt;code&gt;git diff&lt;/code&gt; came from your work.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Open the whole &lt;code&gt;repo-search-workshop&lt;/code&gt; folder in your editor,&lt;/strong&gt; not a single file, so TypeScript navigation works.&lt;/p&gt;

&lt;h2&gt;
  
  
  Start: set the ground rules
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Time: 0–3 minutes&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Task 0: Give the assistant its ground rules
&lt;/h3&gt;

&lt;p&gt;Start a conversation with your assistant in the repository and paste:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;For this investigation, follow these rules until I say otherwise:
- Ignore the workshop/ folder unless I name a file in it.
- You can read docs, READMEs, and package.json files. To find code,
  search instead of opening source or test files. Use rg for text and
  ast-grep for code shape (npx --no-install ast-grep). Show me each
  command and its raw output.
- Only edit files I name.
- Report what you find. Don't suggest causes or fixes until I ask.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;You should see:&lt;/strong&gt; The assistant acknowledges the rules. If you start a new conversation later, paste them again.&lt;/p&gt;

&lt;p&gt;Each rule protects part of the method:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Ignore &lt;code&gt;workshop/&lt;/code&gt;.&lt;/strong&gt; It holds the exercise material. Assistants treat everything in scope as evidence, including hints and stale notes. Real repositories have the same problem.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Read the small files, search the code.&lt;/strong&gt; Docs, READMEs, and manifests are short and describe what the code should do, so reading them is cheap. Source and test files are where the volume is, so those get searched. Showing each command keeps the assistant's context small and its work visible. Without it, the assistant may read files and summarize, and you can't tell what it skipped.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Edit only what I name, and no causes yet.&lt;/strong&gt; Assistants tend to jump ahead to a fix. Keeping investigation and editing separate is what lets you check the reasoning before code changes.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  1 Reproduce the bug
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Time: 3–6 minutes&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why:&lt;/strong&gt; A reproduction turns a vague report into a measured gap between expected and actual behavior. It also becomes your first check after the fix.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The alternative:&lt;/strong&gt; Paste the bug report and say "fix it." But then nobody has defined what "correct" means, and you can't show that a change fixed anything.&lt;/p&gt;

&lt;h3&gt;
  
  
  Task 1: Run the reported scenario and the tests
&lt;/h3&gt;

&lt;p&gt;The bug report in &lt;code&gt;workshop/BUG-REPORT.md&lt;/code&gt; says: "I set &lt;code&gt;maxRetries&lt;/code&gt; to zero, but the client still retries." Reproduce it the two ways you would on a real project, by running the scenario and running the test suite:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run demo
npm &lt;span class="nb"&gt;test&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;You should see:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;npm run demo&lt;/code&gt;&lt;/strong&gt; prints &lt;code&gt;Transport calls: 3&lt;/code&gt;. The demo makes one request with &lt;code&gt;maxRetries: 0&lt;/code&gt; and a transport that always fails. A &lt;em&gt;transport&lt;/em&gt; is the function that sends each request; here it's a fake that fails and counts its calls. The demo doesn't say whether 3 is right. That's for you to decide against the docs in step 2.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;npm test&lt;/code&gt;&lt;/strong&gt; reports 27 passing and 1 failing: &lt;code&gt;maxRetries: 0 makes one attempt&lt;/code&gt;, ending in &lt;code&gt;3 !== 1&lt;/code&gt;. The test expected one call and got three.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In a real project, you'd usually write that failing test yourself from the bug report. It's already in the starter to save time.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fxnxhhags2ov903ayiwm0.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%2Fxnxhhags2ov903ayiwm0.png" alt=" " width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;A retry is an extra attempt after the first. Zero retries should mean one call total.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Takeaway:&lt;/strong&gt; "Retries when it shouldn't" is now "1 call expected, 3 observed," with two commands that show it. Step 6 reruns the same two commands, so before and after compare directly. Note that this is an observation, not a cause. The loop might be off by one, the setting might be dropped, or a default might be applied. Keep all three open.&lt;/p&gt;

&lt;h2&gt;
  
  
  2 Map the repository
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Time: 6–11 minutes&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why:&lt;/strong&gt; Before reading any code, figure out which part of the repository owns the behavior and what correct behavior is. Paths, manifests, and docs are small, so this is cheap.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The alternative:&lt;/strong&gt; Let the assistant explore however it likes. On a large repository, that means hundreds of files in its context, and you can't check how it chose where to look.&lt;/p&gt;

&lt;h3&gt;
  
  
  Task 2: Ask for a map
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Use git ls-files to list the files, skipping workshop/. Then map the
repository from that list, the README, package.json files, and docs.
Don't read source or test files yet.

Bug: with maxRetries: 0, the client makes three calls instead of one.
Which package most likely owns this, and why? Why not the others?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;You should see:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The owner:&lt;/strong&gt; &lt;code&gt;packages/client&lt;/code&gt;. Its &lt;code&gt;package.json&lt;/code&gt; says it handles "transport retry behavior," and &lt;code&gt;docs/client-options.md&lt;/code&gt; documents &lt;code&gt;maxRetries&lt;/code&gt; as a client option.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ruled out, each with a reason:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;packages/jobs&lt;/code&gt; also has a &lt;code&gt;maxRetries&lt;/code&gt; option, but &lt;code&gt;docs/jobs.md&lt;/code&gt; says job retries are separate from client retries. The bug is about client calls.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;packages/config&lt;/code&gt; only reads environment variables, and &lt;code&gt;packages/telemetry&lt;/code&gt; only formats and logs.&lt;/li&gt;
&lt;li&gt;The apps call the client; they don't implement retries.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The contract,&lt;/strong&gt; from &lt;code&gt;docs/client-options.md&lt;/code&gt;: &lt;code&gt;maxRetries: 0&lt;/code&gt; means one call, &lt;code&gt;1&lt;/code&gt; means two calls, and leaving it out means the default of two retries, or three calls.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Expected commands:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git ls-files &lt;span class="nt"&gt;--&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="s1"&gt;':!workshop'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then file reads of &lt;code&gt;README.md&lt;/code&gt;, the &lt;code&gt;package.json&lt;/code&gt; files, and the files in &lt;code&gt;docs/&lt;/code&gt;, and no reads of &lt;code&gt;.ts&lt;/code&gt; files.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Command or action&lt;/th&gt;
&lt;th&gt;What it does for you&lt;/th&gt;
&lt;th&gt;Why it matters here&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;git ls-files -- . ':!workshop'&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Lists every file Git tracks, about 60 here, without opening any of them. &lt;code&gt;':!workshop'&lt;/code&gt; excludes the exercise folder.&lt;/td&gt;
&lt;td&gt;The file list is the cheapest map there is: a few kilobytes, even for a large repository. Folder and file names alone often tell you where a behavior lives.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Reading the README and &lt;code&gt;package.json&lt;/code&gt; files&lt;/td&gt;
&lt;td&gt;Shows what each package says it's responsible for.&lt;/td&gt;
&lt;td&gt;These files are short and written by people to explain intent. One sentence, "transport retry behavior," points at the owner faster than reading any code.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Reading the files in &lt;code&gt;docs/&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Gives the documented contract for &lt;code&gt;maxRetries&lt;/code&gt;, and explains how job retries differ from client retries.&lt;/td&gt;
&lt;td&gt;You can't judge any fix without knowing what correct means. The docs also rule out &lt;code&gt;packages/jobs&lt;/code&gt;, the one package a name search alone would confuse with the owner.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;If the assistant used &lt;code&gt;rg --files&lt;/code&gt; instead of &lt;code&gt;git ls-files&lt;/code&gt;, that's fine. It does the same job but skips hidden files, so it lists a few fewer. If it opened &lt;code&gt;.ts&lt;/code&gt; files, it read more than it needed to. Remind it of the ground rules.&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%2F6ttq5o64f4gnqm8zjp75.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%2F6ttq5o64f4gnqm8zjp75.png" alt=" " width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Takeaway:&lt;/strong&gt; You narrowed about 60 files to one package, without reading any code, and you know what correct looks like. That matters more here than it might seem: &lt;code&gt;maxRetries&lt;/code&gt; also appears in the jobs package, the config package, and both apps. Without the map, any search for it would mix all of them together.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;How far we've narrowed:&lt;/strong&gt; 61 files → &lt;strong&gt;11 source files in one package.&lt;/strong&gt; Three other packages and three apps are ruled out, and the assistant hasn't opened a single &lt;code&gt;.ts&lt;/code&gt; file.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;One clue stands out: zero produces the same three calls as leaving the option out. That hints that something treats zero as "not set." It's still a guess. The searches will check it.&lt;/p&gt;

&lt;h2&gt;
  
  
  3 Search by text, then by shape
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Time: 11–21 minutes&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why:&lt;/strong&gt; Text search finds every place a name appears. Structural search finds every place code has a certain &lt;em&gt;shape&lt;/em&gt;, even when names, spacing, or line breaks differ. Together they find the few lines that matter without reading whole files.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The alternative:&lt;/strong&gt; Ask "where is &lt;code&gt;maxRetries&lt;/code&gt; handled?" and accept the answer. The assistant may read the files it guesses are relevant and stop at the first plausible match. You can't see what it skipped, and asking again may give a different answer.&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%2F65ypsuspymq222qa5as9.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%2F65ypsuspymq222qa5as9.png" alt=" " width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Task 3.1: Search for the setting by name
&lt;/h3&gt;

&lt;p&gt;Search for the most specific name in the bug, the setting that didn't take effect, inside the package from step 2.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Use rg to search packages/client/src for maxRetries, with a few lines
of context.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;You should see:&lt;/strong&gt; 9 matching lines across 5 files. Most just declare, validate, or pass the value along. One line in &lt;code&gt;retry/policy.ts&lt;/code&gt; stands out:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;maxRetries&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;maxRetries&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;DEFAULT_MAX_RETRIES&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's where a fallback can replace the setting, which fits the "zero acts like not set" clue from step 2.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Expected command:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rg &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="nt"&gt;-C&lt;/span&gt; 3 &lt;span class="s1"&gt;'maxRetries'&lt;/span&gt; packages/client/src
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Part&lt;/th&gt;
&lt;th&gt;What it does for you&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;rg 'maxRetries'&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Finds every line containing the name, across all files under the path.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;packages/client/src&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Limits the search to the source of the package from step 2. You already saw the failing test in step 1.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-n&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Adds line numbers, so every result is a location you can cite later.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-C 3&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Shows 3 lines above and below each match, so you can see what the code does with the value without opening the file.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Why this matters:&lt;/strong&gt; The scope is doing most of the work. The same search across the whole repository returns 55 lines in 20 files, including the jobs package's own &lt;code&gt;maxRetries&lt;/code&gt;, the config loader, both apps, and the docs. Scoped to the package the map picked, it returns 9. The assistant reads only those lines and a little context, not 11 files in full. You see every match, so nothing is skipped silently, and anyone can rerun the command and get the same result.&lt;/p&gt;

&lt;p&gt;If the assistant searched the whole repository, or opened files instead of searching, the scope is wrong. Ask it to rerun the search on &lt;code&gt;packages/client/src&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Show it on screen (optional, about 1 minute).&lt;/strong&gt; Run these yourself to make the effect of the map visible. The only difference between the last two commands is the scope from step 2:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git ls-files &lt;span class="nt"&gt;--&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="s1"&gt;':!workshop'&lt;/span&gt; | &lt;span class="nb"&gt;wc&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt;              &lt;span class="c"&gt;# 61: every file in the project&lt;/span&gt;
rg &lt;span class="nt"&gt;-l&lt;/span&gt; maxRetries &lt;span class="nt"&gt;--glob&lt;/span&gt; &lt;span class="s1"&gt;'!workshop/**'&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt; | &lt;span class="nb"&gt;wc&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt;      &lt;span class="c"&gt;# 20: files that mention maxRetries, whole repo&lt;/span&gt;
rg &lt;span class="nt"&gt;-l&lt;/span&gt; maxRetries packages/client/src | &lt;span class="nb"&gt;wc&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt;        &lt;span class="c"&gt;# 5:  same search, after the map&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;rg -l&lt;/code&gt; lists only the names of matching files, and &lt;code&gt;wc -l&lt;/code&gt; counts them.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;How far we've narrowed:&lt;/strong&gt; 20 files that mention &lt;code&gt;maxRetries&lt;/code&gt; → &lt;strong&gt;5&lt;/strong&gt;, because the search stayed inside the package the map picked. That's 9 lines for the assistant to read instead of 55.&lt;/p&gt;
&lt;/blockquote&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%2Fpdo7eg9kp0yszojv7jqk.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%2Fpdo7eg9kp0yszojv7jqk.png" alt=" " width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Task 3.2: Find every expression with the same shape
&lt;/h3&gt;

&lt;p&gt;Before blaming that line, check whether the same pattern appears anywhere else in the package. Some copies may be intentional.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;retry/policy.ts line 10 has: options.maxRetries || DEFAULT_MAX_RETRIES

Find every expression in packages/client/src with that same
value || fallback shape. Use rg for a text search and ast-grep for a
structural search, and show both. Then keep only real fallbacks, not
boolean conditions, and check docs/client-options.md to see whether
each one is intended.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;You should see:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Text search:&lt;/strong&gt; 5 lines, but not 5 expressions. One result is only &lt;code&gt;|| 'workshop-client';&lt;/code&gt; because its left side is on the line above. Text search finds characters, not shapes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Structural search:&lt;/strong&gt; 5 whole expressions, including that two-line one.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fallback candidates for this repository:&lt;/strong&gt; 3 matches:

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;request.ts:6-7&lt;/code&gt;: &lt;code&gt;options.requestLabel || 'workshop-client'&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;headers.ts:6&lt;/code&gt;: &lt;code&gt;options.userAgent || DEFAULT_USER_AGENT&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;retry/policy.ts:10&lt;/code&gt;: &lt;code&gt;options.maxRetries || DEFAULT_MAX_RETRIES&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Intent:&lt;/strong&gt; The docs say an empty label and an empty user agent should both use their defaults. That's exactly what &lt;code&gt;||&lt;/code&gt; does, so those two are intended. The docs say zero retries is valid, so for &lt;code&gt;maxRetries&lt;/code&gt;, &lt;code&gt;||&lt;/code&gt; is wrong. Same shape, different intent.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Expected commands:&lt;/strong&gt; three searches, in this order. The exact ast-grep syntax will vary between assistants.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# 1. Text search for the operator&lt;/span&gt;
rg &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="nt"&gt;-F&lt;/span&gt; &lt;span class="s1"&gt;'||'&lt;/span&gt; packages/client/src

&lt;span class="c"&gt;# 2. Structural search for the shape&lt;/span&gt;
npx &lt;span class="nt"&gt;--no-install&lt;/span&gt; ast-grep run &lt;span class="nt"&gt;--lang&lt;/span&gt; ts &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--pattern&lt;/span&gt; &lt;span class="s1"&gt;'$VALUE || $FALLBACK'&lt;/span&gt; packages/client/src

&lt;span class="c"&gt;# 3. Structural search, fallback candidates for this repository&lt;/span&gt;
npx &lt;span class="nt"&gt;--no-install&lt;/span&gt; ast-grep scan &lt;span class="nt"&gt;--inline-rules&lt;/span&gt; &lt;span class="s1"&gt;'
id: or-fallback
language: TypeScript
rule:
  pattern: $VALUE || $FALLBACK
constraints:
  VALUE:
    kind: member_expression
  FALLBACK:
    any:
      - kind: identifier
      - kind: string
      - kind: number
'&lt;/span&gt; packages/client/src
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Command&lt;/th&gt;
&lt;th&gt;What it does for you&lt;/th&gt;
&lt;th&gt;Why it matters here&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1. `rg -F '\&lt;/td&gt;
&lt;td&gt;\&lt;/td&gt;
&lt;td&gt;'`&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2. &lt;code&gt;ast-grep run --pattern&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Parses the TypeScript and finds every expression shaped like `something \&lt;/td&gt;
&lt;td&gt;\&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3. {% raw %}&lt;code&gt;ast-grep scan --inline-rules&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Same pattern, plus &lt;code&gt;constraints&lt;/code&gt;: the left side must read a property (&lt;code&gt;member_expression&lt;/code&gt;), and the right side must be a plain name, string, or number.&lt;/td&gt;
&lt;td&gt;It filters out boolean conditions like `a === true \&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Why this matters:&lt;/strong&gt; One suspicious line is a lead. Checking for others with the same shape tells you whether the bug is one line or a pattern repeated across the package, and whether a "fix everything that looks like this" change would break working code. Here it would: two of the three fallbacks are correct. The structural search found all three without the assistant reading any file in full.&lt;/p&gt;

&lt;p&gt;If the assistant used only {% raw %}&lt;code&gt;rg&lt;/code&gt;, or wrote a regular expression to match &lt;code&gt;||&lt;/code&gt; with something on each side, it didn't do a structural search. Ask it to use ast-grep. Regular expressions can't reliably match code that spans lines or nests.&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%2Fz3n0jmkhy80v4wlbzu23.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%2Fz3n0jmkhy80v4wlbzu23.png" alt=" " width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Foj9vby4twd1odotlaiqr.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%2Foj9vby4twd1odotlaiqr.png" alt=" " width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Takeaway:&lt;/strong&gt; Five &lt;code&gt;||&lt;/code&gt; expressions became three fallbacks, then one suspect. The boolean conditions dropped out by shape, and the two siblings dropped out by intent. That's also why replacing every &lt;code&gt;||&lt;/code&gt; in the package would break working code: a structural match is a lead to check, not a diagnosis.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;How far we've narrowed:&lt;/strong&gt; 5 files → 3 files with a fallback of this shape → &lt;strong&gt;1 suspect line&lt;/strong&gt;, &lt;code&gt;retry/policy.ts:10&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  4 Follow the symbols
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Time: 21–26 minutes&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why:&lt;/strong&gt; A suspicious line only matters if the failing test actually reaches it, and with the value you expect. Your TypeScript editor's Go to Definition resolves which declaration a name refers to, even across renamed imports. Text search finds matching names; editor navigation resolves their identity. Reading the relevant code then shows how the value flows.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The alternative:&lt;/strong&gt; Let the assistant trace imports by reading files. It works on small repositories but gets unreliable with re-exports and renamed imports, and it costs context. Here, the path crosses three files and two folders.&lt;/p&gt;

&lt;h3&gt;
  
  
  Task 4: Trace the path from the test to the suspect
&lt;/h3&gt;

&lt;p&gt;In your editor:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open &lt;code&gt;packages/client/test/client.test.ts&lt;/code&gt;, find the test &lt;code&gt;maxRetries: 0 makes one attempt&lt;/code&gt;, and use &lt;strong&gt;Go to Definition&lt;/strong&gt; on &lt;code&gt;createClient&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;In &lt;code&gt;client.ts&lt;/code&gt;, find the line that calls &lt;code&gt;resolveRetryPolicy&lt;/code&gt;. Note that it passes &lt;code&gt;options.maxRetries&lt;/code&gt; along unchanged. Use &lt;strong&gt;Go to Definition&lt;/strong&gt; on &lt;code&gt;resolveRetryPolicy&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Back in &lt;code&gt;client.ts&lt;/code&gt;, use &lt;strong&gt;Go to Definition&lt;/strong&gt; on &lt;code&gt;withRetry&lt;/code&gt; to see where the policy is used.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;You should see:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;createClient&lt;/code&gt; passes &lt;code&gt;options.maxRetries&lt;/code&gt; straight into &lt;code&gt;resolveRetryPolicy&lt;/code&gt; (&lt;code&gt;client.ts:9&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;resolveRetryPolicy&lt;/code&gt; is in &lt;code&gt;retry/policy.ts&lt;/code&gt;, and line 10 is the suspect from step 3.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;withRetry&lt;/code&gt; in &lt;code&gt;retry/run.ts&lt;/code&gt; keeps retrying until it has used &lt;code&gt;policy.maxRetries&lt;/code&gt; retries (&lt;code&gt;run.ts:14&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;During setup, the test calls &lt;code&gt;createClient&lt;/code&gt;, which calls &lt;code&gt;resolveRetryPolicy&lt;/code&gt; and stores its returned policy. During the request, &lt;code&gt;client.request&lt;/code&gt; passes that policy to &lt;code&gt;withRetry&lt;/code&gt;. Zero reaches &lt;code&gt;retry/policy.ts&lt;/code&gt; untouched, and the loop uses the returned policy. The policy function does not call the retry loop directly.&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%2Fnala0gtoujw3o4kiahpv.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%2Fnala0gtoujw3o4kiahpv.png" alt=" " width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Takeaway:&lt;/strong&gt; The suspect is on the path the failing test takes, and nothing changed the value before it got there. That rules out "the setting was dropped" from step 1. You also found where the loop reads the result, which rules out "the loop is off by one" once you see it uses the policy's number as is.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;How far we've narrowed:&lt;/strong&gt; The failing test's path runs through &lt;strong&gt;3 files&lt;/strong&gt;: &lt;code&gt;client.ts&lt;/code&gt;, &lt;code&gt;retry/policy.ts&lt;/code&gt;, and &lt;code&gt;retry/run.ts&lt;/code&gt;. Those are the only source files the explanation needs.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  5 Write the evidence and get an explanation
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Time: 26–35 minutes&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why:&lt;/strong&gt; A short evidence note gives the assistant exactly what it needs and nothing else. Asking for an explanation before any edit lets you check the reasoning while changing your mind is still cheap.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The alternative:&lt;/strong&gt; Keep everything in the chat and say "fix it." Long chats get summarized and early evidence drops out. And a diff on its own doesn't show whether the reasoning was sound: a change to the loop and a change to the default both look plausible.&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%2Fhhmoxnrkj3gs4fwf17d7.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%2Fhhmoxnrkj3gs4fwf17d7.png" alt=" " width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Task 5.1: Have the assistant write the evidence
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Fill in the Observed behavior, Repository area, and Relevant code
sections of workshop/INVESTIGATION.md from what we found. Include the
call path I followed: test → createClient → resolveRetryPolicy →
withRetry. Keep it to facts; leave the hypothesis sections empty.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then review it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git diff workshop/INVESTIGATION.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;You should see:&lt;/strong&gt; Only the note changed. The Relevant code section has about five rows on the path from the test to the loop: the test (&lt;code&gt;client.test.ts:31&lt;/code&gt;), &lt;code&gt;client.ts:9&lt;/code&gt;, &lt;code&gt;retry/policy.ts:10&lt;/code&gt;, and &lt;code&gt;retry/run.ts:14&lt;/code&gt;, plus the option type if it's included. Each has a path and line number you saw in a search result. Delete any row that's off the path, and any guess about the cause. Those belong in the next task.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Expected commands:&lt;/strong&gt; one file edit, to &lt;code&gt;workshop/INVESTIGATION.md&lt;/code&gt;. No searches and no other edits. The assistant should write the note from the search output already in the conversation.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Action&lt;/th&gt;
&lt;th&gt;What it does for you&lt;/th&gt;
&lt;th&gt;Why it matters here&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Editing only &lt;code&gt;workshop/INVESTIGATION.md&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Turns the conversation into a short, structured file.&lt;/td&gt;
&lt;td&gt;Chat history gets long and may be summarized. A file keeps the evidence intact, and you or a teammate can hand it to any assistant later.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;git diff workshop/INVESTIGATION.md&lt;/code&gt; (you run it)&lt;/td&gt;
&lt;td&gt;Shows exactly what the assistant added.&lt;/td&gt;
&lt;td&gt;It's your check that every row is a fact you saw in a search, not a guess.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;If the assistant ran new searches or opened source files to write the note, it's re-collecting evidence it already has, which costs context. If it edited anything besides the note, undo that change.&lt;/p&gt;

&lt;h3&gt;
  
  
  Task 5.2: Ask for an explanation before any edit
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Read workshop/INVESTIGATION.md and only the lines it points to.
Explain the bug: the cause, the evidence with line numbers, the
smallest fix, and which tests would prove it. Don't change anything yet.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Optional: do this in a fresh conversation (paste the ground rules first). If the note is good, a fresh assistant can explain the bug from it alone.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You should see:&lt;/strong&gt; An explanation like this: zero is falsy, so &lt;code&gt;0 || DEFAULT_MAX_RETRIES&lt;/code&gt; picks the default of 2. The loop allows two retries, so the transport is called three times. The fix is &lt;code&gt;??&lt;/code&gt;, which falls back only when the value is &lt;code&gt;undefined&lt;/code&gt; or &lt;code&gt;null&lt;/code&gt;, so zero stays zero. &lt;a href="https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html#nullish-coalescing" rel="noopener noreferrer"&gt;Nullish coalescing in TypeScript&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;| Value of &lt;code&gt;x&lt;/code&gt; | &lt;code&gt;x \|\| 2&lt;/code&gt; | &lt;code&gt;x ?? 2&lt;/code&gt; |&lt;br&gt;
| --- | --- | --- |&lt;br&gt;
| &lt;code&gt;0&lt;/code&gt; | &lt;code&gt;2&lt;/code&gt; (wrong here) | &lt;code&gt;0&lt;/code&gt; |&lt;br&gt;
| &lt;code&gt;undefined&lt;/code&gt; (option left out) | &lt;code&gt;2&lt;/code&gt; | &lt;code&gt;2&lt;/code&gt; |&lt;br&gt;
| &lt;code&gt;1&lt;/code&gt; | &lt;code&gt;1&lt;/code&gt; | &lt;code&gt;1&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%2Fdeoxpwcvfc3wde4vmu2y.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%2Fdeoxpwcvfc3wde4vmu2y.png" alt=" " width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Before accepting it, check that it connects all three pieces using evidence from your note: zero arrives unchanged (&lt;code&gt;client.ts:9&lt;/code&gt;), &lt;code&gt;||&lt;/code&gt; replaces it with 2 (&lt;code&gt;retry/policy.ts:10&lt;/code&gt;), and two retries means three calls (&lt;code&gt;retry/run.ts:14&lt;/code&gt;). An answer that only says "use &lt;code&gt;??&lt;/code&gt;" hasn't explained the whole symptom.&lt;/p&gt;

&lt;p&gt;A good explanation may also point out why the existing tests didn't catch this: &lt;code&gt;retry-policy.test.ts&lt;/code&gt; checks an omitted value and a positive value, but not zero. That's a realistic way bugs at a boundary slip through.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Expected commands:&lt;/strong&gt; a read of &lt;code&gt;workshop/INVESTIGATION.md&lt;/code&gt;, then targeted reads of the few lines it cites, mainly around &lt;code&gt;retry/policy.ts:10&lt;/code&gt;, &lt;code&gt;client.ts:9&lt;/code&gt;, and &lt;code&gt;retry/run.ts:14&lt;/code&gt;. No edits.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Action&lt;/th&gt;
&lt;th&gt;What it does for you&lt;/th&gt;
&lt;th&gt;Why it matters here&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Reading the note first&lt;/td&gt;
&lt;td&gt;Gives the assistant the evidence and the scope in one short file.&lt;/td&gt;
&lt;td&gt;This is the payoff of the whole investigation: the assistant starts from a handful of cited lines instead of about 60 files.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Reading only the cited lines&lt;/td&gt;
&lt;td&gt;Lets the assistant confirm each claim in the source.&lt;/td&gt;
&lt;td&gt;It can verify the evidence without spending context on unrelated code.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;No edits&lt;/td&gt;
&lt;td&gt;Keeps this step to reasoning only.&lt;/td&gt;
&lt;td&gt;You can reject a wrong explanation in seconds. Rejecting a wrong edit means undoing files.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;If the assistant read whole files or searched the repository again, your note may be missing something. Check what it went looking for, and add that to the note.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Takeaway:&lt;/strong&gt; You have an explanation that accounts for the exact numbers you observed, backed by lines you can point to, before any code changed.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;How far we've narrowed:&lt;/strong&gt; The assistant explained the bug from a note citing &lt;strong&gt;4 relevant locations and their nearby context&lt;/strong&gt;, rather than 61 files. That's the payoff of the whole method.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
  
  
  6 Make the fix and verify it
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Time: 35–43 minutes&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why:&lt;/strong&gt; A fix has to correct the bug and keep everything else working. Tests, a demo run, and the diff each check something different.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The alternative:&lt;/strong&gt; Accept "fixed, tests pass." But the assistant may have run the wrong command, changed the test to match the bug, or replaced every &lt;code&gt;||&lt;/code&gt; in the package.&lt;/p&gt;
&lt;h3&gt;
  
  
  Task 6: Make the fix and check it yourself
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Edit only packages/client/src/retry/policy.ts to make the smallest
fix for this bug. Keep the public API, default behavior, and existing
test assertions. Then run npm test.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Then run the checks yourself rather than trusting a summary:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;test
&lt;/span&gt;npm run demo
git diff
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;You should see:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;npm test&lt;/code&gt;:&lt;/strong&gt; all 28 tests pass, including the reproduction and the test that leaving the option out still gives three calls.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;npm run demo&lt;/code&gt;:&lt;/strong&gt; &lt;code&gt;Transport calls: 1&lt;/code&gt;. The fake transport still reports a rejected request; that is intentional. The fix changes the number of calls, not whether the fake succeeds.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;git diff&lt;/code&gt;:&lt;/strong&gt; one line changed in &lt;code&gt;retry/policy.ts&lt;/code&gt;, from &lt;code&gt;||&lt;/code&gt; to &lt;code&gt;??&lt;/code&gt;, plus your note. For extra coverage afterward, you can separately authorize a new zero case in &lt;code&gt;packages/client/test/retry-policy.test.ts&lt;/code&gt;. That would make 29 tests; the main task keeps the 28 existing tests unchanged. Nothing else should change.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="gd"&gt;- const maxRetries = options.maxRetries || DEFAULT_MAX_RETRIES;
&lt;/span&gt;&lt;span class="gi"&gt;+ const maxRetries = options.maxRetries ?? DEFAULT_MAX_RETRIES;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Expected commands:&lt;/strong&gt; one edit to &lt;code&gt;packages/client/src/retry/policy.ts&lt;/code&gt;, then &lt;code&gt;npm test&lt;/code&gt;.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Command&lt;/th&gt;
&lt;th&gt;What it does for you&lt;/th&gt;
&lt;th&gt;Why it matters here&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Edit to &lt;code&gt;retry/policy.ts&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Changes the one line the evidence points to.&lt;/td&gt;
&lt;td&gt;A small, targeted edit is easy to review. An edit to &lt;code&gt;request.ts&lt;/code&gt;, &lt;code&gt;headers.ts&lt;/code&gt;, or an existing assertion means the assistant went beyond the evidence.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;npm test&lt;/code&gt; (assistant, then you)&lt;/td&gt;
&lt;td&gt;Runs all 28 tests across the four packages.&lt;/td&gt;
&lt;td&gt;The reproduction checks the bug is fixed. The others check that nothing else broke, like the default still giving three calls, or the label and user-agent fallbacks still working.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;npm run demo&lt;/code&gt; (you)&lt;/td&gt;
&lt;td&gt;Reruns the original scenario from step 1.&lt;/td&gt;
&lt;td&gt;It confirms the symptom from the bug report is gone, in the same terms the report used.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;git diff&lt;/code&gt; (you)&lt;/td&gt;
&lt;td&gt;Shows every line that changed since your clean start.&lt;/td&gt;
&lt;td&gt;It's the only check that sees the whole change. Tests can pass while an unrelated file was edited.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;You run the checks yourself because a summary like "all tests pass" is easy to write without checking. The assistant may have run a different command, or misread the output.&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%2Fsojfwoa8layb72oo71p2.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%2Fsojfwoa8layb72oo71p2.png" alt=" " width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If the diff touches &lt;code&gt;request.ts&lt;/code&gt;, &lt;code&gt;headers.ts&lt;/code&gt;, or an existing test assertion, ask why. Those fallbacks are intended, and changing a test's expected count hides the bug instead of fixing it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Takeaway:&lt;/strong&gt; A one-operator fix, confirmed three ways: the tests check behavior, the demo checks the original symptom, and the diff checks that nothing else changed. It also fixes the worker app, which sets &lt;code&gt;maxRetries: 0&lt;/code&gt;: when each attempt throws a retryable error, the client now makes one request per job run instead of three.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;How far we've narrowed:&lt;/strong&gt; &lt;strong&gt;1 line in 1 file&lt;/strong&gt; changed, out of 61 files.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Wrap up
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Time: 43–45 minutes&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Here's how far each step narrowed the search:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Step&lt;/th&gt;
&lt;th&gt;What was left to look at&lt;/th&gt;
&lt;th&gt;How&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Start&lt;/td&gt;
&lt;td&gt;61 files&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2 Map&lt;/td&gt;
&lt;td&gt;1 package, 11 source files&lt;/td&gt;
&lt;td&gt;File list, manifests, docs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3.1 Search by name&lt;/td&gt;
&lt;td&gt;9 lines in 5 files&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;rg&lt;/code&gt;, scoped to the package&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3.2 Search by shape&lt;/td&gt;
&lt;td&gt;5 expressions → 3 fallbacks → 1 suspect&lt;/td&gt;
&lt;td&gt;ast-grep, then the docs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4 Follow&lt;/td&gt;
&lt;td&gt;Confirmed on the failing test's path&lt;/td&gt;
&lt;td&gt;Go to Definition&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5 Explain&lt;/td&gt;
&lt;td&gt;One explanation, 4 cited locations&lt;/td&gt;
&lt;td&gt;Evidence note&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6 Fix&lt;/td&gt;
&lt;td&gt;1 changed line&lt;/td&gt;
&lt;td&gt;Tests, demo, &lt;code&gt;git diff&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Each step answered one question: what's wrong, where to look, where the name and shape appear, whether the test reaches the suspect, whether we understand it, and whether the fix is complete. The assistant read a handful of lines, not the whole repository, and you could check every step. On a repository with thousands of files, the same steps narrow the search the same way, and that's the difference between an assistant that finds the bug and one that gets lost.&lt;/p&gt;

&lt;h2&gt;
  
  
  Use this on your own codebase
&lt;/h2&gt;

&lt;p&gt;Install ripgrep and ast-grep where your assistant runs commands. On a Mac: &lt;code&gt;brew install ripgrep ast-grep&lt;/code&gt;. Without ast-grep, the assistant may quietly fall back to a text search; checking the command it shows you catches that.&lt;/p&gt;

&lt;p&gt;Then paste these in order, filling in the angle brackets.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ground rules:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;For this investigation, follow these rules until I say otherwise:
- You can read docs, READMEs, and package manifests. To find code,
  search instead of opening source or test files. Use rg for text and
  ast-grep for code shape. Show me each command and its raw output.
- Only edit files I name.
- Report what you find. Don't suggest causes or fixes until I ask.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Map:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Use git ls-files to list the files. Then map the repository from that
list, the README, package manifests, and docs. Don't read source or
test files yet.

Bug: &amp;lt;what happens, with the input and the result&amp;gt;.
Which package most likely owns this, and why? Why not the others?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Search by name, then by shape:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Use rg to search &amp;lt;package&amp;gt; for &amp;lt;setting, error message, or log text&amp;gt;,
with a few lines of context.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;file&amp;gt; line &amp;lt;n&amp;gt; has: &amp;lt;suspicious expression&amp;gt;
Find every expression in &amp;lt;package&amp;gt; with that same shape. Use ast-grep
for a structural search. Check whether each one is intended.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Follow the symbols&lt;/strong&gt; in your editor with Go to Definition, from the failing test or entry point to the suspect.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Explain, then fix:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Explain the bug from what we found: the cause, the evidence with line
numbers, the smallest fix, and which tests would prove it.
Don't change anything yet.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;You can edit code now. Make the smallest fix. Keep &amp;lt;what must not
change&amp;gt; and the existing test assertions.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then run your tests and read &lt;code&gt;git diff&lt;/code&gt; yourself before you commit.&lt;/p&gt;

&lt;h2&gt;
  
  
  If something goes wrong
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Symptom&lt;/th&gt;
&lt;th&gt;What to do&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;The assistant answers without showing a command&lt;/td&gt;
&lt;td&gt;Ask it to rerun the step as a search and show the command and raw output.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;The assistant used a text search when you asked for structure&lt;/td&gt;
&lt;td&gt;Ask it to use ast-grep with &lt;code&gt;npx --no-install ast-grep&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ast-grep is missing or reports a different version&lt;/td&gt;
&lt;td&gt;From the repository root, rerun &lt;code&gt;npm ci&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Go to Definition doesn't work&lt;/td&gt;
&lt;td&gt;Open the whole repository folder, not a single file, and wait for TypeScript to load.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;The reproduction already passes&lt;/td&gt;
&lt;td&gt;You may have an earlier edit. Check &lt;code&gt;git diff&lt;/code&gt;, or clone a fresh copy.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;The assistant edits code before step 6&lt;/td&gt;
&lt;td&gt;Run &lt;code&gt;git diff&lt;/code&gt;, undo the change with &lt;code&gt;git checkout -- &amp;lt;file&amp;gt;&lt;/code&gt;, and paste the ground rules again.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;The fix passes the reproduction but breaks another test&lt;/td&gt;
&lt;td&gt;Compare the failing test with the docs, and revisit the explanation instead of changing the test.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;No cloud resources are created, so there's nothing to clean up.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>coding</category>
      <category>lsp</category>
      <category>programming</category>
    </item>
    <item>
      <title>Setting up the Agent Toolkit for AWS in Kiro (and Codex, Claude Code, and Cursor)</title>
      <dc:creator>Saurabh "Rob" Dahal</dc:creator>
      <pubDate>Tue, 30 Jun 2026 12:59:54 +0000</pubDate>
      <link>https://dev.to/raabdahl/setting-up-the-agent-toolkit-for-aws-in-kiro-and-codex-claude-code-and-cursor-15e5</link>
      <guid>https://dev.to/raabdahl/setting-up-the-agent-toolkit-for-aws-in-kiro-and-codex-claude-code-and-cursor-15e5</guid>
      <description>&lt;p&gt;If you've let a coding agent loose on AWS, you've watched it guess. It invents API parameters that don't exist, or hands you an S3 bucket a security review will bounce on sight. The Agent Toolkit for AWS is built to stop that. By the end of this post you'll have it running in whatever editor you use, plus a tour of what's in it and three workflows worth pointing it at.&lt;/p&gt;

&lt;p&gt;I use Kiro day to day, so I'll walk through that setup first. It also works with Codex, Claude Code, Cursor, and any other agent that speaks MCP, the Model Context Protocol, which is the open standard agents use to connect to outside tools and data. I'll cover those too.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is the Agent Toolkit for AWS?
&lt;/h2&gt;

&lt;p&gt;The Agent Toolkit for AWS is a free, AWS-supported set of tools that gives AI coding agents secure access to AWS, current documentation they can read mid-task, and tested procedures for the work they tend to fumble. It plugs into the agent you already use rather than asking you to switch. In practice, that shows up in a few ways, all detailed in the &lt;a href="https://docs.aws.amazon.com/agent-toolkit/latest/userguide/what-is-agent-toolkit.html" rel="noopener noreferrer"&gt;AWS user guide&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The agent stops guessing about APIs it never saw. The models behind these agents trained on data that's months or years old, so anything AWS shipped recently is missing or wrong in their heads, and the toolkit hands them current docs and references at request time. For multi-step work like least-privilege IAM or a production serverless stack, it follows a vetted skill instead of reconstructing the steps from half-memory. Every call goes through your own IAM credentials, shows up in CloudWatch, and gets logged to CloudTrail, so you can scope an agent to read-only even when your role can write. And the toolkit costs nothing on its own; you pay only for the AWS resources the agent creates.&lt;/p&gt;

&lt;p&gt;It's the successor to the MCP servers, skills, and plugins AWS shipped under &lt;a href="https://github.com/awslabs" rel="noopener noreferrer"&gt;AWS Labs&lt;/a&gt; in 2025. Two things make me reach for it over a raw MCP setup: condition keys that let a policy tell an agent apart from a human, and skills that have been evaluated end to end rather than thrown over the wall.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's included: the MCP server, skills, plugins, and rules files
&lt;/h2&gt;

&lt;p&gt;Four components work together (&lt;a href="https://docs.aws.amazon.com/agent-toolkit/latest/userguide/what-is-agent-toolkit.html" rel="noopener noreferrer"&gt;reference&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;The AWS MCP Server is the access layer, a single endpoint that reaches 300+ AWS services. It runs in two modes depending on what you ask for. Searching AWS docs, pulling service info, and discovering skills need no credentials at all, so the server is useful the moment you connect it. Anything that touches your account, real API calls and the sandboxed Python &lt;code&gt;run_script&lt;/code&gt; tool, runs as you through your local AWS credentials. It also stamps two condition keys on every request, &lt;code&gt;aws:ViaAWSMCPService&lt;/code&gt; and &lt;code&gt;aws:CalledViaAWSMCP&lt;/code&gt;, so your policies can single out agent traffic.&lt;/p&gt;

&lt;p&gt;Skills are curated packages of instructions, scripts, and reference material for one task. The agent loads a skill only when it needs it, so they barely touch your context until they're relevant.&lt;/p&gt;

&lt;p&gt;Plugins bundle the MCP config and a curated skill set into one install. They're available for Claude Code, Codex, and Cursor; Kiro and other MCP agents connect to the server directly instead, which I cover in the setup steps below. Four ship today:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Plugin&lt;/th&gt;
&lt;th&gt;Covers&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;aws-core&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Service selection, CDK/CloudFormation, serverless, containers, storage, observability, billing, SDK usage, deployment. &lt;strong&gt;Start here.&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;aws-agents&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Building AI agents on AWS with Amazon Bedrock and AgentCore.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;aws-data-analytics&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Data lake, analytics, and ETL with S3 Tables, AWS Glue, and Athena.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;aws-agents-for-devsecops&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Incident investigation, code review, UAT, vulnerability scanning, and pen testing with AWS DevOps Agent and AWS Security Agent.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Rules files are project-level config that sets guardrails: use the MCP Server, find a skill before acting, check the docs, prefer infrastructure-as-code. Rules decide how the agent behaves; skills supply what it does for a given job.&lt;/p&gt;

&lt;h3&gt;
  
  
  Which skills does the Agent Toolkit include?
&lt;/h3&gt;

&lt;p&gt;The skills are the part I underestimated at first. There are around 64 today (browse the &lt;a href="https://github.com/aws/agent-toolkit-for-aws/tree/main/skills" rel="noopener noreferrer"&gt;&lt;code&gt;skills/&lt;/code&gt; directory&lt;/a&gt; for the live list), split into core and specialized.&lt;/p&gt;

&lt;p&gt;Core skills, which ship with &lt;code&gt;aws-core&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;amazon-bedrock&lt;/code&gt;, &lt;code&gt;aws-billing-and-cost-management&lt;/code&gt;, &lt;code&gt;aws-blocks&lt;/code&gt;, &lt;code&gt;aws-cdk&lt;/code&gt;, &lt;code&gt;aws-cloudformation&lt;/code&gt;, &lt;code&gt;aws-containers&lt;/code&gt;, &lt;code&gt;aws-iam&lt;/code&gt;, &lt;code&gt;aws-messaging-and-streaming&lt;/code&gt;, &lt;code&gt;aws-observability&lt;/code&gt;, &lt;code&gt;aws-sdk-js-v3-usage&lt;/code&gt;, &lt;code&gt;aws-sdk-python-usage&lt;/code&gt;, &lt;code&gt;aws-sdk-swift-usage&lt;/code&gt;, &lt;code&gt;aws-serverless&lt;/code&gt;, &lt;code&gt;signing-in-to-aws&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Specialized skills, grouped by domain (a few from each):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Serverless (9)&lt;/strong&gt;: &lt;code&gt;connecting-lambda-to-api-gateway&lt;/code&gt;, &lt;code&gt;connecting-lambda-to-dynamodb&lt;/code&gt;, &lt;code&gt;debugging-lambda-timeouts&lt;/code&gt;, &lt;code&gt;processing-s3-uploads-with-step-functions&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Analytics (10)&lt;/strong&gt;: &lt;code&gt;querying-data-lake&lt;/code&gt;, &lt;code&gt;ingesting-into-data-lake&lt;/code&gt;, &lt;code&gt;managing-amazon-msk&lt;/code&gt;, &lt;code&gt;amazon-opensearch-service&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Database (8)&lt;/strong&gt;: &lt;code&gt;amazon-aurora-postgresql&lt;/code&gt;, &lt;code&gt;amazon-elasticache&lt;/code&gt;, &lt;code&gt;exporting-rds-to-s3&lt;/code&gt;, &lt;code&gt;rds-db2&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Networking (5)&lt;/strong&gt;: &lt;code&gt;creating-production-vpc-multi-az&lt;/code&gt;, &lt;code&gt;routing-traffic-with-route53-and-cloudfront&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Storage (5)&lt;/strong&gt;: &lt;code&gt;securing-s3-buckets&lt;/code&gt;, &lt;code&gt;creating-data-lake-table&lt;/code&gt;, &lt;code&gt;storing-and-querying-vectors&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;EC2 (3)&lt;/strong&gt;, &lt;strong&gt;Operations (3)&lt;/strong&gt;, &lt;strong&gt;System table (3)&lt;/strong&gt;, &lt;strong&gt;Migration (2)&lt;/strong&gt;, &lt;strong&gt;Security and identity (1)&lt;/strong&gt;, &lt;strong&gt;Web and mobile (1)&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Don't memorize the list. When you ask for "a Lambda behind API Gateway writing to DynamoDB," the agent pulls the matching skills on its own.&lt;/p&gt;

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

&lt;p&gt;A handful of things need to be in place first. None take long.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;An AWS account.&lt;/strong&gt; Anything that touches AWS needs one. &lt;a href="https://docs.aws.amazon.com/accounts/latest/reference/getting-started.html" rel="noopener noreferrer"&gt;Sign up here&lt;/a&gt; if you don't have one yet.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AWS credentials on your machine&lt;/strong&gt;, for the parts that act on your account. The server still connects and answers documentation and skill questions without them, but API calls and &lt;code&gt;run_script&lt;/code&gt; need them. The proxy reads the standard AWS credential chain, so &lt;code&gt;aws configure&lt;/code&gt;, an SSO login, a named profile, or the usual environment variables all work. New to this? &lt;a href="https://docs.aws.amazon.com/cli/latest/userguide/getting-started-quickstart.html" rel="noopener noreferrer"&gt;Configuring the AWS CLI&lt;/a&gt; is the simplest path. The CLI is the common way to set credentials, not a hard requirement.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://docs.astral.sh/uv/" rel="noopener noreferrer"&gt;uv&lt;/a&gt;&lt;/strong&gt;, a Python package tool that runs the MCP proxy. Install it with &lt;code&gt;brew install uv&lt;/code&gt; on macOS, or the &lt;a href="https://docs.astral.sh/uv/getting-started/installation/" rel="noopener noreferrer"&gt;official installer&lt;/a&gt; elsewhere. The &lt;code&gt;uvx&lt;/code&gt; command in the Kiro config below comes bundled with it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Node.js&lt;/strong&gt;, which gives you the &lt;code&gt;npx&lt;/code&gt; command used to install skills. If &lt;code&gt;npx --version&lt;/code&gt; prints nothing, install it from &lt;a href="https://nodejs.org" rel="noopener noreferrer"&gt;nodejs.org&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AWS CLI &lt;code&gt;2.35.0&lt;/code&gt; or later&lt;/strong&gt;, but only if you use the one-command wizard below. Check with &lt;code&gt;aws --version&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How to set up the Agent Toolkit for AWS
&lt;/h2&gt;

&lt;p&gt;The quickest route is the AWS CLI wizard, which configures every agent you have at once. Prefer to do it by hand, or only use one editor? Skip to the per-agent steps below.&lt;/p&gt;

&lt;h3&gt;
  
  
  Set up every agent at once with the AWS CLI
&lt;/h3&gt;

&lt;p&gt;On a recent AWS CLI, one command detects your installed agents, installs default skills, and configures the MCP Server for all of them:&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 agent-toolkit
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One gotcha worth calling out, because I hit it. On an older CLI you'll see:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aws: [ERROR]: argument subcommand: Found invalid choice 'agent-toolkit'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That means your AWS CLI predates &lt;code&gt;2.35.0&lt;/code&gt;. Update it (&lt;a href="https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html" rel="noopener noreferrer"&gt;instructions&lt;/a&gt;), confirm with &lt;code&gt;aws --version&lt;/code&gt;, and rerun. Restart your agent afterward so it picks up the new MCP config.&lt;/p&gt;

&lt;p&gt;If you only use one agent, or you want to see exactly what gets wired up, the per-agent steps below do the same thing by hand.&lt;/p&gt;

&lt;h3&gt;
  
  
  Kiro
&lt;/h3&gt;

&lt;p&gt;Open your Kiro MCP config and add the AWS server. Use &lt;code&gt;.kiro/settings/mcp.json&lt;/code&gt; for the current project, or &lt;code&gt;~/.kiro/settings/mcp.json&lt;/code&gt; to turn it on everywhere. Create the file if it doesn't exist yet:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"mcpServers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"aws"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"uvx"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"args"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"mcp-proxy-for-aws@1.6.3"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"https://aws-mcp.us-east-1.api.aws/mcp"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"--metadata"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"AWS_REGION=us-west-2"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If your config already lists other servers under &lt;code&gt;mcpServers&lt;/code&gt;, add the &lt;code&gt;aws&lt;/code&gt; entry next to them instead of replacing the block, and keep the JSON valid (mind the commas). Change &lt;code&gt;AWS_REGION&lt;/code&gt; to the region you work in.&lt;/p&gt;

&lt;p&gt;Pin the proxy version rather than tracking latest. You get reproducible behavior and a guard against a bad release. Check &lt;a href="https://pypi.org/project/mcp-proxy-for-aws/" rel="noopener noreferrer"&gt;PyPI&lt;/a&gt; every few weeks and bump it on purpose.&lt;/p&gt;

&lt;p&gt;Then install the skills:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx skills add aws/agent-toolkit-for-aws/skills
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open Kiro's MCP Server view (the Kiro panel in the sidebar, or search "MCP" in the command palette), reconnect the &lt;code&gt;aws&lt;/code&gt; server, and you're live.&lt;/p&gt;

&lt;h3&gt;
  
  
  Codex
&lt;/h3&gt;

&lt;p&gt;Add the marketplace, then install from inside Codex:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;codex plugin marketplace add aws/agent-toolkit-for-aws
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Launch Codex, run &lt;code&gt;/plugins&lt;/code&gt;, and install &lt;code&gt;aws-core&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Claude Code
&lt;/h3&gt;

&lt;p&gt;The plugins live on the official Anthropic marketplace, included by default:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/plugin install aws-core@claude-plugins-official
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Hit &lt;code&gt;Plugin not found&lt;/code&gt;? Refresh the index with &lt;code&gt;/plugin marketplace update claude-plugins-official&lt;/code&gt; and try again. Add &lt;code&gt;aws-agents&lt;/code&gt;, &lt;code&gt;aws-data-analytics&lt;/code&gt;, or &lt;code&gt;aws-agents-for-devsecops&lt;/code&gt; the same way.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cursor
&lt;/h3&gt;

&lt;p&gt;Add the repo as a team marketplace: &lt;strong&gt;Settings → Plugins → Team Marketplaces → Add Marketplace → Import from Repo&lt;/strong&gt;, pointed at &lt;code&gt;aws/agent-toolkit-for-aws&lt;/code&gt;. Open the &lt;strong&gt;Plugins&lt;/strong&gt; panel and install &lt;code&gt;aws-core&lt;/code&gt; first, then the others as needed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Other agents (Windsurf, Cline, and more)
&lt;/h3&gt;

&lt;p&gt;Anything that speaks MCP works, including Windsurf and Cline. Configure the AWS MCP Server directly (see the &lt;a href="https://docs.aws.amazon.com/agent-toolkit/latest/userguide/getting-started-aws-mcp-server.html" rel="noopener noreferrer"&gt;server setup guide&lt;/a&gt;), then run &lt;code&gt;npx skills add aws/agent-toolkit-for-aws/skills&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  How do I check it's working?
&lt;/h2&gt;

&lt;p&gt;Start a fresh conversation and ask: &lt;em&gt;"What AWS Regions are available?"&lt;/em&gt; If the agent returns a list, the MCP Server is connected. For a skill check, ask it to "secure an S3 bucket" and watch it load &lt;code&gt;securing-s3-buckets&lt;/code&gt; before it writes anything. An authentication error instead means your local credentials aren't reaching the server; see Prerequisites for how to set them up.&lt;/p&gt;

&lt;h2&gt;
  
  
  Three workflows that show the payoff
&lt;/h2&gt;

&lt;p&gt;Setup is the boring part. The workflows below are where it pays off, and each one names the skills and components doing the work.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Stand up a serverless API, end to end
&lt;/h3&gt;

&lt;p&gt;Prompt: &lt;em&gt;"Build a REST API: API Gateway in front of a Lambda that reads and writes a DynamoDB table, deployed with CDK."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This is the kind of task agents usually botch, because it spans four services and the IAM glue between them. The agent pulls &lt;code&gt;aws-serverless&lt;/code&gt;, &lt;code&gt;connecting-lambda-to-api-gateway&lt;/code&gt;, &lt;code&gt;connecting-lambda-to-dynamodb&lt;/code&gt;, and &lt;code&gt;aws-cdk&lt;/code&gt;, then uses the MCP Server's API tools to provision and the &lt;code&gt;run_script&lt;/code&gt; sandbox for multi-step setup. The skills carry the wiring, so the Lambda role scopes to your specific table instead of granting access to everything (&lt;code&gt;*&lt;/code&gt;), and the CDK stack follows current patterns instead of a 2023 blog post the model half-remembers.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Troubleshoot a production issue you can't reproduce
&lt;/h3&gt;

&lt;p&gt;Prompt: &lt;em&gt;"My checkout Lambda times out intermittently and error rates spiked this morning. Help me find why."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Point the agent at the symptom and it follows a real diagnostic path. &lt;code&gt;debugging-lambda-timeouts&lt;/code&gt; and &lt;code&gt;troubleshooting-application-failures&lt;/code&gt; give it the procedure, while &lt;code&gt;aws-observability&lt;/code&gt; and &lt;code&gt;querying-aws-cloudwatch&lt;/code&gt; let it read the actual logs and metrics through the MCP Server. It checks the configured timeout against duration metrics, looks for cold starts, and inspects downstream calls that block, then tells you what it found. You get an actual investigation rather than a guess.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Hand an agent production access without losing sleep
&lt;/h3&gt;

&lt;p&gt;Prompt: &lt;em&gt;"Audit this account's S3 buckets and secrets, and flag anything risky."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This is the workflow that separates the toolkit from wiring up a raw MCP server. Before you run it, scope the agent's IAM role to read-only with the condition keys the MCP Server attaches, &lt;code&gt;aws:ViaAWSMCPService&lt;/code&gt; and &lt;code&gt;aws:CalledViaAWSMCP&lt;/code&gt;, so it can inspect and plan but cannot change anything, even though your own role can. Writing that policy is an advanced step, and the &lt;a href="https://docs.aws.amazon.com/agent-toolkit/latest/userguide/what-is-agent-toolkit.html" rel="noopener noreferrer"&gt;user guide&lt;/a&gt; explains how the condition keys fit in; you can skip it the first time through and still get value from the audit. The agent uses &lt;code&gt;securing-s3-buckets&lt;/code&gt; and &lt;code&gt;creating-secrets-using-best-practices&lt;/code&gt; as its rubric for what counts as risky, and every call lands in CloudTrail for you to review later.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to update and remove skills
&lt;/h2&gt;

&lt;p&gt;On AWS CLI &lt;code&gt;2.35.0+&lt;/code&gt;, the &lt;code&gt;aws agent-toolkit&lt;/code&gt; command group manages skills across all your agents from the 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 agent-toolkit list-installed-skills
aws agent-toolkit add-skill &lt;span class="nt"&gt;--skill-name&lt;/span&gt; aws-serverless
aws agent-toolkit update-skill &lt;span class="nt"&gt;--skill-name&lt;/span&gt; aws-serverless
aws agent-toolkit remove-skill &lt;span class="nt"&gt;--skill-name&lt;/span&gt; aws-cdk &lt;span class="nt"&gt;--agent&lt;/span&gt; kiro
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There's also &lt;code&gt;search-skills&lt;/code&gt;, &lt;code&gt;list-available-skills&lt;/code&gt;, and &lt;code&gt;get-skill-metadata&lt;/code&gt; for browsing the catalog from the terminal. Without the CLI, re-run &lt;code&gt;npx skills add aws/agent-toolkit-for-aws/skills&lt;/code&gt; to pull new skills, and remove them with &lt;code&gt;npx skills remove &amp;lt;skill-name&amp;gt;&lt;/code&gt;. The MCP Server itself is AWS-hosted, so its API coverage and docs stay current on their own. The one thing you pin and bump yourself is the proxy version in your config.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frequently asked questions
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Is the Agent Toolkit for AWS free?&lt;/strong&gt;&lt;br&gt;
Yes. The toolkit costs nothing to install or use. You pay only standard AWS rates for the resources your agent creates or calls.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Which AWS CLI version do I need for &lt;code&gt;aws configure agent-toolkit&lt;/code&gt;?&lt;/strong&gt;&lt;br&gt;
Version 2.35.0 or later. Older versions don't recognize the command and fail with &lt;code&gt;Found invalid choice 'agent-toolkit'&lt;/code&gt;. Check yours with &lt;code&gt;aws --version&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How do I fix "Found invalid choice 'agent-toolkit'"?&lt;/strong&gt;&lt;br&gt;
Upgrade the AWS CLI to 2.35.0 or later, since the command shipped in that release. On macOS with Homebrew, run &lt;code&gt;brew upgrade awscli&lt;/code&gt;, then confirm with &lt;code&gt;aws --version&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Do I need an AWS account and credentials?&lt;/strong&gt;&lt;br&gt;
Credentials are needed only for actions that touch your account, like API calls and &lt;code&gt;run_script&lt;/code&gt;. Documentation search and skill discovery work with no credentials. Anything that provisions or reads real resources needs an AWS account.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Which coding agents does it work with?&lt;/strong&gt;&lt;br&gt;
Kiro, Claude Code, Codex, and Cursor have first-class setups, and any MCP-compatible agent works too, including Windsurf and Cline. Plugins cover Claude Code, Codex, and Cursor; Kiro and the rest connect to the MCP server directly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How is it different from the AWS Labs MCP servers?&lt;/strong&gt;&lt;br&gt;
It's the successor to AWS Labs. The differences that matter: IAM condition keys that separate agent actions from human ones, CloudWatch and CloudTrail on every request, and skills evaluated end to end.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How do I give a coding agent read-only access to AWS?&lt;/strong&gt;&lt;br&gt;
Scope its IAM role with the condition keys the MCP server attaches, &lt;code&gt;aws:ViaAWSMCPService&lt;/code&gt; and &lt;code&gt;aws:CalledViaAWSMCP&lt;/code&gt;, to allow reads and deny writes. The agent can inspect and plan but not change anything, even when your own role can.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How do I update or remove skills?&lt;/strong&gt;&lt;br&gt;
On AWS CLI 2.35.0+, use &lt;code&gt;aws agent-toolkit update-skill&lt;/code&gt; and &lt;code&gt;aws agent-toolkit remove-skill&lt;/code&gt;. Otherwise re-run &lt;code&gt;npx skills add aws/agent-toolkit-for-aws/skills&lt;/code&gt; to update, and &lt;code&gt;npx skills remove &amp;lt;skill-name&amp;gt;&lt;/code&gt; to remove.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to try next
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Build the serverless API above, then ask the agent to add a CloudWatch alarm with &lt;code&gt;setting-up-cloudwatch-alarm-notifications&lt;/code&gt; and watch it connect the alarm to an SNS topic.&lt;/li&gt;
&lt;li&gt;Set up the read-only profile from workflow 3, hand it a real account, and confirm the agent can plan a change but not apply one. That's what makes me comfortable letting one near production.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/aws/agent-toolkit-for-aws" rel="noopener noreferrer"&gt;Agent Toolkit for AWS repo&lt;/a&gt;. The source, every skill, and the plugin definitions.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.aws.amazon.com/agent-toolkit/latest/userguide/what-is-agent-toolkit.html" rel="noopener noreferrer"&gt;What is the Agent Toolkit for AWS?&lt;/a&gt;. Components and capabilities.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.aws.amazon.com/agent-toolkit/latest/userguide/quick-start.html" rel="noopener noreferrer"&gt;Getting started&lt;/a&gt;. Install and verify.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.aws.amazon.com/agent-toolkit/latest/userguide/aws-cli.html" rel="noopener noreferrer"&gt;AWS CLI for the toolkit&lt;/a&gt;. The setup wizard and the skill commands.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.aws.amazon.com/agent-toolkit/latest/userguide/understanding-mcp-server-tools.html" rel="noopener noreferrer"&gt;AWS MCP Server tools&lt;/a&gt;. Every tool the server exposes.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  About the author
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Saurabh Dahal is a developer advocate at AWS, working with the latest agentic and AI tools for developers to help boost developer productivity. He set up the Agent Toolkit for AWS across Kiro, Codex, Claude Code, and Cursor for this guide.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Published June 30, 2026. Last updated June 30, 2026.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agentskills</category>
      <category>aws</category>
      <category>agents</category>
    </item>
    <item>
      <title>Setting up the Agent Toolkit for AWS in Kiro (and Codex, Claude Code, and Cursor)</title>
      <dc:creator>Saurabh "Rob" Dahal</dc:creator>
      <pubDate>Tue, 30 Jun 2026 12:30:56 +0000</pubDate>
      <link>https://dev.to/raabdahl/setting-up-the-agent-toolkit-for-aws-in-kiro-and-codex-claude-code-and-cursor-2amm</link>
      <guid>https://dev.to/raabdahl/setting-up-the-agent-toolkit-for-aws-in-kiro-and-codex-claude-code-and-cursor-2amm</guid>
      <description>&lt;p&gt;If you've let a coding agent loose on AWS, you've watched it guess. It invents API parameters that don't exist, or hands you an S3 bucket a security review will bounce on sight. The Agent Toolkit for AWS is built to stop that. By the end of this post you'll have it running in whatever editor you use, plus a tour of what's in it and three workflows worth pointing it at.&lt;/p&gt;

&lt;p&gt;I use Kiro day to day, so I'll walk through that setup first. It also works with Codex, Claude Code, Cursor, and any other agent that speaks MCP, the Model Context Protocol, which is the open standard agents use to connect to outside tools and data. I'll cover those too.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is the Agent Toolkit for AWS?
&lt;/h2&gt;

&lt;p&gt;The Agent Toolkit for AWS is a free, AWS-supported set of tools that gives AI coding agents secure access to AWS, current documentation they can read mid-task, and tested procedures for the work they tend to fumble. It plugs into the agent you already use rather than asking you to switch. In practice, that shows up in a few ways, all detailed in the &lt;a href="https://docs.aws.amazon.com/agent-toolkit/latest/userguide/what-is-agent-toolkit.html" rel="noopener noreferrer"&gt;AWS user guide&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The agent stops guessing about APIs it never saw. The models behind these agents trained on data that's months or years old, so anything AWS shipped recently is missing or wrong in their heads, and the toolkit hands them current docs and references at request time. For multi-step work like least-privilege IAM or a production serverless stack, it follows a vetted skill instead of reconstructing the steps from half-memory. Every call goes through your own IAM credentials, shows up in CloudWatch, and gets logged to CloudTrail, so you can scope an agent to read-only even when your role can write. And the toolkit costs nothing on its own; you pay only for the AWS resources the agent creates.&lt;/p&gt;

&lt;p&gt;It's the successor to the MCP servers, skills, and plugins AWS shipped under &lt;a href="https://github.com/awslabs" rel="noopener noreferrer"&gt;AWS Labs&lt;/a&gt; in 2025. Two things make me reach for it over a raw MCP setup: condition keys that let a policy tell an agent apart from a human, and skills that have been evaluated end to end rather than thrown over the wall.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's included: the MCP server, skills, plugins, and rules files
&lt;/h2&gt;

&lt;p&gt;Four components work together (&lt;a href="https://docs.aws.amazon.com/agent-toolkit/latest/userguide/what-is-agent-toolkit.html" rel="noopener noreferrer"&gt;reference&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;The AWS MCP Server is the access layer, a single endpoint that reaches 300+ AWS services. It runs in two modes depending on what you ask for. Searching AWS docs, pulling service info, and discovering skills need no credentials at all, so the server is useful the moment you connect it. Anything that touches your account, real API calls and the sandboxed Python &lt;code&gt;run_script&lt;/code&gt; tool, runs as you through your local AWS credentials. It also stamps two condition keys on every request, &lt;code&gt;aws:ViaAWSMCPService&lt;/code&gt; and &lt;code&gt;aws:CalledViaAWSMCP&lt;/code&gt;, so your policies can single out agent traffic.&lt;/p&gt;

&lt;p&gt;Skills are curated packages of instructions, scripts, and reference material for one task. The agent loads a skill only when it needs it, so they barely touch your context until they're relevant.&lt;/p&gt;

&lt;p&gt;Plugins bundle the MCP config and a curated skill set into one install. They're available for Claude Code, Codex, and Cursor; Kiro and other MCP agents connect to the server directly instead, which I cover in the setup steps below. Four ship today:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Plugin&lt;/th&gt;
&lt;th&gt;Covers&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;aws-core&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Service selection, CDK/CloudFormation, serverless, containers, storage, observability, billing, SDK usage, deployment. &lt;strong&gt;Start here.&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;aws-agents&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Building AI agents on AWS with Amazon Bedrock and AgentCore.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;aws-data-analytics&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Data lake, analytics, and ETL with S3 Tables, AWS Glue, and Athena.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;aws-agents-for-devsecops&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Incident investigation, code review, UAT, vulnerability scanning, and pen testing with AWS DevOps Agent and AWS Security Agent.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Rules files are project-level config that sets guardrails: use the MCP Server, find a skill before acting, check the docs, prefer infrastructure-as-code. Rules decide how the agent behaves; skills supply what it does for a given job.&lt;/p&gt;

&lt;h3&gt;
  
  
  Which skills does the Agent Toolkit include?
&lt;/h3&gt;

&lt;p&gt;The skills are the part I underestimated at first. There are around 64 today (browse the &lt;a href="https://github.com/aws/agent-toolkit-for-aws/tree/main/skills" rel="noopener noreferrer"&gt;&lt;code&gt;skills/&lt;/code&gt; directory&lt;/a&gt; for the live list), split into core and specialized.&lt;/p&gt;

&lt;p&gt;Core skills, which ship with &lt;code&gt;aws-core&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;amazon-bedrock&lt;/code&gt;, &lt;code&gt;aws-billing-and-cost-management&lt;/code&gt;, &lt;code&gt;aws-blocks&lt;/code&gt;, &lt;code&gt;aws-cdk&lt;/code&gt;, &lt;code&gt;aws-cloudformation&lt;/code&gt;, &lt;code&gt;aws-containers&lt;/code&gt;, &lt;code&gt;aws-iam&lt;/code&gt;, &lt;code&gt;aws-messaging-and-streaming&lt;/code&gt;, &lt;code&gt;aws-observability&lt;/code&gt;, &lt;code&gt;aws-sdk-js-v3-usage&lt;/code&gt;, &lt;code&gt;aws-sdk-python-usage&lt;/code&gt;, &lt;code&gt;aws-sdk-swift-usage&lt;/code&gt;, &lt;code&gt;aws-serverless&lt;/code&gt;, &lt;code&gt;signing-in-to-aws&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Specialized skills, grouped by domain (a few from each):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Serverless (9)&lt;/strong&gt;: &lt;code&gt;connecting-lambda-to-api-gateway&lt;/code&gt;, &lt;code&gt;connecting-lambda-to-dynamodb&lt;/code&gt;, &lt;code&gt;debugging-lambda-timeouts&lt;/code&gt;, &lt;code&gt;processing-s3-uploads-with-step-functions&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Analytics (10)&lt;/strong&gt;: &lt;code&gt;querying-data-lake&lt;/code&gt;, &lt;code&gt;ingesting-into-data-lake&lt;/code&gt;, &lt;code&gt;managing-amazon-msk&lt;/code&gt;, &lt;code&gt;amazon-opensearch-service&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Database (8)&lt;/strong&gt;: &lt;code&gt;amazon-aurora-postgresql&lt;/code&gt;, &lt;code&gt;amazon-elasticache&lt;/code&gt;, &lt;code&gt;exporting-rds-to-s3&lt;/code&gt;, &lt;code&gt;rds-db2&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Networking (5)&lt;/strong&gt;: &lt;code&gt;creating-production-vpc-multi-az&lt;/code&gt;, &lt;code&gt;routing-traffic-with-route53-and-cloudfront&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Storage (5)&lt;/strong&gt;: &lt;code&gt;securing-s3-buckets&lt;/code&gt;, &lt;code&gt;creating-data-lake-table&lt;/code&gt;, &lt;code&gt;storing-and-querying-vectors&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;EC2 (3)&lt;/strong&gt;, &lt;strong&gt;Operations (3)&lt;/strong&gt;, &lt;strong&gt;System table (3)&lt;/strong&gt;, &lt;strong&gt;Migration (2)&lt;/strong&gt;, &lt;strong&gt;Security and identity (1)&lt;/strong&gt;, &lt;strong&gt;Web and mobile (1)&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Don't memorize the list. When you ask for "a Lambda behind API Gateway writing to DynamoDB," the agent pulls the matching skills on its own.&lt;/p&gt;

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

&lt;p&gt;A handful of things need to be in place first. None take long.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;An AWS account.&lt;/strong&gt; Anything that touches AWS needs one. &lt;a href="https://docs.aws.amazon.com/accounts/latest/reference/getting-started.html" rel="noopener noreferrer"&gt;Sign up here&lt;/a&gt; if you don't have one yet.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AWS credentials on your machine&lt;/strong&gt;, for the parts that act on your account. The server still connects and answers documentation and skill questions without them, but API calls and &lt;code&gt;run_script&lt;/code&gt; need them. The proxy reads the standard AWS credential chain, so &lt;code&gt;aws configure&lt;/code&gt;, an SSO login, a named profile, or the usual environment variables all work. New to this? &lt;a href="https://docs.aws.amazon.com/cli/latest/userguide/getting-started-quickstart.html" rel="noopener noreferrer"&gt;Configuring the AWS CLI&lt;/a&gt; is the simplest path. The CLI is the common way to set credentials, not a hard requirement.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://docs.astral.sh/uv/" rel="noopener noreferrer"&gt;uv&lt;/a&gt;&lt;/strong&gt;, a Python package tool that runs the MCP proxy. Install it with &lt;code&gt;brew install uv&lt;/code&gt; on macOS, or the &lt;a href="https://docs.astral.sh/uv/getting-started/installation/" rel="noopener noreferrer"&gt;official installer&lt;/a&gt; elsewhere. The &lt;code&gt;uvx&lt;/code&gt; command in the Kiro config below comes bundled with it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Node.js&lt;/strong&gt;, which gives you the &lt;code&gt;npx&lt;/code&gt; command used to install skills. If &lt;code&gt;npx --version&lt;/code&gt; prints nothing, install it from &lt;a href="https://nodejs.org" rel="noopener noreferrer"&gt;nodejs.org&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AWS CLI &lt;code&gt;2.35.0&lt;/code&gt; or later&lt;/strong&gt;, but only if you use the one-command wizard below. Check with &lt;code&gt;aws --version&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How to set up the Agent Toolkit for AWS
&lt;/h2&gt;

&lt;p&gt;The quickest route is the AWS CLI wizard, which configures every agent you have at once. Prefer to do it by hand, or only use one editor? Skip to the per-agent steps below.&lt;/p&gt;

&lt;h3&gt;
  
  
  Set up every agent at once with the AWS CLI
&lt;/h3&gt;

&lt;p&gt;On a recent AWS CLI, one command detects your installed agents, installs default skills, and configures the MCP Server for all of them:&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 agent-toolkit
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One gotcha worth calling out, because I hit it. On an older CLI you'll see:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aws: [ERROR]: argument subcommand: Found invalid choice 'agent-toolkit'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That means your AWS CLI predates &lt;code&gt;2.35.0&lt;/code&gt;. Update it (&lt;a href="https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html" rel="noopener noreferrer"&gt;instructions&lt;/a&gt;), confirm with &lt;code&gt;aws --version&lt;/code&gt;, and rerun. Restart your agent afterward so it picks up the new MCP config.&lt;/p&gt;

&lt;p&gt;If you only use one agent, or you want to see exactly what gets wired up, the per-agent steps below do the same thing by hand.&lt;/p&gt;

&lt;h3&gt;
  
  
  Kiro
&lt;/h3&gt;

&lt;p&gt;Open your Kiro MCP config and add the AWS server. Use &lt;code&gt;.kiro/settings/mcp.json&lt;/code&gt; for the current project, or &lt;code&gt;~/.kiro/settings/mcp.json&lt;/code&gt; to turn it on everywhere. Create the file if it doesn't exist yet:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"mcpServers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"aws"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"uvx"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"args"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"mcp-proxy-for-aws@1.6.3"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"https://aws-mcp.us-east-1.api.aws/mcp"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"--metadata"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"AWS_REGION=us-west-2"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If your config already lists other servers under &lt;code&gt;mcpServers&lt;/code&gt;, add the &lt;code&gt;aws&lt;/code&gt; entry next to them instead of replacing the block, and keep the JSON valid (mind the commas). Change &lt;code&gt;AWS_REGION&lt;/code&gt; to the region you work in.&lt;/p&gt;

&lt;p&gt;Pin the proxy version rather than tracking latest. You get reproducible behavior and a guard against a bad release. Check &lt;a href="https://pypi.org/project/mcp-proxy-for-aws/" rel="noopener noreferrer"&gt;PyPI&lt;/a&gt; every few weeks and bump it on purpose.&lt;/p&gt;

&lt;p&gt;Then install the skills:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx skills add aws/agent-toolkit-for-aws/skills
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open Kiro's MCP Server view (the Kiro panel in the sidebar, or search "MCP" in the command palette), reconnect the &lt;code&gt;aws&lt;/code&gt; server, and you're live.&lt;/p&gt;

&lt;h3&gt;
  
  
  Codex
&lt;/h3&gt;

&lt;p&gt;Add the marketplace, then install from inside Codex:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;codex plugin marketplace add aws/agent-toolkit-for-aws
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Launch Codex, run &lt;code&gt;/plugins&lt;/code&gt;, and install &lt;code&gt;aws-core&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Claude Code
&lt;/h3&gt;

&lt;p&gt;The plugins live on the official Anthropic marketplace, included by default:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/plugin install aws-core@claude-plugins-official
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Hit &lt;code&gt;Plugin not found&lt;/code&gt;? Refresh the index with &lt;code&gt;/plugin marketplace update claude-plugins-official&lt;/code&gt; and try again. Add &lt;code&gt;aws-agents&lt;/code&gt;, &lt;code&gt;aws-data-analytics&lt;/code&gt;, or &lt;code&gt;aws-agents-for-devsecops&lt;/code&gt; the same way.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cursor
&lt;/h3&gt;

&lt;p&gt;Add the repo as a team marketplace: &lt;strong&gt;Settings → Plugins → Team Marketplaces → Add Marketplace → Import from Repo&lt;/strong&gt;, pointed at &lt;code&gt;aws/agent-toolkit-for-aws&lt;/code&gt;. Open the &lt;strong&gt;Plugins&lt;/strong&gt; panel and install &lt;code&gt;aws-core&lt;/code&gt; first, then the others as needed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Other agents (Windsurf, Cline, and more)
&lt;/h3&gt;

&lt;p&gt;Anything that speaks MCP works, including Windsurf and Cline. Configure the AWS MCP Server directly (see the &lt;a href="https://docs.aws.amazon.com/agent-toolkit/latest/userguide/getting-started-aws-mcp-server.html" rel="noopener noreferrer"&gt;server setup guide&lt;/a&gt;), then run &lt;code&gt;npx skills add aws/agent-toolkit-for-aws/skills&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  How do I check it's working?
&lt;/h2&gt;

&lt;p&gt;Start a fresh conversation and ask: &lt;em&gt;"What AWS Regions are available?"&lt;/em&gt; If the agent returns a list, the MCP Server is connected. For a skill check, ask it to "secure an S3 bucket" and watch it load &lt;code&gt;securing-s3-buckets&lt;/code&gt; before it writes anything. An authentication error instead means your local credentials aren't reaching the server; see Prerequisites for how to set them up.&lt;/p&gt;

&lt;h2&gt;
  
  
  Three workflows that show the payoff
&lt;/h2&gt;

&lt;p&gt;Setup is the boring part. The workflows below are where it pays off, and each one names the skills and components doing the work.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Stand up a serverless API, end to end
&lt;/h3&gt;

&lt;p&gt;Prompt: &lt;em&gt;"Build a REST API: API Gateway in front of a Lambda that reads and writes a DynamoDB table, deployed with CDK."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This is the kind of task agents usually botch, because it spans four services and the IAM glue between them. The agent pulls &lt;code&gt;aws-serverless&lt;/code&gt;, &lt;code&gt;connecting-lambda-to-api-gateway&lt;/code&gt;, &lt;code&gt;connecting-lambda-to-dynamodb&lt;/code&gt;, and &lt;code&gt;aws-cdk&lt;/code&gt;, then uses the MCP Server's API tools to provision and the &lt;code&gt;run_script&lt;/code&gt; sandbox for multi-step setup. The skills carry the wiring, so the Lambda role scopes to your specific table instead of granting access to everything (&lt;code&gt;*&lt;/code&gt;), and the CDK stack follows current patterns instead of a 2023 blog post the model half-remembers.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Troubleshoot a production issue you can't reproduce
&lt;/h3&gt;

&lt;p&gt;Prompt: &lt;em&gt;"My checkout Lambda times out intermittently and error rates spiked this morning. Help me find why."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Point the agent at the symptom and it follows a real diagnostic path. &lt;code&gt;debugging-lambda-timeouts&lt;/code&gt; and &lt;code&gt;troubleshooting-application-failures&lt;/code&gt; give it the procedure, while &lt;code&gt;aws-observability&lt;/code&gt; and &lt;code&gt;querying-aws-cloudwatch&lt;/code&gt; let it read the actual logs and metrics through the MCP Server. It checks the configured timeout against duration metrics, looks for cold starts, and inspects downstream calls that block, then tells you what it found. You get an actual investigation rather than a guess.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Hand an agent production access without losing sleep
&lt;/h3&gt;

&lt;p&gt;Prompt: &lt;em&gt;"Audit this account's S3 buckets and secrets, and flag anything risky."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This is the workflow that separates the toolkit from wiring up a raw MCP server. Before you run it, scope the agent's IAM role to read-only with the condition keys the MCP Server attaches, &lt;code&gt;aws:ViaAWSMCPService&lt;/code&gt; and &lt;code&gt;aws:CalledViaAWSMCP&lt;/code&gt;, so it can inspect and plan but cannot change anything, even though your own role can. Writing that policy is an advanced step, and the &lt;a href="https://docs.aws.amazon.com/agent-toolkit/latest/userguide/what-is-agent-toolkit.html" rel="noopener noreferrer"&gt;user guide&lt;/a&gt; explains how the condition keys fit in; you can skip it the first time through and still get value from the audit. The agent uses &lt;code&gt;securing-s3-buckets&lt;/code&gt; and &lt;code&gt;creating-secrets-using-best-practices&lt;/code&gt; as its rubric for what counts as risky, and every call lands in CloudTrail for you to review later.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to update and remove skills
&lt;/h2&gt;

&lt;p&gt;On AWS CLI &lt;code&gt;2.35.0+&lt;/code&gt;, the &lt;code&gt;aws agent-toolkit&lt;/code&gt; command group manages skills across all your agents from the 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 agent-toolkit list-installed-skills
aws agent-toolkit add-skill &lt;span class="nt"&gt;--skill-name&lt;/span&gt; aws-serverless
aws agent-toolkit update-skill &lt;span class="nt"&gt;--skill-name&lt;/span&gt; aws-serverless
aws agent-toolkit remove-skill &lt;span class="nt"&gt;--skill-name&lt;/span&gt; aws-cdk &lt;span class="nt"&gt;--agent&lt;/span&gt; kiro
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There's also &lt;code&gt;search-skills&lt;/code&gt;, &lt;code&gt;list-available-skills&lt;/code&gt;, and &lt;code&gt;get-skill-metadata&lt;/code&gt; for browsing the catalog from the terminal. Without the CLI, re-run &lt;code&gt;npx skills add aws/agent-toolkit-for-aws/skills&lt;/code&gt; to pull new skills, and remove them with &lt;code&gt;npx skills remove &amp;lt;skill-name&amp;gt;&lt;/code&gt;. The MCP Server itself is AWS-hosted, so its API coverage and docs stay current on their own. The one thing you pin and bump yourself is the proxy version in your config.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frequently asked questions
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Is the Agent Toolkit for AWS free?&lt;/strong&gt;&lt;br&gt;
Yes. The toolkit costs nothing to install or use. You pay only standard AWS rates for the resources your agent creates or calls.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Which AWS CLI version do I need for &lt;code&gt;aws configure agent-toolkit&lt;/code&gt;?&lt;/strong&gt;&lt;br&gt;
Version 2.35.0 or later. Older versions don't recognize the command and fail with &lt;code&gt;Found invalid choice 'agent-toolkit'&lt;/code&gt;. Check yours with &lt;code&gt;aws --version&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How do I fix "Found invalid choice 'agent-toolkit'"?&lt;/strong&gt;&lt;br&gt;
Upgrade the AWS CLI to 2.35.0 or later, since the command shipped in that release. On macOS with Homebrew, run &lt;code&gt;brew upgrade awscli&lt;/code&gt;, then confirm with &lt;code&gt;aws --version&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Do I need an AWS account and credentials?&lt;/strong&gt;&lt;br&gt;
Credentials are needed only for actions that touch your account, like API calls and &lt;code&gt;run_script&lt;/code&gt;. Documentation search and skill discovery work with no credentials. Anything that provisions or reads real resources needs an AWS account.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Which coding agents does it work with?&lt;/strong&gt;&lt;br&gt;
Kiro, Claude Code, Codex, and Cursor have first-class setups, and any MCP-compatible agent works too, including Windsurf and Cline. Plugins cover Claude Code, Codex, and Cursor; Kiro and the rest connect to the MCP server directly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How is it different from the AWS Labs MCP servers?&lt;/strong&gt;&lt;br&gt;
It's the successor to AWS Labs. The differences that matter: IAM condition keys that separate agent actions from human ones, CloudWatch and CloudTrail on every request, and skills evaluated end to end.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How do I give a coding agent read-only access to AWS?&lt;/strong&gt;&lt;br&gt;
Scope its IAM role with the condition keys the MCP server attaches, &lt;code&gt;aws:ViaAWSMCPService&lt;/code&gt; and &lt;code&gt;aws:CalledViaAWSMCP&lt;/code&gt;, to allow reads and deny writes. The agent can inspect and plan but not change anything, even when your own role can.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How do I update or remove skills?&lt;/strong&gt;&lt;br&gt;
On AWS CLI 2.35.0+, use &lt;code&gt;aws agent-toolkit update-skill&lt;/code&gt; and &lt;code&gt;aws agent-toolkit remove-skill&lt;/code&gt;. Otherwise re-run &lt;code&gt;npx skills add aws/agent-toolkit-for-aws/skills&lt;/code&gt; to update, and &lt;code&gt;npx skills remove &amp;lt;skill-name&amp;gt;&lt;/code&gt; to remove.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to try next
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Build the serverless API above, then ask the agent to add a CloudWatch alarm with &lt;code&gt;setting-up-cloudwatch-alarm-notifications&lt;/code&gt; and watch it connect the alarm to an SNS topic.&lt;/li&gt;
&lt;li&gt;Set up the read-only profile from workflow 3, hand it a real account, and confirm the agent can plan a change but not apply one. That's what makes me comfortable letting one near production.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/aws/agent-toolkit-for-aws" rel="noopener noreferrer"&gt;Agent Toolkit for AWS repo&lt;/a&gt;. The source, every skill, and the plugin definitions.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.aws.amazon.com/agent-toolkit/latest/userguide/what-is-agent-toolkit.html" rel="noopener noreferrer"&gt;What is the Agent Toolkit for AWS?&lt;/a&gt;. Components and capabilities.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.aws.amazon.com/agent-toolkit/latest/userguide/quick-start.html" rel="noopener noreferrer"&gt;Getting started&lt;/a&gt;. Install and verify.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.aws.amazon.com/agent-toolkit/latest/userguide/aws-cli.html" rel="noopener noreferrer"&gt;AWS CLI for the toolkit&lt;/a&gt;. The setup wizard and the skill commands.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.aws.amazon.com/agent-toolkit/latest/userguide/understanding-mcp-server-tools.html" rel="noopener noreferrer"&gt;AWS MCP Server tools&lt;/a&gt;. Every tool the server exposes.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  About the author
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Saurabh Dahal is a developer advocate at AWS, working with the latest agentic and AI tools for developers to help boost developer productivity. He set up the Agent Toolkit for AWS across Kiro, Codex, Claude Code, and Cursor for this guide.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Published June 30, 2026. Last updated June 30, 2026.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agentskills</category>
      <category>aws</category>
      <category>agents</category>
    </item>
    <item>
      <title>I Let My AI Agent Build a Bedrock RAG Knowledge Base, Here Are the 2 Mistakes the AWS Agent Toolkit Caught</title>
      <dc:creator>Saurabh "Rob" Dahal</dc:creator>
      <pubDate>Thu, 25 Jun 2026 18:29:01 +0000</pubDate>
      <link>https://dev.to/raabdahl/i-let-my-ai-agent-build-a-bedrock-rag-knowledge-base-here-are-the-2-mistakes-the-aws-agent-toolkit-3l49</link>
      <guid>https://dev.to/raabdahl/i-let-my-ai-agent-build-a-bedrock-rag-knowledge-base-here-are-the-2-mistakes-the-aws-agent-toolkit-3l49</guid>
      <description>&lt;p&gt;&lt;em&gt;Provisioning a Bedrock RAG knowledge base with S3 Vectors, without the hallucinated API calls.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If you've asked an AI coding agent to set up AWS, you've seen it confidently invent a parameter, reach for a deprecated service, or burn ten minutes retrying against a service it never saw in training. The failure mode that bites hardest is the silent one: the agent &lt;em&gt;thinks&lt;/em&gt; it succeeded, and you find out an hour later.&lt;/p&gt;

&lt;p&gt;I hit two of these while standing up the retrieval layer for a LangGraph support bot, an Amazon Bedrock Knowledge Base backed by Amazon S3 Vectors. I'd love to say I caught both with deep AWS expertise. I caught them because the &lt;a href="https://github.com/aws/agent-toolkit-for-aws" rel="noopener noreferrer"&gt;Agent Toolkit for AWS&lt;/a&gt; read the docs I hadn't. Both would have shipped, and neither did.&lt;/p&gt;

&lt;h2&gt;
  
  
  The 30-second setup
&lt;/h2&gt;

&lt;p&gt;The goal: take a folder of markdown product docs and make them queryable by meaning, so an agent can answer "is this safe for color-treated hair?" from the real docs instead of guessing. Think of it as giving the agent a library it can search instead of making things up. That's the &lt;em&gt;retrieval&lt;/em&gt; half of RAG, the foundation a LangGraph agent will later call as a tool.&lt;/p&gt;

&lt;p&gt;Four moving parts, wrapped in one managed service:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Source bucket&lt;/strong&gt;: an S3 bucket holding the docs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Embeddings&lt;/strong&gt;: Amazon Titan Text Embeddings V2 (1024-dim vectors).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Vector store&lt;/strong&gt;: Amazon S3 Vectors. I chose it over OpenSearch Serverless because it has no always-on compute, the difference between cents and a monthly surprise for a demo that sits idle.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Knowledge Base&lt;/strong&gt;: Amazon Bedrock Knowledge Bases ties it together into one thing you can query with a &lt;code&gt;retrieve&lt;/code&gt; call.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To follow along, you need an AWS account, a non-root IAM identity with credentials configured locally, &lt;a href="https://docs.astral.sh/uv/" rel="noopener noreferrer"&gt;uv&lt;/a&gt; installed, and the toolkit installed in your agent. The fastest path across Kiro, Claude Code, Cursor, and Codex is the AWS CLI installer, &lt;a href="https://aws.amazon.com/about-aws/whats-new/2026/06/aws-cli-agent-toolkit/" rel="noopener noreferrer"&gt;&lt;code&gt;aws configure agent-toolkit&lt;/code&gt;&lt;/a&gt;; in Kiro you can instead add the &lt;a href="https://aws.amazon.com/blogs/aws/the-aws-mcp-server-is-now-generally-available/" rel="noopener noreferrer"&gt;AWS MCP Server&lt;/a&gt; to &lt;code&gt;.kiro/settings/mcp.json&lt;/code&gt; (pin the &lt;a href="https://pypi.org/project/mcp-proxy-for-aws/" rel="noopener noreferrer"&gt;&lt;code&gt;mcp-proxy-for-aws&lt;/code&gt;&lt;/a&gt; version) and run &lt;code&gt;npx skills add aws/agent-toolkit-for-aws/skills&lt;/code&gt;. The toolkit plugs into the agent you already use and loads task-specific &lt;em&gt;skills&lt;/em&gt; on demand; I used the &lt;code&gt;amazon-bedrock&lt;/code&gt; skill, which carries the validated, current procedure for building a Knowledge Base. That word, "current," is the whole story.&lt;/p&gt;

&lt;h2&gt;
  
  
  Gotcha #1: the model id was already dead
&lt;/h2&gt;

&lt;p&gt;My first instinct, straight from an older tutorial, was &lt;code&gt;anthropic.claude-3-5-sonnet-20240620-v1:0&lt;/code&gt;. Calling it returned:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ResourceNotFoundException: This model version has reached the end of its life.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The fix the toolkit's doc search surfaced: current Anthropic models on Bedrock are &lt;strong&gt;inference-profile only&lt;/strong&gt;. You invoke them through a cross-region profile id like &lt;code&gt;us.anthropic.claude-sonnet-4-5-20250929-v1:0&lt;/code&gt;, not the bare on-demand id.&lt;/p&gt;

&lt;p&gt;On its own, an agent might not even diagnose this correctly. "Not found" reads like a permissions or region problem, so it could swap in another stale id and hit "on-demand throughput isn't supported" instead, flailing sideways. The toolkit got it right because it read the current model docs, not because it happened to remember them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Gotcha #2: Bedrock won't create the S3 Vectors index for you
&lt;/h2&gt;

&lt;p&gt;I created the vector bucket, pointed the Knowledge Base at an index name, and assumed Bedrock would create the index. It didn't:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ValidationException: The specified index could not be found (S3Vectors 404)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The real requirement, from the S3 Vectors docs: you create the index yourself, and it must declare two &lt;strong&gt;non-filterable metadata keys&lt;/strong&gt; that Bedrock uses to store chunk text and metadata. Miss them and ingestion fails later with a cryptic error far from the cause. The working command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws s3vectors create-index &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--vector-bucket-name&lt;/span&gt; &amp;lt;VECTOR_BUCKET&amp;gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--index-name&lt;/span&gt; &amp;lt;INDEX_NAME&amp;gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--data-type&lt;/span&gt; float32 &lt;span class="nt"&gt;--dimension&lt;/span&gt; 1024 &lt;span class="nt"&gt;--distance-metric&lt;/span&gt; cosine &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--metadata-configuration&lt;/span&gt; &lt;span class="s1"&gt;'{"nonFilterableMetadataKeys":["AMAZON_BEDROCK_TEXT","AMAZON_BEDROCK_METADATA"]}'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--region&lt;/span&gt; us-east-2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the one that best captures why current docs matter. S3 Vectors launched in 2025, so the requirement isn't in most models' training data. A toolkit-less agent would most likely create the index, &lt;em&gt;think it succeeded&lt;/em&gt;, and only hit the wall at ingestion time, then burn an afternoon recreating it with the wrong config. The dimension (1024) and distance metric here aren't arbitrary either: they have to match the Titan embedding model, which is the kind of cross-resource constraint an agent gets wrong when it's guessing.&lt;/p&gt;

&lt;h2&gt;
  
  
  The rest fell into place, and it works
&lt;/h2&gt;

&lt;p&gt;With those two out of the way, the validated sequence ran clean: create the IAM service role (trust &lt;code&gt;bedrock.amazonaws.com&lt;/code&gt; with confused-deputy conditions, so another customer can't trick the role into acting on their resources, plus least-privilege permissions to invoke Titan, read the bucket, and use the vector index), create the Knowledge Base, attach the S3 data source with fixed-size chunking (300 tokens, 20% overlap), and run ingestion. Result: 10/10 documents indexed, zero failures.&lt;/p&gt;

&lt;p&gt;The proof is a retrieval query:&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-agent-runtime retrieve &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--knowledge-base-id&lt;/span&gt; &amp;lt;KB_ID&amp;gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--retrieval-query&lt;/span&gt; &lt;span class="s1"&gt;'{"text":"Is the Curl Cream safe for color-treated hair?"}'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--region&lt;/span&gt; us-east-2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Top hit came back at &lt;strong&gt;0.86 similarity&lt;/strong&gt;, on the exact product doc with the right answer. The library is stocked.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it bought me, and what I'd do differently
&lt;/h2&gt;

&lt;p&gt;Strip away the demo and the toolkit changed two things: it handed the agent the validated setup &lt;em&gt;order&lt;/em&gt; up front (no trial-and-error), and it caught two mistakes a model trained months ago wouldn't know, because it checks current docs and ships procedures AWS maintains. AWS reports developers see fewer iterations and errors with it; on this build, the two catches alone saved me an afternoon.&lt;/p&gt;

&lt;p&gt;Two honest gaps. First, the toolkit's own rules recommend infrastructure-as-code over direct CLI, and I didn't follow that. I ran CLI calls and tracked them in a tagged manifest for teardown. It works, but CDK or CloudFormation would be the reproducible artifact a reader could clone. Second, I left the IAM role's trust policy scoped to &lt;code&gt;knowledge-base/*&lt;/code&gt; instead of the specific KB id; tightening that &lt;code&gt;aws:SourceArn&lt;/code&gt; is the obvious hardening step before this is anything but a demo.&lt;/p&gt;

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

&lt;p&gt;This is the retrieval foundation, not the whole app. Two concrete next steps, and you could take either:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Close the loop.&lt;/strong&gt; Wire a LangGraph agent to call this Knowledge Base as a tool, so it retrieves &lt;em&gt;and&lt;/em&gt; generates grounded answers. That's when "RAG knowledge base" graduates to "RAG application."&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Make it reproducible.&lt;/strong&gt; Convert the ad-hoc CLI provisioning into CDK or CloudFormation, so the whole stack stands up and tears down with one command, the way the toolkit's own rules recommend.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you take one thing: the toolkit's real value isn't typing commands for you, it's making better decisions, grounded in current docs, on the things an AI agent gets wrong in ways you don't notice until an hour later.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>ai</category>
      <category>agentskills</category>
      <category>bedrock</category>
    </item>
  </channel>
</rss>
