<?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: Kiran Manne</title>
    <description>The latest articles on DEV Community by Kiran Manne (@kiran_manne).</description>
    <link>https://dev.to/kiran_manne</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%2F4004581%2F8eb78e0a-8aef-415c-8a6a-a9375dd3ed73.jpg</url>
      <title>DEV Community: Kiran Manne</title>
      <link>https://dev.to/kiran_manne</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/kiran_manne"/>
    <language>en</language>
    <item>
      <title>Designing tools so an LLM actually calls them correctly: 5 patterns from the CCA-F blueprint</title>
      <dc:creator>Kiran Manne</dc:creator>
      <pubDate>Sun, 28 Jun 2026 23:00:00 +0000</pubDate>
      <link>https://dev.to/kiran_manne/designing-tools-so-an-llm-actually-calls-them-correctly-5-patterns-from-the-cca-f-blueprint-7li</link>
      <guid>https://dev.to/kiran_manne/designing-tools-so-an-llm-actually-calls-them-correctly-5-patterns-from-the-cca-f-blueprint-7li</guid>
      <description>&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gt"&gt;&amp;gt; **Update (July 2026):** the certification this maps to now runs on&lt;/span&gt;
&lt;span class="gt"&gt;&amp;gt; Pearson VUE as **CCAR-F** (formerly community-abbreviated CCA-F), with&lt;/span&gt;
&lt;span class="gt"&gt;&amp;gt; multiple-response items added. The Tool Design &amp;amp; MCP domain and its 18%&lt;/span&gt;
&lt;span class="gt"&gt;&amp;gt; weight are unchanged. Details: [CCAR-F vs CCA-F: what actually changed](https://claudecertifiedarchitect.dev/ccar-f-vs-cca-f).&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first time I shipped a tool-using agent, it kept calling the wrong tool. Not occasionally — often enough that I couldn't ship it. The tools worked. The schemas were valid. The descriptions were technically accurate. The model still picked the wrong one, over and over.&lt;/p&gt;

&lt;p&gt;What I learned, painfully, is that designing a tool for an LLM caller is closer to writing technical documentation than writing a function signature. The model is reading your tool definition as part of its decision about whether and how to invoke it. If the description is ambiguous, the model is going to guess — and you don't want that.&lt;/p&gt;

&lt;p&gt;This post walks through five patterns I now use by default, all of which map directly to material in the Tool Design &amp;amp; MCP domain of the Claude Certified Architect Foundations exam (which is, not coincidentally, the domain where a lot of strong backend engineers lose points).&lt;/p&gt;

&lt;h2&gt;
  
  
  Pattern 1: Treat the tool description as a prompt, not a docstring
&lt;/h2&gt;

&lt;p&gt;The most common anti-pattern: writing the tool description the way you'd write a Python docstring.&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;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"get_user"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Returns the user object for a given user ID."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"input_schema"&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;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"object"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"properties"&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;"user_id"&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;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"required"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"user_id"&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;That description tells the model &lt;em&gt;what the tool does&lt;/em&gt;. It does not tell the model &lt;em&gt;when to call it&lt;/em&gt;, &lt;em&gt;when not to call it&lt;/em&gt;, or &lt;em&gt;what "user object" actually contains&lt;/em&gt;. So the model has to guess.&lt;/p&gt;

&lt;p&gt;The rewrite:&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;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"get_user"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Fetch a user's profile (name, email, plan tier, signup date) by their internal user ID. Use this when the user is asking about a specific account and you have a user ID. Do NOT use this for email-based lookups — use lookup_user_by_email instead. Returns null if the user does not exist; does not raise."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"input_schema"&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="err"&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;The rewrite answers four questions the model would otherwise guess at: what's in the response, when to use it, when not to use it, and what happens on the unhappy path. That's the bar.&lt;/p&gt;

&lt;p&gt;Heuristic: if your tool description doesn't contain the word "when", it's probably not finished.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pattern 2: Tighten the schema until ambiguity is impossible
&lt;/h2&gt;

&lt;p&gt;LLMs are excellent at producing plausible-looking arguments. They are less excellent at producing &lt;em&gt;correct&lt;/em&gt; arguments when the schema admits ambiguity.&lt;/p&gt;

&lt;p&gt;A loose schema:&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;"properties"&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;"status"&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;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"string"&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;"priority"&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;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"string"&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;"date"&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;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"string"&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;The tightened version:&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;"properties"&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;"status"&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;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"enum"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"open"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"in_progress"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"closed"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Current status of the ticket."&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;"priority"&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;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"integer"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"minimum"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"maximum"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1 = urgent, 4 = low. Default to 3 if unspecified."&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;"date"&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;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"format"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"date"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ISO 8601 date (YYYY-MM-DD), in UTC."&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;Three changes, each of which removes a class of failure:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;status&lt;/code&gt; is now an enum. The model can't invent &lt;code&gt;"pending"&lt;/code&gt; or &lt;code&gt;"new"&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;priority&lt;/code&gt; has a documented scale and a documented default. The model isn't guessing whether 1 or 4 is higher priority.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;date&lt;/code&gt; has a format and a timezone convention. The model isn't deciding whether to write &lt;code&gt;"tomorrow"&lt;/code&gt; or &lt;code&gt;"2026-05-30"&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Every time you let the model improvise on a string field, you're paying for that improvisation in tail latency and bug reports.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pattern 3: Make errors teach
&lt;/h2&gt;

&lt;p&gt;This is the single pattern that made the biggest difference to my own agent's reliability, and I think it's badly underrated.&lt;/p&gt;

&lt;p&gt;When a tool fails, the model will see the result as part of the next turn's context. If your error is uninformative, the model has nothing to act on. If your error is structured and instructive, the model can recover on its own — no retry logic, no human in the loop.&lt;/p&gt;

&lt;p&gt;Bad:&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;"error"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"bad input"&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;Better:&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;"error"&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;"code"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"USER_NOT_FOUND"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"No user exists with id 'usr_9k2x'."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"hint"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"If you only have an email address, call lookup_user_by_email instead."&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;The &lt;code&gt;hint&lt;/code&gt; field is the one that earns its keep. It turns the tool's error path into a redirect. The model reads the hint, calls the right tool on the next turn, and the agent loop closes successfully without the user ever seeing the failure.&lt;/p&gt;

&lt;p&gt;A good rule: every error your tool returns should answer the question "what should the model do differently next time?"&lt;/p&gt;

&lt;h2&gt;
  
  
  Pattern 4: One tool, one job
&lt;/h2&gt;

&lt;p&gt;There is a strong temptation, especially if you've written REST APIs, to design a single tool with a &lt;code&gt;mode&lt;/code&gt; or &lt;code&gt;action&lt;/code&gt; parameter that switches behavior:&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;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"manage_ticket"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Create, update, close, or reopen a ticket."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"input_schema"&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;"properties"&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;"action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"enum"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"create"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"update"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"close"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"reopen"&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;"ticket_id"&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;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"string"&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;"title"&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;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"string"&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;"body"&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;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"string"&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;This looks elegant. It is, in practice, worse than four separate tools.&lt;/p&gt;

&lt;p&gt;Reasons:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The model has to reason about which fields are required for which action. &lt;code&gt;ticket_id&lt;/code&gt; is required for update/close/reopen but not create. The schema can't enforce that without &lt;code&gt;oneOf&lt;/code&gt;, and even with &lt;code&gt;oneOf&lt;/code&gt;, the model's adherence rate drops.&lt;/li&gt;
&lt;li&gt;The description has to cover four behaviors, which dilutes the "when to use" signal.&lt;/li&gt;
&lt;li&gt;Error messages become generic. &lt;code&gt;"missing required field"&lt;/code&gt; is less useful than &lt;code&gt;"close_ticket requires ticket_id"&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The rewrite is four tools: &lt;code&gt;create_ticket&lt;/code&gt;, &lt;code&gt;update_ticket&lt;/code&gt;, &lt;code&gt;close_ticket&lt;/code&gt;, &lt;code&gt;reopen_ticket&lt;/code&gt;. Each has a focused description, a tight schema, and instructive errors. The model picks correctly more often, and when it doesn't, the failure is local to one tool, not the whole multiplexer.&lt;/p&gt;

&lt;p&gt;The exception: if you have genuinely dozens of near-identical operations (CRUD over hundreds of resource types), at some point a parameterized tool wins on context window cost. That tradeoff is real, but it shows up later than people think.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pattern 5: Design for parallel calls, not just sequential ones
&lt;/h2&gt;

&lt;p&gt;When the model emits multiple &lt;code&gt;tool_use&lt;/code&gt; blocks in a single turn, the runtime executes them in parallel and returns all results before the next model call. This is the agent loop's most underrated feature, and it's the one most tool designs accidentally break.&lt;/p&gt;

&lt;p&gt;A tool is parallel-safe when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It is idempotent, or at least non-destructive when called once.&lt;/li&gt;
&lt;li&gt;It does not depend on state mutated by another tool call in the same turn.&lt;/li&gt;
&lt;li&gt;Its result is interpretable without reference to other concurrent results.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A tool is &lt;em&gt;not&lt;/em&gt; parallel-safe when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It mutates shared state (counters, queues, locks).&lt;/li&gt;
&lt;li&gt;It depends on a previous call's output as input.&lt;/li&gt;
&lt;li&gt;It returns results that are only meaningful in a specific ordering.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you have tools that aren't parallel-safe, document that explicitly in the description: &lt;code&gt;"This tool must be called after fetch_session and not in parallel with other write operations."&lt;/code&gt; The model will respect that.&lt;/p&gt;

&lt;p&gt;The deeper point: when you design a new tool, ask yourself "what happens if the model calls this twice in the same turn?" If the answer is "undefined behavior", you have more work to do.&lt;/p&gt;

&lt;h2&gt;
  
  
  A short MCP note
&lt;/h2&gt;

&lt;p&gt;If you're exposing tools through the Model Context Protocol (MCP), all five patterns still apply — the protocol just standardizes how the host discovers and invokes them. MCP adds two adjacent primitives worth knowing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Resources&lt;/strong&gt; are read-only, addressable content (a file, a database row, a URL). The model can reference them by URI.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prompts&lt;/strong&gt; are reusable, parameterized templates the host can offer to the user.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The practical implication: if your tool is fundamentally "give me the content of X", it might want to be a resource, not a tool. Resources are cheaper to expose, easier to cache, and don't burn an agent-loop turn to read.&lt;/p&gt;

&lt;h2&gt;
  
  
  Closing
&lt;/h2&gt;

&lt;p&gt;Most "the model called the wrong tool" bugs are not model bugs. They're tool design bugs surfaced by the model's willingness to guess when the design is ambiguous. The five patterns above — descriptions that say &lt;em&gt;when&lt;/em&gt;, tight schemas, instructive errors, narrow tools, and parallel-safety — close the ambiguity gaps that LLMs are most likely to fall into.&lt;/p&gt;

&lt;p&gt;If you're studying for the Claude Certified Architect Foundations exam, the Tool Design &amp;amp; MCP domain (18% of the blueprint) is heavy on scenario questions that test exactly these tradeoffs. The independent practice platform I run at &lt;a href="https://claudecertifiedarchitect.dev" rel="noopener noreferrer"&gt;claudecertifiedarchitect.dev&lt;/a&gt; has a free 15-question set — a few of them in this domain — if you want to calibrate where you currently stand. It emails you a diagnostic at the end; no payment to try it.&lt;/p&gt;

&lt;p&gt;Not affiliated with Anthropic; just a thing I built because I wanted blueprint-weighted practice that didn't exist yet.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>architecture</category>
      <category>claude</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>A 6-week study plan for the Claude Certified Architect Foundations exam, based on the published blueprint</title>
      <dc:creator>Kiran Manne</dc:creator>
      <pubDate>Fri, 26 Jun 2026 22:32:33 +0000</pubDate>
      <link>https://dev.to/kiran_manne/a-6-week-study-plan-for-the-claude-certified-architect-foundations-exam-based-on-the-published-588n</link>
      <guid>https://dev.to/kiran_manne/a-6-week-study-plan-for-the-claude-certified-architect-foundations-exam-based-on-the-published-588n</guid>
      <description>&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gt"&gt;&amp;gt; **Update (July 2026):** the exam moved to Pearson VUE under its official&lt;/span&gt;
&lt;span class="gt"&gt;&amp;gt; code **CCAR-F** — "CCA-F" was always the community abbreviation — and now&lt;/span&gt;
&lt;span class="gt"&gt;&amp;gt; mixes multiple-choice with **multiple-response** items ("select TWO").&lt;/span&gt;
&lt;span class="gt"&gt;&amp;gt; The blueprint this plan is built on is unchanged, so the plan still works&lt;/span&gt;
&lt;span class="gt"&gt;&amp;gt; as written; just add multiple-response drills in weeks 5–6. Full&lt;/span&gt;
&lt;span class="gt"&gt;&amp;gt; before-and-after: [CCAR-F vs CCA-F: what actually changed](https://claudecertifiedarchitect.dev/ccar-f-vs-cca-f).&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When I started preparing for the Claude Certified Architect Foundations (CCA-F) exam, the first thing that surprised me was how many people were studying for it the way you'd study for a generic LLM cert: heavy on prompt engineering tricks, light on the actual architecture material.&lt;/p&gt;

&lt;p&gt;The published blueprint tells a different story. If you let the weights drive your hours instead of your comfort zone, you end up with a very different study plan than the one most candidates are running.&lt;/p&gt;

&lt;p&gt;This is the plan I'd give myself if I were starting over. It's six weeks, roughly 6–8 hours per week, and it's organized around the actual blueprint, not vibes.&lt;/p&gt;

&lt;h2&gt;
  
  
  The blueprint, before anything else
&lt;/h2&gt;

&lt;p&gt;The CCA-F is a 60-question, 120-minute exam. Scoring is scaled 100–1000, with 720 to pass. The blueprint is split across five domains:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Agentic Architecture — 27%&lt;/li&gt;
&lt;li&gt;Claude Code — 20%&lt;/li&gt;
&lt;li&gt;Prompt Engineering — 20%&lt;/li&gt;
&lt;li&gt;Tool Design &amp;amp; MCP — 18%&lt;/li&gt;
&lt;li&gt;Context Management — 15%&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The single most useful thing I can tell you is this: &lt;strong&gt;Agentic Architecture is the largest domain, and it's the one most engineers under-prepare on.&lt;/strong&gt; Prompt Engineering feels familiar, so it absorbs disproportionate study time. Agentic Architecture feels abstract, so it gets skipped until the last week. Reverse that instinct.&lt;/p&gt;

&lt;p&gt;A quick sanity check on hour allocation across six weeks at ~7 hours/week (42 hours total):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Agentic Architecture: ~11 hours&lt;/li&gt;
&lt;li&gt;Claude Code: ~8 hours&lt;/li&gt;
&lt;li&gt;Prompt Engineering: ~8 hours&lt;/li&gt;
&lt;li&gt;Tool Design &amp;amp; MCP: ~8 hours&lt;/li&gt;
&lt;li&gt;Context Management: ~6 hours&lt;/li&gt;
&lt;li&gt;Mock exams and review: built into weeks 5–6&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now the week-by-week plan.&lt;/p&gt;

&lt;h2&gt;
  
  
  Week 1 — Agentic Architecture, part 1
&lt;/h2&gt;

&lt;p&gt;Goal: stop thinking about Claude as a chat completion endpoint.&lt;/p&gt;

&lt;p&gt;The core mental model you need is the &lt;strong&gt;agent loop&lt;/strong&gt;: the model emits a response, the runtime inspects &lt;code&gt;stop_reason&lt;/code&gt;, dispatches tool calls if needed, appends results back into the conversation, and re-invokes the model. That loop is the unit of work the exam tests, not the single API call.&lt;/p&gt;

&lt;p&gt;Things to be solid on by end of week 1:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The four common values of &lt;code&gt;stop_reason&lt;/code&gt; (&lt;code&gt;end_turn&lt;/code&gt;, &lt;code&gt;tool_use&lt;/code&gt;, &lt;code&gt;max_tokens&lt;/code&gt;, &lt;code&gt;stop_sequence&lt;/code&gt;) and what the orchestrator should do in response to each one.&lt;/li&gt;
&lt;li&gt;The difference between a single-turn tool-use request and a multi-turn agentic loop.&lt;/li&gt;
&lt;li&gt;Why you append &lt;code&gt;tool_result&lt;/code&gt; blocks to the conversation history rather than re-prompting from scratch.&lt;/li&gt;
&lt;li&gt;When to terminate the loop (budget, max iterations, &lt;code&gt;end_turn&lt;/code&gt;, explicit user interrupt).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A useful exercise: sketch the pseudocode for an agent loop on paper, without looking. If you can't write the &lt;code&gt;while&lt;/code&gt; loop and the &lt;code&gt;stop_reason&lt;/code&gt; branches from memory, you're not ready to move on.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;history&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;max_tokens&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;4096&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;history&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;assistant&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stop_reason&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;end_turn&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;break&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stop_reason&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tool_use&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;tool_results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;run_tools&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;history&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;tool_results&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
        &lt;span class="k"&gt;continue&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stop_reason&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;max_tokens&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# decide: continue, summarize, or fail
&lt;/span&gt;        &lt;span class="k"&gt;break&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That snippet is the spine of half the Agentic Architecture domain.&lt;/p&gt;

&lt;h2&gt;
  
  
  Week 2 — Agentic Architecture, part 2 + Context Management
&lt;/h2&gt;

&lt;p&gt;Now layer on the failure modes the exam loves to ask about.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Runaway loops.&lt;/strong&gt; What stops a model from calling the same tool 40 times? You need a story for max iterations, budget guards, and idempotency.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Subagents and orchestrators.&lt;/strong&gt; When does it make sense to spawn a subagent vs. continue in the same context? What does the orchestrator own that the subagent doesn't?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Parallel vs. sequential tool calls.&lt;/strong&gt; When the model emits multiple &lt;code&gt;tool_use&lt;/code&gt; blocks in one turn, the runtime executes them in parallel and returns all results before the next model call.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then pivot into Context Management, which is the smallest domain (15%) but heavily intertwined with Agentic Architecture. Focus on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The structure of the context window (system, conversation history, tool definitions, tool results).&lt;/li&gt;
&lt;li&gt;Strategies for long-running agents: summarization checkpoints, scratchpads, external memory, retrieval-augmented context.&lt;/li&gt;
&lt;li&gt;The cost of context bloat — both literal dollars and quality degradation.&lt;/li&gt;
&lt;li&gt;Caching: what's eligible, what isn't, and the prefix-stability rule that makes it actually work.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Week 3 — Tool Design &amp;amp; MCP
&lt;/h2&gt;

&lt;p&gt;This is the domain where engineers with strong backend backgrounds tend to overestimate themselves.&lt;/p&gt;

&lt;p&gt;The trap: you already know how to write a good function signature for a human caller. Writing a good function signature for an LLM caller is a different discipline. The model is reading your description as part of its decision about whether and how to invoke the tool.&lt;/p&gt;

&lt;p&gt;Key things to internalize:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Tool descriptions are prompts.&lt;/strong&gt; They should describe &lt;em&gt;when&lt;/em&gt; to use the tool, not just &lt;em&gt;what&lt;/em&gt; it does.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Parameter schemas should be tight.&lt;/strong&gt; Enums beat free-text strings. Required fields should actually be required. Defaults should be documented.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Error returns are part of the interface.&lt;/strong&gt; A tool that returns &lt;code&gt;"error: bad input"&lt;/code&gt; as a string teaches the model nothing. A tool that returns a structured error with a &lt;code&gt;code&lt;/code&gt; and a &lt;code&gt;hint&lt;/code&gt; lets the model self-correct.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;One tool, one job.&lt;/strong&gt; A &lt;code&gt;do_everything&lt;/code&gt; tool with a &lt;code&gt;mode&lt;/code&gt; parameter is almost always worse than three narrow tools.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;MCP&lt;/strong&gt; is the protocol layer: how tools, resources, and prompts are exposed to a host. Know the difference between a tool, a resource, and a prompt in MCP terms — that distinction shows up in scenario questions.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you only do one exercise this week: take a tool you'd normally write for a REST client, and rewrite the schema and description as if the caller were an LLM that has never seen your codebase.&lt;/p&gt;

&lt;h2&gt;
  
  
  Week 4 — Claude Code + Prompt Engineering
&lt;/h2&gt;

&lt;p&gt;Claude Code is 20% of the exam and it's the most concrete domain. Things to be comfortable with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The agent loop as it appears inside Claude Code specifically (tool use, file edits, bash, subagents).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;CLAUDE.md&lt;/code&gt; files and how project-level instructions compose with user-level instructions.&lt;/li&gt;
&lt;li&gt;Skills, plans, and how Claude Code structures multi-step work.&lt;/li&gt;
&lt;li&gt;Hooks and permissions — what the runtime executes vs. what the model proposes.&lt;/li&gt;
&lt;li&gt;Headless mode and the difference between interactive and scripted use.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Prompt Engineering, also 20%, is the domain where most candidates over-prepare. You don't need clever jailbreaks or 50 prompt patterns. You need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;System prompts vs. user prompts and what belongs in each.&lt;/li&gt;
&lt;li&gt;Structured output: when to ask for JSON, when to use tool use as a forcing function instead.&lt;/li&gt;
&lt;li&gt;Few-shot examples and when they hurt more than they help.&lt;/li&gt;
&lt;li&gt;Chain-of-thought and extended thinking — what the difference actually is and when each is appropriate.&lt;/li&gt;
&lt;li&gt;XML-style tag conventions Anthropic recommends for delimiting input sections.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The exam is not asking you to write clever prompts. It's asking you to choose the right prompting strategy for a given scenario.&lt;/p&gt;

&lt;h2&gt;
  
  
  Week 5 — First full mock + targeted remediation
&lt;/h2&gt;

&lt;p&gt;Take a full 60-question, 120-minute timed simulation under exam conditions. No notes, no Claude open in another tab. Then score it by domain.&lt;/p&gt;

&lt;p&gt;The pattern you're looking for is not your overall score. It's your &lt;strong&gt;lowest-scoring domain weighted by blueprint percentage&lt;/strong&gt;. A 60% in Agentic Architecture costs you more points than a 60% in Context Management.&lt;/p&gt;

&lt;p&gt;Spend the rest of the week drilling whichever domain has the worst weighted gap. Don't review what you already know.&lt;/p&gt;

&lt;h2&gt;
  
  
  Week 6 — Second mock + light review
&lt;/h2&gt;

&lt;p&gt;Take a second full mock early in the week. Compare to week 5. If your weighted-worst domain hasn't moved, that's where the remaining hours go.&lt;/p&gt;

&lt;p&gt;The last two days should be light. Re-read your own notes, not new material. Sleep more than you study.&lt;/p&gt;

&lt;h2&gt;
  
  
  A few things I wish I'd known earlier
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The exam rewards orchestration thinking, not API recall.&lt;/strong&gt; You will rarely be asked to recite a parameter name. You will frequently be asked to choose between two valid-looking architectures.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Read the scenario stem twice before reading the options.&lt;/strong&gt; The options are designed to be plausible. The stem usually contains the constraint that makes only one of them correct.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;"All of the above" and "none of the above" rarely appear.&lt;/strong&gt; When two options seem equally right, you've missed a constraint in the stem.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Time pressure is real.&lt;/strong&gt; 60 questions in 120 minutes is two minutes per question, including re-reads. Practice with a clock.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you want to drill against blueprint-weighted scenarios while you work through this plan, the practice platform I maintain at &lt;a href="https://claudecertifiedarchitect.dev" rel="noopener noreferrer"&gt;claudecertifiedarchitect.dev&lt;/a&gt; has a free 15-question set across the five domains (it emails you a diagnostic at the end). It's independent and not affiliated with Anthropic, but the question distribution mirrors the official blueprint, which is the thing that matters most for calibration. The full bank is 1,000+ questions, $24.99 one-time.&lt;/p&gt;

&lt;p&gt;Good luck. Study the weights, not your comfort zone.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>ccaf</category>
      <category>career</category>
      <category>claude</category>
    </item>
  </channel>
</rss>
