<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Anthropic on PHP Boy Scout</title><link>https://phpboyscout.uk/tags/anthropic/</link><description>Recent content in Anthropic on PHP Boy Scout</description><generator>Hugo -- gohugo.io</generator><language>en-gb</language><copyright>Matt Cockayne</copyright><lastBuildDate>Sat, 13 Jun 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://phpboyscout.uk/tags/anthropic/index.xml" rel="self" type="application/rss+xml"/><item><title>They switched it off while it was fixing my code</title><link>https://phpboyscout.uk/they-switched-it-off-while-it-was-fixing-my-code/</link><pubDate>Sat, 13 Jun 2026 00:00:00 +0000</pubDate><guid>https://phpboyscout.uk/they-switched-it-off-while-it-was-fixing-my-code/</guid><description>&lt;img src="https://phpboyscout.uk/they-switched-it-off-while-it-was-fixing-my-code/cover-switched-it-off-while-it-was-fixing-my-code.png" alt="Featured image of post They switched it off while it was fixing my code" /&gt;&lt;p&gt;I woke up this morning to a one-line message from my own tooling:&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;Claude Fable 5 is currently unavailable. Learn more: &lt;a class="link" href="https://www.anthropic.com/news/fable-mythos-access" target="_blank" rel="noopener"
 &gt;https://www.anthropic.com/news/fable-mythos-access&lt;/a&gt;&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;p&gt;I followed the link expecting a status page about a wobble in someone&amp;rsquo;s data centre. Instead it was Anthropic, explaining that the evening before, at 5:21pm Eastern, the US government had ordered them to suspend all access to Fable 5 and Mythos 5 on national security grounds. Globally. Every user. Their own staff included.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;d spent the previous day with Fable doing one very specific thing: pointing it at my own codebase and asking it to read the code and fix the flaws it found. That, very nearly word for word, is the thing it has now been banned for.&lt;/p&gt;
&lt;h2 id="three-days-late-to-the-only-model-that-mattered"&gt;Three days late to the only model that mattered
&lt;/h2&gt;&lt;p&gt;Fable came out on the 9th. I didn&amp;rsquo;t get to it properly until the 12th, which is the sort of timing I specialise in. By the time I sat down with it, I had about a day of real use before it vanished. One day to form a view on what people were calling the most capable coding model anyone had shipped. So treat everything below as the read of a man who got three days&amp;rsquo; notice and used one of them.&lt;/p&gt;
&lt;p&gt;What I had it doing was unsexy and exactly the kind of work I care about: a full security audit of &lt;a class="link" href="https://gitlab.com/phpboyscout/go-tool-base" target="_blank" rel="noopener"
 &gt;go-tool-base&lt;/a&gt;, the same &amp;ldquo;leave the codebase better than you found it&amp;rdquo; pass I&amp;rsquo;d normally run myself. Find the flaws, then start fixing them.&lt;/p&gt;
&lt;p&gt;And it was good. Genuinely good. It surfaced issues that previous passes with Opus had walked straight past, and in a couple of cases the flaw was sitting in code that Opus itself had written. There is something bracing about one model quietly marking another&amp;rsquo;s homework, and being right.&lt;/p&gt;
&lt;h2 id="good-but-lets-not-get-carried-away"&gt;Good, but let&amp;rsquo;s not get carried away
&lt;/h2&gt;&lt;p&gt;Here is where I have to be fair, because the anger that came later is only worth anything if the praise before it is honest.&lt;/p&gt;
&lt;p&gt;Fable is not magic. The class of bug it found is not some exotic thing only it can see. Plenty of models, from plenty of providers, are perfectly capable of reading a codebase and pulling out the same problems, and there is a mountain of evidence that they do, every day. Anthropic say as much themselves: the capability is &amp;ldquo;widely available from other models (including OpenAI&amp;rsquo;s GPT-5.5)&amp;rdquo; and &amp;ldquo;is used every day by the defenders who keep systems safe.&amp;rdquo; I&amp;rsquo;d already arrived at that conclusion from my own keyboard before I read their statement. Fable was excellent. It was not unique. Hold that thought, because the whole argument turns on it.&lt;/p&gt;
&lt;h2 id="it-kept-slipping-out-of-my-hands"&gt;It kept slipping out of my hands
&lt;/h2&gt;&lt;p&gt;The other thing I learned in my one day is that having Fable and using Fable were not the same thing.&lt;/p&gt;
&lt;p&gt;I set my main working thread to Fable and got on with it. What I didn&amp;rsquo;t know, because nothing on screen told me, is that partway through the evening it had quietly handed me back to Opus. The only reason I know now is that the session log records it in black and white:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2026-06-12T06:57:22Z {&amp;#34;type&amp;#34;:&amp;#34;fallback&amp;#34;,&amp;#34;from&amp;#34;:{&amp;#34;model&amp;#34;:&amp;#34;claude-fable-5&amp;#34;},&amp;#34;to&amp;#34;:{&amp;#34;model&amp;#34;:&amp;#34;claude-opus-4-8&amp;#34;}}
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;2026-06-12T18:50:08Z {&amp;#34;type&amp;#34;:&amp;#34;fallback&amp;#34;,&amp;#34;from&amp;#34;:{&amp;#34;model&amp;#34;:&amp;#34;claude-fable-5&amp;#34;},&amp;#34;to&amp;#34;:{&amp;#34;model&amp;#34;:&amp;#34;claude-opus-4-8&amp;#34;}}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;A whole evening of work I thought I was doing on Fable was, in fact, Opus wearing Fable&amp;rsquo;s badge. The audit itself launched on the wrong model first; I only caught it because I happened to be watching the workflow panel, killed it, and relaunched it on Fable, where it chewed through an entire five-hour quota in about forty minutes, then spent $50 of usage credits I&amp;rsquo;d been saving in about five more. Even the run that worked was visibly flaky: of the 282 little agents that audit fanned out into, well over half failed outright and had to be retried.&lt;/p&gt;
&lt;p&gt;Then, in the small hours, it started refusing entirely. My tooling caught the moment before I did:&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;Now failing instantly. Fable appears to be temporarily unavailable for subagents (the first three succeeded). The user explicitly required Fable, so I won&amp;rsquo;t downgrade&amp;hellip; rather than silently switch models.&lt;/p&gt;

 &lt;/blockquote&gt;
&lt;p&gt;It managed three of the fixes before it went, each one green on tests, the race detector and the linter. Three real improvements to my code, written by Fable, sitting in my git history. The other three were finished by Opus, because by morning there was nothing left to finish them with.&lt;/p&gt;
&lt;h2 id="capable-and-almost-impossible-to-build-on"&gt;Capable, and almost impossible to build on
&lt;/h2&gt;&lt;p&gt;There was a second wall, and I hit it before any of this, on the day Fable launched, when I tried to make it go-tool-base&amp;rsquo;s default model.&lt;/p&gt;
&lt;p&gt;Most of what you build on top of a model isn&amp;rsquo;t a chat window. You need it to hand your code an answer in a fixed shape, the same fields in the same places every time, so the program on the other end can rely on what comes back. The usual way to guarantee that is to force the model&amp;rsquo;s hand: you don&amp;rsquo;t ask politely for the structure and hope, you require it, so a wrong-shaped answer fails outright instead of quietly slipping through.&lt;/p&gt;
&lt;p&gt;Fable won&amp;rsquo;t be forced. Ask it to commit to a guaranteed structure and it declines, flat out. As I understand it the reasoning is a safety one: letting anyone compel a model into a precise, mandated output is itself a lever, a way to march it toward saying something it shouldn&amp;rsquo;t. Reasonable enough on paper. In practice it meant the most capable model I&amp;rsquo;d touched couldn&amp;rsquo;t drive the structured parts of my own tool, and by that first afternoon I&amp;rsquo;d quietly set the default back to Opus. It was the same refusal, I realised later, that had collapsed half of that audit&amp;rsquo;s agents.&lt;/p&gt;
&lt;p&gt;And it is not a niche complaint. Guaranteed structure is a hard requirement for a vast swathe of what people are actually building on these models. Not everyone is making another Claude Code. Plenty of us are wiring models into systems that have to get a clean, predictable contract back every single time, and a model that reserves the right to freestyle the shape of its answer is one you simply cannot put in that seat.&lt;/p&gt;
&lt;h2 id="the-part-they-banned-is-my-bread-and-butter"&gt;The part they banned is my bread and butter
&lt;/h2&gt;&lt;p&gt;So let&amp;rsquo;s be precise about what got pulled, because the precision is the whole point.&lt;/p&gt;
&lt;p&gt;Anthropic describe the government&amp;rsquo;s concern as &amp;ldquo;a narrow potential jailbreak, which essentially consists of asking the model to read a specific codebase and fix any software flaws.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;Read that again. Reading a codebase and fixing its flaws. That is not some dark-web misuse I have to strain to imagine. That is my bread and butter, the literal, boring, defensive job I had Fable doing in the open, on my own project, when the shutters came down.&lt;/p&gt;
&lt;p&gt;And here is where that earlier point earns its keep. If the banned capability were unique to Fable, you could at least follow the logic, however much you disagreed. But it isn&amp;rsquo;t, and it isn&amp;rsquo;t even close: give Opus enough time, enough budget and a patient enough hand on the prompts, and it would get to most of the same findings in the end. Fable just did it more efficiently, a difference of degree, not of kind. So banning one company&amp;rsquo;s model, for something every competitor ships and every blue team already relies on, makes precisely nobody safer. The exploit-writers keep their tools. The defenders lose one of theirs.&lt;/p&gt;
&lt;p&gt;When the thing you have banned is available everywhere else, the ban has stopped being about safety. It is theatre. And given who is currently in charge of the theatre, it has the distinct whiff of a knee-jerk reaction, dressed as a national security triumph, by people who do not appear to understand the tool they are confiscating.&lt;/p&gt;
&lt;h2 id="who-im-not-angry-at"&gt;Who I&amp;rsquo;m not angry at
&lt;/h2&gt;&lt;p&gt;I want to be careful where I point this, because it would be lazy to spray it around.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m not angry at Anthropic. They put Fable through more than a thousand hours of external testing, with US government agencies and the UK&amp;rsquo;s AI Safety Institute among the people kicking the tyres, before it ever reached me. They satisfied every requirement put in front of them, and when the order came they complied under protest while saying, plainly, that applying this standard across the board &amp;ldquo;would essentially halt all new model deployments for all frontier model providers.&amp;rdquo; I&amp;rsquo;m a daily Claude user and an advocate for the work, and I am not going to hang the US administration&amp;rsquo;s decision around the neck of the company that did the diligence and then got told to switch the lights off anyway.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ll allow them one small dig, and there was nothing quiet about it. Moving Fable behind a paywall on the 22nd was openly announced and planned well ahead, and the free window was never charity. It was a taster: a few days of the new addiction on the house, enough to hook the punters, before the price went up. That is a bit of a dick move, however neatly it tests in a spreadsheet. Moot now, mind, with no model left to charge for.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ll even grant the other side its strongest point. A government looking at agentic systems that can chain reconnaissance into working exploits has something real to be twitchy about. I get the worry. I just don&amp;rsquo;t accept that yanking one vendor&amp;rsquo;s model, for a thing every vendor does, is a coherent answer to it.&lt;/p&gt;
&lt;p&gt;There is a grim irony in how we got here, and it loops back to something I wrote in the spring. When Anthropic first showed Mythos off, I &lt;a class="link" href="https://phpboyscout.uk/ai-didnt-kill-curls-bug-bounty/" &gt;called the fanfare what it looked like&lt;/a&gt;: a closed model sold on a press release, a result you couldn&amp;rsquo;t independently check, marketing until proven otherwise. Fable 5 was Anthropic finally answering that, handing the rest of us something we could actually test. But all those years of selling Mythos as too dangerous to let out were marketing too, and that half landed rather better than they can have wanted. The US administration appears to have swallowed it whole and pulled the lever. Anthropic have ended up a victim of their own hype, and the reaction that hype provoked is, there is no gentler word for it, ludicrous.&lt;/p&gt;
&lt;h2 id="what-it-comes-down-to"&gt;What it comes down to
&lt;/h2&gt;&lt;p&gt;The lesson I&amp;rsquo;m taking from my one day isn&amp;rsquo;t about how clever Fable was. It&amp;rsquo;s about how little that cleverness is worth if you can&amp;rsquo;t rely on the thing being there.&lt;/p&gt;
&lt;p&gt;I couldn&amp;rsquo;t trust which model I was actually talking to from one hour to the next. I couldn&amp;rsquo;t trust it to stay up for a full overnight run. And it turns out I couldn&amp;rsquo;t trust it to still exist by the weekend. You cannot evaluate, depend on, or build a workflow around a model that gets silently swapped out one evening and switched off by the state a few days later. Capability was never the hard part. Availability is.&lt;/p&gt;
&lt;p&gt;And underneath all of it sits the thing I keep coming back to. A classifier cannot tell a defender from an attacker, because the two of them type the same commands. It turns out a government export control can&amp;rsquo;t tell them apart either. The only thing that ever could is a human being, paying attention, who can be held responsible for the judgement. There wasn&amp;rsquo;t one of those anywhere in this loop. There was a letter, sent at 5:21pm, and by morning the best tool I had for keeping my own code honest was gone, with a polite link where it used to be.&lt;/p&gt;</description></item><item><title>Supporting a provider, or actually using it</title><link>https://phpboyscout.uk/supporting-a-provider-or-actually-using-it/</link><pubDate>Sat, 02 May 2026 00:00:00 +0000</pubDate><guid>https://phpboyscout.uk/supporting-a-provider-or-actually-using-it/</guid><description>&lt;img src="https://phpboyscout.uk/supporting-a-provider-or-actually-using-it/cover-supporting-a-provider-or-actually-using-it.png" alt="Featured image of post Supporting a provider, or actually using it" /&gt;&lt;p&gt;If your CLI tool talks to an AI model, you don&amp;rsquo;t want to hard-wire one vendor. So you reach for a single client interface over several providers, which is the right call. The trap is the next step: build that interface on only what every provider has in common, and you quietly throw away the very features that made you want a particular provider in the first place. rust-tool-base&amp;rsquo;s &lt;code&gt;rtb-ai&lt;/code&gt; refuses to make that trade.&lt;/p&gt;
&lt;h2 id="the-pull-toward-one-interface"&gt;The pull toward one interface
&lt;/h2&gt;&lt;p&gt;If your CLI tool talks to an AI model, hard-wiring one vendor is a poor bet. One user has an Anthropic key, another an OpenAI key. Someone&amp;rsquo;s on Gemini. Someone runs Ollama locally because their data can&amp;rsquo;t leave the building. Someone points at an OpenAI-compatible endpoint from a provider you&amp;rsquo;ve never heard of. You don&amp;rsquo;t want a separate code path for each, so you want one &lt;code&gt;AiClient&lt;/code&gt; that all of them slot behind.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;rtb-ai&lt;/code&gt; gets that unification from the &lt;code&gt;genai&lt;/code&gt; crate, which already speaks to Anthropic, OpenAI, Gemini, Ollama and OpenAI-compatible endpoints. One interface, five providers, the tool author picks one in config. The Go sibling makes the same bet: go-tool-base&amp;rsquo;s &lt;code&gt;chat&lt;/code&gt; package also unifies several providers, behind &lt;a class="link" href="https://phpboyscout.uk/an-ai-interface-that-fits-on-one-screen/" &gt;an interface deliberately kept to four methods&lt;/a&gt;. So far this is the obvious design, and if it were the whole design there&amp;rsquo;d be nothing to write about.&lt;/p&gt;
&lt;h2 id="what-unified-quietly-costs-you"&gt;What &amp;ldquo;unified&amp;rdquo; quietly costs you
&lt;/h2&gt;&lt;p&gt;Here&amp;rsquo;s the catch in any unified interface. It can only expose what every provider behind it has in common.&lt;/p&gt;
&lt;p&gt;The common subset is plain chat. Messages go in, text comes out, optionally streamed token by token. That&amp;rsquo;s real and it&amp;rsquo;s useful and every provider does it. But the common subset is also the &lt;em&gt;floor&lt;/em&gt;, and the features that make a particular provider worth choosing are almost never on the floor. They&amp;rsquo;re the things only that provider does.&lt;/p&gt;
&lt;p&gt;Anthropic is the sharp example, because it has three features that matter and not one of them is common-subset.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Prompt caching.&lt;/strong&gt; You can mark the stable parts of a request, the system prompt and the tool list, as cacheable. The provider keeps them warm, and on the next turn you aren&amp;rsquo;t billed to re-send and re-process text that didn&amp;rsquo;t change. On a long agent loop, where the same large system prompt rides along on every single turn, that&amp;rsquo;s a substantial saving in both cost and latency.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Extended thinking.&lt;/strong&gt; The model works through a hard problem in a visible, budgeted reasoning pass before it commits to an answer, and you can see that reasoning.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Citations.&lt;/strong&gt; Structured references back to source material in the response.&lt;/p&gt;
&lt;p&gt;A client built strictly on the common subset can&amp;rsquo;t express any of those. It has no field for them, because four of the five providers wouldn&amp;rsquo;t know what to do with the field. So a purely lowest-common-denominator client would &amp;ldquo;support&amp;rdquo; Anthropic and then use it badly, leaving its best features unreachable. Support as a checkbox, not as the point.&lt;/p&gt;
&lt;h2 id="the-escape-hatch"&gt;The escape hatch
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;rtb-ai&lt;/code&gt;&amp;rsquo;s answer is to not choose. It runs two implementations under one interface.&lt;/p&gt;
&lt;p&gt;For OpenAI, Gemini, Ollama and OpenAI-compatible endpoints, calls route through &lt;code&gt;genai&lt;/code&gt;, the unified path. For Anthropic, every method drops to a &lt;a class="link" href="https://gitlab.com/phpboyscout/rust-tool-base/-/blob/9c22aa8/crates/rtb-ai/src/anthropic.rs#L1" target="_blank" rel="noopener"
 &gt;direct &lt;code&gt;reqwest&lt;/code&gt; implementation&lt;/a&gt; straight against the Messages API. Same &lt;code&gt;AiClient&lt;/code&gt; on the surface, a different implementation underneath, selected by which provider the config names.&lt;/p&gt;
&lt;p&gt;And the request type has deliberate room for the difference:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-rust" data-lang="rust"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;ChatRequest&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&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;system&lt;/span&gt;: &lt;span class="nb"&gt;Option&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;messages&lt;/span&gt;: &lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Message&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;temperature&lt;/span&gt;: &lt;span class="nb"&gt;Option&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;f32&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;max_tokens&lt;/span&gt;: &lt;span class="nb"&gt;Option&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;u32&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="sd"&gt;/// Anthropic-only: enables prompt caching at every stable point.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="sd"&gt;/// Ignored on non-Anthropic providers.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cache_control&lt;/span&gt;: &lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="sd"&gt;/// Anthropic-only: extended-thinking budget. `None` disables.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="sd"&gt;/// Ignored on non-Anthropic providers.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;thinking&lt;/span&gt;: &lt;span class="nb"&gt;Option&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ThinkingMode&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Set &lt;code&gt;cache_control&lt;/code&gt; and the Anthropic-direct path inserts cache breakpoints at the three stable points: the system prompt, the tool list, and the first message. Set &lt;code&gt;thinking&lt;/code&gt; and it adds the thinking block, and streaming surfaces a separate &lt;code&gt;ThinkingToken&lt;/code&gt; event so you can show the reasoning apart from the answer. On a non-Anthropic provider, both fields are simply ignored. The interface carries them; only the implementation that understands them acts on them.&lt;/p&gt;
&lt;h2 id="a-hatch-not-a-leak"&gt;A hatch, not a leak
&lt;/h2&gt;&lt;p&gt;It&amp;rsquo;s worth being precise about why this isn&amp;rsquo;t the thing it superficially resembles, which is a leaky abstraction.&lt;/p&gt;
&lt;p&gt;A leaky abstraction is one where implementation details bleed through that you didn&amp;rsquo;t intend and can&amp;rsquo;t reason about. The abstraction quietly fails to abstract, and you&amp;rsquo;re left guessing which provider you&amp;rsquo;re really talking to.&lt;/p&gt;
&lt;p&gt;This is the opposite of that. The two Anthropic-only fields aren&amp;rsquo;t a leak. They&amp;rsquo;re named, documented as Anthropic-only, inert everywhere else, and right there in the public type for anyone to see. The interface is uniform for the common case and &lt;em&gt;deliberately, visibly&lt;/em&gt; non-uniform at exactly the points where uniformity would have cost you the good features. You opt into provider-specifics by setting a field. You stay fully portable by leaving it at its default. Nothing bleeds; you decide.&lt;/p&gt;
&lt;p&gt;The same design line explains what &lt;em&gt;does&lt;/em&gt; stay in the unified path. Structured output, &lt;code&gt;chat_structured::&amp;lt;T&amp;gt;&lt;/code&gt;, sends a JSON Schema derived from your Rust type with the request and validates the reply against it before handing you a typed &lt;code&gt;T&lt;/code&gt;. That&amp;rsquo;s a portability win that costs nothing across providers, so it belongs in the common interface. The split isn&amp;rsquo;t &amp;ldquo;Anthropic versus the rest&amp;rdquo;. It&amp;rsquo;s &amp;ldquo;features that are free to unify go in the unified path; features that aren&amp;rsquo;t get a designed door&amp;rdquo;. Prompt caching and extended thinking get the door, because flattening them away would be the expensive kind of convenient.&lt;/p&gt;
&lt;h2 id="to-sum-up"&gt;To sum up
&lt;/h2&gt;&lt;p&gt;A CLI tool that integrates AI wants one client over several providers, and a unified interface can only expose what those providers share. The shared floor is plain chat, and the features worth choosing a provider &lt;em&gt;for&lt;/em&gt;, like Anthropic&amp;rsquo;s prompt caching, extended thinking and citations, are never on the floor.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;rtb-ai&lt;/code&gt; keeps both. &lt;code&gt;genai&lt;/code&gt; provides the unified path across five providers; an Anthropic-direct &lt;code&gt;reqwest&lt;/code&gt; path drops below the abstraction for the features &lt;code&gt;genai&lt;/code&gt; can&amp;rsquo;t reach, and &lt;code&gt;ChatRequest&lt;/code&gt; carries the Anthropic-only fields openly, ignored elsewhere. Uniform where uniformity is free, with a designed escape hatch where it isn&amp;rsquo;t. That&amp;rsquo;s the difference between supporting a provider and actually using it.&lt;/p&gt;</description></item></channel></rss>