<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[Qualiteg Journal]]></title><description><![CDATA[Engineering insights, AI expertise, and the latest news from Qualiteg]]></description><link>https://journal.qualiteg.com/</link><image><url>https://journal.qualiteg.com/favicon.png</url><title>Qualiteg Journal</title><link>https://journal.qualiteg.com/</link></image><generator>Ghost 5.82</generator><lastBuildDate>Tue, 18 Aug 2026 03:03:18 GMT</lastBuildDate><atom:link href="https://journal.qualiteg.com/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[Hardening a Raspberry Pi 5: SSH keys, UFW, fail2ban — and the trap where IPv6 comes back after a reboot]]></title><description><![CDATA[A freshly set up Raspberry Pi 5 is wide open: password auth enabled, no firewall, 172 pending updates. We harden it with SSH key-only auth, UFW, fail2ban, and automatic updates, disable IPv6, and verify it all with real reboots — including the trap where IPv6 comes back after a reboot.]]></description><link>https://journal.qualiteg.com/raspberry-pi-5-hardening-ssh-ufw-ipv6/</link><guid isPermaLink="false">6a7e13e0736fb40d7094aeef</guid><dc:creator><![CDATA[Qualiteg Product Development Team]]></dc:creator><pubDate>Sun, 16 Aug 2026 05:27:54 GMT</pubDate><media:content url="https://journal.qualiteg.com/content/images/2026/08/raspberry-pi-5-hardening-ssh-ufw-ipv6.png" medium="image"/><content:encoded><![CDATA[<img src="https://journal.qualiteg.com/content/images/2026/08/raspberry-pi-5-hardening-ssh-ufw-ipv6.png" alt="Hardening a Raspberry Pi 5: SSH keys, UFW, fail2ban &#x2014; and the trap where IPv6 comes back after a reboot"><p>Hello!<br>This is the Qualiteg Product Development Team!</p><p><a href="https://journal.qualiteg.com/raspberry-pi-5-headless-setup-windows/">In the previous article</a>, we set up a monitor-less Raspberry Pi 5 using only a Windows PC, going from inserting the SD card to an SSH connection in about 3 minutes.</p><p>Eventually, this Raspberry Pi will host a small web server that we want to reach from the internet.</p><p>But before that, there is something we need to do first.<br><br><strong>When we actually measured it, a freshly set up Raspberry Pi OS turned out to be far more exposed than expected</strong><br><br>.</p><p>Password authentication was still enabled with the simple throwaway password from our previous test setup, there was no firewall, 172 upgradable packages had piled up, and the device had even acquired a global IPv6 address we never intended to have.</p><p>In this article, we will </p><p><strong>switch SSH to key-based authentication, set up UFW, fail2ban, and automatic updates, disable IPv6 &#x2014; all with real commands &#x2014; and then actually reboot the machine to verify that every setting survives</strong></p><p>Full disclosure: we stumbled once during this verification.</p><p><strong>The IPv6 we had disabled via sysctl came back after a reboot</strong>.</p><p>The culprit was the NetworkManager connection profile.</p><p>We cover that whole story in detail in the second half.</p><p>This article targets Raspberry Pi OS (64-bit, based on Debian 13 &quot;trixie&quot;).</p><p>All work is done from a Windows PC over SSH; the Raspberry Pi never gets a monitor attached. All numbers in this article are actual measurements taken on August 14, 2026.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://journal.qualiteg.com/content/images/2026/08/raspberry-pi-5-hardening-fig1-v2.jpg" class="kg-image" alt="Hardening a Raspberry Pi 5: SSH keys, UFW, fail2ban &#x2014; and the trap where IPv6 comes back after a reboot" loading="lazy" width="1376" height="768" srcset="https://journal.qualiteg.com/content/images/size/w600/2026/08/raspberry-pi-5-hardening-fig1-v2.jpg 600w, https://journal.qualiteg.com/content/images/size/w1000/2026/08/raspberry-pi-5-hardening-fig1-v2.jpg 1000w, https://journal.qualiteg.com/content/images/2026/08/raspberry-pi-5-hardening-fig1-v2.jpg 1376w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Figure 1: Overview of the series. This installment is (2) hardening &#x2014; building a foundation safe enough to expose, starting from the freshly set-up state of the previous article</span></figcaption></figure><h2 id="we-measured-the-initial-state-%E2%80%94-and-it-was-this-exposed">We measured the initial state &#x2014; and it was this exposed</h2><p>Before touching anything, we measured the current state. Instead of &quot;it&apos;s probably unsafe,&quot; we confirm exactly what is open and how, and then close it.</p>
<!--kg-card-begin: html-->
<div style="overflow-x:auto"><table style="border-collapse:collapse;width:100%;font-size:0.95em"><tr><th style="border:1px solid #d0d7de;padding:8px 12px;text-align:left;background:#f3f6fa;">Aspect</th><th style="border:1px solid #d0d7de;padding:8px 12px;text-align:left;background:#f3f6fa;">Initial state (measured)</th><th style="border:1px solid #d0d7de;padding:8px 12px;text-align:left;background:#f3f6fa;">Why it is a problem</th></tr><tr><td style="border:1px solid #d0d7de;padding:8px 12px;text-align:left;">SSH authentication</td><td style="border:1px solid #d0d7de;padding:8px 12px;text-align:left;">Password authentication enabled (with the simple test password set last time)</td><td style="border:1px solid #d0d7de;padding:8px 12px;text-align:left;">Target for brute-force attacks</td></tr><tr><td style="border:1px solid #d0d7de;padding:8px 12px;text-align:left;">Root login</td><td style="border:1px solid #d0d7de;padding:8px 12px;text-align:left;">permitrootlogin without-password</td><td style="border:1px solid #d0d7de;padding:8px 12px;text-align:left;">Leaves room for direct root login</td></tr><tr><td style="border:1px solid #d0d7de;padding:8px 12px;text-align:left;">Firewall</td><td style="border:1px solid #d0d7de;padding:8px 12px;text-align:left;">None (ufw not installed, 0 nft rules)</td><td style="border:1px solid #d0d7de;padding:8px 12px;text-align:left;">Every port passes straight through</td></tr><tr><td style="border:1px solid #d0d7de;padding:8px 12px;text-align:left;">Brute-force protection</td><td style="border:1px solid #d0d7de;padding:8px 12px;text-align:left;">None (fail2ban not installed)</td><td style="border:1px solid #d0d7de;padding:8px 12px;text-align:left;">Unlimited login attempts allowed</td></tr><tr><td style="border:1px solid #d0d7de;padding:8px 12px;text-align:left;">IPv6</td><td style="border:1px solid #d0d7de;padding:8px 12px;text-align:left;">Holds a global address, listening on [::]:22</td><td style="border:1px solid #d0d7de;padding:8px 12px;text-align:left;">A path we never intended to operate remains open</td></tr><tr><td style="border:1px solid #d0d7de;padding:8px 12px;text-align:left;">Updates</td><td style="border:1px solid #d0d7de;padding:8px 12px;text-align:left;">172 upgradable packages, no automatic updates</td><td style="border:1px solid #d0d7de;padding:8px 12px;text-align:left;">Known fixes never get applied</td></tr><tr><td style="border:1px solid #d0d7de;padding:8px 12px;text-align:left;">Listening ports</td><td style="border:1px solid #d0d7de;padding:8px 12px;text-align:left;">22 and 111 (rpcbind) both listening on 0.0.0.0 (plus port 8080 of the test web server we set up)</td><td style="border:1px solid #d0d7de;padding:8px 12px;text-align:left;">Even unused services are exposed</td></tr></table></div>
<!--kg-card-end: html-->
<p>The IPv6 part may surprise you. Even though we intended LAN-only operation, the device had received router advertisements (RA) and automatically acquired a global IPv6 address starting with <code>2409:</code>.</p><p>Global IPv6 addresses do not assume NAT, so the exposure model is fundamentally different from IPv4.</p><p>Since this article&apos;s policy is to keep IPv6 out of operation, <strong>we explicitly disable it so that no unused path is left behind</strong>.</p><h2 id="policy-open-no-ports-%E2%80%94-publish-through-a-tunnel">Policy: open no ports &#x2014; publish through a tunnel</h2><p>Here is the hardening policy we settled on.</p><p>SSH becomes key-authentication only, restricted to connections from our home LAN. As for every other inbound port, including 8080 for the web server, we open <strong>none at all</strong>&#x3002;</p><p>&quot;We want to use it from outside but won&apos;t open any ports&quot; may sound contradictory, but publishing will happen next time through a WireCanal tunnel. With a tunnel, the Raspberry Pi only needs outbound connections &#x2014; no inbound ports to open, no router port forwarding required.</p><p>In other words, this round of hardening means &quot;<strong>close everything</strong>&#x300D;&#x3001;<br>and next time&apos;s publishing means &quot;reach the outside while staying closed.&quot; That is the division of labor.</p><h2 id="step-1-install-the-ssh-key-the-do-not-lock-yourself-out-order-is-everything">Step 1: Install the SSH key (the do-not-lock-yourself-out order is everything)</h2><p>First, we install the key. There is one iron rule here.<strong>Verify that key-based login actually succeeds before turning off password authentication</strong>. Get the order wrong and you lock yourself out of SSH. On a monitor-less Raspberry Pi, recovering while staying headless is quite painful, so this order must never be broken.</p><p>If you do not have an SSH key yet, first run <code>ssh-keygen -t ed25519</code> on the Windows side to create one.</p><p>We recommend setting the passphrase you are asked for along the way (it is your insurance if the key file ever leaks). You can get the public key with <code>%USERPROFILE%\.ssh\id_ed25519.pub</code>.</p><p>First, place the public key on the Raspberry Pi.</p><pre><code class="language-bash"># On the Raspberry Pi (run as the pi user)
D=/home/pi/.ssh
mkdir -p &quot;$D&quot;; chmod 700 &quot;$D&quot;
cat &gt; &quot;$D/authorized_keys&quot; &lt;&lt;&apos;EOF&apos;
ssh-ed25519 AAAA...(your public key)
EOF
chmod 600 &quot;$D/authorized_keys&quot;; chown -R pi:pi &quot;$D&quot;</code></pre><p>Note that <code>cat &gt;</code> overwrites the existing authorized_keys entirely. We write it this way because this is a brand-new build; on a machine that already has registered keys, append instead (<code>&gt;&gt;</code>).</p><p>If you use GitHub, <code>https://github.com/&lt;your-account&gt;.keys</code> returns the list of your public keys, so copying from there is the quickest way.</p><p>Once the key is in place, confirm from the Windows side that you can log in with the key alone.</p><pre><code class="language-powershell">ssh -o PasswordAuthentication=no pi@192.168.12.17</code></pre><p>Only proceed once this goes through.</p><h2 id="step-2-change-the-password-disable-ipv6-and-make-ssh-key-only">Step 2: Change the password, disable IPv6, and make SSH key-only</h2><p>From here on we work with root privileges (either enter with <code>sudo -i</code> or prefix each command with <code>sudo</code>). First, change the password &#x2014; from the simple test password of last time to a proper one. Even after going key-only, sudo still uses the password, so we sort it out here.</p><pre><code class="language-bash">passwd pi</code></pre><p>Next, disable IPv6 on the OS side.</p><pre><code class="language-bash">cat &gt; /etc/sysctl.d/99-disable-ipv6.conf &lt;&lt;&apos;EOF&apos;
net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1
net.ipv6.conf.lo.disable_ipv6 = 1
EOF
sysctl --system</code></pre><p>Then we harden SSH. Rather than editing the main config file, we add a drop-in.</p><pre><code class="language-bash">cat &gt; /etc/ssh/sshd_config.d/00-hardening.conf &lt;&lt;&apos;EOF&apos;
PasswordAuthentication no
KbdInteractiveAuthentication no
PermitRootLogin no
AddressFamily inet
EOF
sshd -t &amp;&amp; systemctl restart ssh</code></pre><p><code>AddressFamily inet</code> tells sshd to listen on IPv4 only. On Ubuntu, sshd is sometimes activated via a socket (ssh.socket), which needs its own drop-in as well &#x2014; but on our machine ssh was started directly as a service (<code>ssh.socket</code> was disabled), so the sshd_config setting alone made <code>[::]:22</code> disappear (measured).</p><p>At this point, try password authentication from a separate terminal. If it gets rejected, you succeeded. Do not forget to also confirm that your existing key login still works.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://journal.qualiteg.com/content/images/2026/08/raspberry-pi-5-hardening-shot-ssh-auth.png" class="kg-image" alt="Hardening a Raspberry Pi 5: SSH keys, UFW, fail2ban &#x2014; and the trap where IPv6 comes back after a reboot" loading="lazy" width="1099" height="612" srcset="https://journal.qualiteg.com/content/images/size/w600/2026/08/raspberry-pi-5-hardening-shot-ssh-auth.png 600w, https://journal.qualiteg.com/content/images/size/w1000/2026/08/raspberry-pi-5-hardening-shot-ssh-auth.png 1000w, https://journal.qualiteg.com/content/images/2026/08/raspberry-pi-5-hardening-shot-ssh-auth.png 1099w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Password authentication fails with Permission denied (publickey), while key login goes through (measured)</span></figcaption></figure><h2 id="step-3-apply-the-172-pending-updates-then-fail2ban-and-automatic-updates">Step 3: Apply the 172 pending updates, then fail2ban and automatic updates</h2><pre><code class="language-bash">export DEBIAN_FRONTEND=noninteractive
apt-get update -q
apt-get -y -q full-upgrade          # apply all 172 pending updates
apt-get -y -q install ufw fail2ban unattended-upgrades</code></pre><p>fail2ban is the gatekeeper that counts failed SSH attempts and bans the offenders automatically. One thing worth knowing: our Raspberry Pi OS trixie machine has no rsyslog installed and <code>/var/log/auth.log</code> does not exist either.</p><p>That means sshd logs are read from journald. Debian&apos;s fail2ban package ships a setting that reads journald for sshd (<code>sshd_backend = systemd</code>), but many older guides assume auth.log, so we also declared the backend explicitly in our jail config.</p><pre><code class="language-bash">cat &gt; /etc/fail2ban/jail.d/sshd.local &lt;&lt;&apos;EOF&apos;
[sshd]
enabled = true
backend = systemd
maxretry = 5
bantime = 1h
EOF
systemctl enable --now fail2ban</code></pre><p>We also set up automatic updates (unattended-upgrades).</p><p>We do not want surprise reboots in the middle of the night, so we turn off automatic reboots only. Note that the actual periodic execution is driven by APT-side timers (<code>apt-daily.timer</code> / <code>apt-daily-upgrade.timer</code>), so our verification includes confirming that those timers are enabled.</p><pre><code class="language-bash">cat &gt; /etc/apt/apt.conf.d/20auto-upgrades &lt;&lt;&apos;EOF&apos;
APT::Periodic::Update-Package-Lists &quot;1&quot;;
APT::Periodic::Unattended-Upgrade &quot;1&quot;;
EOF
cat &gt; /etc/apt/apt.conf.d/52unattended-upgrades-local &lt;&lt;&apos;EOF&apos;
Unattended-Upgrade::Automatic-Reboot &quot;false&quot;;
EOF
systemctl enable --now unattended-upgrades</code></pre><p>One interesting discovery came as a side effect of full-upgrade.</p><p>Our machine initially had <code>/etc/sudoers.d/010_pi-nopasswd</code>, which let sudo run without a password &#x2014; but <br><br><strong>after full-upgrade this file was gone and sudo started requiring a password</strong><br> (this is what we measured in our environment, not something we verified as an official behavioral change). Since it moves in the right direction for hardening, we simply kept it.</p><h2 id="step-4-with-ufw-add-the-allow-rules-first-then-enable">Step 4: With UFW, add the allow rules first, then enable</h2><p>The scary part of a firewall is locking yourself out. UFW is disabled right after installation, so setting the default policies does not start blocking anything by itself.</p><p><u>The dangerous move is</u> running <code>ufw enable</code> without first adding an allow rule for SSH.</p><p>That is why <strong>we add the allow rules first and enable afterwards</strong>.</p><pre><code class="language-bash">ufw default deny incoming
ufw default allow outgoing
ufw allow from 192.168.12.0/24 to any port 22 proto tcp   # match your home LAN segment
ufw --force enable</code></pre><p>Inbound traffic is denied by default, and the only user-defined allow rule is SSH (22) from the home LAN. We deliberately do not allow port 8080 of the test web server either (next time, that is exactly what we will publish through the tunnel). After enabling, keep your current SSH session open and confirm that a brand-new SSH connection from another terminal still works.</p><h2 id="verification-every-item-actually-measured">Verification: every item, actually measured</h2><p>With the configuration written, it is time to verify. Not &quot;the config file says so, so it must be fine&quot; &#x2014; we check the actual behavior from the outside.</p>
<!--kg-card-begin: html-->
<div style="overflow-x:auto"><table style="border-collapse:collapse;width:100%;font-size:0.95em"><tr><th style="border:1px solid #d0d7de;padding:8px 12px;text-align:left;background:#f3f6fa;">Verification item</th><th style="border:1px solid #d0d7de;padding:8px 12px;text-align:left;background:#f3f6fa;">Measured result</th></tr><tr><td style="border:1px solid #d0d7de;padding:8px 12px;text-align:left;">Key login</td><td style="border:1px solid #d0d7de;padding:8px 12px;text-align:left;">Success</td></tr><tr><td style="border:1px solid #d0d7de;padding:8px 12px;text-align:left;">Password authentication</td><td style="border:1px solid #d0d7de;padding:8px 12px;text-align:left;">Rejected (Permission denied (publickey))</td></tr><tr><td style="border:1px solid #d0d7de;padding:8px 12px;text-align:left;">Effective sshd config (sshd -T)</td><td style="border:1px solid #d0d7de;padding:8px 12px;text-align:left;">passwordauthentication no / permitrootlogin no / addressfamily inet</td></tr><tr><td style="border:1px solid #d0d7de;padding:8px 12px;text-align:left;">Listening on [::]:22</td><td style="border:1px solid #d0d7de;padding:8px 12px;text-align:left;">Gone (confirmed with ss -tlnH)</td></tr><tr><td style="border:1px solid #d0d7de;padding:8px 12px;text-align:left;">Global IPv6 address</td><td style="border:1px solid #d0d7de;padding:8px 12px;text-align:left;">None (ip -6 addr show scope global is empty)</td></tr><tr><td style="border:1px solid #d0d7de;padding:8px 12px;text-align:left;">UFW</td><td style="border:1px solid #d0d7de;padding:8px 12px;text-align:left;">active, deny incoming, only the LAN-restricted allow rule for 22/tcp</td></tr><tr><td style="border:1px solid #d0d7de;padding:8px 12px;text-align:left;">External port check</td><td style="border:1px solid #d0d7de;padding:8px 12px;text-align:left;">From the dev machine: TCP 22 = reachable, TCP 8080 = blocked</td></tr><tr><td style="border:1px solid #d0d7de;padding:8px 12px;text-align:left;">fail2ban</td><td style="border:1px solid #d0d7de;padding:8px 12px;text-align:left;">sshd jail running (watching journald)</td></tr><tr><td style="border:1px solid #d0d7de;padding:8px 12px;text-align:left;">Automatic updates</td><td style="border:1px solid #d0d7de;padding:8px 12px;text-align:left;">apt-daily.timer and apt-daily-upgrade.timer both enabled, next runs scheduled, Automatic-Reboot false</td></tr><tr><td style="border:1px solid #d0d7de;padding:8px 12px;text-align:left;">Upgradable packages</td><td style="border:1px solid #d0d7de;padding:8px 12px;text-align:left;">172 &#x2192; 0</td></tr></table></div>
<!--kg-card-end: html-->
<figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://journal.qualiteg.com/content/images/2026/08/raspberry-pi-5-hardening-shot-v6-ports.png" class="kg-image" alt="Hardening a Raspberry Pi 5: SSH keys, UFW, fail2ban &#x2014; and the trap where IPv6 comes back after a reboot" loading="lazy" width="1099" height="612" srcset="https://journal.qualiteg.com/content/images/size/w600/2026/08/raspberry-pi-5-hardening-shot-v6-ports.png 600w, https://journal.qualiteg.com/content/images/size/w1000/2026/08/raspberry-pi-5-hardening-shot-v6-ports.png 1000w, https://journal.qualiteg.com/content/images/2026/08/raspberry-pi-5-hardening-shot-v6-ports.png 1099w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Zero global IPv6 addresses. Port 8080 is unreachable from outside even though the server is listening on it internally (measured)</span></figcaption></figure><p>So far so good. The problem came next.</p><h2 id="after-a-reboot-ipv6-was-back">After a reboot, IPv6 was back</h2><p>You can only prove persistence by actually rebooting. In the first reboot verification, SSH came back about 21 seconds after the reboot, and both UFW and fail2ban started automatically. And yet:</p><pre><code class="language-bash">ip -6 addr show scope global
# &#x2192; 2409:xx:xxxx:... is still there</code></pre><p>The global IPv6 address we had removed was back.</p><p>The cause was NetworkManager. IPv6 was still enabled in the connection profile, so even with the sysctl <code>disable_ipv6</code> applied, <br><br><strong>the per-interface disable_ipv6 was being written back to 0 the moment the Wi-Fi connection came up</strong> (as observed in our environment).</p><p>Right after applying the setting, <code>ip -6 addr</code> comes back empty, so it looks like a success. But once you reboot and Wi-Fi reconnects, the setting gets rolled back. This behavior only surfaced during the first reboot verification.</p><p>To make it permanent, disable IPv6 in the NetworkManager connection profile itself.</p><pre><code class="language-bash"># Check the profile name (on our machine it was called &quot;preconfigured&quot;)
nmcli connection show --active

# Disable IPv6 on the profile side
nmcli connection modify &quot;&lt;the connection name from above&gt;&quot; ipv6.method &quot;disabled&quot;</code></pre><p>With this in place we ran a second reboot verification, and this time the machine kept zero global addresses after the reboot.</p><p>The real lesson here is not about how to disable IPv6 &#x2014; it is this:</p><p><strong>&quot;I applied the setting and checked it on the spot&quot; guarantees nothing about persistence. Only when verification includes a reboot is the work actually done.</strong></p><p>Our rule is that if even one verification item fails, the whole task is treated as incomplete &#x2014; fix it and verify again. Thanks to that discipline, we caught the &quot;setting I thought I disabled was silently restored after reboot&quot; state before going public.</p><h2 id="differences-from-older-guides-confirmed-on-this-trixie-machine">Differences from older guides, confirmed on this trixie machine</h2><p>With the move to a Debian 13 trixie base, several assumptions from long-standing guides no longer held.</p><p>Here is a summary of what we could confirm on our machine.</p>
<!--kg-card-begin: html-->
<div style="overflow-x:auto"><table style="border-collapse:collapse;width:100%;font-size:0.95em"><tr><th style="border:1px solid #d0d7de;padding:8px 12px;text-align:left;background:#f3f6fa;">Old assumption</th><th style="border:1px solid #d0d7de;padding:8px 12px;text-align:left;background:#f3f6fa;">Reality on this trixie machine</th></tr><tr><td style="border:1px solid #d0d7de;padding:8px 12px;text-align:left;">fail2ban reads /var/log/auth.log</td><td style="border:1px solid #d0d7de;padding:8px 12px;text-align:left;">No rsyslog, and auth.log does not exist. sshd logs are read from journald (the Debian package already sets sshd_backend = systemd)</td></tr><tr><td style="border:1px solid #d0d7de;padding:8px 12px;text-align:left;">The pi user&apos;s sudo is NOPASSWD</td><td style="border:1px solid #d0d7de;padding:8px 12px;text-align:left;">full-upgrade removed 010_pi-nopasswd and sudo now requires a password (measured in our environment)</td></tr><tr><td style="border:1px solid #d0d7de;padding:8px 12px;text-align:left;">Killing [::]:22 requires an ssh.socket drop-in (Ubuntu family)</td><td style="border:1px solid #d0d7de;padding:8px 12px;text-align:left;">Our machine starts the service directly, so AddressFamily inet alone was enough</td></tr></table></div>
<!--kg-card-end: html-->
<h2 id="summary">Summary</h2><p>Right after setup, our Raspberry Pi 5 had password authentication enabled with a simple test password, no firewall, 172 upgradable packages, and an unintended IPv6 address.</p><p>After this session&apos;s work, SSH is key-only and LAN-restricted, UFW denies inbound traffic by default with SSH from the home LAN as the only explicit allow rule, and updates covered by unattended-upgrades are applied automatically.</p><p>Everything was done over SSH; a monitor was never connected even once.</p><p>The biggest takeaway: we caught the phenomenon of NetworkManager writing back over sysctl&apos;s IPv6 disablement &#x2014; through an actual reboot verification. If we had closed the task after only checking right after applying the setting, we would not have noticed the rollback until after going live.</p><p>Next time, we will finally take the web server on this Raspberry Pi and make it reachable from the internet <strong>without opening a single inbound port</strong>, using WireCanal.</p><p>See you in the next article!</p><h2 id="sources-references">Sources &amp; References</h2><ul><li><a href="https://www.raspberrypi.com/documentation/computers/configuration.html?ref=journal.qualiteg.com">Raspberry Pi Documentation | Configuration (official documentation)</a></li><li><a href="https://github.com/fail2ban/fail2ban?ref=journal.qualiteg.com">fail2ban official repository (GitHub)</a></li><li><a href="https://help.ubuntu.com/community/UFW?ref=journal.qualiteg.com">UFW - Community Help Wiki (official Ubuntu wiki)</a></li><li><a href="https://networkmanager.dev/docs/?ref=journal.qualiteg.com">NetworkManager official documentation (freedesktop.org)</a></li></ul><h2 id="related-articles">Related articles</h2><ul><li><a href="https://journal.qualiteg.com/raspberry-pi-5-headless-setup-windows/">Setting up a Raspberry Pi 5 with no monitor: from OS flashing to SSH using only a Windows PC</a></li><li><a href="https://journal.qualiteg.com/ollama-local-llm-from-smartphone-via-wirecanal/">Use your home PC&apos;s local LLM from your phone on the go: Ollama + Open WebUI + WireCanal</a></li><li><a href="https://journal.qualiteg.com/ngrok-wirecanal-comparison/">ngrok vs. WireCanal: the developers compare pricing, operations, and MCP design</a></li></ul>]]></content:encoded></item><item><title><![CDATA[Setting Up a Raspberry Pi 5 Without a Monitor: From OS Imaging to SSH Using Only a Windows PC]]></title><description><![CDATA[Set up a Raspberry Pi 5 with no monitor or micro HDMI cable, using only a Windows PC. We use the Raspberry Pi Imager CLI and firstrun.sh to preconfigure Wi-Fi and SSH, with the full procedure and measured timings — about 3 minutes from SD card insertion to an SSH connection.]]></description><link>https://journal.qualiteg.com/raspberry-pi-5-headless-setup-windows/</link><guid isPermaLink="false">6a7df10f736fb40d7094ae7a</guid><dc:creator><![CDATA[Qualiteg Product Development Team]]></dc:creator><pubDate>Thu, 13 Aug 2026 18:57:16 GMT</pubDate><media:content url="https://journal.qualiteg.com/content/images/2026/08/raspberry-pi-5-headless-setup-windows.png" medium="image"/><content:encoded><![CDATA[<img src="https://journal.qualiteg.com/content/images/2026/08/raspberry-pi-5-headless-setup-windows.png" alt="Setting Up a Raspberry Pi 5 Without a Monitor: From OS Imaging to SSH Using Only a Windows PC"><p>Hello!</p><p>This is the Qualiteg Product Development Team!</p><p>This article kicks off a series on how to control a Raspberry Pi over the internet.</p><p>As shown in the diagram below, the series goes like this:<strong>&#x2460;</strong>After the headless setup (this installment), we&apos;ll harden the Raspberry Pi as a security measure in preparation for exposing it to the internet (part 2), and then make a web server running inside the Raspberry Pi directly accessible from the internet (part 3).<br><br>In this first installment, we&apos;ll cover everything from getting your hands on a Raspberry Pi to the initial setup procedure.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://journal.qualiteg.com/content/images/2026/08/raspberry-pi-5-headless-fig1.jpg" class="kg-image" alt="Setting Up a Raspberry Pi 5 Without a Monitor: From OS Imaging to SSH Using Only a Windows PC" loading="lazy" width="1376" height="768" srcset="https://journal.qualiteg.com/content/images/size/w600/2026/08/raspberry-pi-5-headless-fig1.jpg 600w, https://journal.qualiteg.com/content/images/size/w1000/2026/08/raspberry-pi-5-headless-fig1.jpg 1000w, https://journal.qualiteg.com/content/images/2026/08/raspberry-pi-5-headless-fig1.jpg 1376w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Figure 1: Overview of the series. This installment is part 1, getting to a working SSH connection using only a Windows PC</span></figcaption></figure><p>We&apos;ll walk through the steps we used to go from writing the OS to connecting over SSH using only a Windows 11 PC, with actual measured timings. From inserting the SD card and powering on to logging in via SSH took about 3 minutes.</p><h2 id="what-youll-need">What You&apos;ll Need</h2><ul><li>Raspberry Pi 5 board &#x2014; we use the 4GB model in this article.</li><li>microSD card &#x2014; 64GB this time. It gets automatically expanded to full capacity on first boot</li><li>Heatsink for the Raspberry Pi 5 &#x2014; for thermal management</li><li>USB card reader &#x2014; for writing the Raspberry Pi image to the SD card</li><li>A Windows 11 PC</li><li>USB-C power supply (the Raspberry Pi 5 recommends 5V/5A power, such as the official Raspberry Pi 27W USB-C Power Supply. A 5V/3A-class charger may boot depending on your configuration, but you may run into power throttling or unstable behavior)</li></ul><p></p><h1 id="setting-up-the-hardware">Setting Up the Hardware</h1><h2 id="assembly">Assembly</h2><p>Alright, let&apos;s get the Raspberry Pi assembled!</p><p>Here&apos;s the Raspberry Pi.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://journal.qualiteg.com/content/images/2026/08/image-2.png" class="kg-image" alt="Setting Up a Raspberry Pi 5 Without a Monitor: From OS Imaging to SSH Using Only a Windows PC" loading="lazy" width="1280" height="960" srcset="https://journal.qualiteg.com/content/images/size/w600/2026/08/image-2.png 600w, https://journal.qualiteg.com/content/images/size/w1000/2026/08/image-2.png 1000w, https://journal.qualiteg.com/content/images/2026/08/image-2.png 1280w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Raspberry Pi 5 board (4GB model)</span></figcaption></figure><p>First, let&apos;s attach the heatsink for thermal management.</p><figure class="kg-card kg-image-card"><img src="https://journal.qualiteg.com/content/images/2026/08/image-3.png" class="kg-image" alt="Setting Up a Raspberry Pi 5 Without a Monitor: From OS Imaging to SSH Using Only a Windows PC" loading="lazy" width="1280" height="960" srcset="https://journal.qualiteg.com/content/images/size/w600/2026/08/image-3.png 600w, https://journal.qualiteg.com/content/images/size/w1000/2026/08/image-3.png 1000w, https://journal.qualiteg.com/content/images/2026/08/image-3.png 1280w" sizes="(min-width: 720px) 720px"></figure><p>Before attaching the heatsink, stick the included silicone-rubber-like material onto the heat-generating parts such as the CPU chip. These are what&apos;s known as thermal pads.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://journal.qualiteg.com/content/images/2026/08/image-5.png" class="kg-image" alt="Setting Up a Raspberry Pi 5 Without a Monitor: From OS Imaging to SSH Using Only a Windows PC" loading="lazy" width="1280" height="752" srcset="https://journal.qualiteg.com/content/images/size/w600/2026/08/image-5.png 600w, https://journal.qualiteg.com/content/images/size/w1000/2026/08/image-5.png 1000w, https://journal.qualiteg.com/content/images/2026/08/image-5.png 1280w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Applying thermal pads to the heat-generating parts</span></figcaption></figure><p>OK, with all the thermal pads in place, let&apos;s attach the heatsink itself.</p><figure class="kg-card kg-image-card"><img src="https://journal.qualiteg.com/content/images/2026/08/image-6.png" class="kg-image" alt="Setting Up a Raspberry Pi 5 Without a Monitor: From OS Imaging to SSH Using Only a Windows PC" loading="lazy" width="1280" height="960" srcset="https://journal.qualiteg.com/content/images/size/w600/2026/08/image-6.png 600w, https://journal.qualiteg.com/content/images/size/w1000/2026/08/image-6.png 1000w, https://journal.qualiteg.com/content/images/2026/08/image-6.png 1280w" sizes="(min-width: 720px) 720px"></figure><p>Fasten the heatsink from the back side with the insulated plastic screws like this, and you&apos;re done.</p><figure class="kg-card kg-image-card"><img src="https://journal.qualiteg.com/content/images/2026/08/image-8.png" class="kg-image" alt="Setting Up a Raspberry Pi 5 Without a Monitor: From OS Imaging to SSH Using Only a Windows PC" loading="lazy" width="1280" height="816" srcset="https://journal.qualiteg.com/content/images/size/w600/2026/08/image-8.png 600w, https://journal.qualiteg.com/content/images/size/w1000/2026/08/image-8.png 1000w, https://journal.qualiteg.com/content/images/2026/08/image-8.png 1280w" sizes="(min-width: 720px) 720px"></figure><p>The heatsink is now attached.</p><p>There&apos;s a fan power connector on the upper part of the Raspberry Pi board, so plug the power cable coming from the heatsink into it.</p><figure class="kg-card kg-image-card"><img src="https://journal.qualiteg.com/content/images/2026/08/image-7.png" class="kg-image" alt="Setting Up a Raspberry Pi 5 Without a Monitor: From OS Imaging to SSH Using Only a Windows PC" loading="lazy" width="1280" height="826" srcset="https://journal.qualiteg.com/content/images/size/w600/2026/08/image-7.png 600w, https://journal.qualiteg.com/content/images/size/w1000/2026/08/image-7.png 1000w, https://journal.qualiteg.com/content/images/2026/08/image-7.png 1280w" sizes="(min-width: 720px) 720px"></figure><p>By the way, don&apos;t insert the SD card yet. There&apos;s nothing on it, so inserting it wouldn&apos;t do anything.</p><p>Everything up to this point should only take a few minutes.</p><p>Next, let&apos;s move on to the software.</p><h2 id="setting-up-the-raspberry-pi-without-a-monitor">Setting Up the Raspberry Pi Without a Monitor</h2><p>Let&apos;s get right into the software setup.<br>This time we&apos;ll set everything up using only the CLI &#x2014; in other words, a headless setup.</p><p>The environment we verified this on:</p><p>- Imaging software: Raspberry Pi Imager 2.0.8<br>- OS written: Raspberry Pi OS 64-bit (based on Debian 13 trixie, kernel 6.18)<br>- Work PC: Windows 11 Pro.</p><h2 id="step-1-identify-the-physical-disk-number-to-write-to">Step 1: Identify the Physical Disk Number to Write To</h2><p>We&apos;ll start by preparing the SD card to insert into the Raspberry Pi.</p><p>For that, we use the dedicated imaging tool, Raspberry Pi Imager 2.0.8.</p><p>Writing to an SD card happens at the physical-disk level, so first confirm the disk number.</p><p>Raspberry Pi Imager 2.0.8 has a safety mechanism that refuses to write to devices that shouldn&apos;t be targets, such as internal drives. Even so, if you mix up another USB storage device you&apos;ll wipe its data, so always verify the disk number, capacity, and BusType.</p><p>Connect the SD card to your PC with the card reader and run the following in PowerShell.</p><pre><code class="language-powershell">Get-Disk</code></pre><pre><code class="language-plaintext">Number FriendlyName           BusType SizeGB
------ ------------           ------- ------
     0 CT4000P3PSSD8          NVMe      3726
     1 Generic- SD/MMC/MS PRO USB       59.5</code></pre><p>In our environment, the internal SSD showed up as disk 0 and the SD card via the USB card reader as disk 1. From the capacity (59.5GB) and the BusType being USB, we can tell it&apos;s the SD card.</p><p>In the steps that follow we specify the write target as \\.\PhysicalDrive1. Be sure to substitute the disk number for your own environment.</p><h2 id="step-2-get-raspberry-pi-imager-and-the-os-image">Step 2: Get Raspberry Pi Imager and the OS Image</h2><p>Raspberry Pi Imager can be installed with winget.</p><pre><code class="language-powershell">winget install --id RaspberryPiFoundation.RaspberryPiImager --silent --accept-package-agreements --accept-source-agreements</code></pre><p>It installs to C:\Program Files\Raspberry Pi Ltd\Imager\. The same executable used by the GUI has a CLI mode, and a scripting wrapper, rpi-imager-cli.cmd, is bundled as well.</p><p>Get the OS image from the official download site.<br>The URL raspios_arm64_latest always redirects to the latest 64-bit version (with desktop), which is handy to remember.</p><pre><code class="language-powershell">curl.exe -L --fail -o C:\qualiteg_examples\raspi\raspios.img.xz https://downloads.raspberrypi.com/raspios_arm64_latest</code></pre><p>The size was about 1.3GB. It can be written while still xz-compressed, so there&apos;s no need to extract it yourself.</p><h2 id="step-3-create-the-first-boot-script-firstrunsh">Step 3: Create the First-Boot Script firstrun.sh</h2><p>This is the heart of the headless setup.</p><p>We call the helpers imager_custom and userconf that ship with Raspberry Pi OS to configure the hostname, SSH, user, Wi-Fi, keyboard layout, and timezone all at once. Name the file firstrun.sh; it can live anywhere (you&apos;ll pass its path when writing the image in the next step).</p><pre><code class="language-bash">#!/bin/bash
# set +e keeps the script running to the final cleanup even if a command fails along the way.
# If a setting doesn&apos;t take effect, check the success/failure of each command individually
set +e

/usr/lib/raspberrypi-sys-mods/imager_custom set_hostname raspberrypi
/usr/lib/raspberrypi-sys-mods/imager_custom enable_ssh
/usr/lib/userconf-pi/userconf &apos;pi&apos; &apos;$6$&#x2026; (hash generated with openssl passwd -6)&apos;
/usr/lib/raspberrypi-sys-mods/imager_custom set_wlan &apos;your-ssid&apos; &apos;your-wifi-password&apos; &apos;JP&apos;
/usr/lib/raspberrypi-sys-mods/imager_custom set_keymap &apos;jp&apos;
/usr/lib/raspberrypi-sys-mods/imager_custom set_timezone &apos;Asia/Tokyo&apos;

rm -f /boot/firstrun.sh /boot/firmware/firstrun.sh
sed -i &apos;s| systemd.run.*||g&apos; /boot/cmdline.txt /boot/firmware/cmdline.txt 2&gt;/dev/null
exit 0</code></pre><p>Replace the SSID and Wi-Fi password (&apos;your-ssid&apos; and &apos;your-wifi-password&apos; in the script above) with your own.</p><p>The user&apos;s password is passed as a SHA-512 hash, not in plain text. You can generate the hash in Git Bash or similar like this.</p><pre><code class="language-bash">openssl passwd -6 &apos;your-desired-password&apos;</code></pre><p>The last two lines are cleanup: the script deletes itself and restores normal boot. They remove the entry that Imager plants in the boot configuration (cmdline.txt).</p><p>There is one important caveat.</p><p>The line endings of this file must be LF.</p><p>Files created in a Windows editor tend to end up as CRLF, and with CRLF the script fails on first boot. SSH never gets enabled, Wi-Fi never connects, and with no monitor you can&apos;t even see what went wrong &#x2014; a rather painful situation.</p><p>One security note as well: firstrun.sh contains your Wi-Fi password in plain text. Avoid committing it to Git or placing it in shared folders, and delete any working copies left on the Windows side once they&apos;re no longer needed.</p><h2 id="step-4-write-to-the-sd-card-from-the-cli">Step 4: Write to the SD Card from the CLI</h2><p>Writing to a physical disk requires administrator privileges, so run it elevated from PowerShell. Approve the UAC dialog when it appears.</p><pre><code class="language-powershell">$imgr = &apos;C:\Program Files\Raspberry Pi Ltd\Imager\rpi-imager.exe&apos;
$opts = @(&apos;--cli&apos;, &apos;--debug&apos;, &apos;--disable-eject&apos;,
          &apos;--first-run-script&apos;, &apos;C:\qualiteg_examples\raspi\firstrun.sh&apos;,
          &apos;--log-file&apos;,         &apos;C:\qualiteg_examples\raspi\flash-log.txt&apos;,
          &apos;C:\qualiteg_examples\raspi\raspios.img.xz&apos;,
          &apos;\\.\PhysicalDrive1&apos;)
Start-Process -FilePath $imgr -ArgumentList $opts -Verb RunAs -Wait</code></pre><p>Here&apos;s what the options we&apos;re using mean.</p>
<!--kg-card-begin: html-->
<table style="width:100%;border-collapse:collapse;font-size:0.95em"><thead><tr><th style="border:1px solid #d0d7de;padding:8px 10px;background:#f3f6fa;text-align:left">Option</th><th style="border:1px solid #d0d7de;padding:8px 10px;background:#f3f6fa;text-align:left">Role</th></tr></thead><tbody>
<tr><td style="border:1px solid #d0d7de;padding:8px 10px">--cli</td><td style="border:1px solid #d0d7de;padding:8px 10px">Run in command-line mode without launching the GUI</td></tr><tr><td style="border:1px solid #d0d7de;padding:8px 10px">--first-run-script</td><td style="border:1px solid #d0d7de;padding:8px 10px">Embed the first-boot script (firstrun.sh) into the SD card</td></tr><tr><td style="border:1px solid #d0d7de;padding:8px 10px">--log-file</td><td style="border:1px solid #d0d7de;padding:8px 10px">Write progress and results to a log file</td></tr><tr><td style="border:1px solid #d0d7de;padding:8px 10px">--debug</td><td style="border:1px solid #d0d7de;padding:8px 10px">Make the log verbose. Also records how write speed is auto-adjusted</td></tr><tr><td style="border:1px solid #d0d7de;padding:8px 10px">--disable-eject</td><td style="border:1px solid #d0d7de;padding:8px 10px">Don&apos;t auto-eject the SD card after writing completes. Add this if you want to inspect the write results</td></tr></tbody></table>
<!--kg-card-end: html-->
<p>Read-back verification after writing is enabled by default. In our measurements, extracting the 1.3GB xz image took 53 seconds, and writing plus verification finished in about 5 minutes. With a slow SD card the log will show write-latency warnings, but Imager automatically adjusts the buffer size and keeps going, so just wait it out.</p><p>A note on progress display: with our setup, launching elevated via Start-Process -Verb RunAs, no progress appeared in the original PowerShell window. That&apos;s why we pass --log-file and check progress and results in the log file. If the log ends with succeeded, the write was successful.</p><h2 id="step-5-power-on-wait-3-minutes-and-connect-via-ssh">Step 5: Power On, Wait 3 Minutes, and Connect via SSH</h2><p>Insert the freshly written SD card into the Raspberry Pi 5.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://journal.qualiteg.com/content/images/2026/08/image-9.png" class="kg-image" alt="Setting Up a Raspberry Pi 5 Without a Monitor: From OS Imaging to SSH Using Only a Windows PC" loading="lazy" width="1280" height="868" srcset="https://journal.qualiteg.com/content/images/size/w600/2026/08/image-9.png 600w, https://journal.qualiteg.com/content/images/size/w1000/2026/08/image-9.png 1000w, https://journal.qualiteg.com/content/images/2026/08/image-9.png 1280w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Insert the micro SD card we just wrote the image to into the SD slot</span></figcaption></figure><p>Then simply connect the USB-C power supply and it boots.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://journal.qualiteg.com/content/images/2026/08/image-10.png" class="kg-image" alt="Setting Up a Raspberry Pi 5 Without a Monitor: From OS Imaging to SSH Using Only a Windows PC" loading="lazy" width="1280" height="1649" srcset="https://journal.qualiteg.com/content/images/size/w600/2026/08/image-10.png 600w, https://journal.qualiteg.com/content/images/size/w1000/2026/08/image-10.png 1000w, https://journal.qualiteg.com/content/images/2026/08/image-10.png 1280w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Plug the power adapter into the USB-C power port; once power is supplied, the Raspberry Pi turns on.</span></figcaption></figure><p>The Raspberry Pi 5 does have a power button, but no button press is needed for a normal first boot. On first boot it runs filesystem auto-expansion, firstrun.sh, and a reboot in sequence, so wait 2&#x2013;3 minutes. If the green LED on the board is blinking, the boot process is underway.</p><p>Once you&apos;ve waited, connect via SSH from a Windows terminal.</p><pre><code class="language-powershell">ssh pi@raspberrypi.local</code></pre><p>The name raspberrypi.local is resolved by a mechanism called mDNS. Windows 11 supports it out of the box, so no extra software is needed. In our measurements, the SSH port opened about 3 minutes after inserting the SD card and powering on, and we could log in with the user we configured.</p><p>We also checked the state after logging in. Here are excerpts from the output of uname -a, vcgencmd measure_temp, and df -h.</p><pre><code class="language-plaintext">Linux raspberrypi 6.18.34+rpt-rpi-2712 #1 SMP PREEMPT Debian 1:6.18.34-1+rpt1 (2026-06-09) aarch64 GNU/Linux
temp=34.0&apos;C
/dev/mmcblk0p2   58G  6.6G   49G  12% /</code></pre><p>The entire 64GB card had been expanded into the root filesystem, the CPU temperature was 34.0&#xB0;C, and an IPv4 address had been obtained over Wi-Fi.</p><p>From here on, you can use it like any ordinary Linux machine.</p><h2 id="pitfalls-and-workarounds">Pitfalls and Workarounds</h2><p>Here&apos;s a table of the traps we actually hit during this work.</p>
<!--kg-card-begin: html-->
<table style="width:100%;border-collapse:collapse;font-size:0.95em"><thead><tr><th style="border:1px solid #d0d7de;padding:8px 10px;background:#f3f6fa;text-align:left">Symptom</th><th style="border:1px solid #d0d7de;padding:8px 10px;background:#f3f6fa;text-align:left">Cause</th><th style="border:1px solid #d0d7de;padding:8px 10px;background:#f3f6fa;text-align:left">Workaround</th></tr></thead><tbody>
<tr><td style="border:1px solid #d0d7de;padding:8px 10px">When run elevated, progress may not appear in the original PowerShell</td><td style="border:1px solid #d0d7de;padding:8px 10px">With our elevated launch via Start-Process -Verb RunAs, no progress was shown in the original PowerShell window (observed)</td><td style="border:1px solid #d0d7de;padding:8px 10px">Have it write to a log file with --log-file and check progress and results there</td></tr><tr><td style="border:1px solid #d0d7de;padding:8px 10px">Writing fails with access denied</td><td style="border:1px solid #d0d7de;padding:8px 10px">Writing to a physical disk requires administrator privileges</td><td style="border:1px solid #d0d7de;padding:8px 10px">Run elevated with Start-Process -Verb RunAs</td></tr><tr><td style="border:1px solid #d0d7de;padding:8px 10px">After first boot, no Wi-Fi connection and no SSH</td><td style="border:1px solid #d0d7de;padding:8px 10px">The line endings of firstrun.sh are CRLF, so the script fails to execute</td><td style="border:1px solid #d0d7de;padding:8px 10px">Re-save with LF line endings and redo the write</td></tr><tr><td style="border:1px solid #d0d7de;padding:8px 10px">raspberrypi.local can&apos;t be found, or an IPv6 address is returned</td><td style="border:1px solid #d0d7de;padding:8px 10px">mDNS name resolution may prefer IPv6</td><td style="border:1px solid #d0d7de;padding:8px 10px">Usually you can connect as is. If not, check the IPv4 address in your router&apos;s admin panel and specify it directly</td></tr><tr><td style="border:1px solid #d0d7de;padding:8px 10px">Automated connections from a script with plink hang on first use</td><td style="border:1px solid #d0d7de;padding:8px 10px">The host-key confirmation prompt doesn&apos;t accept responses piped through standard input</td><td style="border:1px solid #d0d7de;padding:8px 10px">Use -batch and -hostkey &quot;SHA256:...&quot; to specify the fingerprint explicitly and suppress the prompt entirely</td></tr></tbody></table>
<!--kg-card-end: html-->
<p>That last plink trap is a bonus note for anyone who wants to script the whole flow up to the SSH connection. You won&apos;t hit it when typing the ssh command by hand.</p><h2 id="summary">Summary</h2><p>A monitor-less Raspberry Pi 5 setup can be completed safely if you keep these five points in mind.</p><ul><li>Confirm the physical disk number with Get-Disk before writing (most important)</li><li>Get the OS image from raspios_arm64_latest and write it while still xz-compressed</li><li>Put your Wi-Fi, SSH, and user settings into firstrun.sh. Line endings must be LF</li><li>Run the write with administrator privileges and check the results in the --log-file log</li><li>Wait 3 minutes after first boot, then ssh pi@raspberrypi.local</li></ul><p>Once you can log in, we recommend changing the password and updating packages as your first moves.</p><pre><code class="language-bash">passwd
sudo apt update &amp;&amp; sudo apt full-upgrade -y</code></pre><p>If you find yourself wanting a desktop, enabling VNC with sudo raspi-config lets you operate it from Windows like a remote desktop.</p><p>We plan to cover that in a separate article.</p><p>See you next time!</p><h2 id="reference-links">Reference Links</h2><ul><li><a href="https://www.raspberrypi.com/software/?ref=journal.qualiteg.com">Raspberry Pi Imager (official download page)</a></li><li><a href="https://www.raspberrypi.com/software/operating-systems/?ref=journal.qualiteg.com">Raspberry Pi OS image list (official download site)</a></li><li><a href="https://www.raspberrypi.com/news/cloud-init-on-raspberry-pi-os/?ref=journal.qualiteg.com">Cloud-init on Raspberry Pi OS (official blog, on the migration from the firstrun.sh approach to cloud-init)</a></li><li><a href="https://www.chiark.greenend.org.uk/~sgtatham/putty/?ref=journal.qualiteg.com">PuTTY official site (plink download)</a></li></ul>]]></content:encoded></item><item><title><![CDATA[Developing a LINE Bot Locally: Solving the Ever-Changing Webhook URL Problem with a Fixed URL]]></title><description><![CDATA[<p>Hello!</p><p>The first wall you hit when building a LINE Bot is not the code &#x2014; it is the webhook.</p><p>LINE&apos;s Messaging API delivers messages that users send to your bot as HTTPS POST requests from LINE&apos;s servers to your server.</p><p>For this receiving endpoint (the</p>]]></description><link>https://journal.qualiteg.com/line-bot-local-webhook-fixed-url/</link><guid isPermaLink="false">6a78ee9d736fb40d7094ae1c</guid><dc:creator><![CDATA[Qualiteg Product Development Team]]></dc:creator><pubDate>Wed, 12 Aug 2026 13:47:34 GMT</pubDate><media:content url="https://journal.qualiteg.com/content/images/2026/08/line-bot-local-webhook-fixed-url.png" medium="image"/><content:encoded><![CDATA[<img src="https://journal.qualiteg.com/content/images/2026/08/line-bot-local-webhook-fixed-url.png" alt="Developing a LINE Bot Locally: Solving the Ever-Changing Webhook URL Problem with a Fixed URL"><p>Hello!</p><p>The first wall you hit when building a LINE Bot is not the code &#x2014; it is the webhook.</p><p>LINE&apos;s Messaging API delivers messages that users send to your bot as HTTPS POST requests from LINE&apos;s servers to your server.</p><p>For this receiving endpoint (the Webhook URL), you can only specify<strong>an HTTPS URL reachable from the internet</strong>, so you cannot simply enter the <code>http://localhost:5000</code> you use during development.</p><p>The standard workaround is to issue a temporary URL with a tunneling tool, but that brings its own problem. Depending on the tunneling method, a random URL is issued every time you start it. In that case, every time you resume development you have to open the LINE Developers console and rewrite the Webhook URL. Every time you fix your code, every time you pick things up the next day &#x2014; you start by pasting in a new URL. It wears on you.</p><p>To state the conclusion up front:</p><p><strong>give your local development server a single public URL that never changes, and configuring the Webhook URL becomes a one-time task.</strong></p><p>This article covers the entire journey: creating a LINE Official Account, configuring the Messaging API, implementing a webhook receiver in Python, exposing it on a fixed URL, and confirming the bot replies on an actual smartphone.</p><p>Every step, command, and screen shown here was actually run and verified by the author<br>(verified on August 11, 2026; LINE&apos;s screens may change over time).</p><p>The bot itself is a minimal echo bot that returns whatever message it receives. The goal of this article is to build out the full path: a webhook from LINE reaches Python running locally, and a reply appears on your phone.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://journal.qualiteg.com/content/images/2026/08/b11-fig1-v1.png" class="kg-image" alt="Developing a LINE Bot Locally: Solving the Ever-Changing Webhook URL Problem with a Fixed URL" loading="lazy" width="1376" height="768" srcset="https://journal.qualiteg.com/content/images/size/w600/2026/08/b11-fig1-v1.png 600w, https://journal.qualiteg.com/content/images/size/w1000/2026/08/b11-fig1-v1.png 1000w, https://journal.qualiteg.com/content/images/2026/08/b11-fig1-v1.png 1376w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Figure 1: Architecture for developing a LINE Bot locally. The Webhook URL only needs to be configured once</span></figcaption></figure><h2 id="step-1-create-a-line-official-account-current-procedure-as-of-august-2026">Step 1: Create a LINE Official Account (Current Procedure as of August 2026)</h2><p>The first thing to know is that<br><br><strong>Messaging API channels can no longer be created directly from the LINE Developers console</strong><br><br>This screen currently displays the guidance<br>&quot;After creating a LINE Official Account, enable the Messaging API in LINE Official Account Manager&quot;<br>.</p><p>The current flow is as follows.</p><ol><li>Create a LINE Business ID (LY Corporation Business ID). It can be created with just an email address; no LINE app account is required</li><li>Register as a developer on the LINE Developers console and create a provider</li><li>Create a LINE Official Account. During creation you will be asked to connect to a Business Manager organization; if you do not have one, create it on the spot (if you leave the organization name blank, it defaults to the account name)</li><li>Enable the Messaging API in LINE Official Account Manager</li></ol><p>A provider represents the individual, company, or organization offering the bot. When combined with features such as LINE Login, it is also shown on the consent screen, so it is safest to use a name that lets users identify the source, such as your company or service name<br>(the author created one named &quot;Qualiteg&quot;).</p><p>The Official Account creation form asks for the account name (the bot name shown in the friends list and chat screen), company/business name, industry, and so on. One thing to note here:<strong>creating a new Official Account requires phone number verification (SMS or voice call)</strong>. According to the on-screen notice, the phone number used for verification is never disclosed to your friends.</p><p>Leaving the account type as an &quot;unverified account&quot; is fine. A verified account (the green verification badge) has benefits such as appearing in LINE&apos;s in-app search, but a development bot does not need it.</p><h2 id="step-2-enable-the-messaging-api-and-obtain-the-three-keys">Step 2: Enable the Messaging API and Obtain the Three Keys</h2><p>Once the Official Account exists, open LINE Official Account Manager and, under Settings, choose &quot;Messaging API&quot; and click &quot;Use Messaging API.&quot; You will be asked to select a provider here, and<strong>once a provider is linked, it cannot be changed later</strong>. Select the provider you created in Step 1.</p><p>Once enabled, this screen displays the Channel ID and Channel secret.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://journal.qualiteg.com/content/images/2026/08/b11-oam-messaging-api-v2.png" class="kg-image" alt="Developing a LINE Bot Locally: Solving the Ever-Changing Webhook URL Problem with a Fixed URL" loading="lazy" width="1291" height="721" srcset="https://journal.qualiteg.com/content/images/size/w600/2026/08/b11-oam-messaging-api-v2.png 600w, https://journal.qualiteg.com/content/images/size/w1000/2026/08/b11-oam-messaging-api-v2.png 1000w, https://journal.qualiteg.com/content/images/2026/08/b11-oam-messaging-api-v2.png 1291w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">The Messaging API screen in Official Account Manager</span></figcaption></figure><p>Three &quot;keys&quot; are needed for bot development.</p>
<!--kg-card-begin: html-->
<table style="width:100%;border-collapse:collapse;font-size:0.95em"><thead><tr><th style="border:1px solid #d0d7de;padding:8px 10px;background:#f3f6fa;text-align:left">Key</th><th style="border:1px solid #d0d7de;padding:8px 10px;background:#f3f6fa;text-align:left">What it is used for</th><th style="border:1px solid #d0d7de;padding:8px 10px;background:#f3f6fa;text-align:left">Where it is found</th></tr></thead><tbody>
<tr><td style="border:1px solid #d0d7de;padding:8px 10px">Channel ID</td><td style="border:1px solid #d0d7de;padding:8px 10px">Identifier for the channel</td><td style="border:1px solid #d0d7de;padding:8px 10px">Official Account Manager / Developers console</td></tr>
<tr><td style="border:1px solid #d0d7de;padding:8px 10px">Channel secret</td><td style="border:1px solid #d0d7de;padding:8px 10px">Webhook signature verification (prevents spoofing)</td><td style="border:1px solid #d0d7de;padding:8px 10px">Same as above</td></tr>
<tr><td style="border:1px solid #d0d7de;padding:8px 10px">Channel access token (long-lived)</td><td style="border:1px solid #d0d7de;padding:8px 10px">Authentication for the bot&apos;s reply API</td><td style="border:1px solid #d0d7de;padding:8px 10px">Click &quot;Issue&quot; on the &quot;Messaging API settings&quot; tab in the Developers console</td></tr>
</tbody></table>
<!--kg-card-end: html-->
<p>Only the channel access token requires an issuing step in the Developers console. Pass the issued token and the Channel secret via environment variables rather than hard-coding them (we will use them in the next step).</p><h2 id="step-3-write-a-minimal-bot-that-receives-the-webhook">Step 3: Write a Minimal Bot That Receives the Webhook</h2><p>We will write the server in Python, using the official SDK (line-bot-sdk) and Flask.</p><pre><code class="language-plaintext">pip install line-bot-sdk flask</code></pre><p>In the author&apos;s environment, this installed line-bot-sdk 3.25.0 and flask 3.1.3 (Python 3.11).</p><p><code>app.py</code>(full source)</p><pre><code class="language-python">import os

from flask import Flask, request, abort
from linebot.v3 import WebhookHandler
from linebot.v3.exceptions import InvalidSignatureError
from linebot.v3.messaging import (
    ApiClient,
    Configuration,
    MessagingApi,
    ReplyMessageRequest,
    TextMessage,
)
from linebot.v3.webhooks import MessageEvent, TextMessageContent

app = Flask(__name__)

configuration = Configuration(access_token=os.environ[&quot;LINE_CHANNEL_ACCESS_TOKEN&quot;])
handler = WebhookHandler(os.environ[&quot;LINE_CHANNEL_SECRET&quot;])


@app.route(&quot;/health&quot;, methods=[&quot;GET&quot;])
def health():
    return &quot;OK&quot;


@app.route(&quot;/callback&quot;, methods=[&quot;POST&quot;])
def callback():
    signature = request.headers.get(&quot;X-Line-Signature&quot;, &quot;&quot;)
    body = request.get_data(as_text=True)
    try:
        handler.handle(body, signature)
    except InvalidSignatureError:
        abort(400)
    return &quot;OK&quot;


@handler.add(MessageEvent, message=TextMessageContent)
def handle_message(event):
    reply = f&quot;Received your message: \&quot;{event.message.text}\&quot;&quot;
    with ApiClient(configuration) as api_client:
        MessagingApi(api_client).reply_message(
            ReplyMessageRequest(
                reply_token=event.reply_token,
                messages=[TextMessage(text=reply)],
            )
        )


if __name__ == &quot;__main__&quot;:
    app.run(host=&quot;127.0.0.1&quot;, port=5000)</code></pre><p>The code does only three things.<code>/callback</code> receives the POST from LINE, <code>X-Line-Signature</code> is verified against the Channel secret (this verification is built into the SDK, so there is no need to implement it yourself), and when a text message arrives, the bot replies with &quot;Received your message: ...&quot;.</p><p>Note that this code is a minimal example for local development. For production, LINE&apos;s official documentation recommends returning the webhook response (200) promptly and processing events asynchronously.</p><p>Put the keys from Step 2 into environment variables and start the server.</p><pre><code class="language-powershell">$env:LINE_CHANNEL_SECRET = &apos;(Channel secret)&apos;
$env:LINE_CHANNEL_ACCESS_TOKEN = &apos;(channel access token)&apos;
python app.py</code></pre><p><code>http://localhost:5000/health</code> returns <code>OK</code>, the server is up. At this point everything is still confined to localhost, and nothing from LINE can reach it yet.</p><h2 id="step-4-give-localhost-a-public-url-that-never-changes">Step 4: Give localhost a Public URL That Never Changes</h2><p>This is the heart of the matter: attaching an HTTPS URL to localhost:5000 that survives restarts.</p><p>In this article we use WireCanal, a service we develop and operate ourselves (so please read this part with that in mind).</p><p>That said, using a fixed URL is not specific to WireCanal &#x2014; the same approach works with the fixed-domain features of other tunneling services.</p><p>Create a canal (the tunnel&apos;s public endpoint) in the dashboard. Choose HTTP as the type, specify <code>localhost:5000</code> as the forwarding target, and a single public URL is issued.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://journal.qualiteg.com/content/images/2026/08/b11-canal-detail-v2.png" class="kg-image" alt="Developing a LINE Bot Locally: Solving the Ever-Changing Webhook URL Problem with a Fixed URL" loading="lazy" width="1178" height="721" srcset="https://journal.qualiteg.com/content/images/size/w600/2026/08/b11-canal-detail-v2.png 600w, https://journal.qualiteg.com/content/images/size/w1000/2026/08/b11-canal-detail-v2.png 1000w, https://journal.qualiteg.com/content/images/2026/08/b11-canal-detail-v2.png 1178w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">The canal detail screen</span></figcaption></figure><p><strong>This URL is issued with a random string, but it does not change each time you start up.</strong> Reboot your PC, stop the agent and reconnect the next day &#x2014; you keep receiving on the same URL. To be precise about the plan differences: on the free plan the public URL remains valid &quot;as long as it is in use&quot; (it expires 72 hours after the agent&apos;s last connection), so if you develop daily, the URL stays the same. If you want a persistent URL that survives even a pause of three days or more, you need the Lite plan or above (the author tested on the Lite plan; the &quot;Reserved (persistent)&quot; label in the screenshot reflects that).</p><p>Next, install and start the agent on your PC. As described in the setup guide (wirecanal.com), it is a single line in PowerShell.</p><pre><code class="language-powershell">irm https://download.wirecanal.com/install.ps1 | iex</code></pre><p>Download the connection settings file (wirecanal.json) from the dashboard, place it in the same folder as the agent, and start it.</p><pre><code class="language-powershell">.\wirecanal.exe -config wirecanal.json</code></pre><p>When the dashboard shows &quot;Connected!&quot;, access to the public URL is reaching localhost:5000.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://journal.qualiteg.com/content/images/2026/08/b11-canal-setup-v1.png" class="kg-image" alt="Developing a LINE Bot Locally: Solving the Ever-Changing Webhook URL Problem with a Fixed URL" loading="lazy" width="1178" height="721" srcset="https://journal.qualiteg.com/content/images/size/w600/2026/08/b11-canal-setup-v1.png 600w, https://journal.qualiteg.com/content/images/size/w1000/2026/08/b11-canal-setup-v1.png 1000w, https://journal.qualiteg.com/content/images/2026/08/b11-canal-setup-v1.png 1178w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">The setup tab, showing a live connection</span></figcaption></figure><p>Let us verify from the outside.</p><pre><code class="language-plaintext">&gt; curl https://7pqvyoih.ja100.wirecanal.com/health
OK</code></pre><p>The Flask server from Step 3 responded across the internet. No inbound port forwarding and no VPN are involved (the agent communicates using outbound connections only).</p><h2 id="step-5-configure-and-verify-the-webhook-url">Step 5: Configure and Verify the Webhook URL</h2><p>Return to the LINE Developers console and set the Webhook URL on the channel&apos;s &quot;Messaging API settings&quot; tab. It is your public URL with the path handled in app.py, <code>/callback</code>, appended.</p><pre><code class="language-plaintext">https://(your-public-URL)/callback</code></pre><p>After setting it, be sure to<strong>turn on &quot;Use webhook&quot; just below</strong>. Entering the URL alone is not enough for webhooks to be delivered.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://journal.qualiteg.com/content/images/2026/08/b11-webhook-setting-v2.png" class="kg-image" alt="Developing a LINE Bot Locally: Solving the Ever-Changing Webhook URL Problem with a Fixed URL" loading="lazy" width="1178" height="721" srcset="https://journal.qualiteg.com/content/images/size/w600/2026/08/b11-webhook-setting-v2.png 600w, https://journal.qualiteg.com/content/images/size/w1000/2026/08/b11-webhook-setting-v2.png 1000w, https://journal.qualiteg.com/content/images/2026/08/b11-webhook-setting-v2.png 1178w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Webhook settings</span></figcaption></figure><p>Pressing the &quot;Verify&quot; button sends an actual test connection from LINE&apos;s servers to this URL. If it reports &quot;Success,&quot; the path from LINE through the tunnel to your local Flask server is working.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://journal.qualiteg.com/content/images/2026/08/b11-webhook-verify-success-v1.png" class="kg-image" alt="Developing a LINE Bot Locally: Solving the Ever-Changing Webhook URL Problem with a Fixed URL" loading="lazy" width="1178" height="721" srcset="https://journal.qualiteg.com/content/images/size/w600/2026/08/b11-webhook-verify-success-v1.png 600w, https://journal.qualiteg.com/content/images/size/w1000/2026/08/b11-webhook-verify-success-v1.png 1000w, https://journal.qualiteg.com/content/images/2026/08/b11-webhook-verify-success-v1.png 1178w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Verification succeeded</span></figcaption></figure><h2 id="a-stumbling-block-duplicate-replies">A Stumbling Block: Duplicate Replies</h2><p>At this point everything should work &#x2014; yet when the author actually sent a message from a phone, something odd happened. Before the bot&apos;s reply, an unfamiliar canned message arrived.</p><blockquote>&quot;Thank you for your message! Unfortunately, this account cannot respond to individual inquiries.&quot;</blockquote><p>The culprit is the<strong>response messages (auto-reply) feature</strong>built into Official Accounts from the start. On the author&apos;s newly created account, a blanket auto-reply named &quot;Default&quot; was enabled. It operates independently of the webhook, so users were receiving both the bot&apos;s reply and the canned message.</p><p>If you see duplicate replies, check the state of response messages in Official Account Manager. There are two ways to stop them: disable the individual message in the response message list, or<strong>turn off &quot;Response messages&quot; for the whole feature under &quot;Settings&quot; &#x2192; &quot;Response settings&quot;</strong>. You can confirm whether they are currently being sent via &quot;Current status&quot; at the top of the response message list (if it says the feature is in use and response messages are being sent, they will still go out). The author failed to notice this status was still &quot;in use&quot; and wasted one round of testing.</p><h2 id="trying-it-from-a-smartphone">Trying It from a Smartphone</h2><p>Scan the friend-add QR code (found under &quot;Add friends guide&quot; in Official Account Manager) with LINE on your phone, add the bot as a friend, and send it a message.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://journal.qualiteg.com/content/images/2026/08/b11-chat-iphone-v1.png" class="kg-image" alt="Developing a LINE Bot Locally: Solving the Ever-Changing Webhook URL Problem with a Fixed URL" loading="lazy" width="400" height="867"><figcaption><span style="white-space: pre-wrap;">On an actual iPhone: the bot replies instantly to &quot;&#x3053;&#x3093;&#x306B;&#x3061;&#x306F;&quot; (hello)</span></figcaption></figure><p>Send &quot;&#x3053;&#x3093;&#x306B;&#x3061;&#x306F;&quot; (hello), and the reply comes back immediately: Received your message: &quot;&#x3053;&#x3093;&#x306B;&#x3061;&#x306F;&quot;. The server-side log also records the POST from LINE.</p><pre><code class="language-plaintext">127.0.0.1 - - [11/Aug/2026 00:24:32] &quot;POST /callback HTTP/1.1&quot; 200 -</code></pre><p>With this, the entire path is connected: LINE on your phone &#x2192; the LINE platform &#x2192; the fixed public URL &#x2192; Flask on your local PC &#x2192; the reply.</p><h2 id="summary-no-more-url-rewriting">Summary: No More URL Rewriting</h2><p>The biggest benefit of this setup is that resuming development the next day comes down to starting the agent and app.py. Because the public URL never changes, there is simply no step where you reopen the LINE Developers console and paste in a new Webhook URL. After a code change, restarting app.py is all it takes to test on the same URL.</p><p>Finally, here are the key points of this setup.</p>
<!--kg-card-begin: html-->
<table style="width:100%;border-collapse:collapse;font-size:0.95em"><thead><tr><th style="border:1px solid #d0d7de;padding:8px 10px;background:#f3f6fa;text-align:left">Key point</th><th style="border:1px solid #d0d7de;padding:8px 10px;background:#f3f6fa;text-align:left">Details</th></tr></thead><tbody>
<tr><td style="border:1px solid #d0d7de;padding:8px 10px">How to create a Messaging API channel</td><td style="border:1px solid #d0d7de;padding:8px 10px">Currently via a LINE Official Account (cannot be created directly from the console; phone number verification required)</td></tr>
<tr><td style="border:1px solid #d0d7de;padding:8px 10px">When webhooks do not arrive</td><td style="border:1px solid #d0d7de;padding:8px 10px">First check that &quot;Use webhook&quot; is on and that &quot;Verify&quot; succeeds</td></tr>
<tr><td style="border:1px solid #d0d7de;padding:8px 10px">When replies arrive in duplicate</td><td style="border:1px solid #d0d7de;padding:8px 10px">Turn off response messages (check &quot;Current status&quot; at the top of the list)</td></tr>
<tr><td style="border:1px solid #d0d7de;padding:8px 10px">URL rewriting</td><td style="border:1px solid #d0d7de;padding:8px 10px">The public URL does not change across restarts (free: valid while in use; Lite and above: persistent). The Webhook URL is configured only once</td></tr>
</tbody></table>
<!--kg-card-end: html-->
<p>See you next time.</p><h2 id="sources-and-references">Sources and References</h2><ul><li><a href="https://developers.line.biz/ja/docs/messaging-api/getting-started/?ref=journal.qualiteg.com">Get started with the Messaging API (LINE Developers official documentation)</a></li><li><a href="https://developers.line.biz/ja/docs/messaging-api/overview/?ref=journal.qualiteg.com">Messaging API overview (LINE Developers official documentation)</a></li><li><a href="https://github.com/line/line-bot-sdk-python?ref=journal.qualiteg.com">line-bot-sdk-python (official LINE SDK, GitHub)</a></li><li><a href="https://wirecanal.com/pricing?ref=journal.qualiteg.com">WireCanal pricing plans</a></li><li><a href="https://wirecanal.com/setup/windows?ref=journal.qualiteg.com">WireCanal setup guide (Windows)</a></li></ul><h2 id="related-articles">Related Articles</h2><ul><li><a href="https://journal.qualiteg.com/ngrok-wirecanal-comparison/">What Sets ngrok and WireCanal Apart? The Developers Compare Pricing, Operations, and MCP Design</a></li><li><a href="https://journal.qualiteg.com/ollama-local-llm-from-smartphone-via-wirecanal/">Use a Local LLM on Your Home PC from Your Phone While Out: Ollama + Open WebUI + WireCanal</a></li></ul>]]></content:encoded></item><item><title><![CDATA[Use a Local LLM on Your Home PC from Your Phone While Out: Ollama + Open WebUI + WireCanal]]></title><description><![CDATA[Add a chat interface to the local LLM on your home PC (Ollama + gemma4) with Open WebUI, expose it safely through a tunnel, and use it from your phone while out — a fully measured, step-by-step guide. No Docker, no WSL, and no port forwarding required.]]></description><link>https://journal.qualiteg.com/ollama-local-llm-from-smartphone-via-wirecanal/</link><guid isPermaLink="false">6a77b295f8da991460bcb61f</guid><dc:creator><![CDATA[Qualiteg Product Development Team]]></dc:creator><pubDate>Mon, 10 Aug 2026 12:26:59 GMT</pubDate><media:content url="https://journal.qualiteg.com/content/images/2026/08/ollama-local-llm-from-smartphone-via-wirecanal--1-.png" medium="image"/><content:encoded><![CDATA[<img src="https://journal.qualiteg.com/content/images/2026/08/ollama-local-llm-from-smartphone-via-wirecanal--1-.png" alt="Use a Local LLM on Your Home PC from Your Phone While Out: Ollama + Open WebUI + WireCanal"><p>Hello!</p><p>If you run a local LLM on a GPU-equipped PC at home, sooner or later a moment arrives when you are out and think, &quot;I&apos;d like to ask my own model about this.&quot;</p><p>Your home PC carries models you chose or tuned yourself, and your conversation history can stay on your own machine.</p><p>Having built that environment, it is only natural to want to use it from your phone as well.</p><p>At the same time, opening a port on your home router and exposing it to the outside is an uncomfortable prospect.</p><p>To state the conclusion up front:<br><br><strong>with a single Windows PC, you can get to a state where you chat in Japanese with your home LLM from your phone while out</strong><br><br>. No Docker, no WSL, and no port forwarding involved.</p><p>This article walks through the entire procedure: running a local LLM with Ollama and gemma4, adding a chat interface with Open WebUI, exposing it through a tunnel, and using it from an actual smartphone.</p><p>Every step, command, and screen shown here was actually run and verified by the author. The test machine is Windows 11 Pro with a GeForce RTX 3090 Ti (24GB), but with an appropriate model choice the same setup works on a 12GB-class GPU.</p><p>Note that this article covers using your home PC&apos;s LLM from outside, by yourself, for yourself.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://journal.qualiteg.com/content/images/2026/08/s1-fig1-v1.png" class="kg-image" alt="Use a Local LLM on Your Home PC from Your Phone While Out: Ollama + Open WebUI + WireCanal" loading="lazy" width="1376" height="768" srcset="https://journal.qualiteg.com/content/images/size/w600/2026/08/s1-fig1-v1.png 600w, https://journal.qualiteg.com/content/images/size/w1000/2026/08/s1-fig1-v1.png 1000w, https://journal.qualiteg.com/content/images/2026/08/s1-fig1-v1.png 1376w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Figure 1: Architecture for using a home local LLM from a smartphone</span></figcaption></figure><h2 id="step-1-install-ollama-and-run-gemma4-on-the-gpu">Step 1: Install Ollama and Run gemma4 on the GPU</h2><p>First, install Ollama, the runtime that runs the LLM.</p><p><a href="https://ollama.com/?ref=journal.qualiteg.com">From the official Ollama site</a>, simply download and run OllamaSetup.exe. Walking through the wizard completes the install (the author used the silent install <code>OllamaSetup.exe /VERYSILENT</code>; the version verified was v0.32.6).</p><p>The GPU is detected automatically, so no manual CUDA setup is required.</p><p>One thing worth deciding in advance is where models are stored. By default, models accumulate in your user folder on the C drive. A single model can easily consume around 10GB, so if you want to move them to a larger drive, specify the location with a system environment variable.<br>The author used the D drive as the storage location.</p><pre><code class="language-plaintext">OLLAMA_MODELS = D:\qualiteg_examples\ollama-models</code></pre><p>For the model, we chose gemma4 (a 9.6GB download) from the top of Ollama&apos;s library rankings &#x2014; its Japanese is natural and it fits within our GPU.</p><pre><code class="language-plaintext">ollama pull gemma4</code></pre><p>Once the download completes, verify it works. Here we ask, in Japanese, &quot;What is the capital of Japan?&quot; and it answers &quot;Tokyo.&quot;</p><pre><code class="language-plaintext">&gt; ollama run gemma4 &quot;&#x65E5;&#x672C;&#x306E;&#x9996;&#x90FD;&#x306F;&quot;
&#x6771;&#x4EAC;&#xFF08;&#x3068;&#x3046;&#x304D;&#x3087;&#x3046;&#xFF09;&#x3067;&#x3059;&#x3002;</code></pre><p>Whether the model is loaded on the GPU can be checked with <code>ollama ps</code>.</p><pre><code class="language-plaintext">NAME             ID              SIZE      PROCESSOR    CONTEXT
gemma4:latest    c6eb396dbd59    3.4 GB    100% GPU     32768</code></pre><p>If PROCESSOR shows 100% GPU, you are in good shape. If it has fallen back to the CPU, responses become orders of magnitude slower, so be sure to check this. Incidentally, while the download is 9.6GB, on the author&apos;s Ollama 0.32.6 the SIZE column in ps showed 3.4GB (reported here as measured, without adjustment).</p><h2 id="step-2-eliminate-the-no-reply-the-first-time-problem-up-front">Step 2: Eliminate the &quot;No Reply the First Time&quot; Problem Up Front</h2><p>This was the most alarming moment during the build.</p><p>Ask a question after leaving the machine idle for a while, and the screen stays silent for tens of seconds. Suspecting something was broken, we checked the logs &#x2014; the inference itself had finished in 2.1 seconds.</p><p>The culprit is Ollama&apos;s default behavior.<strong>After 5 minutes of inactivity, it unloads the model from the GPU.</strong>The moment the next question arrives it reloads all 9.6GB, and during that time the system appears unresponsive.</p><p>When using it from a phone while out, the typical pattern is &quot;open it occasionally and ask one question,&quot; which means hitting this reload every time. Keep the model resident via a system environment variable.</p><pre><code class="language-plaintext">OLLAMA_KEEP_ALIVE = -1</code></pre><p>After setting it, restart Ollama and check <code>ollama ps</code> &#x2014; the UNTIL column will show Forever.</p><pre><code class="language-plaintext">NAME             ID              SIZE      PROCESSOR    CONTEXT    UNTIL
gemma4:latest    c6eb396dbd59    3.4 GB    100% GPU     32768      Forever</code></pre><p>Now the very first question gets an immediate answer no matter how long the machine sits idle. If the PC&apos;s GPU is also used for gaming or training, look for a compromise with a value like <code>24h</code> instead of -1.</p><h2 id="step-3-open-webui-installs-with-pip-no-docker-needed">Step 3: Open WebUI Installs with pip (No Docker Needed)</h2><p>For the chat interface we used<a href="https://docs.openwebui.com/?ref=journal.qualiteg.com">Open WebUI</a>.</p><p>It is a well-established OSS project with a ChatGPT-like UI that discovers Ollama automatically.</p><p>Open WebUI<strong>officially supports installation via pip.</strong></p><p>Open WebUI supports Python 3.11 and 3.12; 3.13 is not supported<br>(the official recommendation is 3.11; the author created a 3.11.15 environment with conda, though venv works just as well).</p><pre><code class="language-plaintext">pip install open-webui</code></pre><p>With its many dependencies, this takes a few minutes. Once installed, start it with two environment variables (the version verified was v0.11.0).</p><pre><code class="language-powershell">$env:OLLAMA_BASE_URL = &apos;http://localhost:11434&apos;
$env:DATA_DIR = &apos;D:\qualiteg_examples\open-webui-data&apos;
open-webui serve --port 3000</code></pre><p>OLLAMA_BASE_URL points to the Ollama instance from Step 1, and DATA_DIR is where user data and chat history are stored.</p><p>In the author&apos;s environment, about 35 seconds after startup <code>http://localhost:3000/health</code> returned <code>{&quot;status&quot;:true}</code>.</p><p>Open <code>http://localhost:3000</code> in a browser and you will be prompted to create the first account.<strong>The first account created here becomes the administrator.</strong>Publishing comes later, but make it a firm habit: complete the administrator registration before exposing anything. If you publish first, any third party who happens to hit the URL could become the administrator.</p><h2 id="step-4-expose-it-externally-without-opening-an-inbound-port">Step 4: Expose It Externally Without Opening an Inbound Port</h2><p>Here is the heart of the matter: making localhost:3000 reachable from your phone while you are out.</p><p>There are several ways to expose it.</p>
<!--kg-card-begin: html-->
<table style="width:100%;border-collapse:collapse;font-size:0.95em"><thead><tr><th style="border:1px solid #d0d7de;padding:8px 10px;background:#f3f6fa;text-align:left">Method</th><th style="border:1px solid #d0d7de;padding:8px 10px;background:#f3f6fa;text-align:left">Ease</th><th style="border:1px solid #d0d7de;padding:8px 10px;background:#f3f6fa;text-align:left">Concerns</th></tr></thead><tbody>
<tr><td style="border:1px solid #d0d7de;padding:8px 10px">Router port forwarding + DDNS</td><td style="border:1px solid #d0d7de;padding:8px 10px">Lots of configuration</td><td style="border:1px solid #d0d7de;padding:8px 10px">An inbound port at home is permanently exposed</td></tr>
<tr><td style="border:1px solid #d0d7de;padding:8px 10px">VPN (Tailscale, etc.)</td><td style="border:1px solid #d0d7de;padding:8px 10px">Easy</td><td style="border:1px solid #d0d7de;padding:8px 10px">Every device you use needs the app installed</td></tr>
<tr><td style="border:1px solid #d0d7de;padding:8px 10px">Tunnel-based (this article)</td><td style="border:1px solid #d0d7de;padding:8px 10px">Easy</td><td style="border:1px solid #d0d7de;padding:8px 10px">Traffic passes through a relay server</td></tr>
</tbody></table>
<!--kg-card-end: html-->
<p>This time we use the tunnel-based approach.</p><p>All communication happens over outbound connections established from the home side to the tunnel provider, so<strong>not a single inbound port at home is opened.</strong></p><p>In this article we use WireCanal, a service we develop and operate ourselves. For the use case in this article, the free plan is more than sufficient, and no card registration is required.</p><p>There are only three steps.</p><p>First, in<a href="https://app.wirecanal.com/?ref=journal.qualiteg.com">the WireCanal dashboard</a>, create a canal (the tunnel&apos;s public endpoint). Choose HTTP as the type, specify <code>localhost:3000</code> as the forwarding target, and a single public URL is issued.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://journal.qualiteg.com/content/images/2026/08/image.png" class="kg-image" alt="Use a Local LLM on Your Home PC from Your Phone While Out: Ollama + Open WebUI + WireCanal" loading="lazy" width="1156" height="707" srcset="https://journal.qualiteg.com/content/images/size/w600/2026/08/image.png 600w, https://journal.qualiteg.com/content/images/size/w1000/2026/08/image.png 1000w, https://journal.qualiteg.com/content/images/2026/08/image.png 1156w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">The detail screen of a canal (the tunnel&apos;s public endpoint). The public URL and the forwarding target are mapped one to one</span></figcaption></figure><p>Next, install the Agent on your home PC.<a href="https://wirecanal.com/setup/windows?ref=journal.qualiteg.com">As described in the setup guide (wirecanal.com)</a>, it is a single line in PowerShell (the Agent version verified was v0.18.0).</p><pre><code class="language-powershell">irm https://download.wirecanal.com/install.ps1 | iex</code></pre><p>Download wirecanal.json (the connection settings) from the dashboard and place it in the same folder as the Agent, and you are ready.</p><p>Finally, register the Agent as a Windows service. It works when started manually as well, but as a service it recovers on its own after a PC reboot.</p><pre><code class="language-powershell">.\wirecanal.exe service install -config wirecanal.json</code></pre><pre><code class="language-plaintext">wirecanal service install: service &quot;wirecanal-agent&quot; installed (auto start; restarts 5s after a failure)
wirecanal service install: service started.</code></pre><p>Now, accessing the public URL brings up the login screen of the Open WebUI running at home. Run through the full flow once in a PC browser (log in &#x2192; ask a question &#x2192; get a response) to confirm it works before taking it outside.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://journal.qualiteg.com/content/images/2026/08/s1-chat-pc-v3.png" class="kg-image" alt="Use a Local LLM on Your Home PC from Your Phone While Out: Ollama + Open WebUI + WireCanal" loading="lazy" width="1506" height="733" srcset="https://journal.qualiteg.com/content/images/size/w600/2026/08/s1-chat-pc-v3.png 600w, https://journal.qualiteg.com/content/images/size/w1000/2026/08/s1-chat-pc-v3.png 1000w, https://journal.qualiteg.com/content/images/2026/08/s1-chat-pc-v3.png 1506w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Chatting with gemma4 from a PC browser via the public URL</span></figcaption></figure><h2 id="step-5-use-it-from-your-phone">Step 5: Use It from Your Phone</h2><p>All that remains is to open the public URL on your phone while out.</p><p>As a convenience, you can display a QR code for the canal&apos;s URL on the canal detail screen beforehand and scan it with your phone, saving you from typing the URL</p><figure class="kg-card kg-image-card"><img src="https://journal.qualiteg.com/content/images/2026/08/image-1.png" class="kg-image" alt="Use a Local LLM on Your Home PC from Your Phone While Out: Ollama + Open WebUI + WireCanal" loading="lazy" width="1153" height="707" srcset="https://journal.qualiteg.com/content/images/size/w600/2026/08/image-1.png 600w, https://journal.qualiteg.com/content/images/size/w1000/2026/08/image-1.png 1000w, https://journal.qualiteg.com/content/images/2026/08/image-1.png 1153w" sizes="(min-width: 720px) 720px"></figure><p>Log in with the account created in Step 3, and the same chat screen you saw on your home PC appears as is.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://journal.qualiteg.com/content/images/2026/08/s1-chat-iphone-v1.png" class="kg-image" alt="Use a Local LLM on Your Home PC from Your Phone While Out: Ollama + Open WebUI + WireCanal" loading="lazy" width="1290" height="2404" srcset="https://journal.qualiteg.com/content/images/size/w600/2026/08/s1-chat-iphone-v1.png 600w, https://journal.qualiteg.com/content/images/size/w1000/2026/08/s1-chat-iphone-v1.png 1000w, https://journal.qualiteg.com/content/images/2026/08/s1-chat-iphone-v1.png 1290w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">On an actual iPhone: gemma4 at home responding over a mobile connection</span></figcaption></figure><p>Over a mobile connection, gemma4 running on the RTX 3090 Ti at home answers in Japanese.</p><p>The model itself and Open WebUI&apos;s conversation history are stored on your home PC (the communication with your phone itself passes through the tunnel&apos;s relay server; the public URL is HTTPS).</p><p>With that, you can access your own dedicated LLM from wherever you are.</p><h2 id="how-to-think-about-safety-when-exposing-to-the-internet">How to Think About Safety When Exposing to the Internet</h2><p>In this setup, Open WebUI&apos;s own login acts as the gatekeeper &#x2014; as noted in Step 3, complete the administrator registration before publishing. WireCanal also provides access protections such as IP, country, and time-of-day restrictions as standard, so combine them as your use case requires.</p><p>A canal can be paused and resumed at any time from a phone browser, so it is also easy to open the line only when you use it and keep the canal stopped otherwise.</p><p>Please read this article as one example of a setup for using your machine from outside without opening ports.</p><h2 id="making-it-persistent-so-it-is-always-available">Making It Persistent So It Is Always Available</h2><p>Finally, we make the setup survive PC reboots and re-logons. The Agent was already registered as a service in Step 4, so what remains is Ollama and Open WebUI. Register them as &quot;at startup&quot; tasks in Task Scheduler (run PowerShell as administrator).</p><pre><code class="language-powershell">$action   = New-ScheduledTaskAction -Execute &apos;powershell.exe&apos; `
  -Argument &apos;-NoProfile -ExecutionPolicy Bypass -File D:\qualiteg_examples\open-webui\run-open-webui.ps1&apos;
$trigger  = New-ScheduledTaskTrigger -AtStartup
$settings = New-ScheduledTaskSettingsSet -ExecutionTimeLimit ([TimeSpan]::Zero) `
  -RestartCount 5 -RestartInterval (New-TimeSpan -Minutes 1)
Register-ScheduledTask -TaskName &apos;openwebui-serve&apos; -Action $action -Trigger $trigger `
  -User &apos;SYSTEM&apos; -RunLevel Highest -Settings $settings</code></pre><p>The contents of run-open-webui.ps1 are almost the same as the startup command in Step 3, with one important difference. A task running as SYSTEM does not go through conda activate, so<strong>open-webui must be specified as the absolute path to the executable inside the environment.</strong></p><pre><code class="language-powershell">$env:OLLAMA_BASE_URL = &apos;http://localhost:11434&apos;
$env:DATA_DIR = &apos;D:\qualiteg_examples\open-webui-data&apos;
&amp; &apos;C:\tools\Anaconda3\envs\openwebui\Scripts\open-webui.exe&apos; serve --port 3000</code></pre><p>The key points are disabling the execution time limit (the default cuts tasks off at 72 hours) and running as SYSTEM, decoupled from logons. Create a task of the same shape for Ollama, <code>ollama serve</code>. Specify ollama.exe by absolute path here as well (in the author&apos;s environment, <code>C:\Users\&lt;your-username&gt;\AppData\Local\Programs\Ollama\ollama.exe</code>). The regular installer version also sets up auto-start at logon, so disable that auto-start to avoid running two instances.</p><p>One more caveat: if a PowerShell script launched from a SYSTEM task contains Japanese comments, it may fail to run due to an encoding mismatch (UTF-8 without BOM being read as ANSI). Write scripts in ASCII only, or save them as UTF-8 with BOM. This cost us another 30 minutes.</p><h2 id="summary-your-home-gpu-available-from-your-pocket">Summary: Your Home GPU, Available from Your Pocket</h2><p>Listing what we did: one installer, one pip install, a tunnel configuration, and a few environment variables. Without any elaborate machinery, your home GPU machine becomes your own dedicated LLM server.</p><p>Finally, here are the key points of this setup.</p>
<!--kg-card-begin: html-->
<table style="width:100%;border-collapse:collapse;font-size:0.95em"><thead><tr><th style="border:1px solid #d0d7de;padding:8px 10px;background:#f3f6fa;text-align:left">Key point</th><th style="border:1px solid #d0d7de;padding:8px 10px;background:#f3f6fa;text-align:left">Setting</th></tr></thead><tbody>
<tr><td style="border:1px solid #d0d7de;padding:8px 10px">Keep the model resident on the GPU</td><td style="border:1px solid #d0d7de;padding:8px 10px"><code>OLLAMA_KEEP_ALIVE=-1</code></td></tr>
<tr><td style="border:1px solid #d0d7de;padding:8px 10px">Prevent administrator takeover</td><td style="border:1px solid #d0d7de;padding:8px 10px">Create the first account before publishing</td></tr>
<tr><td style="border:1px solid #d0d7de;padding:8px 10px">Survive reboots</td><td style="border:1px solid #d0d7de;padding:8px 10px">Agent as a service; Ollama / Open WebUI as startup tasks (absolute paths)</td></tr>
</tbody></table>
<!--kg-card-end: html-->
<p>See you next time.</p><h2 id="sources-and-references">Sources and References</h2><ul><li><a href="https://ollama.com/?ref=journal.qualiteg.com">Ollama official site (download)</a></li><li><a href="https://docs.ollama.com/faq?ref=journal.qualiteg.com">Ollama FAQ (keep_alive behavior)</a></li><li><a href="https://docs.openwebui.com/?ref=journal.qualiteg.com">Open WebUI official documentation (pip installation and Python requirements)</a></li><li><a href="https://wirecanal.com/setup/windows?ref=journal.qualiteg.com">WireCanal setup guide (Windows)</a></li></ul><h2 id="related-articles">Related Articles</h2><ul><li><a href="https://journal.qualiteg.com/mcp-server-python-fastmcp-database-part1/">How to Build an MCP Server &#x2014; Writing Your Own in Python with FastMCP, Until AI Answers Database Questions in Japanese (Part 1)</a></li><li><a href="https://journal.qualiteg.com/mcp-server-python-fastmcp-database-part2/">How to Build an MCP Server &#x2014; Using Your Own MCP Server from Web-Based ChatGPT and Claude (Part 2)</a></li></ul>]]></content:encoded></item><item><title><![CDATA[How to Build an MCP Server — Using Your Own MCP Server from Web-Based ChatGPT and Claude (Part 2)]]></title><description><![CDATA[A step-by-step guide, with real connection screenshots, to making your own MCP server usable from web-based ChatGPT and Claude. We give a localhost server a public URL and OAuth authentication, letting browser AI query a sales database in Japanese without changing a single line of code.]]></description><link>https://journal.qualiteg.com/mcp-server-python-fastmcp-database-part2/</link><guid isPermaLink="false">6a734e32edf69a17d422ab8d</guid><dc:creator><![CDATA[Qualiteg Product Development Team]]></dc:creator><pubDate>Sun, 09 Aug 2026 08:04:52 GMT</pubDate><media:content url="https://journal.qualiteg.com/content/images/2026/08/how_to_make_mcp_server_02.png" medium="image"/><content:encoded><![CDATA[<img src="https://journal.qualiteg.com/content/images/2026/08/how_to_make_mcp_server_02.png" alt="How to Build an MCP Server &#x2014; Using Your Own MCP Server from Web-Based ChatGPT and Claude (Part 2)"><p>Hello! This is the Qualiteg Product Development Team!</p><p>In Part 1, we built our own MCP server with Python and FastMCP, getting to the point where we could query a sales database in Japanese from Claude Code on our local machine. In this Part 2, we continue as promised.</p><p><strong>We will make this MCP server, running locally on localhost, usable from the web versions of ChatGPT and Claude.</strong></p><p>To state the conclusion first: without changing a single line of server code, the question &quot;show me the top 3 occupations by sales&quot; now works from both browser-based ChatGPT and Claude. The numbers returned match the measured values from Part 1 exactly. The three walls &#x2014; reachability, HTTPS, and OAuth authentication &#x2014; are crossed with our own WireCanal. As disclosed at the end of Part 1, it is our own service, but every step in this article uses only features available on the free plan. No credit card registration is required.</p><p>If you have not read Part 1, you can find it here.</p><p><a href="https://journal.qualiteg.com/mcp-server-python-fastmcp-database-part1/">How to Build an MCP Server (Part 1) | Connecting a Sales DB to AI with Python and FastMCP (this blog)</a></p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://journal.qualiteg.com/content/images/2026/08/mcp-tutorial2-fig1-series-nb.jpg" class="kg-image" alt="How to Build an MCP Server &#x2014; Using Your Own MCP Server from Web-Based ChatGPT and Claude (Part 2)" loading="lazy" width="1376" height="768" srcset="https://journal.qualiteg.com/content/images/size/w600/2026/08/mcp-tutorial2-fig1-series-nb.jpg 600w, https://journal.qualiteg.com/content/images/size/w1000/2026/08/mcp-tutorial2-fig1-series-nb.jpg 1000w, https://journal.qualiteg.com/content/images/2026/08/mcp-tutorial2-fig1-series-nb.jpg 1376w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Figure 1: What this series builds. Part 1 reaches local AI; Part 2 connects to web-based ChatGPT and Claude</span></figcaption></figure><h2 id="why-the-web-versions-cannot-use-it-while-it-stays-on-localhost">Why the Web Versions Cannot Use It While It Stays on localhost</h2><p>When the server from Part 1 is started in HTTP mode, <code>http://127.0.0.1:9904/mcp</code> becomes the MCP endpoint. The CLI version of Claude Code lives on the same PC, so this URL is reachable for it.</p><p>The web versions are an entirely different story. For both ChatGPT and Claude, the connection requests to a connector are sent by<strong>their servers</strong> &#x2014; not by your browser. That gives us three walls.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://journal.qualiteg.com/content/images/2026/08/mcp-tutorial2-fig2-three-walls-nb.jpg" class="kg-image" alt="How to Build an MCP Server &#x2014; Using Your Own MCP Server from Web-Based ChatGPT and Claude (Part 2)" loading="lazy" width="1376" height="768" srcset="https://journal.qualiteg.com/content/images/size/w600/2026/08/mcp-tutorial2-fig2-three-walls-nb.jpg 600w, https://journal.qualiteg.com/content/images/size/w1000/2026/08/mcp-tutorial2-fig2-three-walls-nb.jpg 1000w, https://journal.qualiteg.com/content/images/2026/08/mcp-tutorial2-fig2-three-walls-nb.jpg 1376w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Figure 2: Web-based AI cannot reach an MCP server on localhost. There are three walls: reachability, HTTPS, and authentication</span></figcaption></figure><p>The first is reachability. On a typical home or office network, your PC sits behind NAT and a firewall and cannot be reached from outside as is. The second is HTTPS. URLs registered with a connector are expected to be <code>https://</code>. The third is authentication. Making the server reachable from outside means it is reachable by anyone in the world, so running a server connected to an internal database without authentication is simply not an option.</p><p>Of these, the third is the most formidable.</p><p>Both ChatGPT and Claude can, in some configurations, connect to a remote MCP server without authentication. But since exposing a server that reaches an internal database unauthenticated is not an option, we protect it with OAuth in line with the MCP Authorization specification. That means returning 401 to unauthenticated access, publishing authorization server information, handling client information, and providing the authorization screen, token issuance, and per-request verification. Implementing all of this yourself is a far larger job than the tool itself (the 200 lines we wrote in Part 1). This is where people tend to run out of steam and settle for &quot;forget the web versions, we&apos;ll just use the CLI&quot; &#x2014; such was the reality of remote MCP.</p><h2 id="wirecanal-takes-on-all-three-at-once">WireCanal Takes On All Three at Once</h2><p>So in Part 2 we use WireCanal, the secure tunnel service we provide.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://journal.qualiteg.com/content/images/2026/08/mcp-tutorial2-fig3-architecture-nb.jpg" class="kg-image" alt="How to Build an MCP Server &#x2014; Using Your Own MCP Server from Web-Based ChatGPT and Claude (Part 2)" loading="lazy" width="1376" height="768" srcset="https://journal.qualiteg.com/content/images/size/w600/2026/08/mcp-tutorial2-fig3-architecture-nb.jpg 600w, https://journal.qualiteg.com/content/images/size/w1000/2026/08/mcp-tutorial2-fig3-architecture-nb.jpg 1000w, https://journal.qualiteg.com/content/images/2026/08/mcp-tutorial2-fig3-architecture-nb.jpg 1376w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Figure 3: The architecture via WireCanal. Only calls that pass both the OAuth authorization and the tool allowlist reach the MCP server</span></figcaption></figure><p>The mechanism is shown in Figure 3. Run a small program called the Agent on your PC, and the Agent connects<strong>outbound</strong> to WireCanal&apos;s servers to establish a tunnel. No inbound port opening and no VPN are required. On the outside, a public URL of the form <code>https://&lt;name&gt;.wirecanal.com</code> is created, and requests arriving there flow through the tunnel to your local <code>127.0.0.1:9904</code>.</p><p>The same URL also handles OAuth. Unauthenticated access receives a 401, and connections from ChatGPT and Claude go through only if the owner has approved them on WireCanal&apos;s authorization screen.</p><p>There is one more mechanism specific to MCP.<strong>You choose which tools may be shown to outside AI in a local configuration file (wirecanal.json).</strong> The default denies all tools, and only tools listed in the allowlist are exposed. The authoritative copy of this allowlist lives in the local file. Changes made from the dashboard are treated as proposals, and no additional tools become public unless approved and applied on the local side.</p><p>With that, we start from the state where the Part 1 server is running at <code>127.0.0.1:9904</code>.</p><h2 id="step-1-create-a-canal-in-the-dashboard">Step 1: Create a canal in the Dashboard</h2><p><a href="https://app.wirecanal.com/?ref=journal.qualiteg.com">Register an account on the WireCanal dashboard (app.wirecanal.com)</a> and you can create a public route called a &quot;canal.&quot; The creation wizard has five steps.</p><p>First, the type. Choose &quot;MCP &#x2014; expose an internal MCP server to AI services.&quot;</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://journal.qualiteg.com/content/images/2026/08/mcp-tutorial2-canal-type.png" class="kg-image" alt="How to Build an MCP Server &#x2014; Using Your Own MCP Server from Web-Based ChatGPT and Claude (Part 2)" loading="lazy" width="1359" height="704" srcset="https://journal.qualiteg.com/content/images/size/w600/2026/08/mcp-tutorial2-canal-type.png 600w, https://journal.qualiteg.com/content/images/size/w1000/2026/08/mcp-tutorial2-canal-type.png 1000w, https://journal.qualiteg.com/content/images/2026/08/mcp-tutorial2-canal-type.png 1359w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">The canal creation wizard. Choose &quot;MCP&quot; as the type</span></figcaption></figure><p>Next, &quot;Which AI will use it?&quot; This time we checked both Claude and ChatGPT. Based on the AI selected here, the OAuth connection settings are added to the canal automatically.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://journal.qualiteg.com/content/images/2026/08/mcp-tutorial2-canal-ai.png" class="kg-image" alt="How to Build an MCP Server &#x2014; Using Your Own MCP Server from Web-Based ChatGPT and Claude (Part 2)" loading="lazy" width="1359" height="704" srcset="https://journal.qualiteg.com/content/images/size/w600/2026/08/mcp-tutorial2-canal-ai.png 600w, https://journal.qualiteg.com/content/images/size/w1000/2026/08/mcp-tutorial2-canal-ai.png 1000w, https://journal.qualiteg.com/content/images/2026/08/mcp-tutorial2-canal-ai.png 1359w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Checking both Claude and ChatGPT under &quot;Which AI will use it?&quot;</span></figcaption></figure><p>For the public address, proceed with the auto-assigned subdomain. For the forwarding target, enter <code>127.0.0.1:9904</code>, where the Part 1 server is listening.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://journal.qualiteg.com/content/images/2026/08/mcp-tutorial2-canal-forward.png" class="kg-image" alt="How to Build an MCP Server &#x2014; Using Your Own MCP Server from Web-Based ChatGPT and Claude (Part 2)" loading="lazy" width="1359" height="704" srcset="https://journal.qualiteg.com/content/images/size/w600/2026/08/mcp-tutorial2-canal-forward.png 600w, https://journal.qualiteg.com/content/images/size/w1000/2026/08/mcp-tutorial2-canal-forward.png 1000w, https://journal.qualiteg.com/content/images/2026/08/mcp-tutorial2-canal-forward.png 1359w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Specifying 127.0.0.1:9904, where the Part 1 server listens, as the forwarding target</span></figcaption></figure><p>The public URL is finalized on the confirmation screen. In the author&apos;s environment, <code>https://mh1sjzat.ja100.wirecanal.com</code> was issued.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://journal.qualiteg.com/content/images/2026/08/mcp-tutorial2-canal-confirm.png" class="kg-image" alt="How to Build an MCP Server &#x2014; Using Your Own MCP Server from Web-Based ChatGPT and Claude (Part 2)" loading="lazy" width="1359" height="704" srcset="https://journal.qualiteg.com/content/images/size/w600/2026/08/mcp-tutorial2-canal-confirm.png 600w, https://journal.qualiteg.com/content/images/size/w1000/2026/08/mcp-tutorial2-canal-confirm.png 1000w, https://journal.qualiteg.com/content/images/2026/08/mcp-tutorial2-canal-confirm.png 1359w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">The confirmation screen. A public URL with an auto-assigned subdomain is issued</span></figcaption></figure><p>Press &quot;Create&quot; and you move to the canal detail screen. That completes the server-side configuration. No static IP, no certificate acquisition &#x2014; nothing of the sort.</p><h2 id="step-2-list-the-tools-you-are-willing-to-expose-in-wirecanaljson">Step 2: List the Tools You Are Willing to Expose in wirecanal.json</h2><p>The &quot;Setup&quot; tab of the canal detail screen shows the connection file (wirecanal.json). You can download and use it as is, but for MCP there is one edit to make.<code>tools.allow</code>, write the names of the tools that outside AI may see.</p><p><code>wirecanal.json</code>(<code>tools.allow</code> with the two tools added)</p><pre><code class="language-json">{
  &quot;access_key&quot;: &quot;ck_(connection key issued per canal)&quot;,
  &quot;forward_target&quot;: &quot;127.0.0.1:9904&quot;,
  &quot;mode&quot;: &quot;mcp&quot;,
  &quot;tools&quot;: {
    &quot;default&quot;: &quot;deny&quot;,
    &quot;allow&quot;: [&quot;execute_sql_query&quot;, &quot;get_database_stats&quot;]
  },
  &quot;lang&quot;: &quot;ja&quot;
}</code></pre><p>The default is <code>&quot;default&quot;: &quot;deny&quot;</code> with an empty <code>allow</code> &#x2014; in other words,<strong>immediately after connecting, all tools are denied</strong>. The Part 1 server has only two tools so we listed both, but even if, say, an internal MCP server had 20 tools, none beyond the two listed here would be visible to outside AI. They do not appear in the listing (tools/list) either.</p><p>This fail-safe default follows the same philosophy as the &quot;don&apos;t show the AI everything&quot; design from Part 1. Since the authoritative ledger deciding the exposure scope lives locally, dashboard operations alone cannot expand the set of public tools. Applying changes requires local approval.</p><h2 id="step-3-start-the-agent">Step 3: Start the Agent</h2><p>Following the guidance on the Setup tab, install and start the Agent on the machine where the server you want to expose is running. On Windows, it is two commands.</p><pre><code class="language-powershell">irm https://download.wirecanal.com/install.ps1 | iex
.\wirecanal.exe -config wirecanal.json</code></pre><p>The first line downloads the Agent (wirecanal.exe is placed in the current folder); the second starts it. If your organization&apos;s security policy prohibits direct execution of remote scripts, save <code>install.ps1</code> to a file first, review its contents, and then run it. Here is the startup log from the author&apos;s environment.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://journal.qualiteg.com/content/images/2026/08/mcp-tutorial2-agent-startup.png" class="kg-image" alt="How to Build an MCP Server &#x2014; Using Your Own MCP Server from Web-Based ChatGPT and Claude (Part 2)" loading="lazy" width="1099" height="612" srcset="https://journal.qualiteg.com/content/images/size/w600/2026/08/mcp-tutorial2-agent-startup.png 600w, https://journal.qualiteg.com/content/images/size/w1000/2026/08/mcp-tutorial2-agent-startup.png 1000w, https://journal.qualiteg.com/content/images/2026/08/mcp-tutorial2-agent-startup.png 1099w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">The Agent&apos;s startup log. It reports that access to the public URL will be delivered to 127.0.0.1:9904</span></figcaption></figure><p>Within a few seconds the dashboard also shows &quot;Connected!&quot;, and at this point the tunnel is up.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://journal.qualiteg.com/content/images/2026/08/mcp-tutorial2-canal-setup-v2.png" class="kg-image" alt="How to Build an MCP Server &#x2014; Using Your Own MCP Server from Web-Based ChatGPT and Claude (Part 2)" loading="lazy" width="1699" height="880" srcset="https://journal.qualiteg.com/content/images/size/w600/2026/08/mcp-tutorial2-canal-setup-v2.png 600w, https://journal.qualiteg.com/content/images/size/w1000/2026/08/mcp-tutorial2-canal-setup-v2.png 1000w, https://journal.qualiteg.com/content/images/size/w1600/2026/08/mcp-tutorial2-canal-setup-v2.png 1600w, https://journal.qualiteg.com/content/images/2026/08/mcp-tutorial2-canal-setup-v2.png 1699w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">The Setup tab. The &quot;Connected!&quot; indicator and the connection file (wirecanal.json)</span></figcaption></figure><h2 id="confirm-that-unauthenticated-access-is-stopped-with-a-401">Confirm That Unauthenticated Access Is Stopped with a 401</h2><p>Before connecting, let us confirm that the public URL is not in a &quot;callable by anyone&quot; state. As we wrote in Part 1, nothing is more dangerous than a defense that is not actually in effect &#x2014; the reliable way to check is to actually hit it.</p><pre><code class="language-bash">curl -i -X POST https://mh1sjzat.ja100.wirecanal.com/mcp \
  -H &quot;Content-Type: application/json&quot; \
  -H &quot;Accept: application/json, text/event-stream&quot; \
  -d &apos;{&quot;jsonrpc&quot;:&quot;2.0&quot;,&quot;method&quot;:&quot;initialize&quot;,&quot;id&quot;:1}&apos;</code></pre><pre><code class="language-text">HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer resource_metadata=&quot;https://mh1sjzat.ja100.wirecanal.com/.well-known/oauth-protected-resource&quot;</code></pre><p>The request without an authentication token was stopped with a 401 before it ever reached the local server. In addition, the <code>WWW-Authenticate</code> header carries <code>resource_metadata</code>. This is the URL of the &quot;protected resource metadata document&quot; defined in RFC 9728 &#x2014; not the URL of the authorization server itself. ChatGPT and Claude first fetch this document, follow the <code>authorization_servers</code> written in it to find the authorization server, and start the OAuth connection procedure automatically.</p><h2 id="connecting-from-claude">Connecting from Claude</h2><p>From the settings of web-based Claude, open the connectors screen and choose &quot;Add custom connector.&quot; All you enter is a name and the public URL from earlier with <code>/mcp</code> appended. The client ID and secret fields can be left empty (the official WireCanal guide listed at the end describes entering a client ID and secret manually; in the author&apos;s environment as of August 6, 2026, entering only the URL was enough to connect).</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://journal.qualiteg.com/content/images/2026/08/mcp-tutorial2-claude-connector.png" class="kg-image" alt="How to Build an MCP Server &#x2014; Using Your Own MCP Server from Web-Based ChatGPT and Claude (Part 2)" loading="lazy" width="1359" height="703" srcset="https://journal.qualiteg.com/content/images/size/w600/2026/08/mcp-tutorial2-claude-connector.png 600w, https://journal.qualiteg.com/content/images/size/w1000/2026/08/mcp-tutorial2-claude-connector.png 1000w, https://journal.qualiteg.com/content/images/2026/08/mcp-tutorial2-claude-connector.png 1359w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Adding a custom connector in Claude. Only a name and the public URL are entered</span></figcaption></figure><p>After &quot;Add&quot; and then &quot;Connect,&quot; the screen switches to WireCanal&apos;s authorization page. It shows which canal the connection is being requested for; review the details and approve.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://journal.qualiteg.com/content/images/2026/08/mcp-tutorial2-claude-consent.png" class="kg-image" alt="How to Build an MCP Server &#x2014; Using Your Own MCP Server from Web-Based ChatGPT and Claude (Part 2)" loading="lazy" width="1359" height="703" srcset="https://journal.qualiteg.com/content/images/size/w600/2026/08/mcp-tutorial2-claude-consent.png 600w, https://journal.qualiteg.com/content/images/size/w1000/2026/08/mcp-tutorial2-claude-consent.png 1000w, https://journal.qualiteg.com/content/images/2026/08/mcp-tutorial2-claude-consent.png 1359w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">WireCanal&apos;s connection approval screen. Confirm which canal the connection is for, then approve</span></figcaption></figure><p>Once connected, the connector details show the tool list. Note this carefully:</p><p><strong>the only tools listed are the two written in the allow list of wirecanal.json.</strong></p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://journal.qualiteg.com/content/images/2026/08/mcp-tutorial2-claude-tools.png" class="kg-image" alt="How to Build an MCP Server &#x2014; Using Your Own MCP Server from Web-Based ChatGPT and Claude (Part 2)" loading="lazy" width="1359" height="703" srcset="https://journal.qualiteg.com/content/images/size/w600/2026/08/mcp-tutorial2-claude-tools.png 600w, https://journal.qualiteg.com/content/images/size/w1000/2026/08/mcp-tutorial2-claude-tools.png 1000w, https://journal.qualiteg.com/content/images/2026/08/mcp-tutorial2-claude-tools.png 1359w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">The tool list after connecting. Only the two tools written in wirecanal.json&apos;s allow list appear</span></figcaption></figure><p>From here, just ask in chat &#x2014; in Japanese, exactly as with Claude Code in Part 1. By default, you are asked for approval before a tool is used.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://journal.qualiteg.com/content/images/2026/08/mcp-tutorial2-claude-approve.png" class="kg-image" alt="How to Build an MCP Server &#x2014; Using Your Own MCP Server from Web-Based ChatGPT and Claude (Part 2)" loading="lazy" width="1359" height="703" srcset="https://journal.qualiteg.com/content/images/size/w600/2026/08/mcp-tutorial2-claude-approve.png 600w, https://journal.qualiteg.com/content/images/size/w1000/2026/08/mcp-tutorial2-claude-approve.png 1000w, https://journal.qualiteg.com/content/images/2026/08/mcp-tutorial2-claude-approve.png 1359w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Tool use approval. By default, confirmation is requested before execution</span></figcaption></figure><p>After approval, Claude issued SQL against the sales database and returned the answer.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://journal.qualiteg.com/content/images/2026/08/mcp-tutorial2-claude-result.png" class="kg-image" alt="How to Build an MCP Server &#x2014; Using Your Own MCP Server from Web-Based ChatGPT and Claude (Part 2)" loading="lazy" width="1359" height="703" srcset="https://journal.qualiteg.com/content/images/size/w600/2026/08/mcp-tutorial2-claude-result.png 600w, https://journal.qualiteg.com/content/images/size/w1000/2026/08/mcp-tutorial2-claude-result.png 1000w, https://journal.qualiteg.com/content/images/2026/08/mcp-tutorial2-claude-result.png 1359w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Web-based Claude&apos;s answer. The same measured values as in Part 1 were returned</span></figcaption></figure><p>Company executives: &#xA5;25,621,641. Researchers: &#xA5;24,525,975. Civil servants: &#xA5;23,685,112. These match the aggregates Claude Code returned in Part 1 &#x2014; exactly the measured values of the fixed-seed dummy data. From Claude in the browser all the way to SQLite running on the local PC, a single unbroken path is in place.</p><h2 id="connecting-from-chatgpt">Connecting from ChatGPT</h2><p>On the ChatGPT side, first enable developer mode in order to connect an unverified MCP server. In the author&apos;s environment, we turned on &quot;Developer mode&quot; under &quot;Security and login&quot; in Settings (there is also a link to the same place at the bottom of the &quot;Plugins&quot; screen in Settings). This feature lets you add connectors that could damage data, at your own risk, so read the risk explanation carefully before proceeding. The screen layout may vary by plan and rollout timing.</p><p>Next, from &quot;Plugins&quot; in the sidebar, choose &quot;Create an app.&quot; Enter a name and the server URL (<code>https://&lt;name&gt;.wirecanal.com/mcp</code>), and the OAuth settings in the authentication section are detected automatically.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://journal.qualiteg.com/content/images/2026/08/mcp-tutorial2-chatgpt-app.png" class="kg-image" alt="How to Build an MCP Server &#x2014; Using Your Own MCP Server from Web-Based ChatGPT and Claude (Part 2)" loading="lazy" width="1359" height="703" srcset="https://journal.qualiteg.com/content/images/size/w600/2026/08/mcp-tutorial2-chatgpt-app.png 600w, https://journal.qualiteg.com/content/images/size/w1000/2026/08/mcp-tutorial2-chatgpt-app.png 1000w, https://journal.qualiteg.com/content/images/2026/08/mcp-tutorial2-chatgpt-app.png 1359w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Creating a new plugin in ChatGPT. Entering the URL auto-detects the OAuth settings</span></figcaption></figure><p>After &quot;Create,&quot; proceed to &quot;Sign in,&quot; and the same WireCanal authorization screen as with Claude appears; approve it.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://journal.qualiteg.com/content/images/2026/08/mcp-tutorial2-chatgpt-consent.png" class="kg-image" alt="How to Build an MCP Server &#x2014; Using Your Own MCP Server from Web-Based ChatGPT and Claude (Part 2)" loading="lazy" width="1359" height="704" srcset="https://journal.qualiteg.com/content/images/size/w600/2026/08/mcp-tutorial2-chatgpt-consent.png 600w, https://journal.qualiteg.com/content/images/size/w1000/2026/08/mcp-tutorial2-chatgpt-consent.png 1000w, https://journal.qualiteg.com/content/images/2026/08/mcp-tutorial2-chatgpt-consent.png 1359w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">WireCanal&apos;s connection approval screen (from ChatGPT). The same screen as with Claude appears</span></figcaption></figure><p>When using it, there is one trick to know. From the &quot;+&quot; in the chat input field, select the app you just created and attach it to the conversation before asking your question. In the author&apos;s environment, asking in plain prose to &quot;use the sales database&quot; without attaching the app led ChatGPT to start a web search instead of using the connector. Selecting the app explicitly via &quot;+&quot; reliably invokes the MCP server.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://journal.qualiteg.com/content/images/2026/08/mcp-tutorial2-chatgpt-result.png" class="kg-image" alt="How to Build an MCP Server &#x2014; Using Your Own MCP Server from Web-Based ChatGPT and Claude (Part 2)" loading="lazy" width="1359" height="703" srcset="https://journal.qualiteg.com/content/images/size/w600/2026/08/mcp-tutorial2-chatgpt-result.png 600w, https://journal.qualiteg.com/content/images/size/w1000/2026/08/mcp-tutorial2-chatgpt-result.png 1000w, https://journal.qualiteg.com/content/images/2026/08/mcp-tutorial2-chatgpt-result.png 1359w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">ChatGPT&apos;s answer. Asking with the app attached returns a table with the same numbers</span></figcaption></figure><p>The table returned matches Claude&apos;s numbers. The local server log also recorded the request from the ChatGPT side as <code>POST /mcp</code>.</p><h2 id="pricing">Pricing</h2><p>The steps in this article (creating an MCP canal, OAuth authentication, auto-assigned subdomain) are, <a href="https://wirecanal.com/pricing?ref=journal.qualiteg.com">per the comparison table on the WireCanal pricing page (wirecanal.com)</a>, <strong>available on the free plan</strong>. No credit card registration is required either.</p><p>In other words, everything done in this article &#x2014; from publishing a self-built MCP server to connecting it with web-based ChatGPT and Claude &#x2014; can be done entirely for free.</p><p>The public hostname issued on the free plan does not disappear as long as it is in use. While the Agent&apos;s connection is alive, its expiration is extended automatically.</p><p>Conversely, if you sever the connection, for example by stopping the Agent, it expires 72 hours after the last connection (you can recreate it after expiration, but the URL will change).</p><p>If you use the MCP server regularly, the Agent will presumably be running continuously, so in practice you can keep using the same URL on the free plan.</p><p>If you want to reserve a subdomain with a name of your choosing, the Lite plan and above &#x2014; which offer persistent hostnames that survive disconnections &#x2014; are the candidates. Other plan differences include TCP exposure (RDP and SSH) from the Pro plan up, and bringing your own custom domain on Premium.</p><p>Note that some screenshots in this article were taken on a Lite-plan account, but every step can be performed with free-plan features alone.</p><p>One more point, on organizational use. This time the canal&apos;s owner personally approved the OAuth connection, but on Lite and above you can integrate with your company&apos;s identity platform (an OIDC IdP such as Google Workspace) so that<strong>members of the organization can receive connection approval with their own company accounts</strong>. Having the whole team use the MCP server is something we will actually do in a later installment of this series.</p><h2 id="oauth-for-connecting-to-chatgpt-is-solved-on-the-route-side">OAuth for Connecting to ChatGPT Is Solved on the Route Side</h2><p>The point of this installment is that<strong>not a single line of the Part 1 server was touched</strong>. The MCP server written for localhost worked as is from both web-based ChatGPT and Claude. The three walls &#x2014; reachability, HTTPS, and OAuth &#x2014; are problems of the route, not of the server code, so solving them on the route side is the sound approach. That is this installment&apos;s answer.</p><p>The safety of the public route is layered in two. At the entrance, OAuth stops unauthenticated access with a 401; beyond that, the tool allowlist hides everything except the two tools we chose to show. The authoritative allowlist lives in the local wirecanal.json and cannot be changed by dashboard operations alone &#x2014; applying changes requires local approval. The three safety valves built inside the server in Part 1 (read-only access, SELECT-only inspection, and an execution time limit) remain in place as the last line of defense.</p><p>One thing that tripped us up was that ChatGPT did not select the app automatically. If you do not know this beforehand, it looks as though the connector is &quot;connected but never used.&quot; Since many readers are likely to stall at the same spot, we kept it in the article.</p><p>We should also note what was not verified. What we connected were the author&apos;s ChatGPT Plus account, on which developer mode was visible as of August 6, 2026, and a paid Claude account. The availability and screen layout of ChatGPT&apos;s developer mode and custom MCP apps may vary by plan and account rollout, and the same items may not appear on every account. We also have not confirmed how far this works on the AI services&apos; free plans. Furthermore, when connecting to a real internal database, there is work to do beyond this article, as described in Part 1 &#x2014; splitting into task-specific tools, auditing access logs, and so on.</p><p>See you next time.</p><h2 id="sample-code">Sample Code</h2><p>We use the Part 1 code as is. After cloning, the commands up to creating the DB and starting HTTP mode are as follows.</p><p><a href="https://github.com/qualiteg/mcp-server-tutorial?ref=journal.qualiteg.com">qualiteg/mcp-server-tutorial | Complete sample code and README (GitHub)</a></p><pre><code class="language-bash">git clone https://github.com/qualiteg/mcp-server-tutorial.git
cd mcp-server-tutorial
python -m pip install -r requirements.txt
python db_setup.py
python mcp_server_sales.py --http --port 9904</code></pre><h2 id="references">References</h2><ul><li><a href="https://modelcontextprotocol.io/specification/draft/basic/authorization?ref=journal.qualiteg.com">MCP Authorization (official Model Context Protocol specification)</a> * The draft is subject to updates. This article was verified against the content as of August 6, 2026</li><li><a href="https://www.rfc-editor.org/rfc/rfc9728?ref=journal.qualiteg.com">OAuth 2.0 Protected Resource Metadata (RFC 9728)</a></li><li><a href="https://wirecanal.com/?ref=journal.qualiteg.com">WireCanal official site | MCP-ready secure tunnels</a></li><li><a href="https://wirecanal.com/mcp/claude?ref=journal.qualiteg.com">How to connect Claude to an MCP canal (guide on wirecanal.com)</a></li><li><a href="https://wirecanal.com/mcp/chatgpt?ref=journal.qualiteg.com">How to connect ChatGPT to an MCP canal (guide on wirecanal.com)</a></li></ul><h2 id="related-articles">Related Articles</h2><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://journal.qualiteg.com/mcp-server-python-fastmcp-database-part1/"><div class="kg-bookmark-content"><div class="kg-bookmark-title">How to Build an MCP Server &#x2014; Let AI Answer Questions About Your Database with Python and FastMCP (Part 1)</div><div class="kg-bookmark-description">A hands-on guide to building an MCP server, with working code from start to finish. Using Python and FastMCP, we wrap a SQLite sales database as MCP tools so an AI can take a plain-language question, write the SQL itself, and return aggregated results.</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://blog.qualiteg.com/content/images/size/w256h256/2024/04/q_logo_20231023_150x150.png" alt="How to Build an MCP Server &#x2014; Using Your Own MCP Server from Web-Based ChatGPT and Claude (Part 2)"><span class="kg-bookmark-author">Qualiteg Blog</span><span class="kg-bookmark-publisher">Qualiteg &#x30D7;&#x30ED;&#x30C0;&#x30AF;&#x30C8;&#x958B;&#x767A;&#x90E8;</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://blog.qualiteg.com/content/images/2026/08/how_to_make_mcp_server_01.png" alt="How to Build an MCP Server &#x2014; Using Your Own MCP Server from Web-Based ChatGPT and Claude (Part 2)"></div></a></figure><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://journal.qualiteg.com/ngrok-wirecanal-comparison/"><div class="kg-bookmark-content"><div class="kg-bookmark-title">What Sets ngrok and WireCanal Apart? The Developers Compare Pricing, Operations, and MCP Design</div><div class="kg-bookmark-description">An honest comparison from the developers of WireCanal, a Japan-based service built on the same reverse tunnel approach as ngrok. The differences come down to three: pricing philosophy, where operations run, and where permissions live when connecting to AI.</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://blog.qualiteg.com/content/images/size/w256h256/2024/04/q_logo_20231023_150x150.png" alt="How to Build an MCP Server &#x2014; Using Your Own MCP Server from Web-Based ChatGPT and Claude (Part 2)"><span class="kg-bookmark-author">Qualiteg Blog</span><span class="kg-bookmark-publisher">Qualiteg &#x30D7;&#x30ED;&#x30C0;&#x30AF;&#x30C8;&#x958B;&#x767A;&#x90E8;</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://blog.qualiteg.com/content/images/2026/08/ngrok-wirecanal-comparison.png" alt="How to Build an MCP Server &#x2014; Using Your Own MCP Server from Web-Based ChatGPT and Claude (Part 2)"></div></a></figure>]]></content:encoded></item><item><title><![CDATA[What Sets ngrok and WireCanal Apart? The Developers Compare Pricing, Operations, and MCP Design]]></title><description><![CDATA[An honest comparison from the developers of WireCanal, a Japan-based service built on the same reverse tunnel approach as ngrok. The differences come down to three: pricing philosophy, where operations run, and where permissions live when connecting to AI.]]></description><link>https://journal.qualiteg.com/ngrok-wirecanal-comparison/</link><guid isPermaLink="false">6a74df8af8da991460bcb57e</guid><dc:creator><![CDATA[Qualiteg Product Development Team]]></dc:creator><pubDate>Thu, 06 Aug 2026 22:13:30 GMT</pubDate><media:content url="https://journal.qualiteg.com/content/images/2026/08/ngrok-wirecanal-comparison.png" medium="image"/><content:encoded><![CDATA[<img src="https://journal.qualiteg.com/content/images/2026/08/ngrok-wirecanal-comparison.png" alt="What Sets ngrok and WireCanal Apart? The Developers Compare Pricing, Operations, and MCP Design"><p>Hello!<br>This is the Qualiteg Product Development Team!</p><p>&quot;Is there a Japan-based tunnel service that can serve as an alternative to ngrok?&quot;<br><br>Many of you have likely arrived at this article after searching for exactly that.</p><p>This article answers that question head-on, from the developer&apos;s side.</p><p>Let us be clear from the start: the service introduced here, <strong>WireCanal </strong>, is developed and operated by our company (Qualiteg Inc.), a Japanese corporation, with its relay infrastructure running on servers in Japan &#x2014; a<strong>tunnel service</strong>.</p><p>Since this is an article in which we compare our own product, listing only the points that flatter us would earn no one&apos;s trust. Where the two are the same, we say so; where ngrok is the better fit, we say that too.</p><p>To state the conclusion up front:<br><br><strong><u>the basic tunneling mechanism is the same as ngrok&apos;s</u></strong>&#x3002;<br><br>There are three differences.</p><p><strong>The pricing philosophy (a USD-denominated structure with fixed allotments and usage-based elements, versus a flat JPY rate with no overage billing) &#xB7; the shape of operations and contracting (domestic relay infrastructure and a Japanese-language, JPY-denominated contract with a Japanese corporation) &#xB7; and where permissions live when connecting to AI (the authoritative permission ledger stays on the company&apos;s side)</strong></p><p>If none of these three matter for your use case, there is no need to force a switch. Let us look, in order, at what is the same and what is different.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://journal.qualiteg.com/content/images/2026/08/a1-fig1-reverse-tunnel-nb.jpg" class="kg-image" alt="What Sets ngrok and WireCanal Apart? The Developers Compare Pricing, Operations, and MCP Design" loading="lazy" width="1376" height="768" srcset="https://journal.qualiteg.com/content/images/size/w600/2026/08/a1-fig1-reverse-tunnel-nb.jpg 600w, https://journal.qualiteg.com/content/images/size/w1000/2026/08/a1-fig1-reverse-tunnel-nb.jpg 1000w, https://journal.qualiteg.com/content/images/2026/08/a1-fig1-reverse-tunnel-nb.jpg 1376w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Figure 1: How the reverse tunnel approach works. No inbound port is opened; connections always go from inside out</span></figcaption></figure><h2 id="the-mechanism-is-the-same-so-there-is-almost-nothing-to-relearn">The Mechanism Is the Same, So There Is Almost Nothing to Relearn</h2><p>The reverse tunnel approach that ngrok made widely known works like this: place a small program (WireCanal calls it the Agent) on your PC or an internal server, and it connects outward, from the inside, to a relay server to establish a tunnel. A public URL is created on the outside, and access arriving there flows through the tunnel back to your machine.</p><p>The advantage of this approach is that no inbound port needs to be opened on the firewall.</p><p>WireCanal is built on the same idea (Figure 1). Run a command to install the Agent, create a public route called a canal, and specify a local port as the forwarding target. If you have used ngrok, there is essentially nothing conceptual to relearn.</p><p>Note that today&apos;s ngrok has broadened its product scope with cloud-side endpoints and more, but this article compares the basic configuration: publishing local and internal services using an Agent.</p><p>So what this article should address is not &quot;which one is superior,&quot; but how the design beyond that point differs.</p><h2 id="difference-1-pricing-is-a-flat-rate-in-jpy-tax-included">Difference 1: Pricing Is a Flat Rate in JPY, Tax Included</h2><p>ngrok offers plans such as Free, Hobbyist, and Pay-as-you-go (as of August 2026, confirmed on the official site). First, a comparison of the structures.</p>
<!--kg-card-begin: html-->
<table><thead><tr><th>Aspect</th><th>ngrok (official site, as of August 2026)</th><th>WireCanal</th></tr></thead><tbody><tr><td>Plan structure</td><td>Free / Hobbyist ($10/month, fixed) / Pay-as-you-go ($20/month allotment + usage-based overage)</td><td>Free &#xA5;0 / Lite &#xA5;1,580 / Pro &#xA5;3,580 / Premium &#xA5;11,800 (all flat monthly rates, tax included)</td></tr><tr><td>When the allotment is exceeded</td><td>Hobbyist: endpoints suspended until the end of the billing period / Pay-as-you-go: overage billed additionally</td><td>No additional billing. On Free, speeds may be adjusted beyond the guideline of 10GB/month</td></tr><tr><td>Currency and billing</td><td>USD (varies with exchange rates)</td><td>JPY, tax included (invoice payment available for Enterprise)</td></tr></tbody></table>
<!--kg-card-end: html-->
<p>Pay-as-you-go, intended for production use, includes a $20 monthly allotment, with additional charges beyond it based on transfer volume, request counts, endpoint uptime, and so on. Paying for what you use is a rational design, but the bill for a month when usage grows is hard to predict in advance, and being USD-denominated, it also moves with exchange rates.</p><p>WireCanal made every plan a flat monthly rate in JPY, tax included. The differences between plans are as follows.</p>
<!--kg-card-begin: html-->
<table><thead><tr><th>Plan</th><th>Monthly (tax incl., monthly billing)</th><th>Main differences</th></tr></thead><tbody><tr><td>Free</td><td>&#xA5;0</td><td>1 canal &#xB7; HTTPS/MCP publishing &#xB7; 8 types of access protection</td></tr><tr><td>Lite</td><td>&#xA5;1,580</td><td>Persistent public hostname &#xB7; reserve your preferred subdomain</td></tr><tr><td>Pro</td><td>&#xA5;3,580</td><td>3 canals &#xB7; TCP (RDP/SSH/DB, etc.)</td></tr><tr><td>Premium</td><td>&#xA5;11,800</td><td>20 canals &#xB7; 1Gbps (best effort) &#xB7; custom domains &#xB7; API</td></tr></tbody></table>
<!--kg-card-end: html-->
<p>With annual billing, the monthly equivalents become Lite &#xA5;1,280, Pro &#xA5;2,980, and Premium &#xA5;9,980.</p><p><strong>There is no additional billing based on transfer volume.</strong></p><p>The Free plan has a guideline of 10GB per month, and speeds may be adjusted when it is exceeded. Paid plans have no monthly transfer cap for normal use, but to keep usage fair and maintain the network, extreme high-volume traffic may be subject to speed limiting or similar measures.</p><p>To be candid, a flat rate is not always the better deal. Depending on your scale and use case, ngrok&apos;s Free, Hobbyist, or Pay-as-you-go plans may work out cheaper. The value of flat-rate pricing lies in knowing the bill in advance, and it matters more the more your organization relies on approval workflows and budget planning.</p><h2 id="difference-2-runs-in-a-domestic-region-with-contracts-billing-and-support-completed-in-japanese-and-in-jpy">Difference 2: Runs in a Domestic Region, with Contracts, Billing, and Support Completed in Japanese and in JPY</h2><p>WireCanal&apos;s relay infrastructure is deployed in a domestic (Japan) region. Contracts and support are provided in Japanese by our company, a Japanese business, and billing is in JPY. Here too, a table to organize the comparison.</p>
<!--kg-card-begin: html-->
<table><thead><tr><th>Aspect</th><th>ngrok</th><th>WireCanal</th></tr></thead><tbody><tr><td>Points of presence</td><td>8 locations worldwide (including Tokyo) &#xB7; region-pinned routing available</td><td>Operated in a domestic (Japan) region</td></tr><tr><td>Contract and support language</td><td>English</td><td>Japanese (Japanese corporation)</td></tr><tr><td>Billing</td><td>USD</td><td>JPY, tax included. Invoice payment available for Enterprise</td></tr></tbody></table>
<!--kg-card-end: html-->
<p>Note that ngrok also has a Tokyo point of presence (PoP) and a mechanism for region-pinned routing. So this is not a simple &quot;has a domestic route or not&quot; comparison. What sets WireCanal apart is that operating the relay infrastructure on servers in Japan is an explicit part of the service design, packaged together with a contract with a Japanese corporation, Japanese-language support, and JPY billing.</p><p>For organizations where &quot;requests to use overseas SaaS rarely get approved internally&quot; or &quot;accounting is a headache without a JPY invoice,&quot; this is not a matter of feature superiority &#x2014; it is the deciding factor in whether adoption is possible at all.</p><p>To be honest here as well: a domestic region does not mean it is always faster than overseas services. Actual latency varies with your location, destination, and route. Conversely, if your primary goal is to serve users around the world, or to use the service the same way from overseas offices, ngrok or Cloudflare &#x2014; with their global points of presence &#x2014; are the better fit.</p><h2 id="difference-3-the-permission-ledger-for-what-ai-may-see-lives-on-the-companys-side">Difference 3: The &quot;Permission Ledger&quot; for What AI May See Lives on the Company&apos;s Side</h2><p>This is the part we thought through most carefully.</p><p>MCP (Model Context Protocol) is spreading as the way to let generative AI operate internal systems. In practice, the question then becomes: which of your internal system&apos;s capabilities do you let the AI touch? An internal MCP server typically hosts everything from read-only tools to tools that update and delete.</p><p>The idea of controlling MCP at the gateway when connecting to external AI is not ours alone. Here is what can be confirmed in each vendor&apos;s official documentation.</p>
<!--kg-card-begin: html-->
<table><thead><tr><th>Service</th><th>What the gateway can do (from each vendor&apos;s official docs)</th></tr></thead><tbody><tr><td>ngrok</td><td>Source restrictions via Traffic Policy &#xB7; required Authorization headers &#xB7; rate limiting, etc.</td></tr><tr><td>Cloudflare</td><td>MCP Server Portals let you select which tools to expose per portal</td></tr><tr><td>WireCanal</td><td>Per-tool permissions (default: deny all), plus the authoritative permission ledger lives in a configuration file on the company&apos;s side. The cloud console can go only as far as proposing changes</td></tr></tbody></table>
<!--kg-card-end: html-->
<p>What makes WireCanal different is that, in addition to per-tool permissions themselves, the authoritative copy of that permission ledger lives in<strong>a configuration file on the company&apos;s side</strong> (Figure 2).</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://journal.qualiteg.com/content/images/2026/08/a1-fig2-two-key-nb.jpg" class="kg-image" alt="What Sets ngrok and WireCanal Apart? The Developers Compare Pricing, Operations, and MCP Design" loading="lazy" width="1376" height="768" srcset="https://journal.qualiteg.com/content/images/size/w600/2026/08/a1-fig2-two-key-nb.jpg 600w, https://journal.qualiteg.com/content/images/size/w1000/2026/08/a1-fig2-two-key-nb.jpg 1000w, https://journal.qualiteg.com/content/images/2026/08/a1-fig2-two-key-nb.jpg 1376w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Figure 2: The authoritative tool permission ledger lives on the company&apos;s side. The cloud console can go only as far as proposing changes</span></figcaption></figure><p><code>wirecanal.json</code>(the tool permission section, excerpt)</p><pre><code class="language-json">{
  &quot;tools&quot;: {
    &quot;default&quot;: &quot;deny&quot;,
    &quot;allow&quot;: [&quot;execute_sql_query&quot;, &quot;get_database_stats&quot;]
  }
}</code></pre><p>The default denies everything, and only the tools written in this allow list are visible to the AI. Tools that are not permitted do not even appear in the tool listing (tools/list). The cloud console can go only as far as proposing changes; applying them requires an approval action on the company&apos;s side. In other words, ordinary console operations alone cannot widen the exposure scope without in-house approval.</p><p>One more thing: the Agent connects only to the forwarding targets registered in its configuration file, and does not accept instructions from the cloud side to change targets dynamically. The Agent itself is restricted so that the tunnel&apos;s exit cannot become a general-purpose relay toward arbitrary internal destinations.</p><p>The procedure for actually connecting a self-built MCP server to web-based ChatGPT and Claude is published, with screenshots, in a series on this blog. Links are at the end of this article.</p><h2 id="when-staying-with-ngrok-is-the-right-call">When Staying with ngrok Is the Right Call</h2><p>As you can tell from reading this far, WireCanal suits those who want to operate domestically, with predictable pricing, while governing what is exposed to AI. Organized by use case, it looks like this.</p>
<!--kg-card-begin: html-->
<table><thead><tr><th>Use case</th><th>Suitable choice</th></tr></thead><tbody><tr><td>Serving users around the world &#xB7; primary use from overseas offices</td><td>Global services such as ngrok or Cloudflare</td></tr><tr><td>You already have configuration assets such as ngrok Traffic Policy</td><td>Continue with ngrok</td></tr><tr><td>Personal testing with very little transfer volume</td><td>Either ngrok Free or WireCanal Free works; choose by preference</td></tr><tr><td>JPY billing, Japanese-language contracts, and domestic relay infrastructure are requirements</td><td>WireCanal</td></tr><tr><td>You want to publish MCP while governing which tools AI can see</td><td>WireCanal (the authoritative permission ledger stays on the company&apos;s side)</td></tr></tbody></table>
<!--kg-card-end: html-->
<p>Choose your tools by use case. If there is no compelling reason to switch, staying put is itself a sound decision.</p><h2 id="how-far-you-can-go-for-free">How Far You Can Go for Free</h2><p>WireCanal&apos;s free plan has<strong>no time limit</strong>&#x3001;<strong>and requires no credit card registration</strong>&#x3002;<br></p><p>With one canal, everything is available: HTTPS publishing, MCP publishing (OAuth integration with ChatGPT, Claude, and others), and all 8 types of access protection including IP restrictions, BASIC authentication, Bearer tokens, and time-window publishing.</p><p>The public hostname does not disappear as long as it is in use. While the Agent&apos;s connection is alive, its expiration is extended automatically, and it expires 72 hours after the last connection (it can be recreated after expiration). When you find yourself wanting to choose the name yourself, or to keep the same name even while disconnected, that is the time to consider Lite or above.</p><p>We recommend starting by publishing one of your own web apps or an MCP server and seeing how it feels to use.<a href="https://wirecanal.com/?ref=journal.qualiteg.com">WireCanal is free to start (wirecanal.com)</a>&#x3002;</p><h2 id="summary-same-approach-different-placement">Summary: Same Approach, Different Placement</h2><p>ngrok and WireCanal stand on the same foundation: the reverse tunnel. The differences come down to three points &#x2014; how you pay (a USD-denominated structure with fixed allotments and usage-based elements, versus a flat JPY rate with no overage billing), the shape of operations and contracting (domestic relay infrastructure with a Japanese-language, JPY-denominated contract with a Japanese corporation, versus using a global service), and keeping the authoritative AI tool permission ledger on the company&apos;s side.</p><p>A tunnel service, once woven into your operations, is a tool you live with for a long time. Choose not just by the checkmarks on a feature table, but by whether these three placements fit your organization &#x2014; and you will not regret it later.</p><p>See you next time.</p><h2 id="references-primary-sources">References (Primary Sources)</h2><ul><li><a href="https://ngrok.com/pricing?ref=journal.qualiteg.com">ngrok pricing plans (official site)</a>&#x3000;* Confirmed against the content as of August 2026</li><li><a href="https://ngrok.com/docs/using-ngrok-with/using-mcp?ref=journal.qualiteg.com">ngrok&apos;s official MCP gateway guide (ngrok Docs)</a></li><li><a href="https://ngrok.com/docs/universal-gateway/points-of-presence/?ref=journal.qualiteg.com">ngrok points of presence (ngrok Docs)</a></li><li><a href="https://developers.cloudflare.com/cloudflare-one/access-controls/ai-controls/mcp-portals/?ref=journal.qualiteg.com">Cloudflare MCP Server Portals (Cloudflare Docs)</a></li><li><a href="https://wirecanal.com/pricing?ref=journal.qualiteg.com">WireCanal plan and feature comparison table (wirecanal.com)</a></li><li><a href="https://wirecanal.com/mcp?ref=journal.qualiteg.com">WireCanal&apos;s guide to MCP and AI integration (wirecanal.com)</a></li></ul><h2 id="related-articles">Related Articles</h2><ul><li><a href="https://journal.qualiteg.com/mcp-server-python-fastmcp-database-part1/">How to Build an MCP Server (Part 1) | Connecting a Sales DB to AI with Python and FastMCP (this blog)</a></li></ul>]]></content:encoded></item><item><title><![CDATA[How to Build an MCP Server — Let AI Answer Questions About Your Database with Python and FastMCP (Part 1)]]></title><description><![CDATA[A hands-on guide to building an MCP server, with working code from start to finish. Using Python and FastMCP, we wrap a SQLite sales database as MCP tools so an AI can take a plain-language question, write the SQL itself, and return aggregated results.]]></description><link>https://journal.qualiteg.com/mcp-server-python-fastmcp-database-part1/</link><guid isPermaLink="false">6a72d619edf69a17d422ab39</guid><dc:creator><![CDATA[Qualiteg Product Development Team]]></dc:creator><pubDate>Thu, 06 Aug 2026 02:54:01 GMT</pubDate><media:content url="https://journal.qualiteg.com/content/images/2026/08/how_to_make_mcp_server_01.png" medium="image"/><content:encoded><![CDATA[<img src="https://journal.qualiteg.com/content/images/2026/08/how_to_make_mcp_server_01.png" alt="How to Build an MCP Server &#x2014; Let AI Answer Questions About Your Database with Python and FastMCP (Part 1)"><p>Hello! This is the Qualiteg Product Development Team!</p><p><strong>You want to make your local database queryable by an AI.</strong> What you need for that is an MCP server.</p><p>The goal sounds simple, but once you start researching, you can get as far as &quot;just build an MCP server&quot; and still get stuck on <strong>how exactly to turn your own database into MCP</strong>.</p><p>This article walks you through everything up to </p><p><strong>building your own MCP server with Python and FastMCP and querying a sales database in natural language from the CLI version of Claude Code</strong></p><p>, with working code from start to finish. The code is about 200 lines. When you ask &quot;Show me the top 3 occupations by sales&quot; (in Japanese, in our demo), Claude Code assembles the SQL itself and comes back with the aggregated answer.</p><p>All the code is on GitHub. Clone it, install the dependencies, create the DB, and it runs.<strong>The repository README covers every step of running it</strong>, so if you&apos;d rather get your hands moving without reading the article, start there.</p><p><a href="https://github.com/qualiteg/mcp-server-tutorial?ref=journal.qualiteg.com">qualiteg/mcp-server-tutorial | Complete sample code and README (GitHub)</a></p><p>This is a two-part series. Part 1 (this article) gets you to the point where it works from the <strong>CLI version of Claude Code</strong>. In Part 2, we make the same server usable from the <strong>web versions of ChatGPT and Claude</strong>. A CLI version running locally, and a web version running in the browser. Between those two lies a wall that trips up a lot of people.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://journal.qualiteg.com/content/images/2026/08/mcp-tutorial-fig1-series-nb.jpg" class="kg-image" alt="How to Build an MCP Server &#x2014; Let AI Answer Questions About Your Database with Python and FastMCP (Part 1)" loading="lazy" width="1376" height="768" srcset="https://journal.qualiteg.com/content/images/size/w600/2026/08/mcp-tutorial-fig1-series-nb.jpg 600w, https://journal.qualiteg.com/content/images/size/w1000/2026/08/mcp-tutorial-fig1-series-nb.jpg 1000w, https://journal.qualiteg.com/content/images/2026/08/mcp-tutorial-fig1-series-nb.jpg 1376w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">What this series builds. Part 1 reaches the AI on your machine; Part 2 connects to the web versions of ChatGPT and Claude</span></figcaption></figure><h2 id="what-mcp-is-in-three-minutes">What MCP is, in three minutes</h2><p>MCP (Model Context Protocol) is a common standard for connecting AI apps to external data and tools. Anthropic released it in late 2024, and today it is supported not just by Claude but by ChatGPT, Gemini, and a range of coding agents.</p><p>Before MCP, if you wanted an AI to touch your database, you had to build one-off integrations for each AI app&apos;s proprietary plugin or function-calling scheme. MCP standardizes how the &quot;server&quot; (the side exposing data and tools &#x2014; what we build here) and the &quot;client&quot; (the AI app side: Claude, ChatGPT, and so on) talk to each other. Build an MCP server once, and multiple MCP-capable AI apps can use it without app-specific plugins. That said, the available transports, auth methods, plans, and admin settings differ per client.</p><p>An MCP server can expose three kinds of things &#x2014; tools, resources, and prompts &#x2014; but the one you will use first in practice is tools: functions the AI can call. This article covers tools only.</p><p>One more piece of background that pays off in Part 2: the MCP spec defines two standard transports.</p>
<!--kg-card-begin: html-->
<div style="overflow-x:auto"><table style="width:100%;border-collapse:collapse"><thead><tr><th style="border:1px solid #ddd;padding:8px;background:#f6f6f6;text-align:left">Transport</th><th style="border:1px solid #ddd;padding:8px;background:#f6f6f6;text-align:left">How it works</th><th style="border:1px solid #ddd;padding:8px;background:#f6f6f6;text-align:left">Main use</th></tr></thead><tbody><tr><td style="border:1px solid #ddd;padding:8px;vertical-align:top">stdio</td><td style="border:1px solid #ddd;padding:8px;vertical-align:top">The client launches the server process locally and talks to it over standard input/output</td><td style="border:1px solid #ddd;padding:8px;vertical-align:top">Local MCP servers running on the same machine as the client</td></tr><tr><td style="border:1px solid #ddd;padding:8px;vertical-align:top">Streamable HTTP</td><td style="border:1px solid #ddd;padding:8px;vertical-align:top">The server runs as a resident HTTP server and clients connect to its URL</td><td style="border:1px solid #ddd;padding:8px;vertical-align:top">MCP servers that run independently and are used over the network</td></tr></tbody></table></div>
<!--kg-card-end: html-->
<p>In this article, Part 1 uses a local stdio server from the CLI version of Claude Code, and Part 2 uses a remote Streamable HTTP server from the web versions. That said, <strong>it is not a strict one-to-one mapping of &quot;CLI means stdio, web means HTTP&quot;</strong>. Claude Code, for example, can connect to both stdio servers and remote HTTP servers. In Part 1 we will try both.</p><h2 id="what-we-are-building">What we are building</h2><p>A sales database (SQLite) modeled on an online store for PC parts, plus an MCP server that queries it.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://journal.qualiteg.com/content/images/2026/08/mcp-tutorial-fig2-architecture-nb.jpg" class="kg-image" alt="How to Build an MCP Server &#x2014; Let AI Answer Questions About Your Database with Python and FastMCP (Part 1)" loading="lazy" width="1376" height="768" srcset="https://journal.qualiteg.com/content/images/size/w600/2026/08/mcp-tutorial-fig2-architecture-nb.jpg 600w, https://journal.qualiteg.com/content/images/size/w1000/2026/08/mcp-tutorial-fig2-architecture-nb.jpg 1000w, https://journal.qualiteg.com/content/images/2026/08/mcp-tutorial-fig2-architecture-nb.jpg 1376w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Architecture of the MCP server we are building: just two tools and SQLite</span></figcaption></figure><p>There are three tables: a customer master (customers) with 500 people, a product master (products) with 72 products across 8 PC-part categories, and sales line items (sales_transactions) with 4,000 records spanning 2024 through 2026. Customers carry attributes like age, occupation, and income bracket, so you can run analyses like &quot;broken down by occupation.&quot;</p><p>We are going to be bold and give Claude Code just two tools: <code>get_database_stats</code>, which returns the table structure and statistics, and <code>execute_sql_query</code>, which executes SELECT statements.</p><p>You could also design this as a lineup of per-task functions &#x2014; a &quot;sales aggregation tool,&quot; a &quot;customer analysis tool,&quot; and so on. But <strong>it is Claude Code that can write SQL</strong>, so handing over one general-purpose SQL execution tool goes further. The trade-off is that the safety work becomes the server&apos;s responsibility &#x2014; more on that later.</p><h2 id="setup">Setup</h2><p>Implementing the MCP server itself requires Python 3.10 or later and FastMCP. If you want to try it from Claude Code the way this article does, you will also need a working Claude Code environment.</p><pre><code class="language-bash">python -m pip install fastmcp</code></pre><p><code>pip</code> is not the one to use here; go with <code>python -m pip</code> instead.<code>pip</code> can land the package in a different environment from the Python that will later launch your MCP server.</p><p>FastMCP is a high-level framework that lets you define MCP tools by adding a single decorator to a Python function. It also bundles client functionality and an HTTP server. The version I verified against is standalone FastMCP 3.4.5.</p><h2 id="first-a-working-mcp-server-in-10-lines">First, a working MCP server in 10 lines</h2><p>Before diving into the sales DB, let&apos;s get the full picture with a minimal build.</p><pre><code class="language-python"># hello_mcp.py
from fastmcp import FastMCP

mcp = FastMCP(name=&quot;hello-server&quot;)

@mcp.tool(description=&quot;Adds two numbers&quot;)
def add(a: int, b: int) -&gt; int:
    return a + b

if __name__ == &quot;__main__&quot;:
    mcp.run()  # stdio transport by default</code></pre><p>That&apos;s it &#x2014; a complete server. The tool definition handed to the AI is generated automatically from the function&apos;s type hints and description.</p><p>Note that just running <code>python hello_mcp.py</code> prints nothing. It simply sits waiting for input as a stdio server. To see it work, call it from FastMCP&apos;s in-memory client.</p><pre><code class="language-python">import asyncio

from fastmcp import Client
from hello_mcp import mcp


async def main():
    async with Client(mcp) as c:
        print([t.name for t in await c.list_tools()])   # [&apos;add&apos;]
        result = await c.call_tool(&quot;add&quot;, {&quot;a&quot;: 120, &quot;b&quot;: 5})
        print(result.data)                              # 125


if __name__ == &quot;__main__&quot;:
    asyncio.run(main())</code></pre><p>Registering it with Claude Code is a one-liner (we will actually register and use it later in this article).</p><pre><code class="language-bash">claude mcp add hello-server -- python hello_mcp.py</code></pre><p>If it fails to connect, specify absolute paths for both Python and the script. If you are using a virtual environment, you need to point at the Python inside it.</p><p>What I want you to notice here is that the only material the AI has for deciding &quot;this needs a calculation,&quot; &quot;there is a tool called add,&quot; and &quot;let&apos;s call it&quot; is <strong>the tool name, the description, and the inputSchema generated from the argument names and types</strong>. Among these, the description is the central place where you can explain in natural language when the tool should be used &#x2014; and it turns out to matter more than anything else in MCP server design.</p><h2 id="step-1-prepare-the-sales-database">Step 1: Prepare the sales database</h2><p>Create three tables in SQLite.</p><p><code>db_setup.py</code>(<a href="https://github.com/qualiteg/mcp-server-tutorial/blob/c823c9b3518ebc383d3daf33b68b372e3425068b/db_setup.py?ref=journal.qualiteg.com#L111-L176">Full code for the table definitions and dummy-data generation (GitHub)</a>)</p><pre><code class="language-python">cur.execute(&quot;&quot;&quot;
CREATE TABLE sales_transactions (
    transaction_id   INTEGER PRIMARY KEY,
    date             TEXT NOT NULL,     -- &apos;YYYY-MM-DD&apos;
    customer_id      TEXT NOT NULL REFERENCES customers(customer_id),
    product_id       TEXT NOT NULL REFERENCES products(product_id),
    product_name     TEXT NOT NULL,
    product_category TEXT NOT NULL,
    quantity         INTEGER NOT NULL,
    unit_price       INTEGER NOT NULL,
    total_price      INTEGER NOT NULL
)&quot;&quot;&quot;)

cur.execute(&quot;CREATE INDEX idx_trans_date     ON sales_transactions(date)&quot;)
cur.execute(&quot;CREATE INDEX idx_trans_customer ON sales_transactions(customer_id)&quot;)
cur.execute(&quot;CREATE INDEX idx_trans_category ON sales_transactions(product_category)&quot;)</code></pre><p>Do create the indexes. The AI will not hesitate to fire full-period aggregation queries at you.</p><p>The random seed is fixed, so everyone who runs it gets identical data. Here is what it looked like in my environment.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://journal.qualiteg.com/content/images/2026/08/mcp-tutorial-db-setup-v3.png" class="kg-image" alt="How to Build an MCP Server &#x2014; Let AI Answer Questions About Your Database with Python and FastMCP (Part 1)" loading="lazy" width="1099" height="612" srcset="https://journal.qualiteg.com/content/images/size/w600/2026/08/mcp-tutorial-db-setup-v3.png 600w, https://journal.qualiteg.com/content/images/size/w1000/2026/08/mcp-tutorial-db-setup-v3.png 1000w, https://journal.qualiteg.com/content/images/2026/08/mcp-tutorial-db-setup-v3.png 1099w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Running db_setup.py</span></figcaption></figure><p>Every number in this article is a measured value from this data. You should see the same numbers on your machine.</p><h2 id="step-2-write-the-entire-schema-into-the-tool-description">Step 2: Write the entire schema into the tool description</h2><p>This is the single most important point in this article.</p><p><code>execute_sql_query</code>&apos;s description, <strong>we write in the entire database schema plus example queries</strong>&#x3002;</p><p><code>mcp_server_sales.py</code>(<a href="https://github.com/qualiteg/mcp-server-tutorial/blob/c823c9b3518ebc383d3daf33b68b372e3425068b/mcp_server_sales.py?ref=journal.qualiteg.com#L57-L104">Full code for the description (GitHub)</a>)</p><pre><code class="language-python">@mcp.tool(description=&quot;&quot;&quot;Executes a SQL query against the sales data. Only SELECT statements are supported.

[Database schema]

&#x25A0; customers (customer master)
  - customer_id (TEXT): customer ID (e.g. &apos;C0001&apos;)
  - age (INTEGER): age
  - gender (TEXT): gender (&apos;&#x7537;&#x6027;&apos; = male, &apos;&#x5973;&#x6027;&apos; = female)
  - prefecture (TEXT): prefecture
  - occupation (TEXT): occupation (&apos;IT&#x30A8;&#x30F3;&#x30B8;&#x30CB;&#x30A2;&apos; = IT engineer, &apos;&#x4F1A;&#x793E;&#x54E1;&apos; = office worker, &apos;&#x5B66;&#x751F;&apos; = student, &apos;&#x81EA;&#x55B6;&#x696D;&apos; = self-employed, etc.)
  - annual_income (INTEGER): annual income (in units of 10,000 yen)

&#x25A0; products (product master)
  - product_id (TEXT): product ID (e.g. &apos;CPU_001&apos;)
  - product_category (TEXT): CPU, GPU, Memory, SSD, HDD, Motherboard, PowerSupply, PCCase
  - tier (TEXT): &apos;high&apos; / &apos;mid&apos; / &apos;entry&apos;
  (and so on &#x2014; list every column in this style)

&#x25A0; sales_transactions (sales line items)
  - date (TEXT): sale date (YYYY-MM-DD format)
  - customer_id (TEXT): customer ID &#x2192; customers.customer_id
  - product_id (TEXT): product ID &#x2192; products.product_id
  - quantity / unit_price / total_price (INTEGER)

[Data period] 2024-01-01 to 2026-12-31 (4,000 rows)

[Example queries]
- Sales by occupation:
  SELECT c.occupation, SUM(t.total_price) AS sales
  FROM sales_transactions t JOIN customers c ON t.customer_id = c.customer_id
  GROUP BY c.occupation ORDER BY sales DESC

- High-end GPU sales:
  SELECT p.product_name, SUM(t.total_price) AS sales
  FROM sales_transactions t JOIN products p ON t.product_id = p.product_id
  WHERE p.product_category = &apos;GPU&apos; AND p.tier = &apos;high&apos;
  GROUP BY p.product_name ORDER BY sales DESC
&quot;&quot;&quot;)
async def execute_sql_query(sql: str, ctx: Context) -&gt; str:
    ...</code></pre><p>That may look absurdly long. But whether the AI writes correct SQL depends less on how smart the model is and more on <strong>how accurately you hand it the schema</strong>. For a small, fixed schema like this one, putting the necessary columns and JOIN relationships in the description proved effective.</p><p>The AI&apos;s material for choosing tools is the tool name, the description, and the inputSchema generated from argument names and types. Of these, the description is where you can say in natural language when the tool should be called.</p><p>Including two or three example queries is another good trick. With worked examples of how to write the JOINs and use the columns, the accuracy of the AI&apos;s SQL stabilizes visibly.</p><h2 id="step-3-give-the-sql-execution-tool-three-safety-valves">Step 3: Give the SQL execution tool three safety valves</h2><p>If you are letting an AI execute SQL, you have to guard against writes and against heavy queries hogging your resources. We set up three safety valves with distinct roles.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://journal.qualiteg.com/content/images/2026/08/mcp-tutorial-fig3-readonly-nb.jpg" class="kg-image" alt="How to Build an MCP Server &#x2014; Let AI Answer Questions About Your Database with Python and FastMCP (Part 1)" loading="lazy" width="1376" height="768" srcset="https://journal.qualiteg.com/content/images/size/w600/2026/08/mcp-tutorial-fig3-readonly-nb.jpg 600w, https://journal.qualiteg.com/content/images/size/w1000/2026/08/mcp-tutorial-fig3-readonly-nb.jpg 1000w, https://journal.qualiteg.com/content/images/2026/08/mcp-tutorial-fig3-readonly-nb.jpg 1376w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">The three safety valves on the SQL execution tool. Write prevention and resource protection live in separate layers</span></figcaption></figure><p><strong>Layer 1: open the database read-only.</strong> With SQLite, connecting via a URI and specifying <code>mode=ro</code> makes the database refuse writes at the source. Even if something slips past the later checks, it stops here.</p><p><code>mcp_server_sales.py</code>(<a href="https://github.com/qualiteg/mcp-server-tutorial/blob/c823c9b3518ebc383d3daf33b68b372e3425068b/mcp_server_sales.py?ref=journal.qualiteg.com#L33-L40">Code for the read-only connection function (GitHub)</a>)</p><pre><code class="language-python">conn = sqlite3.connect(f&quot;file:{DB_PATH.as_posix()}?mode=ro&quot;, uri=True)</code></pre><p><strong>Layer 2: reject anything that is not a SELECT.</strong> This is a string check, not a SQL parser, so treat it as a conservative helper filter that knocks out obvious write commands early. Final write prevention is layer 1&apos;s job.</p><p><code>mcp_server_sales.py</code>(<a href="https://github.com/qualiteg/mcp-server-tutorial/blob/c823c9b3518ebc383d3daf33b68b372e3425068b/mcp_server_sales.py?ref=journal.qualiteg.com#L110-L117">Code for the SELECT-only filter (GitHub)</a>)</p><pre><code class="language-python">normalized = sql.strip().upper()
if not normalized.startswith(&quot;SELECT&quot;):
    return &quot;Error: only SELECT statements are supported&quot;
for keyword in (&quot;DROP&quot;, &quot;DELETE&quot;, &quot;INSERT&quot;, &quot;UPDATE&quot;, &quot;ALTER&quot;, &quot;CREATE&quot;, &quot;TRUNCATE&quot;, &quot;ATTACH&quot;, &quot;PRAGMA&quot;):
    if keyword in normalized:
        return f&quot;Error: {keyword} is not allowed&quot;</code></pre><p><strong>Layer 3: put a hard limit on execution time.</strong> To keep heavy aggregations from hanging things, we cut them off with SQLite&apos;s progress handler.</p><p><code>mcp_server_sales.py</code>(<a href="https://github.com/qualiteg/mcp-server-tutorial/blob/c823c9b3518ebc383d3daf33b68b372e3425068b/mcp_server_sales.py?ref=journal.qualiteg.com#L42-L55">Code for the execution-time limit (GitHub)</a>)</p><pre><code class="language-python">import time

def install_query_timeout(conn, timeout_sec):
    deadline = time.monotonic() + timeout_sec

    def guard():
        return 1 if time.monotonic() &gt;= deadline else 0

    # Call guard every time the SQLite virtual machine executes 1,000 instructions
    conn.set_progress_handler(guard, 1000)</code></pre><p>This is a spot where I got it wrong once.<strong>I was counting the number of progress-handler invocations and using that as the limit</strong>, but the second argument of <code>set_progress_handler</code> is a count of SQLite virtual-machine instructions, not seconds. The invocation count is not wall-clock time, so the wait varied with machine speed and query content.<code>time.monotonic()</code> and comparing against real elapsed time was the correct answer.</p><p>Note that this third layer is not a measure for enforcing read-only access. It is <strong>protection against a runaway query monopolizing your resources</strong>. Each layer guards something different.</p><p>Whether all three layers actually work is something we will verify for real later on.</p><h2 id="step-4-let-the-server-decide-how-much-goes-back-to-the-ai">Step 4: Let the server decide how much goes back to the AI</h2><p>This is the part that formats query results. Look at where we cap the number of rows returned.</p><p><code>mcp_server_sales.py</code>(<a href="https://github.com/qualiteg/mcp-server-tutorial/blob/c823c9b3518ebc383d3daf33b68b372e3425068b/mcp_server_sales.py?ref=journal.qualiteg.com#L145-L155">Code for formatting query results (GitHub)</a>)</p><pre><code class="language-python">    if not rows:
        return &quot;No data matched your query.&quot;

    lines = [&quot; | &quot;.join(columns), &quot;-&quot; * 40]
    for row in rows[:MAX_ROWS]:                      # MAX_ROWS = 50
        lines.append(&quot; | &quot;.join(&quot;&quot; if v is None else str(v) for v in row))
    if len(rows) &gt; MAX_ROWS:
        lines.append(f&quot;... plus {len(rows) - MAX_ROWS} more rows (aggregate or narrow your conditions to see the whole picture)&quot;)

    return f&quot;Query result ({len(rows)} rows):\n\n&quot; + &quot;\n&quot;.join(lines)</code></pre><p>The AI will happily throw <code>SELECT * FROM sales_transactions</code> at you. Returning all 4,000 rows would just overflow the context window. What worked in practice was reporting the true row count honestly and nudging it to &quot;aggregate or narrow your conditions.&quot;</p><p>Note, though, that what this implementation limits is <strong>only the number of rows returned to the AI</strong> &#x2014; it does not limit how many rows are read from SQLite. Facing millions of rows of real data, you will need additional measures: switch to <code>fetchmany(MAX_ROWS + 1)</code>, add a LIMIT on the SQL side, look at query cost, and so on.</p><h2 id="step-5-add-a-tool-that-shows-the-big-picture-first">Step 5: Add a tool that shows the big picture first</h2><p>The second tool simply returns a summary of the table structures and statistics.</p><p><code>mcp_server_sales.py</code>(<a href="https://github.com/qualiteg/mcp-server-tutorial/blob/c823c9b3518ebc383d3daf33b68b372e3425068b/mcp_server_sales.py?ref=journal.qualiteg.com#L159-L214">Full code for the statistics tool (GitHub)</a>)</p><pre><code class="language-python">@mcp.tool(description=&quot;&quot;&quot;Returns the database&apos;s table structures, row counts, data period, and per-category sales statistics.
Before writing any SQL, always call this tool first to check the structure.&quot;&quot;&quot;)
async def get_database_stats(ctx: Context) -&gt; str:
    ...</code></pre><p>The last sentence of the description does the real work.</p><p><strong>&quot;Before writing any SQL, always call this tool first&quot;</strong></p><p>In my environment, adding this line made the model check the statistics first and then build its SQL.</p><p>Keep in mind, though, that this is <strong>a request to the model, not a control enforced by the server</strong>. Depending on the model, the client, and the flow of conversation, it may fire off SQL without ever looking at the statistics. The important thing is not to let your safety story rest on this one sentence. A healthy mental model: a tool description works not only as feature documentation but as the place to tell the model the conditions and procedure for using the tool.</p><h2 id="trying-it-out">Trying it out</h2><p>Register it with Claude Code.</p><pre><code class="language-bash">claude mcp add sales-db -- python C:\qualiteg_examples\mcp_server_sales.py</code></pre><p>Confirm the registration.</p><pre><code class="language-bash">claude mcp list</code></pre><pre><code class="language-text">sales-db: python C:\qualiteg_examples\mcp_server_sales.py - &#x2714; Connected</code></pre><p><code>&#x2714; Connected</code> shows up, the AI can see this server. After that, you just ask in natural language &#x2014; plain Japanese, in our demo.</p><pre><code class="language-bash">claude -p &quot;&#x8077;&#x696D;&#x5225;&#x306E;&#x58F2;&#x4E0A;&#x30C8;&#x30C3;&#x30D7;3&#x3092;&#x6559;&#x3048;&#x3066;&quot;  # &quot;Show me the top 3 occupations by sales&quot;</code></pre><p>This is what came back.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://journal.qualiteg.com/content/images/2026/08/mcp-tutorial-claude-code.png" class="kg-image" alt="How to Build an MCP Server &#x2014; Let AI Answer Questions About Your Database with Python and FastMCP (Part 1)" loading="lazy" width="1099" height="612" srcset="https://journal.qualiteg.com/content/images/size/w600/2026/08/mcp-tutorial-claude-code.png 600w, https://journal.qualiteg.com/content/images/size/w1000/2026/08/mcp-tutorial-claude-code.png 1000w, https://journal.qualiteg.com/content/images/2026/08/mcp-tutorial-claude-code.png 1099w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Claude Code querying the sales database and answering</span></figcaption></figure><p>The question was a single sentence in natural language. Without me writing a single line of SQL, the AI checked the table structure, issued a query with a JOIN and GROUP BY, and returned the aggregation neatly formatted as a table.</p><p>The amounts match the measured values in the dummy data. On top of that, it also aggregated transaction counts &#x2014; which the question never asked for &#x2014; and added its own reading: researchers have the most transactions but a low average ticket, while executives buy less often but spend more per purchase. It is not just generating SQL; it interprets the aggregated results.</p><p>Multi-step conditions like &quot;high-end GPUs released in 2025, ordered by sales to customers in their 20s&quot; go through in the same easy way. People who have never written SQL can now talk to the sales database.</p><p>That said, being able to ask in natural language and the aggregation being correct for business purposes are two different things. If the results feed important decisions, make sure you can review the executed SQL, the aggregation definitions, the time period, and any exclusion conditions. &quot;Sales,&quot; &quot;customer count,&quot; and &quot;average ticket&quot; can all change depending on your in-house definitions.</p><h2 id="verifying-the-guardrails-actually-work">Verifying the guardrails actually work</h2><p>Nothing is scarier than a defense you wrote but that is not actually working. In fact, while writing this article I discovered the timeout was not functioning.</p><p>The three layers each protect something different, so <strong>they have to be verified in different ways</strong> as well. The keyword check that runs through the tool is verified with FastMCP&apos;s in-memory client; the read-only mode and the timeout are verified by touching the DB connection directly.</p><p><code>verify.py</code>(<a href="https://github.com/qualiteg/mcp-server-tutorial/blob/c823c9b3518ebc383d3daf33b68b372e3425068b/verify.py?ref=journal.qualiteg.com">Full code for the verification script (GitHub)</a>)</p><pre><code class="language-python"># Layer 1: does the connection itself refuse writes?
conn = connect_readonly()
try:
    conn.execute(&quot;DELETE FROM customers&quot;)
    raise AssertionError(&quot;This was supposed to be read-only, but the write went through&quot;)
except sqlite3.OperationalError as e:
    assert &quot;readonly&quot; in str(e).lower()

# Layer 3: is a heavy query interrupted based on real time?
conn = connect_readonly()
install_query_timeout(conn, QUERY_TIMEOUT_SEC)
started = time.monotonic()
try:
    conn.execute(HEAVY_SQL).fetchone()
    raise AssertionError(&quot;The query was not interrupted&quot;)
except sqlite3.OperationalError as e:
    assert &quot;interrupted&quot; in str(e).lower()
    print(f&quot;interrupted after {time.monotonic() - started:.1f} s&quot;)</code></pre><p>Here are the results in my environment.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://journal.qualiteg.com/content/images/2026/08/mcp-tutorial-verify-v4.png" class="kg-image" alt="How to Build an MCP Server &#x2014; Let AI Answer Questions About Your Database with Python and FastMCP (Part 1)" loading="lazy" width="1099" height="612" srcset="https://journal.qualiteg.com/content/images/size/w600/2026/08/mcp-tutorial-verify-v4.png 600w, https://journal.qualiteg.com/content/images/size/w1000/2026/08/mcp-tutorial-verify-v4.png 1000w, https://journal.qualiteg.com/content/images/2026/08/mcp-tutorial-verify-v4.png 1099w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Results of running verify.py</span></figcaption></figure><p><code>SELECT</code> at the start does not save a query that smuggles in a DROP &#x2014; that gets stopped too. The read-only connection rejects writes with &quot;attempt to write a readonly database,&quot; and the heavy query was interrupted at 10.0 seconds of real time. The row cap also works: throwing <code>SELECT * FROM sales_transactions</code> returns 50 rows followed by &quot;... plus 3,950 more rows.&quot;</p><p>Note that this verification used the in-memory client and direct DB connections; it does not cover behavior through the stdio or HTTP transports.</p><p>Only after checking this far should you start letting people in your company use it.</p><h2 id="running-it-as-a-resident-http-server">Running it as a resident HTTP server</h2><p>Everything so far used stdio &#x2014; the AI app launches the server locally. To run it as an independent, long-lived server used over the network, switch to Streamable HTTP. Only one line of the startup code changes.</p><p><code>mcp_server_sales.py</code>(<a href="https://github.com/qualiteg/mcp-server-tutorial/blob/c823c9b3518ebc383d3daf33b68b372e3425068b/mcp_server_sales.py?ref=journal.qualiteg.com#L239-L258">Code for the startup section (GitHub)</a>)</p><pre><code class="language-python">mcp.run(transport=&quot;http&quot;, host=&quot;127.0.0.1&quot;, port=9904)</code></pre><p>With this, <code>http://127.0.0.1:9904/mcp</code> becomes your MCP endpoint.</p><p><strong>Bind to 127.0.0.1.</strong> This server has no authentication.<code>0.0.0.0</code> means anyone who can reach you over that network can execute SQL. The sample code defaults to 127.0.0.1 and prints a warning when you specify an external bind address. Once you move on to sharing it inside the company or using it from outside, the baseline becomes HTTPS, authentication and authorization, source restrictions, Origin validation, and audit logging in front of it. The server in this article is the minimal build that comes before all of that &#x2014; for understanding the mechanism.</p><p>Adding a health-check endpoint also makes operations easier.</p><p><code>mcp_server_sales.py</code>(<a href="https://github.com/qualiteg/mcp-server-tutorial/blob/c823c9b3518ebc383d3daf33b68b372e3425068b/mcp_server_sales.py?ref=journal.qualiteg.com#L216-L237">Health-check code (GitHub)</a>)</p><pre><code class="language-python">@mcp.custom_route(&quot;/health&quot;, methods=[&quot;GET&quot;])
async def health_check(request):
    from starlette.responses import JSONResponse
    return JSONResponse({&quot;status&quot;: &quot;ok&quot;, &quot;service&quot;: &quot;sales-database-server&quot;})</code></pre><p>In the sample code, the <code>--http</code> option lets you switch between them.</p><pre><code class="language-bash">python mcp_server_sales.py --http --port 9904</code></pre><p>Once it is up, hit the health check to confirm it is alive.</p><pre><code class="language-bash">curl http://127.0.0.1:9904/health</code></pre><pre><code class="language-json">{&quot;status&quot;:&quot;ok&quot;,&quot;service&quot;:&quot;sales-database-server&quot;}</code></pre><p>It returns status only. There is no reason to leak information monitoring does not need (like the DB&apos;s absolute path or exception internals).</p><h2 id="what-i-learned-building-this">What I learned building this</h2><p>What helped most this time was limiting the server to two tools. Rather than lining up per-task functions, handing over one general-purpose SQL execution tool lets the AI think for itself and produce answers. That said, this holds for a small dummy DB. With real data, per-task tools that restrict which tables, columns, and aggregation granularity can be accessed are safer and easier to audit.</p><p>In exchange, the way you write the description changes the results dramatically. Writing in the full schema and example queries made the AI&apos;s SQL stable. A description works not only as feature documentation but as the place to tell the model the conditions and procedure for using the tool. Remember, though, that procedural instructions are requests &#x2014; nothing guarantees they are followed.</p><p>The safety work came in three layers: open read-only, reject non-SELECT, cap execution time. And we did not stop at writing them &#x2014; we actually exercised each of the three. Skip that step and you will ship defenses to your company that you merely believe are working. In fact, my first timeout implementation never measured real time and did nothing at all.</p><p>Do not forget the cap on returned rows, either. The AI will happily request full table dumps. Cutting off at 50 rows while honestly reporting the total count was enough, in my environment, to make it switch to aggregation queries.</p><p>If you are going to run it as a resident server, switch to Streamable HTTP and add the health check &#x2014; it makes operations easier. But remember there is no authentication built in, so do not put it on the office LAN or the internet as-is.</p><p>One more thing: this sample is a minimal build for understanding the mechanism. For multiple concurrent users you will separately need measures like moving the synchronous DB work onto threads, capping concurrency, and setting DB-side timeouts.</p><h2 id="coming-up-in-part-2">Coming up in Part 2</h2><p>What Part 2 does is clear-cut.</p><p><strong>We will connect this MCP server, built on localhost, to the web versions of ChatGPT and Claude &#x2014; and get over the OAuth wall.</strong></p><p>The CLI version of Claude Code is for developers. But the web versions, running in a browser, can be handed to people who never touch a command line. A sales-planning teammate can ask &quot;What was our best-selling GPU last month?&quot; right from their usual ChatGPT screen. Same MCP server &#x2014; a dramatically wider audience.</p><p>And this is where it gets genuinely hard. To connect an MCP server to the web versions&apos; connectors, you need two things.</p><p>One is an HTTPS URL reachable from the internet. Nobody outside can reach a server running on your local PC &#x2014; and you cannot simply expose a server that can reach your internal database, either.</p><p>The other is <strong>authentication and authorization to identify users and control access</strong>.</p><p>Depending on configuration, both ChatGPT and Claude can connect to remote MCP servers without authentication. But publishing an unauthenticated MCP server that can reach an internal database is simply not an option. So in Part 2 we use OAuth, following the MCP Authorization spec.</p><p>Implementing that yourself means authorization metadata, client registration, an authorization endpoint, and token issuance and validation &#x2014; an entire implementation completely separate from the tools themselves. The tool code took 200 lines, yet you burn out before reaching the main event. This is where a lot of people stall.</p><p>In Part 2, we will walk through how to get over these two walls, with screenshots, all the way to connecting the web versions of ChatGPT and Claude to this sales DB.<strong>And with a way you can try for free</strong>.</p><p>Full disclosure up front: Part 2 uses WireCanal, a service we provide. It has a free tier, so you can follow along hands-on (terms and the free tier are as of the time of writing).</p><p>See you next time!</p><h2 id="sample-code">Sample code</h2><p>All the code from this article is on GitHub.</p><p><a href="https://github.com/qualiteg/mcp-server-tutorial?ref=journal.qualiteg.com">qualiteg/mcp-server-tutorial | Complete sample code and README (GitHub)</a></p><pre><code class="language-bash">git clone https://github.com/qualiteg/mcp-server-tutorial.git
cd mcp-server-tutorial
python -m pip install -r requirements.txt
python db_setup.py</code></pre><p>Then register it with Claude Code.</p><pre><code class="language-bash">claude mcp add sales-db -- python /path/to/mcp-server-tutorial/mcp_server_sales.py
claude mcp list
claude -p &quot;&#x8077;&#x696D;&#x5225;&#x306E;&#x58F2;&#x4E0A;&#x30C8;&#x30C3;&#x30D7;3&#x3092;&#x6559;&#x3048;&#x3066;&quot;  # &quot;Show me the top 3 occupations by sales&quot;</code></pre><p>When using stdio, you do not need to launch <code>python mcp_server_sales.py</code> manually in a separate terminal. Claude Code starts the registered command as a child process.</p><p><strong>Everything described here is also in the repository&apos;s README.</strong> It covers the quick start, how to register with Claude Code, the tools provided, and running as an HTTP server &#x2014; so when working hands-on, the README alone is enough.</p><h2 id="references">References</h2><ul><li><a href="https://modelcontextprotocol.io/?ref=journal.qualiteg.com">Model Context Protocol official site</a></li><li><a href="https://github.com/jlowin/fastmcp?ref=journal.qualiteg.com">FastMCP</a></li><li><a href="https://www.anthropic.com/news/model-context-protocol?ref=journal.qualiteg.com">Anthropic: Introducing the Model Context Protocol</a></li></ul><h2 id="related-articles">Related articles</h2>]]></content:encoded></item><item><title><![CDATA[Qualiteg Launches WireCanal™, Securely Connecting Internal Systems to Leading AI Services — Available from a Free Plan with No Credit Card Required]]></title><description><![CDATA[For internal systems that implemented MCP but remained out of reach of external AI: an enterprise-authentication-ready secure tunnel that safely connects Claude and ChatGPT with no inbound port openings and no new VPN.]]></description><link>https://journal.qualiteg.com/press-release-wirecanal/</link><guid isPermaLink="false">6a715835edf69a17d422ab18</guid><category><![CDATA[News]]></category><category><![CDATA[MCP]]></category><category><![CDATA[AI Agents]]></category><category><![CDATA[AI Security]]></category><dc:creator><![CDATA[Qualiteg News]]></dc:creator><pubDate>Tue, 04 Aug 2026 03:36:24 GMT</pubDate><media:content url="https://journal.qualiteg.com/content/images/2026/08/01_hero.png" medium="image"/><content:encoded><![CDATA[<img src="https://journal.qualiteg.com/content/images/2026/08/01_hero.png" alt="Qualiteg Launches WireCanal&#x2122;, Securely Connecting Internal Systems to Leading AI Services &#x2014; Available from a Free Plan with No Credit Card Required"><p>Qualiteg Inc. (Headquarters: Chiyoda-ku, Tokyo; CEO: Tomonori Misawa) announced the general availability of WireCanal on August 4, 2026. WireCanal is a service that securely connects cloud AI services such as Claude and ChatGPT to databases and MCP servers inside corporate networks. Users are authenticated through the company&apos;s own identity provider, and only organizational accounts belonging to administrator-approved domains can access internal systems through AI. Beyond AI integration, WireCanal can also be used as a general-purpose secure tunnel for HTTPS and TCP (RDP, SSH, databases, and more).</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://journal.qualiteg.com/content/images/2026/08/02_canal_concept.png" class="kg-image" alt="Qualiteg Launches WireCanal&#x2122;, Securely Connecting Internal Systems to Leading AI Services &#x2014; Available from a Free Plan with No Credit Card Required" loading="lazy" width="1672" height="941" srcset="https://journal.qualiteg.com/content/images/size/w600/2026/08/02_canal_concept.png 600w, https://journal.qualiteg.com/content/images/size/w1000/2026/08/02_canal_concept.png 1000w, https://journal.qualiteg.com/content/images/size/w1600/2026/08/02_canal_concept.png 1600w, https://journal.qualiteg.com/content/images/2026/08/02_canal_concept.png 1672w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">WireCanal&apos;s basic architecture: a &quot;canal&quot; connected outward from inside the corporate network</span></figcaption></figure><p>A canal is an artificial waterway that admits only vessels with an approved destination. In the same way, WireCanal builds a dedicated passage &#x2014; a secure tunnel &#x2014; between cloud AI and internal systems through which only permitted traffic can travel. In WireCanal, each of these individual communication paths is called a &quot;canal.&quot; A canal is opened by the WireCanal Agent, a relay program installed inside the corporate network that connects outward, so there is no need to open inbound ports or build a new VPN environment.</p><p>WireCanal is available starting with a free plan (USD 0) that requires no credit card registration. To mark the start of general availability, Qualiteg is also running a launch campaign: customers who sign up for an annual Light Plan contract (one canal) by August 31, 2026 can use the service for 6,000 yen (tax included; equivalent to 500 yen per month) for the first year. After the campaign ends (from September 1, 2026), the price for new annual contracts is 15,360 yen per year (tax included).</p>
<!--kg-card-begin: html-->
<div style="text-align:center;margin:8px 0;"><a href="https://wirecanal.com/?utm_source=qualiteg_blog&amp;utm_medium=owned_media&amp;utm_campaign=wirecanal_launch&amp;utm_content=intro_cta" target="_blank" rel="noopener" style="display:inline-block;background:#1b5fb8;color:#ffffff;padding:12px 40px;border-radius:6px;text-decoration:none;font-weight:bold;">Learn more</a></div>
<!--kg-card-end: html-->
<h2 id="you-want-ai-to-work-with-live-internal-data-%E2%80%94-but-internal-systems-cannot-be-exposed">You want AI to work with live internal data &#x2014; but internal systems cannot be exposed</h2><p>&quot;I want to ask Claude about our internal sales data.&quot; &quot;I want to check inventory and production status in plain language, without learning SQL or system operations.&quot; As business adoption of cloud AI advances, the databases and core systems that hold the answers &#x2014; and the MCP servers that make them usable from AI &#x2014; remain on local PCs and inside corporate networks. Cloud-hosted AI cannot reach them as-is.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://journal.qualiteg.com/content/images/2026/08/03_wall.png" class="kg-image" alt="Qualiteg Launches WireCanal&#x2122;, Securely Connecting Internal Systems to Leading AI Services &#x2014; Available from a Free Plan with No Credit Card Required" loading="lazy" width="1672" height="941" srcset="https://journal.qualiteg.com/content/images/size/w600/2026/08/03_wall.png 600w, https://journal.qualiteg.com/content/images/size/w1000/2026/08/03_wall.png 1000w, https://journal.qualiteg.com/content/images/size/w1600/2026/08/03_wall.png 1600w, https://journal.qualiteg.com/content/images/2026/08/03_wall.png 1672w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">The wall between cloud AI and internal data / MCP servers</span></figcaption></figure><p>MCP (Model Context Protocol) is a common specification that lets AI discover and execute external tools, and it also defines mechanisms for authentication and authorization. Supporting MCP alone, however, does not automatically provide a secure path from cloud AI into the corporate network, nor account management tied to the company&apos;s IdP.</p><p>The enterprise operational foundation &#x2014; a communication path from cloud AI into the corporate network, user management based on company identities, and access revocation linked to company account suspension when an employee leaves &#x2014; must be built separately.</p><p>At the same time, publishing an MCP server to the internet without proper authentication and access control means exposing a wide-open entrance to internal systems. Trying to solve this with inbound port openings or VPN construction instead places a heavy build-and-operate burden on the IT department. &quot;We want to use it, but there is no safe way to expose it.&quot; This is where many companies come to a halt.</p><h2 id="wirecanals-answer-connect-outward-from-inside-and-guard-the-entrance-with-company-identities">WireCanal&apos;s answer: connect outward from inside, and guard the entrance with company identities</h2><p>Place the WireCanal Agent &#x2014; a connection app that runs on Windows and Linux &#x2014; inside the corporate network, and the Agent establishes an outbound encrypted tunnel. Requests from Claude or ChatGPT reach only the internal MCP servers designated in advance.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://journal.qualiteg.com/content/images/2026/08/04_who_what_where.png" class="kg-image" alt="Qualiteg Launches WireCanal&#x2122;, Securely Connecting Internal Systems to Leading AI Services &#x2014; Available from a Free Plan with No Credit Card Required" loading="lazy" width="1672" height="941" srcset="https://journal.qualiteg.com/content/images/size/w600/2026/08/04_who_what_where.png 600w, https://journal.qualiteg.com/content/images/size/w1000/2026/08/04_who_what_where.png 1000w, https://journal.qualiteg.com/content/images/size/w1600/2026/08/04_who_what_where.png 1600w, https://journal.qualiteg.com/content/images/2026/08/04_who_what_where.png 1672w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Controlling &quot;who, what, and where&quot; independently</span></figcaption></figure><p>And the entrance is guarded by company identities. When a user accesses a canal, the login screen of the company&apos;s identity provider &#x2014; such as Google Workspace &#x2014; appears, and only organizational accounts from administrator-approved domains can connect. There is no need to issue separate WireCanal accounts to each user. When the company suspends an account, for example upon an employee&apos;s departure, that user&apos;s access is automatically revoked within one hour. Delegating the management of &quot;who can use it&quot; entirely to the company&apos;s existing identity infrastructure &#x2014; that is WireCanal&apos;s answer.</p>
<!--kg-card-begin: html-->
<div style="text-align:center;margin:8px 0;"><a href="https://wirecanal.com/?utm_source=qualiteg_blog&amp;utm_medium=owned_media&amp;utm_campaign=wirecanal_launch&amp;utm_content=idp_solution_cta" target="_blank" rel="noopener" style="display:inline-block;background:#1b5fb8;color:#ffffff;padding:12px 40px;border-radius:6px;text-decoration:none;font-weight:bold;">Learn more</a></div>
<!--kg-card-end: html-->
<h2 id="what-sets-wirecanal-apart-the-company-chooses-which-tools-the-ai-can-see">What sets WireCanal apart: the company chooses which tools the AI can see</h2><p>WireCanal also works as a general-purpose secure tunnel, offering HTTPS publishing of web systems along with eight kinds of access protection &#x2014; including IP address restrictions, BASIC authentication, and token authentication &#x2014; on every plan. TCP relaying for RDP, SSH, databases, and more is available on the Pro Plan and above.</p><p>On top of that comes its distinctive feature: per-tool publication control for MCP. Even if an internal MCP server exposes many tools, an allowlist ledger determines which ones the AI can see. The default is deny-all. The authoritative copy of the ledger is a configuration file kept inside the corporate network; the cloud-side console can only &quot;propose&quot; changes, and applying them requires an approval action performed internally. If a tunnel is a plain pipe, WireCanal is a gatekeeper that understands the contents and chooses what to let through.</p><h2 id="defense-in-depth-for-organizational-ai-use">Defense in depth for organizational AI use</h2><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://journal.qualiteg.com/content/images/2026/08/05_layers.png" class="kg-image" alt="Qualiteg Launches WireCanal&#x2122;, Securely Connecting Internal Systems to Leading AI Services &#x2014; Available from a Free Plan with No Credit Card Required" loading="lazy" width="1672" height="941" srcset="https://journal.qualiteg.com/content/images/size/w600/2026/08/05_layers.png 600w, https://journal.qualiteg.com/content/images/size/w1000/2026/08/05_layers.png 1000w, https://journal.qualiteg.com/content/images/size/w1600/2026/08/05_layers.png 1600w, https://journal.qualiteg.com/content/images/2026/08/05_layers.png 1672w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">The layer that relays, and the layer that exposes</span></figcaption></figure><p>The boundaries WireCanal protects are threefold: &quot;who can connect&quot; and &quot;what the AI can see,&quot; as described above, plus &quot;where inside the network traffic can reach.&quot; The connection app connects only to its configured forwarding destinations, which prevents the tunnel from being used as a passage relaying traffic to arbitrary internal destinations. WireCanal&apos;s relay infrastructure is operated on servers in Japan, and inbound access is logged per canal, so you can review afterwards when and from where connections occurred. WireCanal adopts a fail-closed design: any traffic whose authorization cannot be confirmed by its access control is rejected.</p><p>These boundaries are supported by the following five layers of defense.</p><ol><li><strong>Fixed forwarding destinations</strong> &#x2014; The Agent connects only to its configured forwarding destinations. It re-validates the destination on every connection and does not follow redirects</li><li><strong>Restricted entrances</strong> &#x2014; The public entrance can be narrowed to the IP addresses of legitimate callers. Agent connections are verified against issued keys</li><li><strong>Access protection</strong> &#x2014; Eight kinds are available on every plan: IP restrictions, country restrictions, BASIC authentication, token authentication, time-window publishing, path restrictions, automatic blocking, and stealth mode</li><li><strong>Publication allowlists</strong> &#x2014; The MCP tools and URL paths exposed externally are managed in an allowlist ledger kept on the internal side. The default is deny-all</li><li><strong>Standards-compliant MCP authentication</strong> &#x2014; Built-in authentication and authorization conforming to the MCP Authorization specification and related RFCs (RFC 9728, RFC 8414, RFC 8707, and others); credentials verified at the entrance are never passed on to the forwarding destination</li></ol><p>In addition, WireCanal provides isolation via a dedicated subdomain and unique ID per canal, per-canal suspend and resume, immediate shutdown from the internal side, and access logs scaled by plan (the most recent 1,000 to 10,000 entries, with CSV download). Your internal databases and MCP servers themselves stay inside the corporate network. You can start with a single user, and when rolling out to a department, management carries over under the same structure of IdP settings, canals, and allowed tools.</p>
<!--kg-card-begin: html-->
<div style="text-align:center;margin:8px 0;"><a href="https://wirecanal.com/security?utm_source=qualiteg_blog&amp;utm_medium=owned_media&amp;utm_campaign=wirecanal_launch&amp;utm_content=security_cta" target="_blank" rel="noopener" style="display:inline-block;background:#1b5fb8;color:#ffffff;padding:12px 40px;border-radius:6px;text-decoration:none;font-weight:bold;">Learn more</a></div>
<!--kg-card-end: html-->
<h2 id="how-it-works-connecting-claude-to-an-internal-sales-database-in-three-steps">How it works: connecting Claude to an internal sales database in three steps</h2><p>After preparing an internal MCP server and the WireCanal Agent, the connection can be configured in three steps: create an MCP canal, link it to the company&apos;s identity provider, and register the connection URL with Claude.</p>
<!--kg-card-begin: html-->
<div style="position:relative;padding-bottom:56.25%;height:0;overflow:hidden;"><iframe src="https://www.youtube.com/embed/P11wPUt7dVU?rel=0" style="position:absolute;top:0;left:0;width:100%;height:100%;border:0;" referrerpolicy="strict-origin-when-cross-origin" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe></div>
<!--kg-card-end: html-->
<h3 id="1-create-an-mcp-canal">1. Create an MCP canal</h3><p>In the WireCanal console, specify the AI service to use and the internal MCP server as the forwarding destination to create an MCP canal; a connection URL for registering with Claude is then issued. The WireCanal Agent inside the corporate network connects outward, and the communication path is open from this point on.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://journal.qualiteg.com/content/images/2026/08/06_dashboard1.png" class="kg-image" alt="Qualiteg Launches WireCanal&#x2122;, Securely Connecting Internal Systems to Leading AI Services &#x2014; Available from a Free Plan with No Credit Card Required" loading="lazy" width="1024" height="518" srcset="https://journal.qualiteg.com/content/images/size/w600/2026/08/06_dashboard1.png 600w, https://journal.qualiteg.com/content/images/size/w1000/2026/08/06_dashboard1.png 1000w, https://journal.qualiteg.com/content/images/2026/08/06_dashboard1.png 1024w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">The actual dashboard. Each MCP canal shows badges for the AI services it is linked with.</span></figcaption></figure><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://journal.qualiteg.com/content/images/2026/08/07_dashboard2.png" class="kg-image" alt="Qualiteg Launches WireCanal&#x2122;, Securely Connecting Internal Systems to Leading AI Services &#x2014; Available from a Free Plan with No Credit Card Required" loading="lazy" width="1024" height="518" srcset="https://journal.qualiteg.com/content/images/size/w600/2026/08/07_dashboard2.png 600w, https://journal.qualiteg.com/content/images/size/w1000/2026/08/07_dashboard2.png 1000w, https://journal.qualiteg.com/content/images/2026/08/07_dashboard2.png 1024w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">The MCP canal settings view, showing the AI service and the internal forwarding destination at a glance.</span></figcaption></figure><h3 id="2-protect-the-mcp-canal-with-the-companys-identity-provider">2. Protect the MCP canal with the company&apos;s identity provider</h3><p>Assign an organizational IdP such as Google Workspace to the MCP canal and configure the domains permitted to connect. From then on, the entrance to this canal is the company&apos;s login screen.</p><h3 id="3-register-the-connection-url-with-claude">3. Register the connection URL with Claude</h3><p>Register the issued connection URL as a custom connector in Claude and sign in with your company account &#x2014; setup is complete. WireCanal responds automatically to the OAuth configuration required for the connection, so there is no need to build a separate authorization server for connecting to AI services (the initial organizational IdP setup does require registering a client on your IdP&apos;s side). From there, simply talk to Claude to ask questions and run analyses &#x2014; sales by category, annual sales trends, product-level sales movement &#x2014; based on the latest internal data. No SQL required.</p><h2 id="launch-campaign-the-light-plan-with-one-canal-and-a-permanent-subdomain-for-6000-yen-for-the-first-year-tax-included-equivalent-to-500-yen-per-month">Launch campaign: the Light Plan, with one canal and a permanent subdomain, for 6,000 yen for the first year (tax included; equivalent to 500 yen per month)</h2><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://journal.qualiteg.com/content/images/2026/08/08_campaign.png" class="kg-image" alt="Qualiteg Launches WireCanal&#x2122;, Securely Connecting Internal Systems to Leading AI Services &#x2014; Available from a Free Plan with No Credit Card Required" loading="lazy" width="1672" height="941" srcset="https://journal.qualiteg.com/content/images/size/w600/2026/08/08_campaign.png 600w, https://journal.qualiteg.com/content/images/size/w1000/2026/08/08_campaign.png 1000w, https://journal.qualiteg.com/content/images/size/w1600/2026/08/08_campaign.png 1600w, https://journal.qualiteg.com/content/images/2026/08/08_campaign.png 1672w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Launch campaign: first year at 6,000 yen per year (equivalent to 500 yen per month) promotion</span></figcaption></figure><p>To mark the start of general availability, Qualiteg is running a launch campaign for the Light Plan (one canal). Customers who sign up for an annual contract by Monday, August 31, 2026 can use the service for 6,000 yen (tax included; equivalent to 500 yen per month) for the first year. After the campaign ends (from September 1, 2026), the price for new annual contracts is 15,360 yen per year (tax included).</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr><th>Item</th><th>Details</th></tr>
</thead>
<tbody>
<tr><td><strong>Eligible plan</strong></td><td>Light Plan (one canal)</td></tr>
<tr><td><strong>Campaign price</strong></td><td>First year: 6,000 yen per year (tax included; equivalent to 500 yen per month; billed annually)</td></tr>
<tr><td><strong>Application deadline</strong></td><td>Monday, August 31, 2026</td></tr>
<tr><td><strong>Price after the campaign</strong></td><td>15,360 yen per year (tax included; equivalent to 1,280 yen per month; billed annually)</td></tr>
<tr><td><strong>Key features</strong></td><td>Permanent subdomain of your choice, HTTPS/MCP canals, AI connectors, organizational IdP integration, access protection, access logs</td></tr>
<tr><td><strong>How to apply</strong></td><td>During the campaign period, the promotion code &quot;WIRECANAL-PREMIERE&quot; is applied automatically when signing up for an annual contract (no entry required)</td></tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>* The promotion applies only to the initial annual contract. Renewals from the second year onward are billed at the regular price in effect at the time of renewal. The campaign&apos;s content and duration are subject to change or termination without notice.</p>
<!--kg-card-begin: html-->
<div style="text-align:center;margin:8px 0;"><a href="https://wirecanal.com/pricing?utm_source=qualiteg_blog&amp;utm_medium=owned_media&amp;utm_campaign=wirecanal_launch&amp;utm_content=campaign_pricing_cta" target="_blank" rel="noopener" style="display:inline-block;background:#1b5fb8;color:#ffffff;padding:12px 40px;border-radius:6px;text-decoration:none;font-weight:bold;">Learn more</a></div>
<!--kg-card-end: html-->
<h2 id="about-wirecanal">About WireCanal</h2><p>WireCanal is a secure tunnel and MCP policy gateway that safely connects cloud AI and external services to internal systems, with its relay infrastructure operated on servers in Japan. It provides user verification through the company&apos;s identity provider and per-tool MCP permission control, making internal systems available from Claude, ChatGPT, and other AI services without opening inbound ports or building a new VPN. In addition to MCP, it supports HTTPS and TCP (RDP, SSH, databases, and more), and the WireCanal Agent connection app runs on Windows and Linux. Service starts with a free plan that requires no credit card registration.</p><p>Product, pricing, and security details:<a href="https://wirecanal.com/?utm_source=qualiteg_blog&amp;utm_medium=owned_media&amp;utm_campaign=wirecanal_launch&amp;utm_content=footer_text_link" rel="noreferrer">https://wirecanal.com/</a></p><h2 id="about-qualiteg-inc">About Qualiteg Inc.</h2><figure class="kg-card kg-image-card"><img src="https://journal.qualiteg.com/content/images/2026/08/09_logo.png" class="kg-image" alt="Qualiteg Launches WireCanal&#x2122;, Securely Connecting Internal Systems to Leading AI Services &#x2014; Available from a Free Plan with No Credit Card Required" loading="lazy" width="500" height="500"></figure><p>Qualiteg Inc. is an AI company founded in July 2023. Under its corporate philosophy of &quot;deepening the creativity of people around the world,&quot; Qualiteg works to amplify human creativity through cutting-edge AI technology and to realize a world that produces new forms of expression and value once beyond imagination. Rather than leaving AI as the privilege of a few specialists, the company pursues a society free of divides caused by technology gaps &#x2014; one where anyone can use AI intuitively to deepen their own creativity &#x2014; through the research, development, and consulting of generative AI products.</p>
<!--kg-card-begin: html-->
<table>
<tbody>
<tr><td><strong>Company name</strong></td><td>Qualiteg Inc.</td></tr>
<tr><td><strong>Address</strong></td><td>1-10-6 Kajicho, Chiyoda-ku, Tokyo, Japan</td></tr>
<tr><td><strong>Founded</strong></td><td>July 2023</td></tr>
<tr><td><strong>Representative</strong></td><td>Tomonori Misawa, CEO</td></tr>
<tr><td><strong>Business</strong></td><td>AI and software research and development, consulting, and talent development</td></tr>
<tr><td><strong>Website</strong></td><td><a href="https://qualiteg.com/?ref=journal.qualiteg.com" target="_blank" rel="noopener">https://qualiteg.com/</a></td></tr>
<tr><td><strong>Blog</strong></td><td><a href="https://journal.qualiteg.com/" target="_blank" rel="noopener">https://blog.qualiteg.com/</a></td></tr>
<tr><td><strong>Products and services</strong></td><td><p>&#x25A0; An integrated AI platform that accelerates business: <a href="https://bestllam.com/?ref=journal.qualiteg.com" target="_blank" rel="noopener"><strong>Bestllam&#xAE;</strong></a></p><p>&#x25A0; Generates realistic AI avatar videos from text, audio, and more: <a href="https://motionvox.com/?ref=journal.qualiteg.com" target="_blank" rel="noopener"><strong>MotionVox&#xAE;</strong></a></p><p>&#x25A0; Audits LLM inputs and outputs to guard against data-leak risks: <a href="https://llm-audit.com/?ref=journal.qualiteg.com" target="_blank" rel="noopener"><strong>LLM-Audit&#x2122;</strong></a></p><p>&#x25A0; Detects and masks personal and confidential information fast and accurately: <a href="https://pii-fi.com/?ref=journal.qualiteg.com" target="_blank" rel="noopener"><strong>PII-Fi&#x2122; API</strong></a></p><p>&#x25A0; Builds chatbots and inference environments with open-source LLMs: <a href="https://chatstream.qualiteg.com/?ref=journal.qualiteg.com" target="_blank" rel="noopener"><strong>ChatStream&#xAE;</strong></a></p><p>&#x25A0; AI, DX, strategy, new business, and open innovation: <a href="https://qualiteg.com/consulting/business?ref=journal.qualiteg.com" target="_blank" rel="noopener"><strong>Consulting</strong></a></p></td></tr>
</tbody>
</table>
<!--kg-card-end: html-->
<h2 id="media-inquiries">Media inquiries</h2><p>Qualiteg Inc.</p><p>WireCanal PR</p><p>Contact: wirecanal-pr@qualiteg.com</p><hr><p>* Organizational IdP integration is available on the Light Plan and above.</p><p>* When using cloud AI, the requests required to invoke MCP tools and their execution results are also transmitted to the AI service in use. Data handling is subject to each AI service&apos;s terms and settings.</p><p>* Supported AI services, available features, setup procedures, and required administrator privileges vary by each AI service&apos;s plan and workspace settings. Information is current as of August 4, 2026.</p><p>* The number of access log entries viewable in the dashboard varies by plan.</p><p>* Company names, product names, and service names mentioned are trademarks or registered trademarks of their respective owners. Third-party service names are given as connection examples and do not indicate any partnership, sponsorship, or endorsement.</p>]]></content:encoded></item><item><title><![CDATA[TensorRT 10 × Blackwell Migration Guide (Part 2): A Passing Build Does Not Mean Correct Output — Five Cases of Silent Degradation]]></title><description><![CDATA[<p>Hello!</p><p>In the previous article, &quot;<a href="https://journal.qualiteg.com/tensorrt10-blackwell-rtx50-migration-guide-part1/" rel="noreferrer">TensorRT 10 &#xD7; Blackwell Migration Guide (Part 1): Inference Assets Won&apos;t Run on RTX 50 &#x2014; The Basics and the First Walls</a>,&quot; we covered why existing inference assets stop working in the move to the Blackwell generation, and how to get</p>]]></description><link>https://journal.qualiteg.com/tensorrt10-blackwell-silent-degradation-part2/</link><guid isPermaLink="false">6a60f8b0edf69a17d422a9f1</guid><category><![CDATA[GPU]]></category><category><![CDATA[PyTorch]]></category><category><![CDATA[Daily Dev Tips]]></category><dc:creator><![CDATA[Qualiteg Product Development Team]]></dc:creator><pubDate>Mon, 03 Aug 2026 03:00:00 GMT</pubDate><media:content url="https://journal.qualiteg.com/content/images/2026/08/tensorrt10-blackwell-rtx50-migration-guide-par2.png" medium="image"/><content:encoded><![CDATA[<img src="https://journal.qualiteg.com/content/images/2026/08/tensorrt10-blackwell-rtx50-migration-guide-par2.png" alt="TensorRT 10 &#xD7; Blackwell Migration Guide (Part 2): A Passing Build Does Not Mean Correct Output &#x2014; Five Cases of Silent Degradation"><p>Hello!</p><p>In the previous article, &quot;<a href="https://journal.qualiteg.com/tensorrt10-blackwell-rtx50-migration-guide-part1/" rel="noreferrer">TensorRT 10 &#xD7; Blackwell Migration Guide (Part 1): Inference Assets Won&apos;t Run on RTX 50 &#x2014; The Basics and the First Walls</a>,&quot; we covered why existing inference assets stop working in the move to the Blackwell generation, and how to get a minimal TensorRT 10 conversion through. The problems that appeared in Part 1 actually have one thing in common.<br><br><strong>Every one of them had the decency to stop with an error</strong>.</p><p>What is truly frightening lies beyond that. In a TensorRT migration pipeline, there exists a way to fail where:</p><ul><li><strong>the build passes</strong></li><li><strong>execution passes too</strong></li><li><strong>the speed is properly there</strong></li><li><strong>the output&apos;s shape and values look plausible at a glance</strong></li><li><strong>and yet the contents are wrong</strong></li></ul><p>.</p><p>In this article &#x2014; covering not only TensorRT&apos;s own behavior but also export mistakes, precision settings, and engine deployment mistakes &#x2014; we take <strong>failures that produce wrong output without stopping on an error</strong> and, for convenience, call them <strong>&quot;silent degradation&quot;</strong>.</p><p>It is exceptionally troublesome, because it comes to light only after the tests pass, the benchmarks post good numbers, and you have already reported &quot;we made it N times faster.&quot;</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://journal.qualiteg.com/content/images/2026/07/fig1_silent_matrix_v2.png" class="kg-image" alt="TensorRT 10 &#xD7; Blackwell Migration Guide (Part 2): A Passing Build Does Not Mean Correct Output &#x2014; Five Cases of Silent Degradation" loading="lazy" width="1958" height="1015" srcset="https://journal.qualiteg.com/content/images/size/w600/2026/07/fig1_silent_matrix_v2.png 600w, https://journal.qualiteg.com/content/images/size/w1000/2026/07/fig1_silent_matrix_v2.png 1000w, https://journal.qualiteg.com/content/images/size/w1600/2026/07/fig1_silent_matrix_v2.png 1600w, https://journal.qualiteg.com/content/images/2026/07/fig1_silent_matrix_v2.png 1958w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Figure 1: Failures that raise no error &#x2014; five kinds of silent degradation</span></figcaption></figure><p>In this article we share five instances of silent degradation we actually stepped on, in the order of <strong>symptom &#x2192; why it happens &#x2192; how to find it &#x2192; workaround</strong>.</p><p>At the end, we consolidate a verification design for detecting these systematically. First, in the interest of honesty, here is how far each case has been substantiated.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr><th>Case</th><th>Reproduced with this article&apos;s dummy</th><th>Experienced in production</th><th>Scope confirmed in this article</th></tr>
</thead>
<tbody>
<tr><td>Input/output dtype mix-up</td><td>Yes</td><td>Yes</td><td>Undefined behavior. In our environment we observed finite but wrong outputs</td></tr>
<tr><td>GridSample swap</td><td>Yes</td><td>Yes</td><td>Measured: becomes nearest-equivalent on our TensorRT 10.16, and correctly bilinear at opset 16</td></tr>
<tr><td>Cross-model engines</td><td>Outputs matched on a small model</td><td>Yes</td><td>Confirmed the two warnings and matching output on a small model. Breaking conditions unidentified</td></tr>
<tr><td>FP32 configuration and TF32 permission</td><td>Yes</td><td>Yes</td><td>Disabling TF32 shrank this model&apos;s error. Cause of the speed difference not isolated</td></tr>
<tr><td>Swapped export arguments</td><td>No (production case only)</td><td>Yes</td><td>Identified and fixed the argument-order mistake in production code</td></tr>
</tbody>
</table>
<!--kg-card-end: html-->
<h2 id="part-1-mixing-up-inputoutput-dtypes">Part 1: Mixing up input/output dtypes</h2><h3 id="symptom">Symptom</h3><p>We built an engine with FP16 tactics allowed and ran it by passing PyTorch half tensors directly<br> (the naive implementation, from before we added the &quot;two dtype-matching lines&quot; included in Part 1&apos;s <code>TRTRunner</code>).</p><p>No errors. Good speed.<strong>But the output was completely different from PyTorch&apos;s.</strong></p><p>How different? <strong>On a model whose output range is a bit under 0.5, the maximum absolute error was about 13.8</strong>. That is not on the level of an fp16 precision issue. It is a different animal entirely.</p><h3 id="why-it-happens">Why it happens</h3><p><code>config.set_flag(trt.BuilderFlag.FP16)</code> means &quot;allow FP16 implementation candidates,&quot; so <strong>FP16 tactics become selectable for internal computation</strong> (some layers may still get fp32). However, <strong>the network&apos;s input and output tensor types remain as defined in the ONNX</strong>. If you exported the ONNX in fp32, the engine&apos;s inputs and outputs stay fp32.</p><p>Now, what happens when you hand it the address of a PyTorch half tensor (<code>data_ptr()</code>)? TensorRT treats that region <strong>as an input buffer laid out with fp32 elements</strong>. Since fp16 is 2 bytes per element and fp32 is 4, not only does the interpretation of the values change &#x2014; <strong>TensorRT may also read past the region PyTorch allocated</strong>. The behavior is undefined: beyond corrupted output, some environments may see CUDA errors or crashes.</p><p>And the worst part is that <strong>in our measurements, even in this state `execute_async_v3` returned `True` (success), produced no NaN, and threw no exception</strong>.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr><th>How it was passed</th><th>enqueue return value</th><th>Maximum absolute error</th></tr>
</thead>
<tbody>
<tr><td>Matched to the engine&apos;s required dtype before passing</td><td>True</td><td><strong>about 0.001</strong> (no major numerical breakdown in this configuration)</td></tr>
<tr><td>Half tensor&apos;s address passed as-is</td><td><strong>True</strong></td><td><strong>about 13.8</strong> (completely different. One observation in our environment, not a reproducible error magnitude)</td></tr>
</tbody>
</table>
<!--kg-card-end: html-->
<h3 id="workaround">Workaround</h3><p><strong>Query the dtype the engine requires and explicitly convert before passing.</strong> The two lines we put into Part 1&apos;s <code>TRTRunner</code> are exactly this.</p><pre><code class="language-python">want = _TRT2TORCH[self.engine.get_tensor_dtype(name)]   # query the dtype the engine requires
t = t.to(device=self.device, dtype=want).contiguous()   # match it, then pass
if not self.ctx.set_tensor_address(name, t.data_ptr()):
    raise RuntimeError(f&quot;set_tensor_address failed: {name}&quot;)
</code></pre><p>&quot;I built with fp16, so the input must be fp16&quot; does not hold.<strong>Always ask the engine.</strong></p><h2 id="part-2-modelinear-was-silently-being-executed-as-nearest">Part 2: <code>mode=&apos;linear&apos;</code> was silently being executed as <code>nearest</code> </h2><p>Of the five, this was the hardest to find and the most surprising trap.</p><h3 id="symptom-1">Symptom</h3><p>With the 5D <code>grid_sample</code> covered in Part 1, TensorRT refuses to build (which is, in its way, kind). So what about <strong>4D `grid_sample`</strong>? There, <strong>both the build and the execution succeed without a problem</strong>&#x3002;</p><p>But compare the output against PyTorch and it is <strong>uniformly off</strong>. It is off by the same amount in fp16 and fp32. So this is not a precision issue &#x2014; <strong>something is structurally different</strong>. And yet, at a glance, the output image looks perfectly plausible.</p><h3 id="first-pin-down-what-is-happening">First, pin down what is happening</h3><p>The minimal reproduction is just this (<code>build_engine</code> / <code>TRTRunner</code> are used unchanged from Part 1).</p><pre><code class="language-python">class PlanarWarp(nn.Module):
    &quot;&quot;&quot;Minimal module containing a 4D grid_sample&quot;&quot;&quot;
    def forward(self, im, grid):
        return F.grid_sample(im, grid, align_corners=False)

torch.manual_seed(0)
im = torch.randn(1, 8, 128, 128, device=&quot;cuda&quot;)
grid = torch.rand(1, 128, 128, 2, device=&quot;cuda&quot;) * 2 - 1
model = PlanarWarp().eval().cuda()

torch.onnx.export(model, (im, grid), &quot;planar_warp.onnx&quot;,
                  input_names=[&quot;im&quot;, &quot;grid&quot;], output_names=[&quot;y&quot;],
                  opset_version=20, dynamo=True)
build_engine(&quot;planar_warp.onnx&quot;, &quot;planar_warp.plan&quot;, fp16=False)
runner = TRTRunner(&quot;planar_warp.plan&quot;)
trt_out = runner.run({&quot;im&quot;: im, &quot;grid&quot;: grid})[&quot;y&quot;]
</code></pre><p>To identify the cause, <strong>we cross-checked TensorRT&apos;s output exhaustively against every interpretation of PyTorch&apos;s `F.grid_sample`</strong>&#x3002;<code>mode</code> (bilinear / nearest) &#xD7; <code>align_corners</code> (True / False) &#xD7; <code>padding_mode</code> (zeros / border / reflection) &#x2014; all 12 combinations.</p><pre><code class="language-python">for mode, align, pad in itertools.product(
        [&quot;bilinear&quot;, &quot;nearest&quot;], [False, True], [&quot;zeros&quot;, &quot;border&quot;, &quot;reflection&quot;]):
    ref = F.grid_sample(im, grid, mode=mode, align_corners=align, padding_mode=pad)
    print(mode, align, pad,
          (trt_out - ref).abs().max().item(),   # maximum absolute error
          torch.equal(trt_out, ref))            # bitwise equality check
</code></pre><p>Here are the results.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://journal.qualiteg.com/content/images/2026/07/fig2_gridsample_semantics.png" class="kg-image" alt="TensorRT 10 &#xD7; Blackwell Migration Guide (Part 2): A Passing Build Does Not Mean Correct Output &#x2014; Five Cases of Silent Degradation" loading="lazy" width="2000" height="909" srcset="https://journal.qualiteg.com/content/images/size/w600/2026/07/fig2_gridsample_semantics.png 600w, https://journal.qualiteg.com/content/images/size/w1000/2026/07/fig2_gridsample_semantics.png 1000w, https://journal.qualiteg.com/content/images/size/w1600/2026/07/fig2_gridsample_semantics.png 1600w, https://journal.qualiteg.com/content/images/2026/07/fig2_gridsample_semantics.png 2200w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Figure 2: The ONNX says mode=&apos;linear&apos;, yet what actually ran was nearest</span></figcaption></figure><p><strong>TensorRT&apos;s output matched the result of `mode=&apos;nearest&apos;, align_corners=False` with `torch.equal` returning True &#x2014; a bitwise exact match.</strong> Meanwhile, the difference from the intended <code>bilinear</code> is more than 3.1. When bilinear interpolation is swapped for nearest-neighbor, the output changes only to the extent of &quot;looking somewhat jaggy.&quot; Buried inside a warping pipeline, you will almost never catch it by eye.</p><h3 id="why-it-happens-%E2%80%94-isolating-with-opset-16-versus-20">Why it happens &#x2014; isolating with opset 16 versus 20</h3><p>Inspecting the node attributes in the ONNX file, this is what we found.</p><pre><code>ONNX GridSample attributes: {&apos;align_corners&apos;: 0, &apos;mode&apos;: &apos;linear&apos;, &apos;padding_mode&apos;: &apos;zeros&apos;}
</code></pre><p><code>mode</code> is, per the opset 20 specification, correctly written as <code>linear</code>. And here an important fact comes in.<strong>In ONNX&apos;s GridSample, the interpolation mode name was `bilinear` in opset 16 and was renamed to `linear` in opset 20</strong>. And according to NVIDIA&apos;s official documentation, linear interpolation for GridSample is supported by TensorRT. So it is not that &quot;TensorRT does not support linear.&quot; What is suspect is <strong>how the parser interprets the new opset 20 attribute name</strong>.</p><p>So <strong>we exported the same model with the same inputs at both opset 16 and opset 20 and compared</strong>.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr><th>export</th><th>ONNX mode attribute</th><th>Interpretation matching TensorRT&apos;s output</th><th>Verdict</th></tr>
</thead>
<tbody>
<tr><td>opset 16</td><td><code>bilinear</code></td><td><strong>bilinear</strong> (max_abs 2.4e-07)</td><td><strong>correctly linear-interpolated</strong></td></tr>
<tr><td>opset 20</td><td><code>linear</code></td><td><strong>nearest</strong> (<code>torch.equal</code> = True)</td><td><strong>swapped for nearest</strong></td></tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>Same TensorRT, same model: <strong>opset 16 is correct, opset 20 comes out nearest</strong>. From this measurement we can infer with high confidence that the ONNX ingestion path of TensorRT 10.16 in our environment fails to map the <code>mode=&apos;linear&apos;</code> introduced in opset 20 to linear interpolation and falls back to nearest (in both the ONNX specification and TensorRT&apos;s documentation, linear is supported and is the default-side value, so this is not a case of &quot;nearest is the default&quot;). We have not inspected the post-parse layer attributes or the parser implementation, so we are not asserting the exact location, and a future version may fix it.</p><h3 id="workarounds-%E2%80%94-three-in-order-of-ease">Workarounds &#x2014; three, in order of ease</h3><p><strong>Workaround 1: export at opset 16 (easiest; verified by measurement)</strong></p><p>As the table shows, exporting at opset 16 yields correct bilinear behavior in our environment. Unless you need 5D (which requires opset 20), this is sufficient.</p><p><strong>Workaround 2: decompose `grid_sample` into primitive operations (verified through TensorRT execution)</strong></p><p>If you have reasons to use opset 20, or would rather not entrust the operation to TensorRT, another option is to <strong>rebuild the operation as a mathematically equivalent composition of primitive operations with proven numerics in TensorRT</strong>. Bilinear interpolation is, at heart, just &quot;fetch the 4 neighbors and take a weighted average,&quot; so it decomposes into Floor / Clamp / Gather and basic arithmetic.</p><p><strong>Workaround 3: a custom plugin</strong>(covered in the final installment)</p><pre><code class="language-python">import torch
import torch.nn.functional as F

def bilinear_grid_sample(im, grid, align_corners=False):
    &quot;&quot;&quot;Reimplements the forward inference of F.grid_sample(im, grid, mode=&apos;bilinear&apos;, padding_mode=&apos;zeros&apos;).

    Swap this in only at export time. Assumes finite-valued grids;
    NaN/Inf, backward, border/reflection, and 5D inputs are out of scope.
      im:   (N, C, H, W)
      grid: (N, Hg, Wg, 2)  range [-1, 1] (x, y order)
    &quot;&quot;&quot;
    n, c, h, w = im.shape
    gx, gy = grid[..., 0], grid[..., 1]

    # normalized coordinates [-1, 1] &#x2192; pixel coordinates
    if align_corners:
        x = (gx + 1) / 2 * (w - 1)
        y = (gy + 1) / 2 * (h - 1)
    else:
        x = ((gx + 1) * w - 1) / 2
        y = ((gy + 1) * h - 1) / 2

    x0, y0 = torch.floor(x), torch.floor(y)
    x1, y1 = x0 + 1, y0 + 1

    # weights for the 4 neighbors
    wa = (x1 - x) * (y1 - y)
    wb = (x1 - x) * (y - y0)
    wc = (x - x0) * (y1 - y)
    wd = (x - x0) * (y - y0)

    # Reproducing padding_mode=&apos;zeros&apos;:
    # add 1px of zero padding, clamp indices to [-1, size], then add 1.
    # However far out of range a coordinate goes, it ends up referencing a zero-valued padding pixel.
    im_p = F.pad(im, (1, 1, 1, 1), mode=&quot;constant&quot;, value=0.0)
    x0i = (x0.clamp(-1.0, float(w)) + 1).long()
    x1i = (x1.clamp(-1.0, float(w)) + 1).long()
    y0i = (y0.clamp(-1.0, float(h)) + 1).long()
    y1i = (y1.clamp(-1.0, float(h)) + 1).long()

    wp = w + 2
    im_flat = im_p.reshape(n, c, -1)          # flatten to (N, C, (H+2)*(W+2))

    def gather(yi, xi):
        # shape it as GatherElements(dim=2) to guarantee the ONNX / TensorRT correspondence
        idx = (yi * wp + xi).reshape(n, 1, -1).expand(-1, c, -1)
        return torch.gather(im_flat, 2, idx)

    va, vb, vc, vd = gather(y0i, x0i), gather(y1i, x0i), gather(y0i, x1i), gather(y1i, x1i)

    hg, wg = grid.shape[1], grid.shape[2]
    out = (va * wa.reshape(n, 1, -1) + vb * wb.reshape(n, 1, -1)
           + vc * wc.reshape(n, 1, -1) + vd * wd.reshape(n, 1, -1))
    return out.reshape(n, c, hg, wg)
</code></pre><p>This decomposed version was <strong>verified not only with self-tests in PyTorch but all the way through ONNX export &#x2192; TensorRT build &#x2192; execution</strong>. The three-way comparison measured as follows.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr><th>Comparison</th><th>Maximum absolute error</th></tr>
</thead>
<tbody>
<tr><td>PyTorch <code>F.grid_sample</code> vs PyTorch decomposed version</td><td>2.4e-07</td></tr>
<tr><td>PyTorch <code>F.grid_sample</code> vs <strong>TensorRT-built decomposed version</strong></td><td><strong>2.4e-07</strong></td></tr>
<tr><td>PyTorch decomposed version vs TensorRT-built decomposed version</td><td>4.8e-07</td></tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>We have confirmed that it stays correctly bilinear when running on TensorRT. It is also worth writing a self-test that includes out-of-range grids alongside it.</p><pre><code class="language-python">torch.manual_seed(0)
dev = &quot;cuda:0&quot;
src = torch.randn(4, 3, 256, 256, device=dev)

cases = {
    &quot;uniform_pm1&quot;:   torch.rand(4, 256, 256, 2, device=dev) * 2 - 1,
    &quot;outside_pm1.5&quot;: torch.rand(4, 256, 256, 2, device=dev) * 3 - 1.5,   # includes out-of-range values
}
ys, xs = torch.meshgrid(torch.linspace(-1, 1, 256, device=dev),
                        torch.linspace(-1, 1, 256, device=dev), indexing=&quot;ij&quot;)
ident = torch.stack([xs, ys], dim=-1).expand(4, -1, -1, -1)
cases[&quot;identity_plus_flow&quot;] = ident + torch.randn(4, 256, 256, 2, device=dev) * 0.05

for name, grid in cases.items():
    ref = F.grid_sample(src, grid)          # bilinear / zeros / align_corners=False
    got = bilinear_grid_sample(src, grid)
    ma = float((ref - got).abs().max())
    print(f&quot;[selftest] {name}: max_abs={ma:.3e} -&gt; {&apos;PASS&apos; if ma &lt; 1e-5 else &apos;FAIL&apos;}&quot;)
</code></pre><p><strong>The point is to perform this swap only inside the export wrapper.</strong> Your production model code stays completely untouched.</p><h2 id="part-3-even-within-the-same-generation-engines-can-break-across-gpu-models">Part 3: Even within the same generation, engines can break across GPU models</h2><h3 id="symptom-2">Symptom</h3><p>We took an engine built on one GPU and ran it on <strong>a different model of the same Blackwell generation (sm_120)</strong>. It runs. It is fast.</p><p><strong>But the output was corrupted.</strong></p><p>TensorRT&apos;s log said this (quoting the latter sentence verbatim).</p><pre><code>[TRT] [WARNING] Using an engine plan file across different models of devices is not
supported and is likely to affect performance or even cause errors or deadlock.
</code></pre><p>Before it, one more warning appears, to the effect of <strong>&quot;this engine requires more SMs (Streaming Multiprocessors) than this device has; a deadlock is likely&quot;</strong>. Even so, <strong>`deserialize` succeeds, `execute_async_v3` returns `True`, and processing does not stop.</strong></p><h3 id="why-it-happens-1">Why it happens</h3><p>As described in Part 1, TensorRT <strong>benchmarks kernels on the actual machine at build time and picks the fastest implementations</strong>. A default-configuration engine bases its execution plan not only on Compute Capability but on <strong>multiple hardware characteristics of the GPU it was built on (SM count, shared memory, L2 cache, and so on)</strong>. A different model differs in these, which can lead not only to performance loss but to execution problems &#x2014; and TensorRT itself detects the mismatch and warns.</p><p><strong>&quot;Same Compute Capability means compatible&quot; is wrong.</strong> Even between two sm_120 GPUs, different models must be treated as different targets.</p><h3 id="the-genuinely-nasty-part">The genuinely nasty part</h3><p>We also ran an experiment reproducing this situation: build the engine on a model with more SMs, then load and run it on one with fewer. The result was this.</p><p><strong>Both warnings appeared. Yet the output matched the result on the build machine (the measured maximum absolute error was exactly 0.0, though we did not verify as far as `torch.equal`).</strong></p><p>In other words, <strong>with a small, simple model, ignoring the warnings still &quot;works&quot;</strong>. That is the worst possible outcome. Once you have seen it &quot;work&quot; during development, the warning starts to look like mere noise. Then, when you switch to the complex production model, it bares its teeth &#x2014; spewing CUDA errors while continuing to stream corrupted output. What we actually experienced was the latter.</p><p>The official documentation does note that an engine may function on a different GPU of the same architecture with only a small performance loss. Even so, for production we <strong>treat this warning as a fail-fast condition (stop when it appears)</strong>. As long as the breaking conditions remain unidentified, our judgment is that one should not bet on &quot;it works now, so it is fine.&quot;</p><h3 id="workarounds">Workarounds</h3><ol><li><strong>Manage and build engines per GPU model, not per Compute Capability</strong> &#x2014; splitting the storage directory by <code>sm_120/</code> alone is not enough; separate by model name as well</li><li><strong>At build time, save &quot;GPU product name, Compute Capability, SM count, TensorRT / CUDA versions&quot; as metadata (a sidecar JSON, for example); at startup, check it against the runtime environment and refuse to deserialize on mismatch</strong> &#x2014; this is the effective seawall. Note that <strong>checking the return value of `execute_async_v3` cannot detect this trap</strong> &#x2014; in our experiment, <code>True</code> was returned even under the model mismatch</li><li><strong>Treat TensorRT warnings as errors in production</strong> &#x2014; do not swallow the logger&apos;s WARNING; combine it with the check above and fail fast</li><li><strong>If distribution to multiple models is truly unavoidable, build with hardware compatibility mode (`SAME_COMPUTE_CAPABILITY`, etc.)</strong> &#x2014; the official mechanism for use across GPUs with the same Compute Capability. It constrains performance and features, however, so verify both speed and numerics separately before adopting it</li></ol><h2 id="part-4-building-in-fp32-still-lets-tf32-into-the-candidate-pool">Part 4: Building in fp32 still lets TF32 into the candidate pool</h2><h3 id="symptom-3">Symptom</h3><p>A module whose accuracy fell short under FP16-allowed settings was rebuilt with an FP32 configuration that disallows FP16 tactics. Yet its agreement with PyTorch did not improve as expected. What is more, <strong>the agreement fluctuated slightly with every rebuild</strong> &#x2014; sometimes clearing the acceptance bar, sometimes not.</p><h3 id="why-it-happens-2">Why it happens</h3><p><strong>For convolutions and matrix multiplications on fp32 tensors, TensorRT by default &quot;permits&quot; the use of TF32 tactics.</strong> TF32 is a fast format with the mantissa trimmed to 10 bits, used by Tensor Cores on Ampere and later. Not every fp32 operation becomes TF32 &#x2014; ordinary fp32 implementations may still be chosen &#x2014; but the assumption &quot;built in fp32, therefore everything runs in fp32&quot; does not hold.</p><p>A plausible cause of the per-build fluctuation is measurement noise at build time. Because TensorRT&apos;s build relies on on-device measurement, different tactics may be chosen on different builds from candidates with similar performance (the official documentation describes this as well). That said, we did not go as far as comparing which tactics were actually selected.</p><h3 id="the-workaround-%E2%80%94-and-a-surprising-side-effect">The workaround &#x2014; and a surprising side effect</h3><p><strong>For engines that strictly verify fidelity, disable TF32 explicitly.</strong></p><pre><code class="language-python">config = builder.create_builder_config()
config.clear_flag(trt.BuilderFlag.TF32)     # &#x2605; remove TF32 tactics from the candidate pool
</code></pre><p>Here are the measured results.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://journal.qualiteg.com/content/images/2026/07/fig3_tf32_v2.png" class="kg-image" alt="TensorRT 10 &#xD7; Blackwell Migration Guide (Part 2): A Passing Build Does Not Mean Correct Output &#x2014; Five Cases of Silent Degradation" loading="lazy" width="2000" height="835" srcset="https://journal.qualiteg.com/content/images/size/w600/2026/07/fig3_tf32_v2.png 600w, https://journal.qualiteg.com/content/images/size/w1000/2026/07/fig3_tf32_v2.png 1000w, https://journal.qualiteg.com/content/images/size/w1600/2026/07/fig3_tf32_v2.png 1600w, https://journal.qualiteg.com/content/images/2026/07/fig3_tf32_v2.png 2200w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Figure 3: Even with an FP32 configuration, the error differed between TF32 allowed and TF32 disabled</span></figcaption></figure><p>The maximum absolute error <strong>improved by three orders of magnitude, from 2.55e-04 to 6.26e-07</strong>.</p><p>And interestingly, <strong>in this one pair of builds, the TF32-disabled side came out faster</strong> (0.874 ms &#x2192; 0.772 ms). A different tactic may have been selected, but we did not isolate the cause (no comparison of the selected tactics). The difference is within reach of build-time measurement noise, so do not read this roughly 12% as a general trend. Still, it would be a shame to skip the experiment out of the assumption that &quot;disabling TF32 always slows things down,&quot; so <strong>measure speed in that exact configuration as well</strong>. We should add that even with TF32 disabled, numerical differences from PyTorch arising from operation ordering and tactic choices do not disappear entirely.</p><h2 id="part-5-swapped-arguments-in-the-onnx-export-the-accident-that-hurt-the-most">Part 5: Swapped arguments in the ONNX export (the accident that hurt the most)</h2><p>The last one is not a TensorRT problem but <strong>our own mistake</strong>. Yet it took longer to find than anything else in this series. The same shape of accident can happen to anyone, so we are sharing it. Note that this case occurred in a production model that confidentiality prevents us from publishing, and we have not run a reproduction experiment with a dummy model for this article.</p><h3 id="symptom-4">Symptom</h3><p>After converting a certain module to TensorRT, we hit a strange symptom: <strong>how the output broke depended on the input</strong>. Under some conditions it matched perfectly; under others it clearly degraded. Moreover, the amount of degradation <strong>grew in proportion to the &quot;magnitude of motion&quot; in the input</strong>.</p><p>fp16 or fp32, TF32 on or off &#x2014; the degradation did not change.<strong>At that point we strongly suspected a structural problem rather than a simple precision difference.</strong></p><h3 id="why-it-happened">Why it happened</h3><p><code>torch.onnx.export</code> had received its arguments in an order that disagreed with the parameter order of the model&apos;s <code>forward</code>.</p><pre><code class="language-python"># forward definition:   forward(self, feature, kp_driving, kp_source)
# what export was given:      (feature, kp_source, kp_driving)   &#x2190; 2nd and 3rd swapped
torch.onnx.export(model, (feature, kp_source, kp_driving), &quot;m.onnx&quot;, ...)
</code></pre><p><strong>These are positional arguments, so Python raises no complaint.</strong> The export succeeds, the ONNX file is generated, the TensorRT build passes, and it runs. Except what you end up with is <strong>an ONNX in which the roles of two inputs are swapped and frozen that way inside the model</strong>.</p><p>Because the internal computation took a difference form along the lines of &quot;reference &#x2212; input A + input B,&quot; the error comes out to exactly <strong>2 &#xD7; (the difference between the two inputs)</strong>. Hence the symptom: inputs with a small difference match, and the larger the difference, the more spectacularly it breaks.</p><h3 id="why-discovery-took-so-long-%E2%80%94-the-self-reenactment-verification-pitfall">Why discovery took so long &#x2014; the &quot;self-reenactment&quot; verification pitfall</h3><p>This is the biggest problem. Our verification at the time was performed by <strong>feeding the same data to both inputs</strong>. Under that condition the two inputs are equal, so <strong>even with them swapped, the results match perfectly</strong>. The tests passed with full marks.</p><p>We call this <strong>the &quot;self-reenactment parity&quot; trap</strong>.<strong>If you verify equivalence only under conditions where the inputs coincide with the reference, structural bugs like swapped arguments are rendered completely harmless-looking.</strong></p><h3 id="how-to-find-it-%E2%80%94-determining-whether-the-culprit-is-tensorrt-or-the-onnx">How to find it &#x2014; determining whether the culprit is TensorRT or the ONNX</h3><p>What proved effective here was <strong>isolation using onnxruntime</strong>.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://journal.qualiteg.com/content/images/2026/07/fig4_triangulation.png" class="kg-image" alt="TensorRT 10 &#xD7; Blackwell Migration Guide (Part 2): A Passing Build Does Not Mean Correct Output &#x2014; Five Cases of Silent Degradation" loading="lazy" width="2000" height="1059" srcset="https://journal.qualiteg.com/content/images/size/w600/2026/07/fig4_triangulation.png 600w, https://journal.qualiteg.com/content/images/size/w1000/2026/07/fig4_triangulation.png 1000w, https://journal.qualiteg.com/content/images/size/w1600/2026/07/fig4_triangulation.png 1600w, https://journal.qualiteg.com/content/images/2026/07/fig4_triangulation.png 2047w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Figure 4: Is the culprit the export or TensorRT &#x2014; triangulate to decide</span></figcaption></figure><ol><li>First, split the model into stages and binary-search for where the numbers start to diverge (comparing intermediate tensors)</li><li>Once the diverging subgraph is identified, <strong>run the same ONNX on onnxruntime&apos;s CPU execution</strong></li><li>If onnxruntime diverges in the same direction, <strong>suspect the ONNX graph, the input binding at export, or operator specification differences first</strong>. If PyTorch and onnxruntime agree and only TensorRT diverges, <strong>prioritize TensorRT&apos;s parser, engine, and runtime-side configuration</strong></li></ol><p>This is not a procedure that logically convicts the culprit; it is <strong>a triage that decides where to look first</strong> (onnxruntime can have implementation differences of its own, and the issue can also be how input names or dtypes are passed on the TensorRT side). Even so, it dramatically changes the opening moves of an investigation. In our case, onnxruntime disagreed by exactly the same amount, so we examined the export side first and pinned down the positional-argument mix-up in the code.</p><p>For per-layer comparison, polygraphy&apos;s compare-all-layers mode (mark all) is convenient, but <strong>on large models it exhausts memory and dies</strong>. In practice, a binary search that carves out only the suspicious part was more dependable.</p><h3 id="the-fix-%E2%80%94-keyword-binding-via-kwargs">The fix &#x2014; keyword binding via kwargs</h3><p><strong>Make the argument passing to export itself keyword-based.</strong> <code>torch.onnx.export</code> provides, separate from the positional <code>args</code>, <strong>an official `kwargs` parameter for passing inputs by keyword</strong>. Use it, and the very concept of tuple ordering disappears.</p><pre><code class="language-python"># Problem: args is a tuple, bound by position. Get the forward argument
#       order wrong and the export still succeeds, generating an ONNX with
#       the input roles left swapped (input_names merely attaches names;
#       it guarantees no semantic correspondence)
# Fix:  bind &quot;name &#x2192; tensor&quot; explicitly via the kwargs parameter
torch.onnx.export(
    model,
    args=(),
    kwargs={
        &quot;feature&quot;: feature,
        &quot;kp_source&quot;: kp_source,
        &quot;kp_driving&quot;: kp_driving,
    },
    f=&quot;m.onnx&quot;,
    input_names=[&quot;feature&quot;, &quot;kp_source&quot;, &quot;kp_driving&quot;],
    output_names=[&quot;y&quot;], opset_version=20, dynamo=True,
)
</code></pre><p>After the fix, the degradation vanished completely.</p><h2 id="a-verification-design-that-catches-silent-degradation">A verification design that catches silent degradation</h2><p>Lay the five traps side by side, and shared countermeasures come into view.</p><h3 id="1-measure-numerics-before-speed">1. Measure numerics before speed</h3><p>Reverse the order, and the good news &#x2014; &quot;it got faster&quot; &#x2014; arrives first, reducing numerical verification to a formality.<strong>A speedup with wrong numbers has no value.</strong></p><h3 id="2-do-not-trust-agreement-on-random-inputs-%E2%80%94-verify-with-real-data">2. Do not trust agreement on random inputs &#x2014; verify with real data</h3><p>We were able to back this up with measurements as well. We built an engine from a block stacking LayerNorm and GELU with FP16 tactics allowed, and measured the error while varying only the input range. The results follow (the reference is PyTorch fp32; in both the &quot;FP16 allowed / disallowed&quot; columns, TF32 remains at its default, i.e., allowed).</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr><th>Input scale</th><th>Max absolute error with FP16 allowed (nRMSE)</th><th>Max absolute error with FP16 disallowed (nRMSE)</th></tr>
</thead>
<tbody>
<tr><td>1&#xD7; (standard normal random)</td><td>0.0074 (8.9e-04)</td><td>0.0010 (1.9e-04)</td></tr>
<tr><td>300&#xD7;</td><td>1.77 (5.4e-04)</td><td>0.0010 (6.9e-07)</td></tr>
<tr><td>3000&#xD7;</td><td>5.41 (2.5e-04)</td><td>0.0029 (1.0e-07)</td></tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>As the input scale widened, the FP16 configuration&apos;s <strong>maximum absolute error grew substantially</strong> (though the growth is not simple proportionality to the input multiplier, because LayerNorm normalizes the scale). The nRMSE, meanwhile, actually fell from 8.9e-04 to 2.5e-04 &#x2014; at the very least it does not worsen with input scale. In other words, <strong>absolute error and normalized error paint completely different pictures of the same result</strong>. What this tells us is that <strong>an acceptance bar of &quot;absolute error below X&quot; calibrated only on standard normal randoms is easily broken at real-data ranges</strong>.</p><p>In our real model, moreover, this went beyond mere error growth and appeared as <strong>every output turning NaN the moment real data went in</strong> (an intermediate value just before a LayerNorm exceeded fp16&apos;s representable range). The remedy was to disallow FP16 tactics for that module and build it with an FP32 configuration.</p><h3 id="3-do-not-verify-equivalence-by-self-reenactment">3. Do not verify equivalence by &quot;self-reenactment&quot;</h3><p>As in Part 5, tests confined to conditions where the input coincides with the reference hide structural bugs completely.<strong>Make sure your verification data includes the large-difference cases that can occur in real operation.</strong></p><h3 id="4-triangulate-the-culprit-with-pytorch-onnxruntime-tensorrt">4. Triangulate the culprit with PyTorch / onnxruntime / TensorRT</h3><ul><li>PyTorch and onnxruntime agree, only TensorRT diverges &#x2192; <strong>suspect TensorRT&apos;s semantics and kernels</strong> (Part 2)</li><li>onnxruntime diverges as well &#x2192; <strong>suspect the ONNX &#x2014; that is, the export</strong> (Part 5)</li></ul><p>Being able to make this cut changes investigation time by an order of magnitude.</p><h3 id="5-carve-out-the-suspicious-operation-and-test-it-alone">5. Carve out the suspicious operation and test it alone</h3><p>Chasing a vague &quot;somehow off&quot; across a whole model is inefficient. Part 2 was settled in a single stroke by carving out one <code>grid_sample</code> and cross-checking it exhaustively.</p><h3 id="6-toggle-precision-and-watch-whether-the-symptom-changes">6. Toggle precision and watch whether the symptom changes</h3><p>If switching among fp16 / fp32 / TF32 <strong>barely changes the amount of degradation, prioritize structural problems &#x2014; input binding, operator semantics &#x2014; over rounding error</strong>. It is not a proof, but as a signal for setting investigation priorities it served us extremely well.</p><h3 id="7-build-in-mechanisms-that-refuse-to-swallow-failure">7. Build in mechanisms that refuse to swallow failure</h3><p><code>execute_async_v3</code> return-value checks, engine-to-device consistency checks, and a design that refuses to start when a component is missing.<strong>Never allowing a state that &quot;looks normal while partly broken&quot;</strong> is the last seawall against silent degradation.</p><h2 id="what-we-have-not-yet-confirmed">What we have not yet confirmed</h2><ul><li><strong>The root location of `mode=&apos;linear&apos;` becoming nearest</strong> &#x2014; from the opset 16/20 comparison we strongly infer interpretation at the parser stage, but we have not examined the parser source code or the layer attributes immediately after parsing. Verification also covered a single version, TensorRT 10.16.1.11, and a future version may fix it</li><li><strong>The conditions under which cross-model engines break</strong> &#x2014; with this article&apos;s dummy model, the warnings appeared yet the outputs matched. We have not identified at what scale or structure breakage begins</li><li><strong>The same class of problems under int8 quantization</strong> &#x2014; this article covers fp16 / fp32 / TF32 only</li></ul><h2 id="summary">Summary</h2><p>Summed up in one sentence: <strong>&quot;in a TensorRT migration pipeline, neither &apos;the build passed&apos; nor &apos;it ran&apos; nor &apos;it got faster&apos; guarantees in any way that the output is correct.&quot;</strong>.</p><p>That is exactly why we measure numerics before speed, measure with real data rather than randoms, triangulate the culprit when things diverge, and build in mechanisms that refuse to swallow failure. We consider these the minimum conditions for putting TensorRT into production.</p><p>Next time (the final installment) takes on the biggest homework left over from Part 1: <strong>getting 5D grid_sample, which TensorRT does not natively support, through with a custom plugin</strong>. Building it against the new CUDA / TensorRT generation involves quite a few hurdles: what to do when your local nvcc cannot generate code for Blackwell; the problem that pip-installed TensorRT <strong>ships without the development headers</strong>; and <strong>the plugin&apos;s fp16 kernel breaking down numerically</strong> &#x2014; once again, a story bordering on silent degradation.</p><p>See you next time!</p><hr><h3 id="references-primary-sources">References (primary sources)</h3><ul><li><a href="https://docs.nvidia.com/deeplearning/tensorrt/latest/?ref=journal.qualiteg.com" rel="noreferrer">NVIDIA TensorRT documentation (Developer Guide / Release Notes)</a></li><li><a href="https://onnx.ai/onnx/operators/onnx__GridSample.html?ref=journal.qualiteg.com" rel="noreferrer">ONNX Operators: GridSample (specification of mode / align_corners / padding_mode)</a></li><li><a href="https://pytorch.org/docs/stable/generated/torch.nn.functional.grid_sample.html?ref=journal.qualiteg.com" rel="noreferrer">PyTorch: torch.nn.functional.grid_sample</a></li><li><a href="https://github.com/NVIDIA/TensorRT/issues/3890?ref=journal.qualiteg.com" rel="noreferrer">NVIDIA/TensorRT issue #3890: request for native 5D GridSample support</a></li><li><a href="https://blogs.nvidia.com/blog/tensorfloat-32-precision-format/?ref=journal.qualiteg.com" rel="noreferrer">NVIDIA: TensorFloat-32 (TF32) explained</a></li><li><a href="https://github.com/NVIDIA/TensorRT/tree/main/tools/Polygraphy?ref=journal.qualiteg.com" rel="noreferrer">polygraphy (TensorRT debugging and comparison tool)</a></li><li>Related article from Qualiteg: <a href="https://journal.qualiteg.com/2026-nvidia-gpu-list-filtering-app/" rel="noreferrer">2026 NVIDIA GPU quick-lookup tool</a></li></ul>]]></content:encoded></item><item><title><![CDATA[Claude Opus 5.0 Complete Guide: Model Specifications, API Notes, and Claude Code Operations]]></title><description><![CDATA[<p>Hello!</p><p>On July 24, 2026, Anthropic released Claude Opus 5.</p><p>That is a generational change just two months after Opus 4.8 (released May 28). The pace here keeps accelerating.</p><p>Now, this blog has followed the Opus line through the <a href="https://journal.qualiteg.com/claude-opus-4-7-claude-code-guide/" rel="noreferrer">Claude Opus 4.7 Complete Guide</a>&#x3001;<a href="https://journal.qualiteg.com/claude-opus-4-8-claude-code-guide/" rel="noreferrer">Claude Opus 4.</a></p>]]></description><link>https://journal.qualiteg.com/claude-opus-5-claude-code-guide/</link><guid isPermaLink="false">6a662682edf69a17d422aabb</guid><category><![CDATA[LLM]]></category><category><![CDATA[Generative AI Frontlines]]></category><dc:creator><![CDATA[Qualiteg Product Development Team]]></dc:creator><pubDate>Tue, 28 Jul 2026 07:24:03 GMT</pubDate><media:content url="https://journal.qualiteg.com/content/images/2026/07/claude-opus-5-claude-code-guide--1-.png" medium="image"/><content:encoded><![CDATA[<img src="https://journal.qualiteg.com/content/images/2026/07/claude-opus-5-claude-code-guide--1-.png" alt="Claude Opus 5.0 Complete Guide: Model Specifications, API Notes, and Claude Code Operations"><p>Hello!</p><p>On July 24, 2026, Anthropic released Claude Opus 5.</p><p>That is a generational change just two months after Opus 4.8 (released May 28). The pace here keeps accelerating.</p><p>Now, this blog has followed the Opus line through the <a href="https://journal.qualiteg.com/claude-opus-4-7-claude-code-guide/" rel="noreferrer">Claude Opus 4.7 Complete Guide</a>&#x3001;<a href="https://journal.qualiteg.com/claude-opus-4-8-claude-code-guide/" rel="noreferrer">Claude Opus 4.8 Complete Guide</a> &#x2014; but this Opus 5 is fundamentally different in structure from those two updates within 4.x.</p><p>What is different? First of all, <strong>Opus 5 is not the top-of-the-line model</strong>&#x3002;</p><p>Anthropic&apos;s lineup already has, at the top, the June 9, 2026 release <a href="https://journal.qualiteg.com/claude-fable-5-claude-code-guide/" rel="noreferrer">Claude Fable 5</a>, and Opus 5 was slotted in below it and above Sonnet 5 &#x2014; an upper-middle position.</p><p>The era when the name Opus meant &quot;top tier&quot; ended with the arrival of Fable 5.</p><p>On top of that, Anthropic positions Opus 5 as &quot;<strong>a model that approaches Fable 5&apos;s frontier-class intelligence at half the price</strong>&quot; &#x2014; and has even published benchmark scores where it beats Fable 5.</p><p>Pricing is unchanged from Opus 4.8: $5 input / $25 output.</p><p>In other words, this is a character no previous Opus has had: not the top model, but the practical workhorse.</p><p>And remember: Fable 5 went through the turmoil of being suspended on June 12 by order of the U.S. government and returning on July 1 (we covered the full story in <a href="https://journal.qualiteg.com/fable-5-mythos-5-us-government-directive/" rel="noreferrer">The Fable 5 / Mythos 5 Suspension: What Happened</a>).</p><p>The &quot;<strong>safety classifiers</strong>&quot; at the center of that incident <strong>have, in fact, been added to Opus 5 as well</strong>&#x3002;</p><p>Something Opus 4.8 did not have is now on board &#x2014; a change you absolutely need to know about when migrating (covered in detail in <a href="#ch7" rel="noreferrer">Chapter 7</a>).</p><p>This is a long piece, so there is no need to read it start to finish. Skim the chapters that interest you. Sources are collected at the end.</p><p>The intended readers: engineers considering a migration from Opus 4.8, tech leads deciding between Fable 5 and Opus 5, lead engineers running Claude Code across a team, and anyone optimizing API costs.</p><h3 id="table-of-contents">Table of Contents</h3><p><a href="#part1" rel="noreferrer">Part 1</a> What Claude Opus 5 Is</p><ul><li><a href="#ch1" rel="noreferrer">1. Where Opus 5 sits in the Claude 5 family</a></li><li><a href="#ch2" rel="noreferrer">2. Claude Opus 5 core specifications</a></li><li><a href="#ch3" rel="noreferrer">3. What &quot;beating Fable 5&quot; actually means in the benchmarks</a></li><li><a href="#ch4" rel="noreferrer">4. Two breaking API changes around thinking</a></li><li><a href="#ch5" rel="noreferrer">5. Migration checklist (from the official guide)</a></li><li><a href="#ch6" rel="noreferrer">6. New and related features</a></li></ul><p><a href="#part2" rel="noreferrer">Part 2</a> Notes for API Use</p><ul><li><a href="#ch7" rel="noreferrer">7. Safety classifiers that 4.8 did not have</a></li><li><a href="#ch8" rel="noreferrer">8. Choosing effort levels</a></li><li><a href="#ch9" rel="noreferrer">9. Task budgets (beta): giving agents a sense of budget</a></li><li><a href="#ch10" rel="noreferrer">10. Prompting to get the most out of Opus 5</a></li></ul><p><a href="#part3" rel="noreferrer">Part 3</a> Opus 5 in Claude Code</p><ul><li><a href="#ch11" rel="noreferrer">11. Prerequisites for using Opus 5 in Claude Code</a></li><li><a href="#ch12" rel="noreferrer">12. Watch the carry-over behavior of Claude Code&apos;s effort setting</a></li><li><a href="#ch13" rel="noreferrer">13. What changed in Fast mode</a></li><li><a href="#ch14" rel="noreferrer">14. What happens when you get flagged: the automatic model fallback</a></li><li><a href="#ch15" rel="noreferrer">15. The 1M context and opusplan</a></li><li><a href="#ch16" rel="noreferrer">16. A rhythm for day-to-day operation</a></li></ul><h3 id="the-updates-from-48-at-a-glance">The updates from 4.8, at a glance</h3><p>From Opus 4.8, which we covered last time, the main changes in Opus 5 are the following.</p><p>Details come in each chapter; first, the overall picture.</p><p><strong>Not incremental &#x2014; a &quot;step-change&quot;</strong></p><p>The official documentation itself describes the gain over 4.8 as &quot;a step-change, not incremental.&quot; The biggest gains are in deep reasoning, long-horizon agentic tasks, and test-time compute scaling (<a href="#ch3" rel="noreferrer">Chapter 3</a>).</p><p><strong>thinking is ON by default</strong></p><p>On 4.8, requests without the <code>thinking</code> field ran without thinking; on Opus 5, the same requests run with thinking.<code>max_tokens</code> settings need revisiting (<a href="#ch4" rel="noreferrer">Chapter 4</a>).</p><p><strong>Disabling thinking is possible only at effort `high` or below (breaking change)</strong></p><p><code>thinking: {type: &quot;disabled&quot;}</code> combined with effort <code>xhigh</code>/<code>max</code> returns a 400 error (<a href="#ch4" rel="noreferrer">Chapter 4</a>).</p><p><strong>The recommended starting effort has changed</strong></p><p>The API default remains <code>high</code>, unchanged. What changed is the recommended starting point: from 4.7/4.8&apos;s &quot;start coding with <code>xhigh</code>&quot; to Opus 5&apos;s &quot;start with <code>high</code> and step up to <code>xhigh</code> only for demanding work&quot; &#x2014; with active use of <code>low</code>/<code>medium</code> now spelled out explicitly (<a href="#ch8" rel="noreferrer">Chapter 8</a>).</p><p><strong>No Web Fetch server tool</strong></p><p>The Web Fetch tool available on Opus 4.8 is not available on Opus 5 (it is separate from web search). API integrations using it need an alternative design (<a href="#ch5" rel="noreferrer">Chapter 5</a>).</p><p><strong>Safety classifiers on board</strong></p><p>Model-specific cyber and biology classifiers absent from 4.8 are present on Opus 5. Interventions are said to be about 85% less frequent than Fable 5&apos;s, but for 4.8 migrants this is a new constraint (<a href="#ch7" rel="noreferrer">Chapter 7</a>).</p><p><strong>Knowledge cutoff of May 2026</strong></p><p>Newer than Fable 5 and Sonnet 5 (both January 2026) &#x2014; the freshest knowledge in the current lineup (<a href="#ch2" rel="noreferrer">Chapter 2</a>).</p><p><strong>New and related features</strong></p><p>Mid-conversation tool changes (beta), the <code>fallbacks</code> parameter&apos;s <code>&quot;default&quot;</code> mode (beta), Task budgets (beta), and the minimum cacheable length dropping to 512 tokens, among others (<a href="#ch6" rel="noreferrer">Chapter 6</a>, <a href="#ch7" rel="noreferrer">Chapter 7</a>, <a href="#ch9" rel="noreferrer">Chapter 9</a>).</p><p><strong>Pricing unchanged</strong></p><p>$5 input / $25 output, as before. Fast mode is also $10/$50, the same as Opus 4.8 (<a href="#ch2" rel="noreferrer">Chapter 2</a>).</p><p><strong>No Priority Tier</strong></p><p>Priority Tier, usable with Opus 4.8, is not supported on Opus 5. Organizations with commitments should watch their capacity planning (<a href="#ch5" rel="noreferrer">Chapter 5</a>).</p><p>One more note: code written for Opus 4.8 <strong>will not necessarily run with just a model ID swap</strong>&#x3002;</p><p>With two behavior changes &#x2014; the thinking default and the restriction on disabling thinking &#x2014; we recommend running through the migration checklist (<a href="#ch5" rel="noreferrer">Chapter 5</a>) once.</p><hr>
<!--kg-card-begin: html-->
<div id="part1"></div>
<!--kg-card-end: html-->
<h2 id="part-1-what-claude-opus-5-is">Part 1: What Claude Opus 5 Is</h2>
<!--kg-card-begin: html-->
<div id="ch1"></div>
<!--kg-card-end: html-->
<h3 id="1-where-opus-5-sits-in-the-claude-5-family">1. Where Opus 5 sits in the Claude 5 family</h3><p>First, a recap of how Anthropic&apos;s lineup changed over the roughly two months from June 2026.</p><p>In that period, Anthropic shipped four models in rapid succession.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://journal.qualiteg.com/content/images/2026/07/fig1_timeline.png" class="kg-image" alt="Claude Opus 5.0 Complete Guide: Model Specifications, API Notes, and Claude Code Operations" loading="lazy" width="2000" height="835" srcset="https://journal.qualiteg.com/content/images/size/w600/2026/07/fig1_timeline.png 600w, https://journal.qualiteg.com/content/images/size/w1000/2026/07/fig1_timeline.png 1000w, https://journal.qualiteg.com/content/images/size/w1600/2026/07/fig1_timeline.png 1600w, https://journal.qualiteg.com/content/images/2026/07/fig1_timeline.png 2200w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Figure 1: The Claude 5 family&apos;s whirlwind two months (June&#x2013;July 2026 release timeline)</span></figcaption></figure><ul><li><strong>June 9</strong> Claude Fable 5 / Claude Mythos 5 released (the newly created top &quot;Mythos class.&quot; <a href="https://journal.qualiteg.com/claude-fable-5-mythos-5-guide-benchmarks/" rel="noreferrer">Benchmark deep-dive</a>)</li><li><strong>June 12</strong> Both models suspended worldwide under a U.S. Commerce Department export-control directive (<a href="https://journal.qualiteg.com/fable-5-mythos-5-us-government-directive/" rel="noreferrer">full story</a>)</li><li><strong>June 26</strong> Mythos 5 partially restored, limited to vetted U.S. organizations</li><li><strong>June 30</strong> Export restrictions lifted. Same day, Claude Sonnet 5 released (introductory pricing $2/$10 through August 31, 2026; $3/$15 thereafter)</li><li><strong>July 1</strong> Fable 5 fully restored on claude.ai, Claude Code, and elsewhere</li><li><strong>July 24</strong> Claude Opus 5 released. Same day, Opus 4.7&apos;s Fast mode discontinued</li></ul><p>As a result, the current lineup is a four-tier structure, from the top: Fable 5 ($10/$50), Opus 5 ($5/$25), Sonnet 5 ($3/$15), and Haiku 4.5 ($1/$5).</p><p>Opus 5&apos;s official positioning is &quot;for complex agentic coding and enterprise work.&quot;</p><p>Anthropic made it the new default model for Claude Max and the top model available on the Pro plan.</p><p>The arrangement Anthropic itself recommends: Opus 5 as the daily mainstay, Fable 5 only for truly frontier work.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr><th>Model</th><th>Price (input/output per MTok)</th><th>Context</th><th>Knowledge cutoff (reliable)</th><th>Positioning</th></tr>
</thead>
<tbody>
<tr><td>Claude Fable 5</td><td>$10 / $50</td><td>1M</td><td>January 2026</td><td>Top of the line. For long-horizon autonomous agents</td></tr>
<tr><td><strong>Claude Opus 5</strong></td><td><strong>$5 / $25</strong></td><td><strong>1M</strong></td><td><strong>May 2026</strong></td><td>Mainstay for complex agentic coding and enterprise work</td></tr>
<tr><td>Claude Sonnet 5</td><td>$3 / $15 ($2/$10 through 8/31)</td><td>1M</td><td>January 2026</td><td>Balance of speed and intelligence. Everyday coding</td></tr>
<tr><td>Claude Haiku 4.5</td><td>$1 / $5</td><td>200k</td><td>February 2025</td><td>Fast, lightweight tasks</td></tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>(Source: Anthropic&apos;s official model list. Prices and cutoffs as of July 27, 2026.)</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://journal.qualiteg.com/content/images/2026/07/fig2_pricing.png" class="kg-image" alt="Claude Opus 5.0 Complete Guide: Model Specifications, API Notes, and Claude Code Operations" loading="lazy" width="2000" height="873" srcset="https://journal.qualiteg.com/content/images/size/w600/2026/07/fig2_pricing.png 600w, https://journal.qualiteg.com/content/images/size/w1000/2026/07/fig2_pricing.png 1000w, https://journal.qualiteg.com/content/images/size/w1600/2026/07/fig2_pricing.png 1600w, https://journal.qualiteg.com/content/images/2026/07/fig2_pricing.png 2200w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Figure 2: API pricing across the Claude 5 family (Opus 5 is half the price of Fable 5)</span></figcaption></figure><p>Easily overlooked but important is the <strong>knowledge cutoff</strong>.</p><p>Opus 5&apos;s reliable knowledge cutoff is May 2026, <br>four months newer than Fable 5 and Sonnet 5&apos;s January 2026 &#x2014; the newest in the current lineup.</p><p>When working with newer libraries and APIs, it may hold fresher knowledge than its &quot;superior,&quot; Fable 5.</p><p>A newer cutoff does not guarantee accuracy on any specific detail, though. As noted below, Opus 5 lacks the Web Fetch server tool (<a href="#ch5" rel="noreferrer">Chapter 5</a>), so supplement fresh information via the web search tool or your own retrieval, and keep cross-checking against official documentation.</p><p>For a comparison of LLM vendors&apos; pricing, see our <a href="https://journal.qualiteg.com/llm-api-claude-gpt-gemini-grok-pricing/" rel="noreferrer">LLM API price roundup</a>; on Fable 5&apos;s cost problem, see <a href="https://journal.qualiteg.com/claude-fable5-cost-and-outlook/" rel="noreferrer">Fable 5: Costs and Outlook</a> as well.</p><p>User complaints that Fable 5 &quot;burns tokens aggressively&quot; have been widely reported; per Fortune, Opus 5 leading with token efficiency is in part an answer to that complaint.</p><p>OpenAI&apos;s GPT-5.6, released July 9, also markets economical token consumption &#x2014; the axis of competition is shifting from &quot;intelligence&quot; to &quot;the balance of intelligence and cost.&quot;</p>
<!--kg-card-begin: html-->
<div id="ch2"></div>
<!--kg-card-end: html-->
<h3 id="2-claude-opus-5-core-specifications">2. Claude Opus 5 core specifications</h3>
<!--kg-card-begin: html-->
<table>
<thead>
<tr><th>Item</th><th>Details</th></tr>
</thead>
<tbody>
<tr><td>Model ID</td><td><code>claude-opus-5</code> (dateless fixed snapshot; same scheme as 4.8 / Sonnet 5)</td></tr>
<tr><td>Release</td><td>July 24, 2026</td></tr>
<tr><td>Context window</td><td><strong>1M tokens, default and maximum</strong> (no reduced variant)</td></tr>
<tr><td>Max output tokens</td><td>128k (300k on the Batch API with the <code>output-300k-2026-03-24</code> beta header)</td></tr>
<tr><td>Thinking mode</td><td><strong>Adaptive thinking ON by default</strong> (no <code>thinking</code> field required)</td></tr>
<tr><td>effort</td><td>All five levels supported: <code>low</code>/<code>medium</code>/<code>high</code>/<code>xhigh</code>/<code>max</code>. Default <code>high</code></td></tr>
<tr><td>Price (standard)</td><td>$5 input / $25 output (same as Opus 4.8)</td></tr>
<tr><td>Price (Fast mode)</td><td>$10 input / $50 output (research preview, Claude API only)</td></tr>
<tr><td>Minimum cacheable prompt length</td><td><strong>512 tokens</strong> (halved from 4.8&apos;s 1,024)</td></tr>
<tr><td>Knowledge cutoff</td><td>May 2026 for both reliable and training data</td></tr>
<tr><td>Unsupported features</td><td><strong>Web Fetch server tool</strong> and <strong>Priority Tier</strong> (both available on Opus 4.8)</td></tr>
<tr><td>Availability</td><td>Claude API / Amazon Bedrock (<code>anthropic.claude-opus-5</code>) / Google Cloud (<code>claude-opus-5</code>) / Microsoft Foundry</td></tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>Much carries over from 4.8, but two points signal a generational shift: &quot;1M is the default and the maximum, with no smaller-context variant at all,&quot; and &quot;thinking is ON by default.&quot;</p><p>Note that <code>claude-opus-5</code> is a fixed snapshot, not an evergreen pointer (the dateless-ID scheme in place since the Claude 4.6 generation).</p>
<!--kg-card-begin: html-->
<div id="ch3"></div>
<!--kg-card-end: html-->
<h3 id="3-what-beating-fable-5-actually-means-in-the-benchmarks">3. What &quot;beating Fable 5&quot; actually means in the benchmarks</h3><p>Anthropic&apos;s launch announcement claims Opus 5 beats Fable 5 on several benchmarks.</p><p>In this blog&apos;s usual style, we will go through them while distinguishing who measured each number.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://journal.qualiteg.com/content/images/2026/07/fig3_benchmarks_v2.png" class="kg-image" alt="Claude Opus 5.0 Complete Guide: Model Specifications, API Notes, and Claude Code Operations" loading="lazy" width="2000" height="835" srcset="https://journal.qualiteg.com/content/images/size/w600/2026/07/fig3_benchmarks_v2.png 600w, https://journal.qualiteg.com/content/images/size/w1000/2026/07/fig3_benchmarks_v2.png 1000w, https://journal.qualiteg.com/content/images/size/w1600/2026/07/fig3_benchmarks_v2.png 1600w, https://journal.qualiteg.com/content/images/2026/07/fig3_benchmarks_v2.png 2200w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Figure 3: Claude Opus 5 key benchmarks (Anthropic in-house evaluations and ARC Prize-verified external evaluations)</span></figcaption></figure><p><strong>Frontier-Bench v0.1 (run internally by Anthropic)</strong></p><p>In the System Card&apos;s evaluation summary table, Opus 5 tops the compared models at 43.3%, well above Fable 5&apos;s 33.7% and Opus 4.8&apos;s 18.7% &#x2014; more than double 4.8. Cost per task is also said to be lower.</p><p>The official launch chart also shows multiple values by effort level, so 43.3% is not necessarily Opus 5&apos;s per-effort peak.</p><p><strong>ARC-AGI 3 (verified external evaluation by ARC Prize)</strong></p><p>Opus 5 scored, at <code>high</code> effort, 30.16% (rounded to 30.2% at publication) &#x2014; about 3.9 times the 7.8% of the runner-up, GPT-5.6 Sol (Anthropic&apos;s announcement modestly calls it &quot;3&#xD7;&quot;).</p><p>Opus 4.8 was at 1.5% &#x2014; essentially zero. Note that because the evaluation window was short, Opus 5&apos;s <code>max</code> has not been evaluated on ARC-AGI 3.</p><p><strong>CursorBench 3.2 (external evaluation by Cursor)</strong></p><p><code>max</code> effort: Opus 5 at 70.0%, Fable 5 at 70.5% &#x2014; a 0.5-point gap. Average cost per task is $8.23 for Opus 5 versus $17.32 for Fable 5, more than double.</p><p>Cursor itself notes, however, that small score differences may not be statistically significant.</p><p><strong>OSWorld 2.0 (computer use; Anthropic evaluation, listed in the System Card)</strong></p><p>70.57% (mean first-attempt success over 5 runs), up sharply from Opus 4.8&apos;s 55.7%. It is said to beat Fable 5&apos;s best result at roughly one-third the cost.</p><p><strong>Zapier AutomationBench (results from an external evaluation provider)</strong></p><p>A pass rate about 1.5&#xD7; the runner-up model&apos;s (at comparable cost per task).</p><p><strong>Life sciences (Anthropic&apos;s own evaluations)</strong></p><p>+10.2 points over Opus 4.8 on organic chemistry tasks and +7.7 on protein prediction. Anthropic is pitching Opus 5 as &quot;the most capable generally available model for scientific research.&quot;</p><p>Two caveats.</p><p>First, the numbers fall into three kinds of attribution: (a) evaluations Anthropic ran itself (Frontier-Bench, OSWorld, life sciences), (b) external evaluations run and published by benchmark providers (ARC Prize, Cursor, Zapier), and (c) press coverage of those.</p><p>(b) is not self-reporting, but neither is it independent replication by a third-party community.</p><p>Second, &quot;beating Fable 5&quot; does not apply across all benchmarks.</p><p>Anthropic itself continues to recommend Fable 5 for the hardest long-horizon autonomous tasks, and states plainly that in cybersecurity exploit capability Opus 5 &quot;does not reach Mythos 5.&quot;</p><p>How it fares in blind voting (Arena-style) and in our <a href="https://journal.qualiteg.com/llm-ranking-2026-03/" rel="noreferrer">LLM rankings</a> will be settled once independent evaluations are in.</p><p>TechCrunch highlights the trait Anthropic emphasized: Opus 5 &quot;verifies its own work and iterates carefully until it succeeds.&quot;</p><p>No premature victory declarations; verify, then fix. This is the change that symbolizes Opus 5&apos;s character &#x2014; two sides of the same coin as the prompting changes described later (removing re-verification instructions that duplicate its self-verification; <a href="#ch5" rel="noreferrer">Chapter 5</a> and <a href="#ch10" rel="noreferrer">Chapter 10</a>).</p>
<!--kg-card-begin: html-->
<div id="ch4"></div>
<!--kg-card-end: html-->
<h3 id="4-two-breaking-api-changes-around-thinking">4. Two breaking API changes around thinking</h3><p>Opus 4.7 to 4.8 was a &quot;swap the model ID and go&quot; migration.</p><p>This time there are two breaking changes in API parameters. On top of that, on the feature side, there are the effective incompatibilities noted above &#x2014; no Web Fetch and no Priority Tier (covered in <a href="#ch5" rel="noreferrer">Chapter 5</a>&apos;s checklist).</p><p><strong>Change 1: thinking is now ON by default</strong></p><p>On Opus 4.8, requests without the <code>thinking</code> field ran without thinking.</p><p>On Opus 5, the same requests run with thinking (adaptive thinking: the model decides, turn by turn, whether and how deeply to think).</p><p>Nothing changed on the wire &#x2014; explicitly sending <code>thinking: {type: &quot;adaptive&quot;}</code> behaves the same.</p><p>The practical caution concerns <code>max_tokens</code>.</p><p><code>max_tokens</code> is a hard limit on the combined total of thinking and visible text. Move a workload that ran thinking-free on 4.8 over as-is, and the added thinking tokens can truncate the visible text mid-response (<code>stop_reason: &quot;max_tokens&quot;</code>).</p><p>Revisit anywhere you set a smallish <code>max_tokens</code> on the assumption of no thinking.</p><p><strong>Change 2: disabling thinking now works only at effort `high` or below</strong></p><p>If you want the old behavior, you can pass <code>thinking: {type: &quot;disabled&quot;}</code>, but Opus 5 accepts it only when the effort level is <code>high</code> or below.</p><p><code>thinking: {type: &quot;disabled&quot;}</code> combined with effort <code>xhigh</code>/<code>max</code> returns a 400 error.</p><p>This combination was accepted on 4.8, so audit your requests for it before migrating.</p><p>The check runs on every single request, so &quot;the first half of the conversation was fine, then a 400 the moment we raised effort mid-conversation&quot; can happen.</p><pre><code class="language-python"># Passes on 4.8 but returns a 400 error on Opus 5
client.messages.create(
    model=&quot;claude-opus-5&quot;,
    max_tokens=16000,
    thinking={&quot;type&quot;: &quot;disabled&quot;},
    output_config={&quot;effort&quot;: &quot;xhigh&quot;},   # disabled cannot be combined with xhigh
    messages=[{&quot;role&quot;: &quot;user&quot;, &quot;content&quot;: &quot;...&quot;}],
)

# Fix A: drop the thinking field (back to the default, thinking on)
client.messages.create(
    model=&quot;claude-opus-5&quot;,
    max_tokens=16000,
    output_config={&quot;effort&quot;: &quot;xhigh&quot;},   # thinking is ON by default
    messages=[{&quot;role&quot;: &quot;user&quot;, &quot;content&quot;: &quot;...&quot;}],
)

# Fix B: keep thinking disabled and lower effort to high or below
client.messages.create(
    model=&quot;claude-opus-5&quot;,
    max_tokens=16000,
    thinking={&quot;type&quot;: &quot;disabled&quot;},
    output_config={&quot;effort&quot;: &quot;high&quot;},    # high / medium / low are acceptable
    messages=[{&quot;role&quot;: &quot;user&quot;, &quot;content&quot;: &quot;...&quot;}],
)
</code></pre><p>The official documentation also spells out side effects of disabling thinking.</p><p>Without thinking, Opus 5 can occasionally write a tool call as body text instead of a <code>tool_use</code> block. The call is never executed, and in agent loops the leaked text remains in the conversation history and affects subsequent turns.</p><p><code>&lt;thinking&gt;</code> and similar internal XML tags can also end up mixed into visible output.</p><p>The official recommendation: keep thinking enabled and control cost with lower effort.</p><p>For most tasks, &quot;thinking on at <code>low</code> effort&quot; is said to beat &quot;thinking off&quot; at comparable cost. Prompt-level mitigations for integrations that truly must disable it are covered in <a href="#ch10" rel="noreferrer">Chapter 10</a>.</p>
<!--kg-card-begin: html-->
<div id="ch5"></div>
<!--kg-card-end: html-->
<h3 id="5-migration-checklist-from-the-official-guide">5. Migration checklist (from the official guide)</h3><p>The official migration guide&apos;s checklist, reordered for practical workflow.</p><ol><li>Update the model name from <code>claude-opus-4-8</code> to <code>claude-opus-5</code> in your code</li><li><strong>Audit requests that use the Web Fetch server tool</strong>. It is unavailable on Opus 5, so design alternatives: the web search tool, client-side fetching, or routing just those requests to another model</li><li><code>thinking</code>-less workloads: audit anything you ran without the field (it runs with thinking on Opus 5). Either revisit <code>max_tokens</code>, or keep the old behavior with <code>thinking: {type: &quot;disabled&quot;}</code> plus effort <code>high</code> or below</li><li><code>thinking: {type: &quot;disabled&quot;}</code> with effort <code>xhigh</code>/<code>max</code>: fix requests combining them (they will return 400)</li><li>Re-evaluate effort from a blank slate. Do not carry settings over from the old model; re-run an effort sweep on your own evals.<code>low</code>/<code>medium</code> are worth trying aggressively as cost/latency controls, and <code>max</code> is worth trying on capability-first tasks.<code>xhigh</code>/<code>max</code> runs should start with <code>max_tokens</code> at 64k or higher</li><li>Check prompts near the cache boundary (cacheable from 512 tokens; 4.8 required 1,024)</li><li><code>stop_reason: &quot;refusal&quot;</code> handling should be reviewed; consider adopting <code>fallbacks: &quot;default&quot;</code> (beta) (<a href="#ch7" rel="noreferrer">Chapter 7</a>)</li><li><strong>Organizations with Priority Tier commitments should plan capacity separately</strong>. Priority Tier is unsupported on Opus 5 and remains available on Opus 4.8</li><li>For agentic workloads, consider Task budgets (beta) and mid-conversation tool changes (beta) (<a href="#ch9" rel="noreferrer">Chapter 9</a> and <a href="#ch6" rel="noreferrer">Chapter 6</a>)</li><li>Re-tune prompts for length and verbosity. Opus 5 tends toward longer visible responses and longer deliverable documents, and lowering effort does not shorten them (<a href="#ch10" rel="noreferrer">Chapter 10</a>)</li><li><strong>Remove re-verification instructions written for older models (&quot;add a final verification step,&quot; &quot;double-check,&quot; &quot;verify with a subagent,&quot; etc.)</strong>. Opus 5 self-verifies unprompted, so leaving them in wastes tokens on redundant verification. Do not remove project-specific acceptance criteria such as running designated tests, lint, and type checks (<a href="#ch10" rel="noreferrer">Chapter 10</a>)</li><li>Re-baseline cost and latency on your own workloads</li></ol><p>Of these, items 5, 10, and 11 are of the &quot;won&apos;t break, but becomes suboptimal&quot; kind &#x2014; skipping them causes no errors.</p><p>That said, item 11 (removing redundant re-verification instructions) is one of the few the official guide flatly describes as &quot;token savings with no quality loss,&quot; so it deserves higher priority.</p>
<!--kg-card-begin: html-->
<div id="ch6"></div>
<!--kg-card-end: html-->
<h3 id="6-new-and-related-features">6. New and related features</h3><p>A roundup of the new and related features available with Opus 5.</p><p>This includes not only features added alongside Opus 5 but also existing features that now support it. Details in the relevant chapters.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr><th>Feature</th><th>Summary</th><th>Status / positioning on Opus 5</th></tr>
</thead>
<tbody>
<tr><td>Mid-conversation tool changes</td><td>Keep the prompt cache when adding or removing tools mid-conversation</td><td>beta (<code>mid-conversation-tool-changes-2026-07-01</code> header); newly added</td></tr>
<tr><td><code>fallbacks: &quot;default&quot;</code></td><td>Automatic re-run on the Anthropic-recommended fallback model per refusal category</td><td>beta (<code>server-side-fallback-2026-07-01</code> header); the <code>&quot;default&quot;</code> mode is new</td></tr>
<tr><td>Task budgets</td><td>Give the entire agentic loop an advisory token budget</td><td>beta (<code>task-budgets-2026-03-13</code> header); existing beta now supports Opus 5</td></tr>
<tr><td>Minimum cache length 512 tokens</td><td>Halved from 4.8&apos;s 1,024; short prompts become cacheable</td><td>GA; spec improvement</td></tr>
<tr><td>Fast mode</td><td>Up to 2.5&#xD7; faster at $10/$50. Claude API only (not Bedrock/GCP/Foundry)</td><td>Research preview; existing feature now supports Opus 5</td></tr>
<tr><td>Full effort ladder</td><td>All five levels from <code>low</code> to <code>max</code> supported</td><td>GA; full support for the existing parameter</td></tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p><strong>Mid-conversation tool changes</strong> is an unglamorous change, but one that matters to agent developers.</p><p>Previously, changing the tool list invalidated the cached prefix, so the standard practice was to hand over every tool at the start of the session.</p><p>With the beta header <code>mid-conversation-tool-changes-2026-07-01</code>, you can progressively expose or retire tools as the task advances while keeping cache hits for earlier turns.</p><p>It is easiest understood as the sequel to the mid-conversation system messages introduced in 4.8.</p><hr>
<!--kg-card-begin: html-->
<div id="part2"></div>
<!--kg-card-end: html-->
<h2 id="part-2-notes-for-api-use">Part 2: Notes for API Use</h2>
<!--kg-card-begin: html-->
<div id="ch7"></div>
<!--kg-card-end: html-->
<h3 id="7-safety-classifiers-that-48-did-not-have">7. Safety classifiers that 4.8 did not have</h3><p>First, pin down the key fact.</p><p><strong>Model-specific safety classifiers of the same family as Fable 5&apos;s (cybersecurity and biology) are now on Opus 5 as well.</strong></p><p>And <strong>Opus 4.8 does not carry these classifiers</strong>&#x3002;</p><p>The only models the official documentation describes as classifier-equipped are Fable 5 and Opus 5. The very fact that flagged requests are routed to Opus 4.8 corroborates that 4.8 lacks the same classifiers.</p><p>To be fair, the 4.8 era also saw false positives from the platform-side Usage Policy safeguards.<a href="https://journal.qualiteg.com/claude-code-usage-policy-violation-fix/" rel="noreferrer">Our June article</a> covered exactly that &#x2014; a different layer from the model-specific classifiers.</p><p>So for users migrating from 4.8, this is a newly added constraint.</p><p>The accurate reading is not &quot;it got safer&quot; but &quot;a classifier has been attached &#x2014; though it intervenes far less often than Fable 5&apos;s.&quot;</p><p>That said, in the context of having just lived through work stopping during the Fable 5 suspension, the differences from Fable 5 carry practical meaning too. Four points.</p><p><strong>(1) Alignment itself is the best in the line&apos;s history</strong></p><p>In Anthropic&apos;s automated behavioral audit, Opus 5&apos;s misaligned-behavior score is 2.3 (lower is better).</p><p>That is the best among recent models including Opus 4.8, Sonnet 5, and Fable 5; Anthropic calls it &quot;the most aligned Opus, and the hardest to steer toward misuse&quot; (bear in mind this is self-evaluation).</p><p><strong>(2) Classifier interventions about 85% fewer than Fable 5&apos;s (not zero)</strong></p><p>Because of its high cybersecurity capability, Fable 5 runs strong safety classifiers at all times, and there were complaints that this obstructed even legitimate security work.</p><p>For Opus 5, Anthropic says it deliberately capped raw exploit capability below Mythos 5 and reduced classifier intervention frequency to &quot;about 85% less than Fable 5.&quot;</p><p>Put the other way around: model-classifier interventions that never happened on 4.8 will happen at some frequency on Opus 5.</p><p>The line is drawn so that vulnerability discovery against source code is allowed, while vulnerability scanning against binaries and exploit generation are blocked.</p><p>For Project Glasswing &#x2014; the special defensive-security framework under which Mythos 5 is offered &#x2014; see our <a href="https://journal.qualiteg.com/anthropic-glasswing-and-the-defender-paradigm-shift/" rel="noreferrer">Glasswing explainer</a>.</p><p>Companies and researchers already in the Cyber Verification Program (CVP) get immediate access to Opus 5 with relaxed restrictions.</p><p><strong>(3) Automatic fallback on flags (API side)</strong></p><p>When the classifier flags a request, there is now an option to route it automatically to another model instead of ending in an error.</p><p><code>fallbacks</code> parameter&apos;s new <code>&quot;default&quot;</code> mode (<code>fallbacks: &quot;default&quot;</code>) automatically selects the Anthropic-recommended fallback model per refusal category. Opus 5&apos;s cyber refusals, for example, flow to Opus 4.8.</p><p>The existing explicit model-list form remains available, and the <code>&quot;default&quot;</code> mode requires the <code>server-side-fallback-2026-07-01</code> beta header.</p><p><strong>(4) Data retention differences (confirmed in official documentation)</strong></p><p>Anthropic&apos;s official &quot;API and data retention&quot; documentation names Fable 5 and Mythos 5 as &quot;Covered Models&quot; subject to mandatory 30-day data retention; those two cannot be used under ZDR (zero data retention). They do not appear in Claude Code&apos;s model picker in ZDR environments either.</p><p>Opus 5 is not among the Covered Models, and the launch announcement imposes no model-specific data-retention requirement on generally accessible Opus 5.</p><p>Organizations with ZDR agreements on the Claude API can therefore use Opus 5 within the scope of ZDR-eligible features.</p><p>Note that ZDR is an organization-level agreement; consumer plans like Pro/Max are not themselves covered. Features such as the Batch API and code execution sit outside ZDR, so check your contract terms and per-feature ZDR eligibility for actual coverage.</p><p>In sum, this is a change whose assessment depends on where you stand.</p><p>Seen from 4.8, adding the classifiers is purely an added constraint. Workloads touching security or biology may see processing that passed on 4.8 get stopped (staying on 4.8 is an option; <a href="#ch16" rel="noreferrer">Chapter 16</a>).</p><p>Seen from Fable 5, though, interventions are about 85% fewer, there is no model-specific 30-day retention requirement, and cyber refusals get automatic fallback &#x2014; clearly easier to live with.</p><p>Caveats remain: the automatic fallback is opt-in on the API, and Opus 5&apos;s biology category has no fallback destination (<a href="#ch14" rel="noreferrer">Chapter 14</a>). Nor does any of this guarantee against future regulatory action.</p>
<!--kg-card-begin: html-->
<div id="ch8"></div>
<!--kg-card-end: html-->
<h3 id="8-choosing-effort-levels">8. Choosing effort levels</h3><p>Since Opus 4.7, effort has remained the single most important lever for getting the most out of Opus.</p><p>With Opus 5, the wording of the official guide&apos;s recommendation changed.</p><p>To clear up a common misreading first: the API default has stayed <code>high</code> ever since 4.7. What changed is the description of the recommended starting point.</p><p>The 4.7/4.8 official guides said plainly: &quot;Start with <code>xhigh</code> for coding and agentic use cases.&quot;</p><p>The Opus 5 guide instead reads: &quot;Start with <code>high</code>, the default, and adjust based on evals; step up to <code>xhigh</code> for demanding coding and agentic work.&quot;</p><p>In table form.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr><th>Level</th><th>Recommendation on Opus 4.7/4.8</th><th>Recommendation on Opus 5</th></tr>
</thead>
<tbody>
<tr><td><code>max</code></td><td>Only truly frontier problems. Watch for overthinking</td><td><strong>Worth trying</strong> when capability outweighs token spend (still watch diminishing returns and overthinking)</td></tr>
<tr><td><code>xhigh</code></td><td><strong>Recommended starting point for coding and agentic work</strong></td><td><strong>The step-up destination</strong> for demanding coding and agentic work</td></tr>
<tr><td><code>high</code></td><td>Floor for intelligence-sensitive uses</td><td><strong>Recommended starting point (API default)</strong></td></tr>
<tr><td><code>medium</code></td><td>Cost-driven compromise</td><td><strong>The workhorse cost control &#x2014; use it wherever quality holds</strong></td></tr>
<tr><td><code>low</code></td><td>Short, tightly scoped tasks and subagents</td><td>Same, but <strong>quality has improved substantially</strong>, widening its range</td></tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>The background to the change is the improved efficiency of Opus 5&apos;s lower effort levels.</p><p>The official guide says &quot;<code>low</code> and <code>medium</code> deliver strong quality at a small fraction of the tokens and latency of the upper settings,&quot; and goes as far as &quot;use <code>low</code>/<code>medium</code> liberally as the primary control over cost and response time.&quot;</p><p>Carry the 4.8-era habit of &quot;default to <code>xhigh</code>&quot; over unconditionally, and you can end up doubling tokens for a barely measurable quality gain.</p><p>The official recommendation is unambiguous: do not carry effort settings over from the old model; re-run sweeps on your own evals.</p><p>At the top end, meanwhile, <code>max</code> is more worth trying than in the 4.8 era, because Opus 5 converts additional effort into results (test-time compute scaling) better than any previous Opus.</p><p>The CursorBench run that came within 0.5 points of Fable 5&apos;s peak was also at <code>max</code> effort.</p><p><code>xhigh</code>/<code>max</code> runs need headroom for thinking and tool calls, so start <code>max_tokens</code> at 64k or higher and tune from there.</p><p>Two effort-specific cautions.</p><p><strong>effort does not control visible response length</strong></p><p>Lowering effort on Opus 5 reduces thinking, but does not reliably shorten user-facing responses. If you want shorter responses, say so in the prompt (<a href="#ch10" rel="noreferrer">Chapter 10</a>).</p><p><strong>do not change effort mid-conversation</strong></p><p>effort affects the rendered prompt, so changing the value between requests invalidates the prompt cache for the preceding prefix. In long cache-dependent sessions, fix the value you chose at the start.</p><p>Also, the restriction that <code>thinking: {type: &quot;disabled&quot;}</code> can only be combined with <code>high</code> or below (<a href="#ch4" rel="noreferrer">Chapter 4</a>) affects effort selection too.</p><p>The configuration &quot;thinking off but effort up&quot; simply cannot be built on Opus 5.</p>
<!--kg-card-begin: html-->
<div id="ch9"></div>
<!--kg-card-end: html-->
<h3 id="9-task-budgets-beta-giving-agents-a-sense-of-budget">9. Task budgets (beta): giving agents a sense of budget</h3><p>Among the beta features usable with Opus 5, the most interesting one for agent-infrastructure developers is Task budgets.</p><p>The beta header is <code>task-budgets-2026-03-13</code>. Supported on Opus 5 / Fable 5 / Mythos 5 / Opus 4.8 / 4.7; Sonnet 5 is not supported. It is not an Opus 5-exclusive new feature but an existing beta gaining Opus 5 support.</p><p><code>output_config.task_budget</code> given a <code>{type: &quot;tokens&quot;, total: N}</code> conveys to the model a token budget for the entire agentic loop &#x2014; thinking, tool calls, tool results, and output included.</p><p>Watching a server-injected countdown, the model prioritizes work against the remaining budget and lands gracefully before it runs out &#x2014; summarizing findings, reporting progress, and so on.</p><pre><code class="language-python">with client.beta.messages.stream(
    model=&quot;claude-opus-5&quot;,
    max_tokens=128000,
    output_config={
        &quot;effort&quot;: &quot;high&quot;,
        &quot;task_budget&quot;: {&quot;type&quot;: &quot;tokens&quot;, &quot;total&quot;: 64000},
    },
    messages=[{&quot;role&quot;: &quot;user&quot;, &quot;content&quot;: &quot;Review the codebase and propose a refactor plan.&quot;}],
    betas=[&quot;task-budgets-2026-03-13&quot;],
) as stream:
    response = stream.get_final_message()
</code></pre><p>Let&apos;s keep the concepts straight.</p><p>Where effort controls the depth of reasoning at each step, task_budget controls the amount of work across the whole loop.</p><p>Effort for depth, task budget for volume, and the per-request hard cap of <code>max_tokens</code> &#x2014; a three-layer structure.</p><p>Four operational cautions.</p><p><strong>The budget is advisory, not enforced</strong></p><p>In the middle of work where interruption would be more destructive, it can overrun. Hard caps still go through <code>max_tokens</code>.</p><p><strong>The minimum is 20,000 tokens</strong></p><p>Anything below returns a 400 error.</p><p><strong>Budgets that are too small trigger refusal-like behavior</strong></p><p>Hand a 20k-token budget to an hours-scale task and the model may decline the task outright, over-trim scope, or wrap up early.</p><p>If you see mysterious refusals or early exits after setting a budget, raise the budget before suspecting any other parameter.</p><p><strong>Only the model sees the countdown</strong></p><p>There is no remaining-budget field in API responses.</p><p>Decrementing <code>remaining</code> client-side every turn breaks the cache, and the double counting makes the budget appear to shrink faster than reality &#x2014; a cause of premature wrap-ups.</p><p>The basic pattern: set <code>total</code> once on the first request and leave the rest to the server.<code>remaining</code> is used only when compaction (context compression) rewrites the history and you need to carry over the tokens already consumed.</p><p>The official recommendation on setting budgets: do not guess.</p><p>First run representative tasks without task_budget, measure the distribution of loop-wide <code>usage.output_tokens</code> and tool-result tokens, then start around p99 and tune.</p><p>Note that Task budgets are not available in Claude Code / Cowork. This is a feature for agent platforms calling the Messages API directly (Claude Code&apos;s workflow feature has its own similar budget mechanism).</p>
<!--kg-card-begin: html-->
<div id="ch10"></div>
<!--kg-card-end: html-->
<h3 id="10-prompting-to-get-the-most-out-of-opus-5">10. Prompting to get the most out of Opus 5</h3><p>Opus 5 runs well as-is even on prompts written for 4.8.</p><p>But the official prompting guide names five behaviors that &quot;tend to need adjustment.&quot; All are cases where the model now does things on its own, making legacy instructions excessive.</p><p><strong>(1) Responses and deliverables got longer</strong></p><p>Both conversational responses and reports or Markdown documents written to disk tend to run longer than 4.8&apos;s.</p><p>As noted, lowering effort does not shorten them; state it in the prompt.</p><pre><code class="language-text">Keep responses focused, brief, and concise. Keep disclaimers and caveats short, and spend most of the response on the main answer. When asked to explain something, give a high-level summary unless an in-depth explanation is specifically requested.
</code></pre><p>In long system prompts, layering a short reminder near the end (something like <code>&lt;tone_preference&gt;Keep outputs reasonably concise.&lt;/tone_preference&gt;</code>) is said to work.</p><p>For document length, add a calibration instruction: cover the substance, and do not pad with filler sections, redundant summaries, or boilerplate.</p><p><strong>(2) More progress narration</strong></p><p>During agentic work it actively announces what it is about to do, and output per message runs longer.</p><p>Specifying frequency and format explicitly works well; the official example is this.</p><pre><code class="language-text">Before your first tool call, say in one sentence what you&apos;re about to do. While working, give a brief update only when you find something important or change direction. When you finish, lead with the outcome: your first sentence should answer &quot;what happened&quot; or &quot;what did you find,&quot; with supporting detail after it for readers who want it.
</code></pre><p>Conversely, if you want more narration or a different style, showing positive examples of the desired form beats prohibitions.</p><p><strong>(3) It self-verifies and self-corrects on its own</strong></p><p>This is Opus 5&apos;s biggest character change.</p><p>The official recommendation is to delete re-verification instructions that duplicate the model&apos;s self-verification &#x2014; &quot;add a final verification step,&quot; &quot;double-check,&quot; &quot;verify with a subagent,&quot; and the like.</p><p>They overlap with the model&apos;s own verification behavior, producing over-verification: added cost with no quality gain.</p><p>But the only safe deletions are these duplicated instructions.</p><p>Project-specific acceptance criteria &#x2014; &quot;run the designated test suite after changes,&quot; &quot;pass lint and type checks&quot; &#x2014; are completion conditions, not duplicated self-checks. Keep them.</p><p>It has also become more willing to voice corrections to its own earlier statements. For user-facing products, the guide shows a narrowing instruction: correct only errors that change the user&apos;s code, conclusions, or decisions concisely, and fix inconsequential misstatements silently.</p><p><strong>(4) It tends to widen task scope</strong></p><p>It may add steps you did not ask for, or reshape the task based on its own judgment of how things &quot;really ought to be.&quot;</p><p>For narrow tasks, bound the scope explicitly.</p><pre><code class="language-text">Deliver what was asked, at the scope intended. Make routine judgment calls yourself, and check in only when different readings of the request would lead to materially different work. If the request seems mistaken or a better approach exists, say so in a sentence and continue with the task as asked rather than quietly narrowing, widening, or transforming it.
</code></pre><p><strong>(5) More delegation to subagents</strong></p><p>On multi-agent platforms, it spawns subagents more aggressively than 4.8.</p><p>A strength for genuinely independent, large work; for small tasks it multiplies cost and time. Recommended: explicit delegation criteria, or a deterministic cap on spawn count.</p><p>The official guide includes example lines like &quot;do not delegate work that finishes in a few tool calls&quot; and &quot;do not use subagents to verify your own work.&quot;</p><p>Amusingly, the 4.8 prompting guide said the exact opposite, with examples nudging toward more subagents.</p><p>Default behavior swings like a pendulum between generations, so harness-side steering prompts need review every generation.</p><p>Two more strengths deserve mention.</p><p><strong>Code review</strong></p><p>Opus 5 is described as &quot;finding real bugs at a high rate per pass, with the additional findings mostly non-spurious.&quot;</p><p>And accuracy holds even at low effort, enabling a two-stage setup: a fast pass at review time, a more thorough pass later.</p><p>As in the 4.8 era, an instruction like &quot;report high-severity only&quot; is obeyed literally and reduces reporting &#x2014; so the standard practice remains: have it report everything at the discovery stage, and filter in a separate pass.</p><p><strong>Vision (image understanding)</strong></p><p>Understanding of charts, documents, and figures &#x2014; and visual reproduction of UI and front-end work &#x2014; has improved.</p><p>We recommend re-validating image workarounds added for older models.</p><p>Giving it tools to iteratively analyze, crop, and inspect images is said to be more cost-effective than piling on thinking.</p><hr>
<!--kg-card-begin: html-->
<div id="part3"></div>
<!--kg-card-end: html-->
<h2 id="part-3-opus-5-in-claude-code">Part 3: Opus 5 in Claude Code</h2>
<!--kg-card-begin: html-->
<div id="ch11"></div>
<!--kg-card-end: html-->
<h3 id="11-prerequisites-for-using-opus-5-in-claude-code">11. Prerequisites for using Opus 5 in Claude Code</h3><p>If you have never used Claude Code, start with our <a href="https://journal.qualiteg.com/getting-started-claude-code-cli-and-web/" rel="noreferrer">Claude Code primer (CLI and web)</a>.</p><p>Here we cover the operational prerequisites.</p><p><strong>Version</strong></p><p>Opus 5 requires Claude Code v2.1.219 or later (Sonnet 5: v2.1.197+; Opus 4.8: v2.1.154+).<code>claude update</code> to update.</p><p><strong>Alias resolution</strong></p><p><code>opus</code>Alias resolution has advanced considerably since the 4.8 era.</p><p>Not only on the Anthropic API but also on Claude Platform on AWS, Amazon Bedrock, and Google Cloud&apos;s Agent Platform, <code>opus</code> resolves to Opus 5 (in the 4.8 era this varied by provider).</p><p>The exception is Microsoft Foundry, where <code>opus</code> remains Opus 4.6. On Foundry, use the full model name or <code>ANTHROPIC_DEFAULT_OPUS_MODEL</code>.</p><p><strong>The `best` alias</strong></p><p>An alias that resolves to Fable 5 if your organization has access, and otherwise to the latest Opus: <code>best</code> is available.<code>fable</code>Direct alias specification also works.</p><p><code>default</code> (when no model is specified) resolves as follows.</p><p>Note that the Pro plan&apos;s default is now Sonnet 5.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr><th>Account type</th><th><code>default</code> resolves to</th></tr>
</thead>
<tbody>
<tr><td>Max / Team Premium / Enterprise (pay-as-you-go) / Anthropic API</td><td><strong>Opus 5</strong></td></tr>
<tr><td>Claude Platform on AWS / Amazon Bedrock / Google Cloud Agent Platform</td><td><strong>Opus 5</strong></td></tr>
<tr><td>Pro / Team Standard / Enterprise (subscription seats)</td><td>Sonnet 5</td></tr>
<tr><td>Microsoft Foundry</td><td>Sonnet 4.5</td></tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>Fable 5 is never the default for any account type (<code>/model fable</code> or similar explicit selection is required).</p><p>To pin a version, the standard practice is unchanged: use the full model name (<code>claude-opus-5</code>) or the environment variable (<code>ANTHROPIC_DEFAULT_OPUS_MODEL</code>) instead of an alias.</p>
<!--kg-card-begin: html-->
<div id="ch12"></div>
<!--kg-card-end: html-->
<h3 id="12-watch-the-carry-over-behavior-of-claude-codes-effort-setting">12. Watch the carry-over behavior of Claude Code&apos;s effort setting</h3><p>The ways to control effort in Claude Code (<code>/effort</code>, <code>--effort</code>, <code>CLAUDE_CODE_EFFORT_LEVEL</code>, the settings-file <code>effortLevel</code>, and skill/subagent frontmatter) are the same as in the 4.8 era.</p><p>The thing to watch on Opus 5 is the carry-over behavior of the effort setting.</p><p>On Fable 5, Opus 4.8, and 4.7, the first use of a model force-applied the model default even if you had set a level on another model earlier (behavior we flagged in the 4.8 guide).</p><p>Opus 5 has no such hold: a previously set level carries over as-is.</p><p>So someone who lived at <code>xhigh</code> on 4.8 will, after switching to Opus 5, keep running at <code>xhigh</code> without noticing.</p><p><a href="#ch8" rel="noreferrer">Chapter 8</a> explains that the official recommendation on Opus 5 is to start at <code>high</code> and adjust as needed &#x2014; so right after switching, check the current value with <code>/effort</code> and re-choose deliberately.</p><p>You can also see the current effort in the session header&apos;s &quot;with xxx effort&quot; display.</p><p>Everything else is as before.</p><p><code>max</code> is session-only (cannot be saved to settings files); <code>ultracode</code> is a Claude Code-side setting meaning &quot;<code>xhigh</code> plus dynamic-workflow orchestration,&quot; not a model effort level; and for a one-off deep think you write <code>ultrathink</code> in the prompt &#x2014; for these, see the <a href="https://journal.qualiteg.com/claude-opus-4-8-claude-code-guide/" rel="noreferrer">4.8 guide</a>&apos;s <a href="#ch9" rel="noreferrer">Chapter 9</a> and <a href="#ch11" rel="noreferrer">Chapter 11</a>.</p><p>Dynamic Workflows themselves work as detailed in the 4.8 guide; no mechanism changes in Opus 5.</p>
<!--kg-card-begin: html-->
<div id="ch13"></div>
<!--kg-card-end: html-->
<h3 id="13-what-changed-in-fast-mode">13. What changed in Fast mode</h3><p><code>/fast</code>-toggled Fast mode (same model, same quality, up to 2.5&#xD7; faster) covers Opus 5 by default from v2.1.219.</p><p>Pricing is $10 input / $50 output for both Opus 5 and Opus 4.8, keeping the level set by the 4.8-era price cut (flat across the whole 1M window).</p><p>The cautions carry over from the 4.8 era, with one new development.</p><ul><li><strong>Opus 4.7&apos;s Fast mode was removed on July 24, 2026 (Opus 5 launch day)</strong>. Moreover, Claude Code still treats 4.7 as Fast mode-eligible, so a 4.7 session with Fast mode left ON gets its requests rejected by the API (an error, not a fallback to standard speed). If you used Fast mode on 4.7, switch to Opus 5 or 4.8</li><li>On subscription plans (Pro/Max/Team/Enterprise), it is <strong>usage-credits only</strong>. It is not part of the plan&apos;s normal allowance; Fast mode rates apply from the first token</li><li><strong>Turning it ON mid-conversation charges the uncached input rate once for the entire conversation context at that point</strong>, so if you use it, use it from session start</li><li>Unavailable on Bedrock / Google Cloud / Foundry / Claude Platform on AWS. The VS Code extension does not support it (CLI only)</li></ul>
<!--kg-card-begin: html-->
<div id="ch14"></div>
<!--kg-card-end: html-->
<h3 id="14-what-happens-when-you-get-flagged-the-automatic-model-fallback">14. What happens when you get flagged: the automatic model fallback</h3><p><a href="#ch7" rel="noreferrer">Chapter 7</a> described the API-side <code>fallbacks</code>; separately from that, Claude Code has gained its own category-based automatic fallback (v2.1.219+).</p><p>Fable 5 and Opus 5 run with cybersecurity/biology safety classifiers, and when a request is flagged, the behavior is as follows.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr><th>Flagged on</th><th>Category</th><th>Behavior</th></tr>
</thead>
<tbody>
<tr><td>Fable 5</td><td>Biology</td><td><strong>Automatically re-run on Opus 5</strong></td></tr>
<tr><td>Fable 5</td><td>Cyber</td><td><strong>Automatically re-run on Opus 4.8</strong></td></tr>
<tr><td>Opus 5</td><td>Cyber</td><td><strong>Automatically re-run on Opus 4.8</strong></td></tr>
<tr><td>Opus 5</td><td>Biology</td><td><strong>Ends in refusal</strong> (no fallback destination)</td></tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>As the table shows, Opus 4.8 serves as the fallback precisely because it lacks the classifiers.</p><p>After a fallback the session continues on that model, so to go back, use <code>/model</code>.</p><p>Three behaviors worth knowing operationally.</p><p><strong>It can fire on the very first request of a session</strong></p><p>The first request carries workspace context such as CLAUDE.md and git status.</p><p>In repositories with security or biology content, the classifier can react even when you asked for nothing unusual.</p><p>For isolation, <code>claude --safe-mode</code> (start with CLAUDE.md, skills, MCP, and hooks disabled) is useful.</p><p><strong>If you don&apos;t want automatic switching, it is configurable</strong></p><p><code>/config</code> lets you turn off &quot;switch models when a message is flagged.&quot;</p><p>When flagged, the session pauses and offers a choice: switch to the fallback model, or edit the prompt and retry on the current model.</p><p><strong>In penetration testing, CTFs, and biology-adjacent codebases, frequent firing is &quot;working as intended&quot;</strong></p><p>It does not mean your account has been flagged.</p><p>For organizations that need Fable-class capability in these domains, Anthropic&apos;s trusted access programs (CVP and others) are the indicated route.</p><p>Claude Code has also had confusing bugs around refusals in the past. Our guide to the &quot;usage policy violation&quot; message is collected in <a href="https://journal.qualiteg.com/claude-code-usage-policy-violation-fix/" rel="noreferrer">this article</a>.</p>
<!--kg-card-begin: html-->
<div id="ch15"></div>
<!--kg-card-end: html-->
<h3 id="15-the-1m-context-and-opusplan">15. The 1M context and opusplan</h3><p>Handling of the 1M context carries over the 4.8-era framework, and with &quot;1M as default and maximum&quot; on Opus 5 it got even simpler.</p><ul><li><strong>On the Anthropic API, Opus 5 (and Opus 4.7+, Sonnet 5, Fable 5) always runs with the 1M window</strong></li><li>On Max / Team / Enterprise plans, Opus upgrades to 1M automatically with no extra configuration (included in the subscription; no premium billing beyond 200k)</li><li>To disable it entirely, use <code>CLAUDE_CODE_DISABLE_1M_CONTEXT=1</code></li></ul><p><code>opusplan</code> (an alias that switches automatically: plan mode on <code>opus</code>, execution on the <code>sonnet</code> alias) now means, on the Anthropic API, that Opus 5 plans and Sonnet 5 executes.</p><p>The actual combination follows the per-provider alias resolution explained in <a href="#ch11" rel="noreferrer">Chapter 11</a>. Note that it becomes Opus 5 + Sonnet 4.6 on Claude Platform on AWS, Opus 5 + Sonnet 4.5 on Bedrock and Google Cloud Agent Platform, and Opus 4.6 + Sonnet 4.5 on Foundry.</p><p>Sonnet 5 bills itself as &quot;the most agentic Sonnet,&quot; with execution capability approaching Opus class &#x2014; and it is at introductory pricing of $2/$10 through August 31.</p><p>&quot;Let Opus 5 think the design through, stream code generation to Sonnet 5&quot; is an attractive setup cost-wise.</p><p>When the execution side is Sonnet 5 on the Anthropic API, Sonnet 5 always runs the 1M window, and auto-compaction kicks in around 967k tokens by default (per the Claude Code model-config docs; <code>CLAUDE_CODE_AUTO_COMPACT_WINDOW</code> changes the threshold).</p>
<!--kg-card-begin: html-->
<div id="ch16"></div>
<!--kg-card-end: html-->
<h3 id="16-a-rhythm-for-day-to-day-operation">16. A rhythm for day-to-day operation</h3><p><a href="#ch10" rel="noreferrer">Chapter 10</a>&apos;s prompting changes apply directly to daily Claude Code operation.</p><p>Three operational patterns.</p><p><strong>(1) Sort the verification instructions in CLAUDE.md</strong></p><p>Split the verification-related instructions in your project&apos;s CLAUDE.md and skills into two kinds.</p><p>One: mandatory acceptance criteria (running the designated test suite, lint, type checks, the Definition of Done). Two: instructions that merely duplicate the model&apos;s self-checking (&quot;double-check before completing,&quot; &quot;verify once more at the end&quot;).</p><p>On Opus 5, only the latter should be deleted. The former are the project&apos;s completion conditions; keep them.</p><p>Opus 5 checks its own changes unprompted, so keeping the latter wastes tokens on over-verification.</p><p>The inversion also happens: it is precisely the situations where you don&apos;t want verification (fast draft-stage iteration, for example) that now require explicit instruction.</p><p><strong>(2) Front-loading information into the first prompt is still paramount</strong></p><p>The trait &quot;hand over the complete task spec up front, then let it run&quot; has strengthened further since 4.8.</p><p>Writing out intent, completion criteria, allowed scope, and constraints at the start remains as effective as ever.</p><p>Interim progress reporting, meanwhile, moved in the direction of more &#x2014; so if you want a quiet run, put <a href="#ch10" rel="noreferrer">Chapter 10</a>&apos;s narration-suppression prompt into CLAUDE.md.</p><p><strong>(3) Redesign your model assignments</strong></p><p>With Opus 5&apos;s arrival, the realistic division of labor inside Claude Code looks like this.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr><th>Use case</th><th>Recommended model</th><th>Why</th></tr>
</thead>
<tbody>
<tr><td>Everyday coding, smaller fixes</td><td>Sonnet 5</td><td>Fast and inexpensive. Introductory pricing through end of August. Pro plan default</td></tr>
<tr><td>Complex implementations, larger refactors, code review</td><td><strong>Opus 5 (<code>high</code> to <code>xhigh</code>)</strong></td><td>The mainstay with the best quality-cost balance. Newest cutoff, too</td></tr>
<tr><td>Hours-to-overnight autonomous runs, the hardest design work</td><td>Fable 5</td><td>Still unmatched stamina for long-horizon autonomous tasks</td></tr>
<tr><td>Repositories touching security or biology</td><td>Consider staying on Opus 4.8</td><td>4.8 has no model-specific classifiers; on Opus 5 they can fire (<a href="#ch14">Chapter 14</a>)</td></tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>&quot;Just use Fable 5 for everything&quot; now pays off less often, both on cost (<a href="https://journal.qualiteg.com/claude-fable5-cost-and-outlook/" rel="noreferrer">Fable 5: Costs and Outlook</a>) and on classifier intervention frequency.</p><p>Reserving Fable 5 for the hardest problems and making Opus 5 the everyday ceiling is, we think, the right balance for now.</p><hr><h2 id="what-we-dont-know-yet-unconfirmed-items">What we don&apos;t know yet / unconfirmed items</h2><p>In the interest of honesty, here is what we have not been able to confirm at this point.</p><ul><li><strong>The individual points in Frontier-Bench&apos;s by-effort chart</strong> (press readings put xhigh at about 44%) are shown only as an image; we could not confirm them in text form. The 43.3% in this article is the value listed in the System Card&apos;s evaluation summary table</li><li><strong>Independent evaluations are not yet in</strong>. We could not confirm Opus 5&apos;s position in Arena-style blind voting or on Artificial Analysis and the like as of writing (three days after release). We plan to check the answers in our August <a href="https://journal.qualiteg.com/llm-ranking-2026-03/" rel="noreferrer">LLM rankings</a> series</li><li><strong>Timelines for Opus 5 support in Priority Tier and Web Fetch</strong> have not been announced</li><li>Fast mode, Task budgets, mid-conversation tool changes, and <code>fallbacks</code> are all <strong>beta / research preview</strong>, and specs and pricing may change</li></ul><hr><h2 id="summary">Summary</h2><p>In one sentence: &quot;Opus 5 is not the top model, yet it has become the practical workhorse.&quot; That is the essence of this release.</p><p>The practical takeaways condense to these five.</p><p><strong>1. Migration is not &quot;just swap the ID&quot;</strong></p><p>thinking is now ON by default, and disabling thinking is limited to effort <code>high</code> or below (a 400 error otherwise). Counting the Web Fetch and Priority Tier gaps as well, you need to revisit <code>max_tokens</code> and audit the affected requests.</p><p><strong>2. Do not carry effort over &#x2014; re-measure</strong></p><p>The default is still <code>high</code>. The official starting point moved from &quot;coding at <code>xhigh</code>&quot; to &quot;start at <code>high</code>, step up to <code>xhigh</code> only for demanding work,&quot; while the practical range of <code>low</code>/<code>medium</code> has widened. In Claude Code, note also that Opus 5 alone inherits your previous effort setting.</p><p><strong>3. Delete duplicated re-verification instructions</strong></p><p>Opus 5 self-verifies on its own. &quot;Double-check&quot; style instructions become a source of token waste through over-verification. Keep required tests, lint, and other acceptance criteria.</p><p><strong>4. Understand the safety classifiers, then choose</strong></p><p>Opus 5 carries model-specific classifiers (cyber, biology) that 4.8 lacks. For 4.8 migrants this is an added constraint, and staying on 4.8 remains an option for security workloads. Compared with Fable 5, interventions are 85% fewer, there is no 30-day retention requirement, and fallback exists &#x2014; an easier landing spot for those moving off Fable 5.</p><p><strong>5. Redesign the division of labor</strong></p><p>Sonnet 5 for the everyday, Opus 5 as the mainstay (Max&apos;s default), Fable 5 for the hardest problems. The newest knowledge cutoff (May 2026) is Opus 5&apos;s quiet, exclusive advantage.</p><p>That Anthropic assembled this lineup just six weeks after the Fable 5 suspension is startling speed.</p><p>Once independent evaluations are in, we will revisit them in our regular rankings article.</p><p>See you next time!</p><hr><h2 id="sources">Sources</h2>
<!--kg-card-begin: html-->
<table>
<thead>
<tr><th>Topic</th><th>Source</th></tr>
</thead>
<tbody>
<tr><td>Release announcement, benchmarks, safety</td><td><a href="https://www.anthropic.com/news/claude-opus-5?ref=journal.qualiteg.com">Introducing Claude Opus 5 (Anthropic)</a></td></tr>
<tr><td>New features, behavior changes, migration</td><td><a href="https://platform.claude.com/docs/en/about-claude/models/whats-new-opus-5?ref=journal.qualiteg.com">What&apos;s new in Claude Opus 5 (official docs)</a></td></tr>
<tr><td>Migration steps, breaking changes</td><td><a href="https://platform.claude.com/docs/en/about-claude/models/migration-guide?ref=journal.qualiteg.com">Migration guide (official docs)</a></td></tr>
<tr><td>Model specs, pricing, cutoffs</td><td><a href="https://platform.claude.com/docs/en/about-claude/models/overview?ref=journal.qualiteg.com">Models overview (official docs)</a></td></tr>
<tr><td>Using effort levels</td><td><a href="https://platform.claude.com/docs/en/build-with-claude/effort?ref=journal.qualiteg.com">Effort (official docs)</a></td></tr>
<tr><td>Prompting for Opus 5</td><td><a href="https://platform.claude.com/docs/en/build-with-claude/prompt-engineering/prompting-claude-opus-5?ref=journal.qualiteg.com">Prompting Claude Opus 5 (official docs)</a></td></tr>
<tr><td>Task budgets</td><td><a href="https://platform.claude.com/docs/en/build-with-claude/task-budgets?ref=journal.qualiteg.com">Task budgets (official docs)</a></td></tr>
<tr><td>Data retention, ZDR, Covered Models</td><td><a href="https://platform.claude.com/docs/en/manage-claude/api-and-data-retention?ref=journal.qualiteg.com">API and data retention (official docs)</a></td></tr>
<tr><td>ARC-AGI 3 verified results</td><td><a href="https://arcprize.org/results/anthropic-claude-opus-5?ref=journal.qualiteg.com">ARC Prize official Claude Opus 5 results</a></td></tr>
<tr><td>CursorBench 3.2</td><td><a href="https://cursor.com/cursorbench?ref=journal.qualiteg.com">Cursor official leaderboard</a></td></tr>
<tr><td>OSWorld and safety details</td><td><a href="https://www-cdn.anthropic.com/c5fbac3f0b1280a933ebd26d3cb8bb9f5bdeaf48/Claude%20Opus%205%20System%20Card.pdf?ref=journal.qualiteg.com">Claude Opus 5 System Card (Anthropic, PDF)</a></td></tr>
<tr><td>Claude Code model config and fallback</td><td><a href="https://code.claude.com/docs/en/model-config?ref=journal.qualiteg.com">Model configuration (Claude Code Docs)</a></td></tr>
<tr><td>Fast mode</td><td><a href="https://code.claude.com/docs/en/fast-mode?ref=journal.qualiteg.com">Fast mode (Claude Code Docs)</a></td></tr>
<tr><td>Press (positioning, data retention, competitive context)</td><td><a href="https://techcrunch.com/2026/07/24/anthropic-launches-opus-5/?ref=journal.qualiteg.com">TechCrunch</a> / <a href="https://fortune.com/2026/07/24/anthropic-debuts-claude-opus-5-with-feature-that-lets-users-toggle-between-cost-and-capability/?ref=journal.qualiteg.com">Fortune</a> / <a href="https://www.axios.com/2026/07/24/anthropic-releases-new-model-opus-5?ref=journal.qualiteg.com">Axios</a></td></tr>
<tr><td>Fable 5 suspension and restoration</td><td><a href="https://www.cnbc.com/2026/06/30/anthropic-says-trump-admin-has-lifted-export-controls-on-claude-fable-5-and-mythos-5.html?ref=journal.qualiteg.com">CNBC</a> / <a href="https://www.anthropic.com/news/redeploying-fable-5?ref=journal.qualiteg.com">Redeploying Claude Fable 5 (Anthropic)</a></td></tr>
<tr><td>Sonnet 5 release</td><td><a href="https://www.anthropic.com/news/claude-sonnet-5?ref=journal.qualiteg.com">Introducing Claude Sonnet 5 (Anthropic)</a> / <a href="https://techcrunch.com/2026/06/30/anthropic-launches-claude-sonnet-5-as-a-cheaper-way-to-run-agents/?ref=journal.qualiteg.com">TechCrunch</a></td></tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>The information in this article is based on official documentation, official announcements, and press coverage as of July 27, 2026.</p><p>Beta features and research previews may change; check each source for the latest.</p>]]></content:encoded></item><item><title><![CDATA[TensorRT 10 × Blackwell Migration Guide (Part 1): Inference Assets Won't Run on RTX 50 — The Basics and the First Walls]]></title><description><![CDATA[<p>Hello!</p><p>You get a new GPU, excitedly move your existing inference stack over, and <br><br><strong>everything that ran fine yesterday now stops with errors across the board</strong> <br><br> &#x2014; sound familiar? In migrations to the NVIDIA RTX 50 series and NVIDIA RTX PRO series (the Blackwell generation), this happens with rather high</p>]]></description><link>https://journal.qualiteg.com/tensorrt10-blackwell-rtx50-migration-guide-part1/</link><guid isPermaLink="false">6a60f676edf69a17d422a9ea</guid><category><![CDATA[GPU]]></category><category><![CDATA[PyTorch]]></category><category><![CDATA[Python]]></category><category><![CDATA[IT & AI Technology]]></category><dc:creator><![CDATA[Qualiteg Product Development Team]]></dc:creator><pubDate>Thu, 23 Jul 2026 20:16:40 GMT</pubDate><media:content url="https://journal.qualiteg.com/content/images/2026/07/tensorrt10-blackwell-rtx50-migration-guide--1-.png" medium="image"/><content:encoded><![CDATA[<img src="https://journal.qualiteg.com/content/images/2026/07/tensorrt10-blackwell-rtx50-migration-guide--1-.png" alt="TensorRT 10 &#xD7; Blackwell Migration Guide (Part 1): Inference Assets Won&apos;t Run on RTX 50 &#x2014; The Basics and the First Walls"><p>Hello!</p><p>You get a new GPU, excitedly move your existing inference stack over, and <br><br><strong>everything that ran fine yesterday now stops with errors across the board</strong> <br><br> &#x2014; sound familiar? In migrations to the NVIDIA RTX 50 series and NVIDIA RTX PRO series (the Blackwell generation), this happens with rather high probability.</p><p>And here is the troublesome part: <strong>stopping with an error is actually the kind case. TensorRT</strong>&apos;s world also contains <br><br>&quot;the build passes, execution passes, the speed is there &#x2014; but the output alone is quietly broken&quot;<br><br> &#x2014; the hardest kind of failure to find.</p><p>This article is Part 1 of a series covering the whole picture.</p><p><strong>Target environment</strong> <br><strong>OS:</strong> Ubuntu 24.04 (WLS)<br><strong>GPU:</strong> NVIDIA RTX PRO 4000 Blackwell / GeForce RTX 5060 Ti<br> (both Compute Capability 12.0 = sm_120)<br><strong>Stack:</strong> PyTorch 2.11.0 + cu128 / <strong>TensorRT 10.16.1.11</strong>.</p><p>Part 1 delivers the following three things.</p><ol><li><strong>What TensorRT conversion actually is</strong> <br>Why it is faster than running plain PyTorch &#x2014; and what you pay in exchange<br></li><li><strong>Why existing assets stop working on Blackwell (RTX 50 series, RTX PRO series)</strong><br>There is not one area to check but, broadly, three<br></li><li><strong>Steps to get a minimal TensorRT 10 conversion through</strong> <br>From environment setup to engine build, numerical comparison, and speed measurement, <strong>in a form you can reproduce by running the code in this article in order</strong>.</li></ol><p>As the subject &#x2014; so the same verification steps can be followed without depending on any particular product &#x2014; we use <strong>a small dummy model whose full code is included in this article</strong>.</p><p>This is not about any specific product or model; read it as a story about TensorRT conversion itself.</p><blockquote>The numbers, error logs, and behaviors shown in this article are actual results from real runs. The code targets the TensorRT 10.x API.<br><strong>TensorRT 11 has changed or removed some APIs, including the precision flags (`BuilderFlag.FP16`, etc.), so the code does not run there as-is</strong>.<br>We deliberately use 10.16 to reproduce the migration path of existing assets.</blockquote><p>To find out which generation (which SM) your GPU belongs to, you can use our &quot;<a href="https://journal.qualiteg.com/2026-nvidia-gpu-list-filtering-app/" rel="noreferrer">2026 NVIDIA GPU quick-lookup tool</a>.&quot; Start there to check whether this article applies to your environment.</p><h2 id="part-1-what-tensorrt-conversion-is-%E2%80%94-and-why-it-beats-pytorch">Part 1: What TensorRT conversion is &#x2014; and why it beats PyTorch</h2><h3 id="in-one-phrase-ahead-of-time-compilation">In one phrase: ahead-of-time compilation</h3><p>When you run PyTorch inference plainly &#x2014; <code>torch.compile</code> and CUDA Graphs not in use, i.e. <strong>eager execution</strong> &#x2014; think about what is happening inside the GPU.</p><p>Every operator call goes through dispatch, and <strong>a GPU kernel is launched per operation</strong>. Between unfused operations, intermediate results are written out to GPU memory (VRAM) and read back by the next operation.</p><p>TensorRT conversion changes this mode of execution at the root.</p><p><strong>The model&apos;s entire computation graph is compiled ahead of time into an execution plan specific to that GPU, and at inference time the host merely submits that plan in a single call</strong>.</p><p>TensorRT calls this precompiled artifact an <strong>engine</strong> (engine / plan).</p><p>Note that the comparison target throughout this article is <strong>PyTorch eager execution</strong>. PyTorch itself has acceleration paths such as <code>torch.compile</code> and CUDA Graphs, and comparisons against those are a separate story.</p><p>The mental image is close to the difference between interpreting source code line by line and compiling it ahead of time into a native binary.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://journal.qualiteg.com/content/images/2026/07/fig2_why_fast.png" class="kg-image" alt="TensorRT 10 &#xD7; Blackwell Migration Guide (Part 1): Inference Assets Won&apos;t Run on RTX 50 &#x2014; The Basics and the First Walls" loading="lazy" width="2000" height="1163" srcset="https://journal.qualiteg.com/content/images/size/w600/2026/07/fig2_why_fast.png 600w, https://journal.qualiteg.com/content/images/size/w1000/2026/07/fig2_why_fast.png 1000w, https://journal.qualiteg.com/content/images/size/w1600/2026/07/fig2_why_fast.png 1600w, https://journal.qualiteg.com/content/images/2026/07/fig2_why_fast.png 2076w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Figure 1: PyTorch&apos;s sequential execution versus TensorRT&apos;s fused engine</span></figcaption></figure><h3 id="five-mechanisms-behind-the-speed">Five mechanisms behind the speed</h3><p>Break down &quot;why is it fast&quot; and you get roughly these five.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr><th>Mechanism</th><th>PyTorch eager (no torch.compile)</th><th>TensorRT engine</th></tr>
</thead>
<tbody>
<tr><td><strong>Layer fusion</strong></td><td>Unfused Conv, BatchNorm, ReLU, etc. run as separate kernels, with intermediate tensors read and written between them</td><td>Fuses multiple layers into a single kernel and keeps intermediate results in the GPU&apos;s fast internal memory. The more memory-bound the model, the more dramatic the effect</td></tr>
<tr><td><strong>Kernel auto-tuning</strong></td><td>cuDNN and friends pick implementations per operation (with benchmark-based selection for input shapes, depending on settings)</td><td><strong>At build time, looks at the whole network, measures multiple implementation candidates on the actual device, and adopts the combination that makes the whole fastest</strong> (this is why builds take time &#x2014; and why engines end up specific to a GPU model)</td></tr>
<tr><td><strong>Low-precision engineering</strong></td><td>Coarse-grained fp16 via autocast</td><td>Controls permitted precision per layer to saturate the Tensor Cores. Enables things like pinning only the risky layers to fp32</td></tr>
<tr><td><strong>Static memory planning</strong></td><td>Creates intermediate tensors per operation and manages memory with a caching allocator (whole-graph lifetime planning has limits)</td><td>With fixed shapes, every tensor&apos;s lifetime is known in advance. Reuses regions to trim VRAM and suppresses the overhead of runtime dynamic allocation</td></tr>
<tr><td><strong>Reduced runtime overhead</strong></td><td>Passes through the Python interpreter and dispatcher for every operation (autograd also stays active unless <code>inference_mode</code> is used)</td><td>A C++ runtime submits the whole graph in a single enqueue. <strong>The more small operations a model has, the wider the gap</strong></td></tr>
</tbody>
</table>
<!--kg-card-end: html-->
<h3 id="the-cost-what-you-give-up-with-tensorrt-conversion">[The cost] What you give up with TensorRT conversion</h3><p>TensorRT articles tend to end with &quot;it got faster!&quot;, but <br>in practice, understanding <strong><u>what you lose</u></strong> matters more.</p><ol><li><strong>Builds take time</strong> &#x2014;<br>Because kernels are measured on the real machine, builds can take minutes to tens of minutes depending on the model<br></li><li><strong>Engines have poor portability</strong> &#x2014;<br>An engine built with default settings depends strongly on the TensorRT version and GPU used to create it; &quot;copy the engine from the dev machine to production&quot; is, as a rule, not possible. Compatibility modes (version compatibility, hardware compatibility) can widen the target range, at the cost of performance and feature constraints<br></li><li><strong>An unsupported operation makes the build fail outright</strong> <br>Part 4 of this article is exactly this<br></li><li><strong>The numbers change &#x2014; sometimes breaking silently</strong> <br>Beyond precision loss, the very meaning of an operation can get swapped (the subject of Part 2 of the series)<br></li><li><strong>Fixed shapes are easiest to handle</strong> &#x2014;<br>Dynamic shapes are officially supported via optimization profiles, but covering too wide a range can make per-shape optimal implementations harder to select and can increase memory<br></li><li><strong>Harder to debug</strong> <br> Unlike PyTorch, you cannot drop a <code>print</code> into the middle of the model to peek inside</li></ol><h3 id="criteria-for-deciding-should-we-tensorrt-this">Criteria for deciding &quot;should we TensorRT this?&quot;</h3><p>Given all that, the decision becomes fairly clear.</p><p><strong>Cases where it pays off</strong></p><ul><li><strong>An ONNX model still running on CPU remains in the pipeline</strong><br> (top priority &#x2014; the gain is an order of magnitude)<br></li><li>Models with lots of small operations where kernel-launch overhead is the bottleneck<br></li><li>Inference services with fixed input shapes that keep running the same model at volume</li></ul><p><strong>Cases where it pays off less, or deserves caution</strong></p><ul><li><strong>Modules that spend most of their time on the computation itself</strong> &#x2014; with the main operations&apos; compute time already dominant, the per-item latency gain from a straightforward ONNX &#x2192; TensorRT conversion was limited<br> (increasing the batch barely changed the per-item time; this is the result for this particular module, though &#x2014; with quantization or dedicated kernels the story changes, and throughput is another metric altogether)<br></li><li>Workloads with wide shape variation, where the cost of designing optimization profiles or managing multiple engines does not match the benefit<br></li><li>Models containing operations TensorRT does not support<br> (&#x2192; apply it partially with Part 4&apos;s hybrid configuration)<br></li><li><strong>Workloads that can simply be batched</strong> <br>This point deserves emphasis. If kernel-launch overhead is the bottleneck, <strong>you can sometimes gain several&#xD7; just by batching on the PyTorch side, without TensorRT at all</strong>.<br>In our case, running one module in batches shrank the per-frame time by more than 2&#xD7; &#x2014; <strong>faster than the configuration we had painstakingly converted to TensorRT</strong>. The optimal answer differs between &quot;process one frame at a time in real time&quot; and &quot;render everything out in bulk&quot;</li></ul><p>In short, <br><br><strong>TensorRT is not a universal speed button; it is <br>a tool you apply after measuring which stage is losing time, and to what</strong><br><br>. Skip that and charge into converting every stage, and the result will not repay the build effort.</p><h2 id="part-2-why-assets-that-worked-yesterday-stop-working-on-blackwell">Part 2: Why assets that worked yesterday stop working on Blackwell</h2><p>Now, on to Blackwell.</p><p><strong>The RTX 50 series, and the RTX PRO Blackwell workstation GPU we tested, are sm_120 (Compute Capability 12.0)</strong> &#x2014; a new generation, and this is where the causes of broken assets converge<br> (within the wider Blackwell family, some data-center products carry a different Compute Capability; check each product&apos;s generation with the GPU lookup tool introduced above).<br><br>In our test environment, problems appeared in the following three areas.</p><ul><li><strong>TensorRT</strong><br>The first release to support sm_120 was <strong>TensorRT 10.8.0</strong> (the release notes state &quot;supports NVIDIA Blackwell GPUs, such as the GeForce 50-series&quot;).<br>Put the other way around, <br><strong>TensorRT 8-series `.engine` / `.plan` files built with default settings fail the compatibility check and, as a rule, cannot be reused on sm_120</strong><br> (engines built on TensorRT 8.6+ with version compatibility and hardware compatibility enabled can be exceptions, but for existing assets whose compatibility settings cannot be confirmed, the safe assumption is a rebuild)<br></li><li><strong>PyTorch</strong><br> The first stable release with native Blackwell support is <strong>2.7.0 (CUDA 12.8 wheel = cu128)</strong>. Install an earlier wheel and it gets rejected with an error like <code>sm_120 is not compatible with the current PyTorch installation.</code>.<br></li><li><strong>onnxruntime</strong>: <strong>In our test environment (onnxruntime 1.27), CUDAExecutionProvider failed to initialize and execution fell back to CPU</strong>.<br>Because nothing stops with an error, it is easy to miss &#x2014; the only symptom left is &quot;things feel slow.&quot;<br>This depends on the combination of onnxruntime version, distributed build, and CUDA, though &#x2014; it does not mean official wheels uniformly fail on Blackwell. Verify with the versions you actually use<br></li></ul><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://journal.qualiteg.com/content/images/2026/07/fig1_compat_matrix.png" class="kg-image" alt="TensorRT 10 &#xD7; Blackwell Migration Guide (Part 1): Inference Assets Won&apos;t Run on RTX 50 &#x2014; The Basics and the First Walls" loading="lazy" width="2000" height="921" srcset="https://journal.qualiteg.com/content/images/size/w600/2026/07/fig1_compat_matrix.png 600w, https://journal.qualiteg.com/content/images/size/w1000/2026/07/fig1_compat_matrix.png 1000w, https://journal.qualiteg.com/content/images/size/w1600/2026/07/fig1_compat_matrix.png 1600w, https://journal.qualiteg.com/content/images/2026/07/fig1_compat_matrix.png 2206w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Figure 2: Do existing inference assets run as-is on the RTX 50 series?</span></figcaption></figure><p>In other words, Blackwell migration is not just swapping the GPU; it is <br><br><strong>&quot;move PyTorch to the cu128 generation&quot;<br> and &quot;move TensorRT to the 10.x generation,&quot; plus <br>&quot;re-examine which backend peripheral runtimes such as onnxruntime are actually running on&quot;<br> &#x2014; all run at the same time</strong><br><br>.</p><p>The third item, onnxruntime, tends to be left alone with a shrug of &quot;if CUDA won&apos;t work, CPU is fine&quot; &#x2014; but <strong>there is a good chance that is exactly where your pipeline&apos;s bottleneck sits</strong>, so beware.<br>Start by actually printing the providers and checking whether you have fallen back to CPU.</p><pre><code class="language-python">import onnxruntime as ort
print(ort.__version__)
print(ort.get_available_providers())   # if CUDAExecutionProvider is absent, the CUDA EP cannot be used in this environment

sess = ort.InferenceSession(&quot;model.onnx&quot;,
                            providers=[&quot;CUDAExecutionProvider&quot;, &quot;CPUExecutionProvider&quot;])
print(sess.get_providers())            # providers registered to the session, in priority order
</code></pre><p>One caution.<br><code>sess.get_providers()</code> tells you only &quot;which providers were registered to the session&quot; &#x2014; <strong>it is not proof that every node ran on the GPU</strong><br> (some nodes may be assigned to CPU). To confirm node-level placement, use onnxruntime&apos;s profiling or verbose logs.</p><h2 id="part-3-getting-a-minimal-tensorrt-10-conversion-through-%E2%80%94-five-steps">Part 3: Getting a minimal TensorRT 10 conversion through &#x2014; five steps</h2><p>From here on, we get hands-on.<br><br><strong>Do not start by converting your real model.</strong> <br><br>First push a minimal model of a few dozen lines through the five steps &#x2014; export &#x2192; build &#x2192; run &#x2192; numerical comparison &#x2192; speed measurement &#x2014; and confirm the environment itself is healthy.</p><p>With this self-check in place, when the real model later fails you can instantly separate &quot;is it the environment, or the model.&quot;</p><h3 id="environment-setup-%E2%80%94-the-first-trap-lives-here">Environment setup &#x2014; the first trap lives here</h3><p>All verification was done on WSL2 (Ubuntu 24.04).</p><p>We choose WSL2 because the Linux-first toolchain around CUDA / TensorRT works as-is. The venv is created with <code>uv</code>, and the system Python is left untouched.</p><pre><code class="language-bash"># Create a working venv with uv (leaves the system Python untouched)
uv venv ~/work/trt_venv --python 3.11
source ~/work/trt_venv/bin/activate

# Pin PyTorch to the cu128 (CUDA 12.8) generation (confirmed to resolve to 2.11.0 as of 2026-07-23)
uv pip install torch --index-url https://download.pytorch.org/whl/cu128

# Pin TensorRT to the 10.x cu12 build (&#x2605; reasons below)
uv pip install &quot;tensorrt-cu12==10.16.1.11&quot;
# onnxscript is required by PyTorch&apos;s new exporter (dynamo=True)
uv pip install onnx onnxscript numpy
</code></pre><p><strong>Trap 1: pip install tensorrt pulls in the CUDA 13 series</strong></p><p>A bare <code>pip install tensorrt</code> resolved, at the time of testing, to <strong>TensorRT 11.1.0.106 (a CUDA 13-series build)</strong>.</p><p>Meanwhile, this article&apos;s PyTorch environment is cu128 (CUDA 12.8). Having libraries from different CUDA major series in the same environment is not immediately invalid in itself, but <strong>it complicates dependencies and troubleshooting</strong>.</p><p>And above all, <strong>this article&apos;s code does not run on the TensorRT 11 API</strong>.</p><p>So, to keep the test conditions aligned, <strong>we match TensorRT&apos;s CUDA series to torch&apos;s</strong> and explicitly pin the cu12 build of TensorRT 10.16.</p><p>&quot;Just install the latest&quot; is not the rule here.</p><p>Once the environment is up, first confirm <strong>the GPU really is recognized as sm_120</strong>.</p><pre><code class="language-python">import torch
print(torch.__version__, torch.version.cuda)   # e.g. 2.11.0+cu128 / 12.8
print(torch.cuda.is_available())               # must be True
print(torch.cuda.get_device_capability())      # (12, 0) on RTX 50 series and the GPUs tested here
</code></pre><h3 id="step-1-prepare-the-dummy-model">Step 1: Prepare the dummy model</h3><p>We set up a small convolution block &#x2014; unrelated to any product, just Conv + BatchNorm + ReLU stacked.</p><pre><code class="language-python"># tiny_model.py
import torch
import torch.nn as nn

class TinyBlock(nn.Module):
    &quot;&quot;&quot;Minimal model for verifying TensorRT conversion (Conv+BN+ReLU &#xD7;3).
    Deliberately lines up small operations so the effect of layer fusion is easy to see.&quot;&quot;&quot;
    def __init__(self, ch=64):
        super().__init__()
        layers = []
        for _ in range(3):
            layers += [nn.Conv2d(ch, ch, 3, padding=1), nn.BatchNorm2d(ch), nn.ReLU(inplace=True)]
        self.body = nn.Sequential(*layers)

    def forward(self, x):
        return self.body(x)

INPUT_SHAPE = (1, 64, 256, 256)   # handled as a fixed shape
</code></pre><h3 id="step-2-export-to-onnx">Step 2: Export to ONNX</h3><p>In later steps we compare numbers against &quot;the very model we exported,&quot; so <strong>the `model` and `x` created here are reused throughout what follows</strong>.</p><p>Fixing the seed also makes the results reproducible.</p><pre><code class="language-python">torch.manual_seed(0)
model = TinyBlock().eval().cuda().float()
x = torch.randn(*INPUT_SHAPE, device=&quot;cuda&quot;)

torch.onnx.export(
    model, (x,), &quot;tiny.onnx&quot;,
    input_names=[&quot;x&quot;], output_names=[&quot;y&quot;],
    opset_version=20,
    dynamo=True,          # PyTorch 2.x&apos;s new exporter (requires onnxscript)
)
</code></pre><p>For models with multiple inputs, there is <strong>the seed of an extremely hard-to-find accident</strong> right here.</p><p><code>torch.onnx.export</code>&apos;s <code>args</code> parameter is a tuple, <strong>bound positionally, in order</strong>.</p><p>Get the parameter order of the model&apos;s <code>forward</code> wrong, and <strong>the export succeeds without error or warning, with the arguments swapped inside the ONNX</strong>.</p><p>That accident, and the permanent fix, are covered in detail in Part 2 of the series.</p><h3 id="step-3-build-the-tensorrt-engine">Step 3: Build the TensorRT engine</h3><pre><code class="language-python">import tensorrt as trt

TRT_LOGGER = trt.Logger(trt.Logger.WARNING)

def build_engine(onnx_path, engine_path, fp16=True, workspace_gb=4, tf32=True):
    builder = trt.Builder(TRT_LOGGER)
    # TensorRT 10 defaults to explicit batch. The flag below remains for backward compatibility
    network = builder.create_network(1 &lt;&lt; int(trt.NetworkDefinitionCreationFlag.EXPLICIT_BATCH))
    parser = trt.OnnxParser(network, TRT_LOGGER)

    # parse_from_file also resolves large models&apos; external data (.onnx.data)
    # automatically from the same directory as the ONNX
    if not parser.parse_from_file(onnx_path):
        errs = [str(parser.get_error(i)) for i in range(parser.num_errors)]
        raise RuntimeError(&quot;ONNX parse failed:\n&quot; + &quot;\n&quot;.join(errs))

    config = builder.create_builder_config()
    config.set_memory_pool_limit(trt.MemoryPoolType.WORKSPACE, workspace_gb * (1 &lt;&lt; 30))

    if fp16:
        # Add FP16 implementation candidates (tactics) to the choices. This does not guarantee
        # every layer becomes FP16; some layers may get FP32. The actual execution precision
        # can be confirmed by dumping layer information
        config.set_flag(trt.BuilderFlag.FP16)

    # &#x2605; Even in fp32 builds, TensorRT uses TF32 (10-bit mantissa) by default.
    #    Disable it when strictly verifying fidelity (details in Part 2 of the series)
    if not tf32:
        config.clear_flag(trt.BuilderFlag.TF32)

    plan = builder.build_serialized_network(network, config)
    if plan is None:
        raise RuntimeError(&quot;build_serialized_network returned None (engine build failed)&quot;)
    with open(engine_path, &quot;wb&quot;) as f:
        f.write(plan)
    return engine_path

build_engine(&quot;tiny.onnx&quot;, &quot;tiny_fp16.plan&quot;, fp16=True)
</code></pre><p>As the comment says, <code>BuilderFlag.FP16</code> does not mean &quot;make everything fp16&quot;; it means <strong>&quot;allow FP16 implementation candidates&quot;</strong>. From here on, whenever the text says &quot;built with fp16,&quot; read it as &quot;built with FP16 tactics allowed.&quot;</p><h3 id="step-4-run-the-engine-passing-pytorch-tensors-directly">Step 4: Run the engine (passing PyTorch tensors directly)</h3><p>This is probably the part practitioners most want to know.</p><p><strong>If device, dtype, shape, and memory layout (contiguous) already match the engine&apos;s requirements, you can register the PyTorch tensor&apos;s GPU memory address (`data_ptr()`) with TensorRT directly and avoid an extra copy at the boundary.</strong> </p><p>Once you can do this, the hybrid configuration &#x2014; &quot;convert only part of the model to TensorRT and leave the rest in PyTorch&quot; &#x2014; becomes realistic (we use it in Part 4).</p><p>For safety, the sample below <strong>automatically matches</strong> dtype and device before passing<br> (when the conditions do not match, a converting copy happens there; why this auto-conversion is needed is explained in the trap just below).</p><pre><code class="language-python">_TRT2TORCH = {
    trt.float32: torch.float32, trt.float16: torch.float16,
    trt.int32: torch.int32, trt.int64: torch.int64,
    trt.int8: torch.int8, trt.bool: torch.bool,
}

class TRTRunner:
    &quot;&quot;&quot;Loads an engine and runs it using PyTorch tensors for I/O (fixed shapes assumed)&quot;&quot;&quot;

    def __init__(self, engine_path, device=&quot;cuda:0&quot;):
        self.device = torch.device(device)
        # Runtime / engine / context are tied to the current CUDA device, so create them
        # with the target device made explicit (mandatory when using anything other than cuda:0)
        with torch.cuda.device(self.device):
            self.runtime = trt.Runtime(TRT_LOGGER)
            with open(engine_path, &quot;rb&quot;) as f:
                self.engine = self.runtime.deserialize_cuda_engine(f.read())
            if self.engine is None:
                raise RuntimeError(f&quot;deserialize failed: {engine_path}&quot;)
            self.ctx = self.engine.create_execution_context()

        self.inputs, self.outputs = [], []
        for i in range(self.engine.num_io_tensors):
            name = self.engine.get_tensor_name(i)
            if self.engine.get_tensor_mode(name) == trt.TensorIOMode.INPUT:
                self.inputs.append(name)
            else:
                self.outputs.append(name)

    def prepare(self, feed: dict):
        &quot;&quot;&quot;Set input shapes and addresses, and allocate output buffers.
        If input buffers are reused, once is enough (in speed measurement, keep this outside the timed region)&quot;&quot;&quot;
        self._feed = {}
        for name, t in feed.items():
            # &#x2605; Even with FP16 tactics allowed at build time, the engine&apos;s I/O types stay as defined
            #   in the ONNX (usually fp32). Pass a half tensor&apos;s address as-is and the fp16 bits get
            #   read as fp32, corrupting the output. And no exception is raised (details below)
            want = _TRT2TORCH[self.engine.get_tensor_dtype(name)]
            t = t.to(device=self.device, dtype=want).contiguous()
            # The set_* calls also return bool. Swallowing failures is strictly off-limits, given this article&apos;s theme
            if not self.ctx.set_input_shape(name, tuple(t.shape)):
                raise RuntimeError(f&quot;set_input_shape failed: {name}, shape={tuple(t.shape)}&quot;)
            if not self.ctx.set_tensor_address(name, t.data_ptr()):
                raise RuntimeError(f&quot;set_tensor_address failed: {name}&quot;)
            self._feed[name] = t

        self._outs = {}
        for name in self.outputs:
            shape = tuple(self.ctx.get_tensor_shape(name))
            if any(d &lt; 0 for d in shape):
                raise RuntimeError(f&quot;output shape unresolved: {name} {shape}&quot;)
            dtype = _TRT2TORCH[self.engine.get_tensor_dtype(name)]
            o = torch.empty(shape, dtype=dtype, device=self.device).contiguous()
            self._outs[name] = o
            if not self.ctx.set_tensor_address(name, o.data_ptr()):
                raise RuntimeError(f&quot;set_tensor_address failed: {name}&quot;)
        return self._outs

    def enqueue(self):
        &quot;&quot;&quot;Queue execution on the current stream (asynchronous). &#x2605; Always check the return value&quot;&quot;&quot;
        ok = self.ctx.execute_async_v3(torch.cuda.current_stream(self.device).cuda_stream)
        if not ok:
            raise RuntimeError(&quot;TensorRT enqueue failed: possibly an engine/runtime mismatch. &quot;
                               &quot;The output cannot be trusted, so processing stops here&quot;)

    def run(self, feed: dict):
        &quot;&quot;&quot;Convenience version for verification (prepare + synchronize every call). Not for speed measurement&quot;&quot;&quot;
        outs = self.prepare(feed)
        self.enqueue()
        torch.cuda.current_stream(self.device).synchronize()
        return outs
</code></pre><p><strong>Trap 2: Even built with FP16 tactics allowed, the engine&apos;s I/O stays fp32</strong></p><p>We actually stepped on this one during this verification.</p><p><code>config.set_flag(trt.BuilderFlag.FP16)</code> enabled adds FP16 implementation candidates to TensorRT&apos;s choices (not every layer becomes fp16), but <br><br><strong>the network&apos;s input/output tensor types follow the ONNX definition &#x2014; fp32 in this example</strong>.<br><br>Pass a PyTorch half tensor&apos;s address here as-is, and TensorRT treats the region as an input buffer of fp32 elements. Since fp16 is 2 bytes per element and fp32 is 4, <strong>not only does the interpretation of the values change &#x2014; TensorRT may also read beyond the region PyTorch allocated</strong>.</p><p>The behavior is undefined; beyond corrupted output, some environments may see CUDA errors or crashes<br> (<code>set_tensor_address</code> registers only the pointer and conveys nothing about the buffer&apos;s size).</p><p>Measured, it came out like this.</p><ul><li>With dtype correctly matched:<br>maximum absolute error <strong>about 0.001</strong><br> (no major numerical breakdown under this FP16-tactics-allowed configuration)<br></li><li>With the half tensor&apos;s address passed as-is:<br> maximum absolute error <strong>about 13.8</strong><br> (on a model whose output range is a bit under 0.5. This value is one observation in our environment and does not represent a reproducible error magnitude)</li></ul><p>And the worst part: <strong>in our measurements, even in this state `execute_async_v3` returned `True` (success), produced no NaN, and threw no exception</strong>. The reason the code above includes the two <code>want = _TRT2TORCH[...]</code> lines is to prevent exactly this silent degradation.</p><p><strong>Trap 3: Never discard the return value of `execute_async_v3`</strong></p><p>This method <strong>throws no exception on failure &#x2014; it merely returns `False`</strong>.</p><p>Leave that unchecked, and the un-updated output buffer (garbage, or the previous frame&apos;s values) flows straight downstream.</p><p><strong>Processing looks &quot;successful&quot; while only the output is broken</strong> &#x2014; the worst possible shape of failure. As in the code above, we strongly recommend making <code>False</code> raise immediately.</p><h3 id="step-5-match-the-numbers-first-then-measure-speed">Step 5: Match the numbers first, then measure speed</h3><p><strong>Before measuring speed, first confirm the numbers match.<br>Do not reverse the order.</strong></p><p>The reference for the comparison is <strong>the very fp32 `model` and `x` used for the export in Step 2</strong>. Do not construct a new model here<br> (you would be comparing against randomly initialized &quot;different weights&quot;), and do not use an fp16-converted variant as the reference either (that would no longer verify &quot;are the export and the engine correct&quot;).</p><pre><code class="language-python"># model / x are the same fp32 objects used for the export in Step 2
with torch.inference_mode():
    torch_ref = model(x)

runner = TRTRunner(&quot;tiny_fp16.plan&quot;)
trt_out = runner.run({&quot;x&quot;: x})[&quot;y&quot;]

diff = trt_out.float() - torch_ref.float()
print(&quot;max_abs :&quot;, diff.abs().max().item())
print(&quot;nRMSE   :&quot;, (diff.norm() / torch_ref.norm()).item())
</code></pre><p>Without the output&apos;s own value range alongside it, the size of a maximum absolute error cannot be judged. An untrained dummy model has a different value range from a real model, so <strong>a normalized relative error (nRMSE)</strong> should be checked alongside &#x2014; that is the safe practice.</p><p>For this TinyBlock: max_abs about 0.001, nRMSE about 0.0016 &#x2014; a small error level for an engine with FP16 tactics allowed, under this configuration.</p><p>Measurement is done with <strong>a dedicated CUDA stream + CUDA Events</strong>.<code>time.time()</code> cannot correctly measure the GPU&apos;s asynchronous execution.</p><pre><code class="language-python">import numpy as np

def bench_callable(fn, n_warmup=30, n_iter=200, device=&quot;cuda:0&quot;):
    &quot;&quot;&quot;Measures fn() and returns mean/median/min/max (milliseconds).
    Using a dedicated stream lets PyTorch and TensorRT be compared fairly under identical conditions&quot;&quot;&quot;
    dev = torch.device(device)
    # Complete any work queued earlier on other streams (model conversion, prepare, etc.).
    # Streams have no guaranteed ordering unless explicitly synchronized
    torch.cuda.synchronize(dev)
    stream = torch.cuda.Stream(dev)
    with torch.cuda.stream(stream):
        for _ in range(n_warmup):      # warmup is mandatory (first runs are slow)
            fn()
        stream.synchronize()

        times = []
        for _ in range(n_iter):
            s = torch.cuda.Event(enable_timing=True)
            e = torch.cuda.Event(enable_timing=True)
            s.record(stream)
            fn()
            e.record(stream)
            stream.synchronize()
            times.append(s.elapsed_time(e))

    t = np.array(times)
    return {&quot;mean&quot;: float(t.mean()), &quot;median&quot;: float(np.median(t)),
            &quot;min&quot;: float(t.min()), &quot;max&quot;: float(t.max())}
</code></pre><p>For the speed measurement, the PyTorch side uses <strong>an fp16-converted model</strong> as its realistic production candidate. We want to keep the fp32 <code>model</code> used for the comparison intact, so we copy before converting to fp16. The key point: <strong>on the TensorRT side, run `prepare()` (buffer allocation and address registration) once, outside the timed region, and call only `enqueue()` during measurement</strong>.</p><p>Call <code>run()</code> every iteration and the dtype conversion, output allocation, and synchronization all get counted into TensorRT&apos;s time &#x2014; no longer a fair comparison.</p><pre><code class="language-python">import copy

# The fp16 model for speed measurement is made separately via deepcopy, to preserve the fp32 model used for export
model_half = copy.deepcopy(model).half()
x_half = x.half()

# PyTorch side (eager + inference_mode, fp16)
def torch_fn():
    with torch.inference_mode():
        model_half(x_half)

# TensorRT side: prepare runs once, outside the timed region. Only enqueue is measured
runner.prepare({&quot;x&quot;: x})
def trt_fn():
    runner.enqueue()

print(&quot;torch:&quot;, bench_callable(torch_fn))
print(&quot;trt  :&quot;, bench_callable(trt_fn))
</code></pre><p>Here are the results.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://journal.qualiteg.com/content/images/2026/07/fig3_tinyblock_speed_v3.png" class="kg-image" alt="TensorRT 10 &#xD7; Blackwell Migration Guide (Part 1): Inference Assets Won&apos;t Run on RTX 50 &#x2014; The Basics and the First Walls" loading="lazy" width="2000" height="914" srcset="https://journal.qualiteg.com/content/images/size/w600/2026/07/fig3_tinyblock_speed_v3.png 600w, https://journal.qualiteg.com/content/images/size/w1000/2026/07/fig3_tinyblock_speed_v3.png 1000w, https://journal.qualiteg.com/content/images/size/w1600/2026/07/fig3_tinyblock_speed_v3.png 1600w, https://journal.qualiteg.com/content/images/2026/07/fig3_tinyblock_speed_v3.png 2100w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Figure 3: The same model run on PyTorch versus TensorRT</span></figcaption></figure><blockquote>Measurement conditions: GeForce RTX 5060 Ti / batch=1 / PyTorch 2.11 eager + <code>inference_mode</code>, fp16 model / TensorRT 10.16, fp32 I/O, FP16 tactics enabled. TensorRT preallocates I/O buffers and only the <strong>enqueue region</strong> is measured. Median of 200 runs with 30 warmups each.</blockquote><p>For a small model that merely stacks Conv + BatchNorm + ReLU three deep, <strong>the GPU-execution region showed about a 2.5&#xD7; difference</strong>.</p><p>Reading this number takes care, though.</p><p>This compares &quot;fully fp16 PyTorch eager&quot; against &quot;a TensorRT engine with fp32 I/O and FP16 tactics allowed,&quot; over the GPU-execution region excluding upfront dtype conversion and buffer preparation.</p><p><strong>It is neither a same-precision comparison nor an end-to-end speedup figure for a whole pipeline</strong>.</p><p>Even so, the fact that the same model structure shows this much difference when each side runs in its realistic production configuration is consistent with the effects listed in Part 1: layer fusion, kernel selection, and reduced runtime overhead.</p><p>For the comparison, look at <strong>median</strong>.</p><p>Averages get dragged around by the occasional outlier.</p><p>Also, <strong>keep the GPU exclusively yours during measurement</strong>. If other inference processes or desktop rendering share the GPU, the numbers swing by tens of percent easily and the comparison loses meaning.</p><h2 id="part-4-the-first-wall-%E2%80%94-the-build-falls-over-on-gridsamples-dimensionality">Part 4: The first wall &#x2014; the build falls over on <code>grid_sample</code>&apos;s dimensionality</h2><p>When you start converting your real model, this is what most people hit first.<strong>If the model contains a 5-dimensional (volumetric) `grid_sample`, the TensorRT build does not pass.</strong></p><p>Warping 3D volumes appears in many domains: medical image registration, NeRF-family methods, 3D feature warping. The minimal reproduction module is as follows.</p><pre><code class="language-python">import torch.nn.functional as F

class VolumetricWarp(nn.Module):
    &quot;&quot;&quot;Minimal module containing a 5D (volumetric) grid_sample.
    input: [N, C, D, H, W] / grid: [N, D, H, W, 3]&quot;&quot;&quot;
    def forward(self, vol, grid):
        return F.grid_sample(vol, grid, align_corners=False)

VOL_SHAPE  = (1, 32, 16, 64, 64)
GRID_SHAPE = (1, 16, 64, 64, 3)
</code></pre><p>Export and build can be tried with the exact same tooling as Steps 2&#x2013;3.</p><pre><code class="language-python">warp_model = VolumetricWarp().eval().cuda()
vol = torch.randn(*VOL_SHAPE, device=&quot;cuda&quot;)
grid = torch.rand(*GRID_SHAPE, device=&quot;cuda&quot;) * 2 - 1

torch.onnx.export(
    warp_model, (vol, grid), &quot;volumetric_warp.onnx&quot;,
    input_names=[&quot;vol&quot;, &quot;grid&quot;], output_names=[&quot;y&quot;],
    opset_version=20, dynamo=True,
)

# The ONNX export succeeds. What fails is the build that follows
build_engine(&quot;volumetric_warp.onnx&quot;, &quot;volumetric_warp.plan&quot;, fp16=False)
</code></pre><p>Run it, and it fails with the following error (verbatim log from the real machine).</p><pre><code>[TRT] [E] INetworkDefinition::addGridSample: Error Code 3: API Usage Error
    (Parameter check failed, condition: input.getDimensions().nbDims == 4.
     In addGridSample at /_src/optimizer/api/network.cpp:1803)
[TRT] [E] ModelImporter.cpp:138: While parsing node number 0 [GridSample -&gt; &quot;y&quot;]:
[TRT] [E] ModelImporter.cpp:149: ERROR: ModelImporter.cpp:490 In function parseNode:
[6] Invalid Node - node_GridSample_0
</code></pre><p><code>input.getDimensions().nbDims == 4</code> <br><br>In other words, <strong>TensorRT 10.16&apos;s native `GridSample` accepts only 4-dimensional inputs</strong>.</p><p>5D calls are rejected at the point where the parser adds the node.</p><p>This matches the primary sources. The onnx-tensorrt operators documentation states, for <code>GridSample</code>, <strong>&quot;Input must be 4D input.&quot;</strong>, and the request for 5D support exists as NVIDIA/TensorRT issue <strong>#3890</strong>, which remains open / triaged with no native support provided.</p><h3 id="raise-the-onnx-opset-and-it-will-pass-is-wrong">&quot;Raise the ONNX opset and it will pass&quot; is wrong</h3><p>This is a common source of confusion, so let&apos;s make it explicit.</p><p>The ONNX standard defines 4D grid_sample at opset 16 and <strong>5D (volumetric) grid_sample at opset 20</strong>.</p><p>Therefore <strong>the export from PyTorch succeeds fine at opset 20, and a 5D GridSample node is duly generated inside the ONNX file</strong>. Indeed, the error log above shows the failure happening at build time, after a successful export.</p><p>What fails is not the export but <strong>TensorRT&apos;s build</strong>. What ONNX can express and what TensorRT can digest are separate questions.</p><h3 id="the-practical-answer-%E2%80%94-leave-only-the-failing-module-in-pytorch">The practical answer &#x2014; leave only the failing module in PyTorch</h3><p>One workaround is to write the operation TensorRT lacks as your own CUDA kernel and register it as a plugin. For 5D grid_sample there are existing OSS implementations (<a href="https://github.com/SeanWangJS/grid-sample3d-trt-plugin?ref=journal.qualiteg.com" rel="noreferrer">grid-sample3d-trt-plugin</a>, among others), and rebuilding one for the new CUDA / TensorRT generation is a viable approach.</p><p>But <strong>that is expert work</strong>, so we cover it in the final installment of this series.</p><p>Making zero migration progress until the plugin is finished is not realistic. What works here is the <strong>hybrid configuration</strong>. The idea is utterly simple: <strong>convert to TensorRT only the modules that pass, and leave the failing modules in PyTorch</strong>.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://journal.qualiteg.com/content/images/2026/07/fig4_hybrid.png" class="kg-image" alt="TensorRT 10 &#xD7; Blackwell Migration Guide (Part 1): Inference Assets Won&apos;t Run on RTX 50 &#x2014; The Basics and the First Walls" loading="lazy" width="2000" height="908" srcset="https://journal.qualiteg.com/content/images/size/w600/2026/07/fig4_hybrid.png 600w, https://journal.qualiteg.com/content/images/size/w1000/2026/07/fig4_hybrid.png 1000w, https://journal.qualiteg.com/content/images/size/w1600/2026/07/fig4_hybrid.png 1600w, https://journal.qualiteg.com/content/images/2026/07/fig4_hybrid.png 2099w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Figure 4: Leave only the failing module in PyTorch &#x2014; the hybrid configuration</span></figcaption></figure><pre><code class="language-python"># Configuration sketch (head_fp16.plan is a placeholder name meaning &quot;the engine for the TensorRT-converted latter stage&quot;)
warp = VolumetricWarp().eval().cuda()      # 5D grid_sample &#x2192; stays in PyTorch
head = TRTRunner(&quot;head_fp16.plan&quot;)         # latter stage &#x2192; TensorRT engine

def forward(vol, grid):
    with torch.no_grad():
        feat = warp(vol, grid)             # PyTorch produces its output on the GPU
    return head.run({&quot;x&quot;: feat})[&quot;y&quot;]      # and that address is handed to TensorRT as-is
</code></pre><p>As Step 4 showed, when dtype, device, and shape match, PyTorch tensors and TensorRT can exchange addresses on the same device and the same stream, <strong>so bridging the two incurs no additional copies</strong>.</p><p>In our case, this configuration alone &#x2014; without writing a single plugin &#x2014; improved things nearly 2&#xD7;, and as we progressively replaced the modules that load cleanly onto TensorRT, <strong>the pipeline as a whole reached roughly 2&#xD7; within the plugin-free scope</strong>.</p><p><strong>&quot;First, secure reliable speedups in the low-risk scope. Carve the custom plugin out as a separate project.&quot;</strong> <br><br> That, we believe, is the realistic way to run this migration.</p><h2 id="what-we-have-not-yet-confirmed">What we have not yet confirmed</h2><p>In the interest of honesty: the verification in this article was done on a single software configuration, &quot;TensorRT 10.16 + PyTorch 2.11 + cu128.&quot; The following have not been confirmed here.</p><ul><li><strong>Reproducibility on other TensorRT versions</strong> <br> &#x2014; in particular, the behavior of 4D <code>grid_sample</code> (covered in Part 2 of the series) may be fixed in future versions. TensorRT 11 has also changed its APIs (strong typing), so this article&apos;s code does not run there as-is<br></li><li><strong>Comparison against PyTorch with torch.compile or CUDA Graphs</strong> <br> &#x2014; this article compares against eager execution only<br></li><li><strong>Combination with int8 quantization</strong> <br> &#x2014; this article covers fp16 / fp32 only<br></li><li><strong>Builds with dynamic shapes</strong> <br> &#x2014; everything in this article is fixed-shape.<br>Speed and accuracy with optimization profiles require separate verification<br></li><li><strong>Numbers and speed for the 5D grid_sample plugin built for Blackwell</strong> <br> &#x2014; planned for the final installment</li></ul><h2 id="summary">Summary</h2><p>To sum it up in one sentence: <br><br><strong>&quot;Blackwell migration is not a GPU swap; it is updating PyTorch&apos;s and TensorRT&apos;s support status plus re-confirming which execution backend the peripheral runtimes are actually using &#x2014; and TensorRT conversion is a separate investment decision layered on top.&quot;</strong><br><br> That is the story<br> (not exactly one sentence, we admit. <br>Incidentally, our environment did hit the onnxruntime CPU fallback).</p><p>Now, to close, let us restate the important points.</p><ol><li>Check the GPU&apos;s Compute Capability first<br> (RTX 50 series is sm_120. Other Blackwell product lines carry different values, so check per product)<br></li><li>PyTorch on the cu128 generation<br> (stable from 2.7.0)<br></li><li>Use TensorRT 10.8 or later.<br>Existing TensorRT 8 engines should, after checking compatibility settings and target GPU, be rebuilt as a rule<br></li><li>Match TensorRT&apos;s CUDA series to torch&apos;s (pin to cu12)<br></li><li>Check whether onnxruntime has fallen back to CPU by actually printing the version and providers. If it has, it is your top TensorRT conversion candidate<br></li><li>Self-diagnose with a minimal model before moving to the real one<br></li><li><strong>Pass tensors matched to the engine&apos;s I/O dtypes</strong><br> (even FP16-tactics builds usually keep fp32 I/O)<br></li><li><strong>Always check the return values of execute_async_v3 and set_input_shape / set_tensor_address</strong><br> (no exception is thrown on failure)<br></li><li>Do the numerical comparison before the speed measurement, <strong>with the same weights and the same input used for the export</strong>.<br></li><li>Check the dimensionality of <code>grid_sample</code> inside your model<br> (5D does not pass natively; raising the opset does not solve it)<br></li><li>Carve out the failing modules and go hybrid<br></li><li>Measure with the GPU exclusively occupied, using the median of CUDA Events. For engine-only comparisons, separate the buffer preparation and time the enqueue region; for production decisions, also measure end-to-end time including dtype conversion, module boundaries, and synchronization</li></ol><h2 id="coming-next-part-2-%E2%80%94-a-passing-build-is-not-necessarily-correct">Coming next (Part 2) &#x2014; a passing build is not necessarily correct</h2><p>Next up is not the finale but the middle installment.<br><br>What this Part 1 covered were problems of the kind that <strong>have the decency to stop with an error</strong>.<br><br>What is truly frightening in a migration lies beyond that.<br><br>We will cover the &quot;<strong>silent degradation</strong>&quot; we actually stepped on.</p><ul><li><strong>The build succeeds, execution succeeds, and the output&apos;s shape and values look plausible &#x2014; yet the meaning of an operation has been swapped for something else</strong> &#x2014; one such case<br> (this one we could fully reproduce with a publishable dummy model)<br></li><li>A build that succeeds with good speed &#x2014; yet <strong>the output breaks the moment real data goes in</strong> &#x2014; one such module</li><li><strong>An engine that worked perfectly on the dev machine quietly emitting garbage on a different GPU of the same generation</strong> &#x2014; that phenomenon</li><li>Building in fp32 that <strong>turned out not to be fp32</strong> &#x2014; that story</li><li>And the one that made us cry the hardest: <strong>the export-time argument mix-up accident</strong></li></ul><p>Every one of these is deeply troublesome when it surfaces after you have reported &quot;it&apos;s faster now, all good&quot; &#x2014; so stay tuned.</p><p>See you next time!</p><hr><h3 id="references-primary-sources">References (primary sources)</h3><ul><li><a href="https://docs.nvidia.com/deeplearning/tensorrt/latest/?ref=journal.qualiteg.com" rel="noreferrer">NVIDIA TensorRT documentation (Release Notes 10.8.0 &#x2014; the Blackwell support entry)</a></li><li><a href="https://forums.developer.nvidia.com/t/software-migration-guide-for-nvidia-blackwell-rtx-gpus-a-guide-to-cuda-12-8-pytorch-tensorrt-and-llama-cpp/321330?ref=journal.qualiteg.com" rel="noreferrer">NVIDIA official forum: Software Migration Guide for NVIDIA Blackwell RTX GPUs (CUDA 12.8 / PyTorch / TensorRT)</a></li><li><a href="https://github.com/pytorch/pytorch/issues/159207?ref=journal.qualiteg.com" rel="noreferrer">PyTorch issue #159207: sm_120 is not compatible with the current PyTorch installation</a></li><li><a href="https://github.com/microsoft/onnxruntime/issues/27875?ref=journal.qualiteg.com" rel="noreferrer">onnxruntime issue #27875: report on CUDAExecutionProvider initialization in Blackwell environments</a></li><li><a href="https://github.com/NVIDIA/TensorRT/issues/3890?ref=journal.qualiteg.com" rel="noreferrer">NVIDIA/TensorRT issue #3890: request for native 5D GridSample support</a></li><li><a href="https://github.com/SeanWangJS/grid-sample3d-trt-plugin?ref=journal.qualiteg.com" rel="noreferrer">SeanWangJS/grid-sample3d-trt-plugin (custom plugin implementation of 5D grid_sample)</a></li><li><a href="https://onnx.ai/onnx/operators/onnx__GridSample.html?ref=journal.qualiteg.com" rel="noreferrer">ONNX Operators: GridSample (opset 16 / 20 specifications)</a></li><li>Related article from Qualiteg: <a href="https://journal.qualiteg.com/2026-nvidia-gpu-list-filtering-app/" rel="noreferrer">2026 NVIDIA GPU quick-lookup tool</a></li></ul>]]></content:encoded></item><item><title><![CDATA[Kimi K3 Deep Dive — 2.8T Parameters: Will the "Largest Open Weights in History" Materialize?]]></title><description><![CDATA[<p>Hello!</p><p>On July 16, 2026, Moonshot AI of Beijing, China announced its new flagship model <strong>Kimi K3</strong> and began offering it via its API and web services.</p><p>The sheer scale of 2.8 trillion total parameters, a 1-million-token context, and the declaration that <br><br><strong>&quot;it will become the largest open-weight</strong></p>]]></description><link>https://journal.qualiteg.com/kimi-k3-introduce/</link><guid isPermaLink="false">6a5ce18eedf69a17d422a987</guid><category><![CDATA[LLM]]></category><category><![CDATA[AI Agents]]></category><category><![CDATA[Generative AI Frontlines]]></category><dc:creator><![CDATA[Qualiteg Product Development Team]]></dc:creator><pubDate>Mon, 20 Jul 2026 06:41:30 GMT</pubDate><media:content url="https://journal.qualiteg.com/content/images/2026/07/kimi_k3--1-.png" medium="image"/><content:encoded><![CDATA[<img src="https://journal.qualiteg.com/content/images/2026/07/kimi_k3--1-.png" alt="Kimi K3 Deep Dive &#x2014; 2.8T Parameters: Will the &quot;Largest Open Weights in History&quot; Materialize?"><p>Hello!</p><p>On July 16, 2026, Moonshot AI of Beijing, China announced its new flagship model <strong>Kimi K3</strong> and began offering it via its API and web services.</p><p>The sheer scale of 2.8 trillion total parameters, a 1-million-token context, and the declaration that <br><br><strong>&quot;it will become the largest open-weight model in history&quot;</strong><br><br> have set the AI community abuzz.</p><p>In our article this past May, &quot;<a href="https://journal.qualiteg.com/mythos-level-open-source-llm-timing/" rel="noreferrer">When Will a Mythos-Level Open Model Arrive?</a>,&quot; we predicted when open models would catch up to the closed frontier.</p><p>Kimi K3 is one of the latest &quot;answers&quot; to that very question as of today.</p><p>On the other hand, as of July 20 &#x2014; the day this article is being written &#x2014; <strong>neither the model weights nor the technical report has been released yet</strong>&#x3002;</p><p>That said, on X and other corners of social media, comments such as </p><p><strong>&quot;the guardrails are on the loose side &#x2014; it handles prompts that Fable 5 would refuse&quot;</strong></p><p><strong> and &quot;it&apos;s easier to work with than Fable 5, which falls back to Opus 4.8 at the drop of a hat&quot;</strong></p><p> can be spotted here and there; against <br><strong>the strong-guardrail policy of US-made models</strong>, <strong>a Chinese-made model with weaker guardrails</strong> may just hold the hidden potential to ultimately win users over.</p><p>That said, in this article we&apos;ll set aside the social-media chatter and instead cross-check primary sources (Moonshot&apos;s official blog, official API documentation, GitHub) against English-language press coverage and analyses from independent evaluation organizations, sorting out the full picture of Kimi K3 while distinguishing &quot;officially announced,&quot; &quot;independently evaluated,&quot; and &quot;unconfirmed.&quot;</p><h2 id="part-1-what-is-kimi-k3">Part 1: What Is Kimi K3?</h2><h3 id="how-the-release-unfolded">How the Release Unfolded</h3><p>Kimi K3 was announced on July 16, 2026, and became available through the following channels the same day.</p><ul><li><strong>Kimi.com</strong>(chat UI)</li><li><strong>Kimi Work</strong>(workspace product)</li><li><strong>Kimi Code</strong>(coding agent)</li><li><strong>Kimi API</strong>(OpenAI SDK compatible)</li></ul><p>It was also added to the third-party API aggregator OpenRouter the same day &#x2014; an API-first launch in the style of &quot;make it available via API and web first, weights later.&quot;</p><p>The official blog explicitly states, &quot;<u>we will make the full model weights public <strong>by July 27, 2026</strong> at the latest</u>,&quot; and explains that the delay is &quot;to ensure a smooth rollout with our inference partners.&quot;</p><h3 id="quick-reference-basic-specs">Quick Reference: Basic Specs</h3>
<!--kg-card-begin: html-->
<table>
<thead>
<tr><th>Item</th><th>Details</th><th>Confidence</th></tr>
</thead>
<tbody>
<tr><td>Total parameters</td><td>2.8 trillion (MoE)</td><td>Official announcement (weights unreleased, so internal configuration cannot be independently verified)</td></tr>
<tr><td>MoE configuration</td><td>16 of 896 experts activated (approx. 1.8%)</td><td>Official announcement</td></tr>
<tr><td>Active parameters</td><td>Some analyses put it at ~50B (A50B)</td><td><strong>Unconfirmed</strong> (not officially disclosed)</td></tr>
<tr><td>Context length</td><td>1 million tokens</td><td>Official announcement and API documentation</td></tr>
<tr><td>Multimodal</td><td>Native vision (image and video understanding)</td><td>Official announcement plus third-party hands-on verification</td></tr>
<tr><td>Thinking mode</td><td>Always on. Currently &apos;max&apos; only on the official Kimi API; low/high/max selectable in Kimi Code</td><td>Official documentation</td></tr>
<tr><td>New mechanisms</td><td>Kimi Delta Attention (KDA) / Attention Residuals (AttnRes)</td><td>Official announcement (efficiency figures are vendor claims)</td></tr>
<tr><td>Quantization</td><td>MXFP4 weights / MXFP8 activations</td><td>Official announcement</td></tr>
<tr><td>API pricing</td><td>$3.00 input / $15.00 output (per million tokens)</td><td>Official pricing page</td></tr>
<tr><td>Weight release</td><td>Scheduled by July 27, 2026. Distribution file format <strong>unconfirmed</strong> (awaiting the model card)</td><td>Official commitment (unreleased as of 7/20)</td></tr>
<tr><td>License</td><td>Reported as &quot;Modified MIT&quot;</td><td><strong>Unconfirmed</strong> (no primary source)</td></tr>
</tbody>
</table>
<!--kg-card-end: html-->
<h2 id="part-2-architecture-%E2%80%94-an-extremely-sparse-28-trillion-parameters">Part 2: Architecture &#x2014; An Extremely &quot;Sparse&quot; 2.8 Trillion Parameters</h2><h3 id="an-moe-that-uses-only-16-experts-out-of-896">An MoE That Uses Only 16 Experts out of 896</h3><p>Kimi K3 is a sparse MoE (Mixture of Experts) model built on a framework Moonshot calls &quot;Stable LatentMoE.&quot; What stands out is its low activation rate: <strong>of the 896 experts, only 16 (about 1.8%) are activated per token</strong>.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://journal.qualiteg.com/content/images/2026/07/chart2_moe.png" class="kg-image" alt="Kimi K3 Deep Dive &#x2014; 2.8T Parameters: Will the &quot;Largest Open Weights in History&quot; Materialize?" loading="lazy" width="2000" height="1280" srcset="https://journal.qualiteg.com/content/images/size/w600/2026/07/chart2_moe.png 600w, https://journal.qualiteg.com/content/images/size/w1000/2026/07/chart2_moe.png 1000w, https://journal.qualiteg.com/content/images/size/w1600/2026/07/chart2_moe.png 1600w, https://journal.qualiteg.com/content/images/2026/07/chart2_moe.png 2000w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">The sparse MoE configuration in which only 16 of 896 experts are activated (Source: chart by Qualiteg based on figures published on the Moonshot AI official blog)</span></figcaption></figure><p>The 2.8-trillion total parameter figure is rounded up in marketing as &quot;the world&apos;s first open 3T-class model,&quot; but only a small fraction of it actually runs at inference time.</p><p>This <br><strong>&quot;open only the shelves you need in a vast warehouse of knowledge&quot;</strong><br> design aims to reconcile scale with inference cost.</p><p>Note that Latent.Space describes the active parameter count per token as &quot;A50B&quot; (roughly 50 billion), but Moonshot has not stated it officially, so this number is <strong>unconfirmed</strong>. Once the weights are released, it may become verifiable from the config files or model card.</p><h3 id="two-homegrown-innovations-kda-and-attnres">Two Homegrown Innovations: KDA and AttnRes</h3><p>The architectural highlights are two new mechanisms Moonshot developed in-house.</p><ul><li><strong>Kimi Delta Attention (KDA)</strong><br>A hybrid linear attention mechanism, claimed to deliver <strong>up to 6.3x faster decoding</strong> at 1-million-token-class context lengths<br><br></li><li><strong>Attention Residuals (AttnRes)</strong><br> A mechanism that replaces conventional residual connections. <strong>Roughly 25% better training efficiency at under 2% additional cost</strong> is the claim.</li></ul><p>Both are intriguing numbers, but at this point they are vendor claims originating from official announcements on X; with no technical report published, no third party has reproduced them.</p><h3 id="native-vision-and-an-always-on-thinking-mode">Native Vision and an Always-On Thinking Mode</h3><p>K3 is a natively multimodal model that handles text, images, and video.</p><p>On the vision side, noted AI blogger Simon Willison actually tested it and confirmed &quot;Vision works well&quot; &#x2014; one of the few independent, hands-on data points. In his single test he also observed the thinking mode consuming 13,241 reasoning tokens (one example, not a typical value for the model in general).</p><p>The thinking mode is always on, and the <code>reasoning_effort</code> you can specify on the official Kimi API is currently limited to &apos;max&apos;. Kimi Code, on the other hand, officially offers a choice of low/high/max &#x2014; worth remembering that the options differ by channel.</p><h2 id="part-3-benchmarks-%E2%80%94-read-self-reported-and-independent-separately">Part 3: Benchmarks &#x2014; Read &quot;Self-Reported&quot; and &quot;Independent&quot; Separately</h2><p>When reading Kimi K3&apos;s benchmark numbers, the most important thing is distinguishing <strong>which figures are Moonshot&apos;s self-reported ones and which come from independent evaluations</strong>.</p><p>For independent comparative evaluations we have Arena.AI (blind voting) and Artificial Analysis (an evaluation organization); separately, Simon Willison has published an API hands-on.</p><h3 id="independent-evaluation-1-first-place-in-the-frontend-code-arena">Independent Evaluation #1: First Place in the Frontend Code Arena</h3><p>This one was perhaps the biggest surprise.</p><p>In Arena.AI&apos;s Frontend Code Arena, which is decided by blind user voting, <strong>Kimi K3 took first place with 1,679 points as of the announcement (July 16)</strong>.</p><p><u>That score surpasses even Claude Fable 5</u>, and from the previous-generation Kimi K2.6&apos;s 18th place it <strong>shot up 17 ranks in one leap</strong>. Because it is blind voting, self-report bias is unlikely to creep in, though noise from early vote counts and prompt skew remains. Even so, it is one of the strongest external signals to date of the model&apos;s frontend generation capability.</p><h3 id="independent-evaluation-2-artificial-analysis-%E2%80%94-opus-48-gpt-55-class">Independent Evaluation #2: Artificial Analysis &#x2014; &quot;Opus 4.8 / GPT-5.5 Class&quot;</h3><p>On evaluation firm Artificial Analysis&apos;s Intelligence Index it scores <strong>57</strong>, which &#x2014; to borrow the firm&apos;s own phrasing &#x2014; positions it as &quot;<strong>comparable to Claude Opus 4.8 and GPT-5.5, </strong></p><p><strong>but not reaching Claude Fable 5 or GPT-5.6 Sol</strong>.&quot;</p><p>On the same firm&apos;s GDPval-AA v2 (an Elo evaluation on real-world work tasks), it also ranks third, right behind the two frontier leaders.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://journal.qualiteg.com/content/images/2026/07/chart3_gdpval_v2.png" class="kg-image" alt="Kimi K3 Deep Dive &#x2014; 2.8T Parameters: Will the &quot;Largest Open Weights in History&quot; Materialize?" loading="lazy" width="2000" height="982" srcset="https://journal.qualiteg.com/content/images/size/w600/2026/07/chart3_gdpval_v2.png 600w, https://journal.qualiteg.com/content/images/size/w1000/2026/07/chart3_gdpval_v2.png 1000w, https://journal.qualiteg.com/content/images/size/w1600/2026/07/chart3_gdpval_v2.png 1600w, https://journal.qualiteg.com/content/images/2026/07/chart3_gdpval_v2.png 2200w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Kimi K3&apos;s position in the GDPval-AA v2 evaluation (Source: chart by Qualiteg based on Artificial Analysis GDPval-AA v2 as of 2026-07-19 and reporting by The Decoder)</span></figcaption></figure><p>What deserves attention here is the agentic Elo in the right panel.</p><p>On GDPval-AA v2&apos;s agentic Elo, <strong>K3 (1,668) beats Claude Opus 4.8 (1,600) and GPT-5.5 (1,494)</strong> according to reports (The Decoder and others), which is consistent with Moonshot&apos;s own claim that it &quot;trails Fable 5 / GPT-5.6 Sol overall, but surpasses Opus 4.8 / GPT-5.5 in coding and agentic work.&quot;</p><p>That said, not every independent evaluation is positive.</p><p>On Artificial Analysis&apos;s AA-Omniscience, while accuracy improved from K2.6&apos;s 33% to 46%, <strong><u>the hallucination rate rose from 39% to 51%</u></strong>, the firm reports.</p><p>Gains in knowledge and reasoning do not automatically translate into more cautious or more factual answers &#x2014; a point worth remembering as input for enterprise adoption decisions.</p><p>Also, in the analysis Artificial Analysis published on July 17, Kimi K3 placed just behind Fable 5 on the firm&apos;s private agentic evaluation AA-Briefcase as well, at <strong>second place (Elo 1,547)</strong>.</p><p>We use the 1,547 that the evaluator itself published in its analysis, rather than the 1,527 reported by VentureBeat (Elo is recomputed dynamically, so it drifts somewhat over time).</p><h3 id="position-in-aggregate-rankings-for-reference">Position in Aggregate Rankings (For Reference)</h3><p>On the benchmark aggregator BenchLM.ai, it sat in 4th place with an overall score of 80.96 as of our July 19 survey.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://journal.qualiteg.com/content/images/2026/07/chart1_benchlm_v2.png" class="kg-image" alt="Kimi K3 Deep Dive &#x2014; 2.8T Parameters: Will the &quot;Largest Open Weights in History&quot; Materialize?" loading="lazy" width="2000" height="1120" srcset="https://journal.qualiteg.com/content/images/size/w600/2026/07/chart1_benchlm_v2.png 600w, https://journal.qualiteg.com/content/images/size/w1000/2026/07/chart1_benchlm_v2.png 1000w, https://journal.qualiteg.com/content/images/size/w1600/2026/07/chart1_benchlm_v2.png 1600w, https://journal.qualiteg.com/content/images/2026/07/chart1_benchlm_v2.png 2000w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">BenchLM.ai overall score Top 5 (as of 2026-07-19; a reference ranking aggregated from published values. Source: chart by Qualiteg based on BenchLM.ai)</span></figcaption></figure><p>That said, BenchLM is not an evaluation body that runs every model itself under identical conditions; it is a service that aggregates multiple published scores.</p><p>Because the available benchmarks and evaluation conditions differ from model to model, &quot;4th overall&quot; is best treated as a <strong>reference value</strong> for getting a sense of direction.</p><h3 id="highlights-from-moonshots-official-evaluations">Highlights from Moonshot&apos;s Official Evaluations</h3><p>Among Moonshot&apos;s official numbers, the agentic web-browsing benchmark <strong>BrowseComp comes in at 91.2</strong>.</p><p>That figure is under the company&apos;s evaluation setup, which applies context compression upon reaching 300K tokens; without compression it is explicitly stated as 90.4.</p><p>External aggregations, moreover, place it just behind GPT-5.6 Sol (92.2), so it is not an unconditional &quot;SOTA.&quot;</p><p>Meanwhile, independent evaluations by Arena.AI and Artificial Analysis are already underway via the API. At this stage, the accurate framing is: &quot;<strong>the externally observable performance has some corroboration, but the model&apos;s internal specifications and the reproduction conditions of the official benchmarks cannot yet be verified</strong>.&quot;</p><h2 id="part-4-api-pricing-%E2%80%94-cheaper-than-the-closed-top-tier-but-a-big-hike-within-the-kimi-line">Part 4: API Pricing &#x2014; Cheaper Than the Closed Top Tier, but a Big Hike Within the Kimi Line</h2><p>The API pricing is primary information confirmed on the official pricing page.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://journal.qualiteg.com/content/images/2026/07/chart4_pricing.png" class="kg-image" alt="Kimi K3 Deep Dive &#x2014; 2.8T Parameters: Will the &quot;Largest Open Weights in History&quot; Materialize?" loading="lazy" width="2000" height="945" srcset="https://journal.qualiteg.com/content/images/size/w600/2026/07/chart4_pricing.png 600w, https://journal.qualiteg.com/content/images/size/w1000/2026/07/chart4_pricing.png 1000w, https://journal.qualiteg.com/content/images/size/w1600/2026/07/chart4_pricing.png 1600w, https://journal.qualiteg.com/content/images/2026/07/chart4_pricing.png 2200w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">The Kimi API pricing lineup (Source: chart by Qualiteg based on the Moonshot AI official pricing page as of 2026-07-19)</span></figcaption></figure><ul><li><strong>Kimi K3</strong>: $3.00 input / $15.00 output (per million tokens), <strong>with cache-hit input at $0.30</strong></li><li><strong>K2.7 Code</strong> (coding-focused) / <strong>K2.6</strong> (general-purpose): $0.95 input / $4.00 output each</li><li>No surcharge for long context. You can use the OpenAI SDK, and calling it is just a matter of swapping the <code>base_url</code>, API key, and model name</li></ul><p>English-language coverage has described this as &quot;Claude Sonnet-class pricing.&quot;</p><p>Indeed, K3&apos;s $3/$15 matches Claude Sonnet 5&apos;s standard pricing effective September 1, 2026 (though Sonnet 5 is offered at an introductory $2/$10 through August 31, so as of July 20, K3 works out 50% more expensive on both input and output).</p><p>Within the Kimi lineup, it is a substantial hike from K2.6&apos;s $0.95/$4, and Simon Willison likewise notes that Moonshot has &quot;stepped into a higher price tier for a Chinese AI lab.&quot;</p><p>Moonshot also claims that its distributed inference architecture called Mooncake achieves &quot;a 90%+ cache hit rate on coding workloads&quot;; if that is close to reality, effective costs for agentic use would come down considerably (this figure, too, is a vendor claim).</p><h2 id="part-5-open-weights-is-still-only-a-promise">Part 5: &quot;Open Weights&quot; Is Still Only a Promise</h2><p>This is the single most important point in this article.</p><p><strong>As of July 20, 2026, Kimi K3 is not an &quot;open-weight model&quot; but a &quot;model that is scheduled to become open-weight.&quot;</strong></p><p>Checking Moonshot&apos;s official GitHub organization, there is still no model repository for Kimi K3, and the pinned model repository remains Kimi-K2.5. There is no model card on Hugging Face either.</p><p>On quantization, the official tech blog explicitly specifies <strong>MXFP4 weights / MXFP8 activations</strong>, which counts as primary information; whether the files distributed on Hugging Face will be MXFP4 as-is, however, is <strong>unconfirmed</strong> since the model card has not been published.</p><p>The technical report is likewise &quot;to be released in the future.&quot;</p><p>There is one more practically important caveat: <br><strong><u>&quot;the weights being released&quot; and &quot;being able to run it yourself&quot; are separate problems</u></strong>.</p><p>Moonshot recommends super-node configurations with 64 or more accelerators as the deployment target for K3.</p><p>Even quantized, this is a 2.8-trillion-parameter-class model; self-hosting the full model is out of reach not just at home but probably in office environments too. For the time being, think of it as something for specialized data centers and large-scale inference providers.</p><p>Multiple reports put the license at &quot;Modified MIT,&quot; but with no model card in existence, it cannot be confirmed against a primary source (<strong>unconfirmed</strong>).</p><p>If released as scheduled, it would overtake DeepSeek v4 Pro (1.6 trillion parameters) to become <strong>the largest open-weight model in history</strong>.</p><h2 id="part-6-agentic-capabilities-%E2%80%94-k3s-main-battleground">Part 6: Agentic Capabilities &#x2014; K3&apos;s Main Battleground</h2><p>What Moonshot pitches hardest for K3 is agentic use.</p><ul><li>BrowseComp (agentic web browsing): 91.2 (under Moonshot&apos;s evaluation conditions; external aggregations place it just behind GPT-5.6 Sol)</li><li>2nd place on AA-Briefcase (Artificial Analysis&apos;s agentic evaluation)</li><li>Beats Opus 4.8 and GPT-5.5 on the GDPval-AA v2 agentic Elo</li><li><strong>Kimi Code</strong> &#x2014; offered as its coding-agent product line</li><li>The API supports tool calling, and migrating from the OpenAI SDK is easy</li></ul><p>In Kimi Code, a new plan structure &#x2014; Starter / Explorer / Expert / Master &#x2014; was introduced on July 20. K3 itself is available on all plans, and <strong>the 1M context requires Explorer or above</strong> (existing Moderato / Allegretto subscribers keep the terms of their old plans).</p><h3 id="caveats-for-production-adoption">Caveats for Production Adoption</h3><p>There are also constraints that the official documentation and blog themselves acknowledge.</p><ul><li><strong>Full re-sending of thinking history is required</strong> <br> Unless you return assistant messages verbatim &#x2014; including the thinking from past turns &#x2014; quality can become unstable<br></li><li><strong>Excessive autonomous judgment</strong><br> The official docs explicitly note that, given ambiguous instructions, it may make unexpected decisions on the user&apos;s behalf<br></li><li>Sampling settings are fixed, and the web-search feature is not recommended for production use for the time being</li></ul><p></p><h2 id="part-7-whats-new-since-the-k2-generation">Part 7: What&apos;s New Since the K2 Generation</h2><p>The changes from the previous generation sum up as follows.</p><ol><li><strong>A leap in scale</strong><br> &#x2014; a massive expansion to 2.8 trillion total parameters from the previous flagship K2/K2.5 on GitHub<br></li><li><strong>Homegrown new mechanisms</strong><br> &#x2014; introduces KDA and AttnRes, with an extremely sparse Stable LatentMoE design at roughly 1.8% activation<br></li><li><strong>A jump in capability</strong> <br>From K2.6&apos;s 18th place to 1st place with K3 in the Frontend Code Arena<br></li><li><strong>Native vision</strong><br> &#x2014; image and video understanding as standard<br></li><li><strong>Always-on thinking mode</strong><br></li><li><strong>Product-line reorganization</strong><br> &#x2014; a three-tier structure: K3 (flagship) / K2.7 Code (coding-focused) / K2.6 (general-purpose budget tier)</li></ol><p>Comparisons with K2.6 are partly verifiable through the Arena.AI and Artificial Analysis evaluations (18th place &#x2192; 1st in the Frontend Code Arena, 33% &#x2192; 46% accuracy on AA-Omniscience, and so on). However, cross-generation comparisons under identical conditions &#x2014; including K2 and K2.5 &#x2014; remain limited, and details including the architecture and training methods await the technical report.</p><h2 id="part-8-what-we-still-dont-know">Part 8: What We Still Don&apos;t Know</h2><p>Let&apos;s also organize what remains unannounced or unconfirmed at this point.</p><ul><li><strong>Training data scale, training token count, and training methods</strong> (pre-training corpus, RL/post-training setup) &#x2192; undisclosed in both primary and secondary sources</li><li><strong>Active parameter count</strong> &#x2192; &quot;~50B (A50B)&quot; is an analyst&apos;s notation, not officially disclosed</li><li><strong>Technical report / paper</strong> &#x2192; unpublished (only an official statement that one is forthcoming)</li><li><strong>Hugging Face model card and distribution file format</strong> &#x2192; nonexistent (weights unreleased)</li><li><strong>Exact license terms</strong>: &quot;Modified MIT&quot; is mentioned only at the level of press reports</li></ul><p>Once the July 27 weight-release deadline passes, check three things: (1) whether the weights were actually released, (2) whether the evaluation conditions behind the official scores are disclosed in enough detail in the technical report to allow retesting under equivalent conditions, and (3) the license terms. We plan to cover any follow-up news in detail on this blog.</p><h2 id="conclusion">Conclusion</h2><p>To sum up Kimi K3 in one line: <br><br>&#x300C;<strong>an ultra-large-scale, &quot;open-weights-to-be&quot; MoE that falls one step short of the frontier&apos;s very top (Claude Fable 5 / GPT-5.6 Sol) overall, yet is positioned to aim at or above the Opus 4.8 / GPT-5.5 class in coding and agentic work</strong>&#x300D;<br><br>.</p><p>The independent result of first place in the blind-voted Frontend Code Arena carries real weight as corroboration of its ability; on the other hand, for the model&apos;s internal specifications and the reproduction conditions of the official benchmarks, we must wait for the weight release scheduled by July 27 and the technical report to come. Whether the &quot;largest open weights in history&quot; billing becomes real &#x2014; the answer starts arriving in about a week.</p><p>In our May article &quot;<a href="https://journal.qualiteg.com/mythos-level-open-source-llm-timing/" rel="noreferrer">When Will a Mythos-Level Open Model Arrive?</a>,&quot; we predicted when open models would catch up to the frontier based on the slope of benchmark trends.</p><p>If K3 releases its weights as planned, &quot;the weights of a model in the same league as Opus 4.8 on Artificial Analysis&apos;s overall index&quot; will be obtainable in the summer of 2026 &#x2014; meaning the trend we sketched in that article is running along the upper edge of our projected band.</p><p>However, for the cybersecurity capabilities that were the centerpiece of that article (CyberGym and the AISI real-environment tests), no evaluation data for K3 exists yet. The reckoning with our line that &quot;capability attainment and the decision to release are separate problems&quot; will have to wait for independent evaluations after the weights are out &#x2014; and we intend to revisit it then.</p><h2 id="coming-up-next">Coming Up Next</h2><p>Next time, we plan to cover Qwen&apos;s <a href="https://x.com/Alibaba_Qwen/status/2078759124914098291?ref=journal.qualiteg.com" rel="noreferrer">officially announced</a> next flagship, <strong>Qwen3.8</strong>. With 2.4 trillion total parameters and an open-weight release planned, it is another ultra-large open-series model standing right alongside Kimi K3. Just as with Kimi K3, we&apos;ll dig in with thorough, primary-source-based research &#x2014; stay tuned.</p><p>See you next time!</p><hr><h3 id="references-primary-and-key-sources">References (Primary and Key Sources)</h3><ul><li><a href="https://www.kimi.com/blog/kimi-k3?ref=journal.qualiteg.com" rel="noreferrer">Moonshot AI official blog: Kimi K3 Tech Blog</a></li><li><a href="https://platform.kimi.ai/docs/guide/kimi-k3-quickstart?ref=journal.qualiteg.com" rel="noreferrer">Kimi API official documentation: K3 Quickstart</a></li><li><a href="https://platform.kimi.ai/docs/pricing/chat-k3?ref=journal.qualiteg.com" rel="noreferrer">Kimi API official pricing page</a></li><li><a href="https://www.kimi.com/code/docs/en/kimi-code/whats-new.html?ref=journal.qualiteg.com" rel="noreferrer">Kimi Code What&apos;s New (new plan structure)</a></li><li><a href="https://github.com/moonshotai?ref=journal.qualiteg.com" rel="noreferrer">Moonshot AI official GitHub</a></li><li><a href="https://x.com/Kimi_Moonshot?ref=journal.qualiteg.com" rel="noreferrer">Moonshot AI official X (source of the KDA / AttnRes efficiency figures)</a></li><li><a href="https://artificialanalysis.ai/articles/kimi-k3-achieves-3-in-the-artificial-analysis-intelligence-index-comparable-to-opus-4-8-and-gpt-5-5?ref=journal.qualiteg.com" rel="noreferrer">Artificial Analysis: Kimi K3 analysis (Intelligence Index / GDPval-AA v2 / AA-Briefcase / AA-Omniscience)</a></li><li><a href="https://simonwillison.net/2026/Jul/16/kimi-k3/?ref=journal.qualiteg.com" rel="noreferrer">Simon Willison: Kimi K3 hands-on</a></li><li><a href="https://www.tomshardware.com/tech-industry/artificial-intelligence/moonshot-releases-2-8-trillion-parameter-kimi-k3?ref=journal.qualiteg.com" rel="noreferrer">Tom&apos;s Hardware: Moonshot releases 2.8-trillion-parameter Kimi K3</a></li><li><a href="https://venturebeat.com/technology/chinas-moonshot-ai-releases-kimi-k3-the-largest-open-source-model-ever-rivaling-top-u-s-systems?ref=journal.qualiteg.com" rel="noreferrer">VentureBeat: China&apos;s Moonshot AI releases Kimi K3</a></li><li><a href="https://x.com/arena/status/2077824029126504525?ref=journal.qualiteg.com" rel="noreferrer">Arena.AI official X: Frontend Code Arena results</a></li><li><a href="https://openrouter.ai/moonshotai/kimi-k3?ref=journal.qualiteg.com" rel="noreferrer">OpenRouter: moonshotai/kimi-k3</a></li><li><a href="https://www.latent.space/p/ainews-kimi-k3-28t-a50b-the-largest?ref=journal.qualiteg.com" rel="noreferrer">Latent.Space: Kimi K3 analysis</a></li><li><a href="https://benchlm.ai/models/kimi-3?ref=journal.qualiteg.com" rel="noreferrer">BenchLM.ai: Kimi K3</a></li><li><a href="https://x.com/Alibaba_Qwen/status/2078759124914098291?ref=journal.qualiteg.com" rel="noreferrer">Alibaba Qwen official X: Qwen3.8 announcement (source for the preview above)</a></li><li><a href="https://www.bloomberg.com/news/articles/2026-07-19/alibaba-s-qwen-unveils-preview-of-flagship-ai-model?ref=journal.qualiteg.com" rel="noreferrer">Bloomberg: Alibaba&apos;s Qwen unveils preview of flagship AI model</a></li></ul><p>* This article is based on research as of July 20, 2026. All charts were drawn by Qualiteg from published figures and are not reproductions of official charts.</p>]]></content:encoded></item><item><title><![CDATA[The Essence of PII De-identification — You May Fake the "Who," Never the "What Happened"]]></title><description><![CDATA[<p>Hello! This is the Qualiteg Product Development Team!</p><p>Today we would like to discuss the de-identification of PII (Personally Identifiable Information).</p><p>To date, we have published technical explainers on personal-information detection and AI security, including <a href="https://journal.qualiteg.com/llm-audit-pii-detection-technology-part1/" rel="noreferrer">high-accuracy PII detection</a>, <a href="https://journal.qualiteg.com/llm-audit-pii-detection-technology-part2/" rel="noreferrer">staged PII masking when using LLMs</a>&#x3001;<a href="https://journal.qualiteg.com/pii-detection-cross-recognizer-collision-and-test-design/" rel="noreferrer">test design for PII detection</a></p>]]></description><link>https://journal.qualiteg.com/pii-deidentification-design-principles/</link><guid isPermaLink="false">6a54f72eedf69a17d422a88f</guid><category><![CDATA[PII-FI]]></category><category><![CDATA[AI Security]]></category><dc:creator><![CDATA[Qualiteg Product Development Team]]></dc:creator><pubDate>Fri, 17 Jul 2026 05:53:35 GMT</pubDate><media:content url="https://journal.qualiteg.com/content/images/2026/07/pii-deidentification-design-principles-v2.png" medium="image"/><content:encoded><![CDATA[<img src="https://journal.qualiteg.com/content/images/2026/07/pii-deidentification-design-principles-v2.png" alt="The Essence of PII De-identification &#x2014; You May Fake the &quot;Who,&quot; Never the &quot;What Happened&quot;"><p>Hello! This is the Qualiteg Product Development Team!</p><p>Today we would like to discuss the de-identification of PII (Personally Identifiable Information).</p><p>To date, we have published technical explainers on personal-information detection and AI security, including <a href="https://journal.qualiteg.com/llm-audit-pii-detection-technology-part1/" rel="noreferrer">high-accuracy PII detection</a>, <a href="https://journal.qualiteg.com/llm-audit-pii-detection-technology-part2/" rel="noreferrer">staged PII masking when using LLMs</a>&#x3001;<a href="https://journal.qualiteg.com/pii-detection-cross-recognizer-collision-and-test-design/" rel="noreferrer">test design for PII detection</a>, and more.</p><p>Today, we develop and offer our PII detection and masking technology, the &quot;PII-FI Engine,&quot; along with &quot;<a href="https://pii-fi.com/?ref=journal.qualiteg.com" rel="noreferrer">PII-FI Scan&#x300D;&#x300C;PII-FI API</a>,&quot; a PII masking and de-identification service built on it.</p><p>In this article, we take up the design principles behind <strong>&quot;once PII has been detected, how should it be rewritten?&quot;</strong> &#x2014; using a single example sentence as a touchstone, we present the framework we have actually adopted in our products.</p><p>One caveat up front: what we call &quot;<strong>de-identification (</strong>de-identification<strong>)</strong>&quot; in this article refers to technical processing that makes documents and logs safe to share and analyze (processing data so that individuals can no longer be identified).</p><p>It is not a guarantee that the result qualifies as &quot;pseudonymized information&quot; or &quot;anonymized information&quot; under Japan&apos;s Act on the Protection of Personal Information (we touch on the relationship with these legal terms later in the article).</p><h2 id="what-is-de-identification-for">What Is De-identification For?</h2><p>Let us start from first principles.</p><p>If you can use your logs and documents &quot;as they are,&quot; you do not need de-identification.</p><p>If the original is in your hands and you are the only one who will see it, there is no reason to process it.</p><p>The need for de-identification arises at <br><br><strong>&quot;we want to hand this data to someone so the work can proceed, but we cannot hand it over raw&quot;<br><br> &#x2014; precisely that moment</strong>.<br><br>For example:</p><ul><li>You want to outsource an analysis task, but customer information is mixed in</li><li>You want to feed operational logs into an LLM for incident analysis</li><li>You want to send a full set of logs to a security vendor for analysis</li><li>You want to review files containing PII before sending them to another company</li><li>You want AI to organize medical-record information, but need to mask PII before it goes into the AI</li></ul><p></p><p>Data is a mixture of &quot;<strong>what happened</strong>&quot; and &quot;<strong>who it is about</strong>.&quot;</p><p>It is the former that creates value in analysis and sharing.</p><p>It is the latter that can lead to harm for the individual (impersonation, discrimination, reputational damage, and so on).</p><p>In other words, de-identification is the technique of <br><br><strong>keeping the &quot;events&quot; while severing the &quot;who&quot;</strong><br><br>.</p><p>And it is not only the individuals appearing in the data who are protected.</p><p>The provider is protected from liability for leaks, and the recipient reduces both the risk and the management burden of holding &quot;information that is a liability merely to possess.&quot;</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://journal.qualiteg.com/content/images/2026/07/chart1_naze_v2.png" class="kg-image" alt="The Essence of PII De-identification &#x2014; You May Fake the &quot;Who,&quot; Never the &quot;What Happened&quot;" loading="lazy" width="2000" height="1148" srcset="https://journal.qualiteg.com/content/images/size/w600/2026/07/chart1_naze_v2.png 600w, https://journal.qualiteg.com/content/images/size/w1000/2026/07/chart1_naze_v2.png 1000w, https://journal.qualiteg.com/content/images/size/w1600/2026/07/chart1_naze_v2.png 1600w, https://journal.qualiteg.com/content/images/2026/07/chart1_naze_v2.png 2300w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">The essence of de-identification: separating the &quot;events&quot; that create value from the &quot;who&quot; that can harm the individual (Diagram: Qualiteg)</span></figcaption></figure><h2 id="the-touchstone-%E3%80%8C%E7%94%B2%E9%87%8E%E5%A4%AA%E9%83%8E%E3%81%AF%E9%AB%98%E8%A1%80%E5%9C%A7%E3%81%A7%E3%81%99%E3%80%8D-kono-taro-has-hypertension">The Touchstone: &#x300C;&#x7532;&#x91CE;&#x592A;&#x90CE;&#x306F;&#x9AD8;&#x8840;&#x5727;&#x3067;&#x3059;&#x300D; (&quot;Kono Taro has hypertension&quot;)</h2><p>Now for the main topic. Consider de-identifying the following sentence.</p><p><strong>&#x300C;&#x7532;&#x91CE;&#x592A;&#x90CE;&#x306F;&#x9AD8;&#x8840;&#x5727;&#x3067;&#x3059;&#x300D; &#x2014; &quot;Kono Taro has hypertension.&quot;</strong></p><p>There is more than one way to process it.</p><p>Let us compare three representative patterns.</p><h3 id="pattern-1-replace-only-the-name-with-a-pseudonym">Pattern 1: Replace Only the Name with a Pseudonym</h3><blockquote><strong>&#x4E59;&#x5C71;&#x6B21;&#x90CE;</strong>&#x306F;&#x9AD8;&#x8840;&#x5727;&#x3067;&#x3059; (&quot;Otsuyama Jiro has hypertension&quot;)</blockquote><p>The link between &#x7532;&#x91CE;&#x592A;&#x90CE; (Kono Taro) and hypertension has been severed.<br>The reader receives only the event that &quot;someone has hypertension.&quot; And this event is <strong>still true, and still usable</strong>. For a reader examining the case details or the appropriateness of the response, this sentence continues to function as working material.</p><p>This is the basic form of de-identification. Note, however, that what succeeded here is only &quot;severing the link within this one sentence.&quot; In real documents, the surrounding context can still suggest who the person is even after the name is changed &#x2014; a limitation we confront head-on in Pitfall 3.</p><h3 id="pattern-2-fake-the-disease-name-too">Pattern 2: Fake the Disease Name Too</h3><blockquote>&#x4E59;&#x5C71;&#x6B21;&#x90CE;&#x306F;<strong>&#x82B1;&#x7C89;&#x75C7;</strong>&#x3067;&#x3059; (&quot;Otsuyama Jiro has hay fever&quot;)</blockquote><p>At first glance this looks even safer.</p><p>But this processing has a serious problem.</p><p><strong>The reader has <u>no way to tell that &quot;&#x82B1;&#x7C89;&#x75C7; (hay fever)&quot; is fake</u></strong>&#x3002;</p><p>Whoever tallies the cases, and whoever evaluates the appropriateness of the response, <br><strong>ends up doing their work on top of a falsehood</strong>&#x3002;</p><p>&quot;Hiding&quot; is a fail-safe operation: information only decreases, and no lies are added.</p><p>&quot;Substituting another plausible-looking value,&quot; by contrast, is <strong>an injection of falsehood</strong>. One might fairly call it poisoning the data.</p><h3 id="pattern-3-redact-everything">Pattern 3: Redact Everything</h3><blockquote>&#x25A0;&#x25A0;&#x25A0;&#x25A0;&#x306F;&#x25A0;&#x25A0;&#x25A0;&#x3067;&#x3059; (&quot;&#x25A0;&#x25A0;&#x25A0;&#x25A0; has &#x25A0;&#x25A0;&#x25A0;&quot;)</blockquote><p>Yes, this is safe.</p><p>But the sentence now carries zero information &#x2014; &quot;someone is something&quot; &#x2014; and as data it is dead. There is no longer any point in handing it over at all.</p><h2 id="the-principle-there-are-two-kinds-of-words">The Principle: There Are Two Kinds of Words</h2><p>This comparison can be distilled into the following principle.</p><blockquote><strong>There are two kinds of words.<br><br>Words that point to &quot;who&quot; (identifiers)</strong> &#x2014; names, employee numbers, phone numbers, email addresses. These may be replaced with natural-looking fakes. The reader does not consume their truthfulness; the only thing that needs to be severed is the &quot;link.&quot;<br><br><strong>Words that tell &quot;what happened&quot; (attributes)</strong> &#x2014; disease names, monetary amounts, performance reviews, events. For these there are <strong>only two choices: keep them, or honestly redact them</strong>. They must never be faked, because the reader&apos;s work depends on their being true.</blockquote><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://journal.qualiteg.com/content/images/2026/07/chart2_flow_v2.png" class="kg-image" alt="The Essence of PII De-identification &#x2014; You May Fake the &quot;Who,&quot; Never the &quot;What Happened&quot;" loading="lazy" width="2000" height="1287" srcset="https://journal.qualiteg.com/content/images/size/w600/2026/07/chart2_flow_v2.png 600w, https://journal.qualiteg.com/content/images/size/w1000/2026/07/chart2_flow_v2.png 1000w, https://journal.qualiteg.com/content/images/size/w1600/2026/07/chart2_flow_v2.png 1600w, https://journal.qualiteg.com/content/images/2026/07/chart2_flow_v2.png 2300w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">May this word be faked? &#x2014; the decision flow (Diagram: Qualiteg)</span></figcaption></figure><p>In reality, of course, words do not split cleanly into these two categories.<br><br>&quot;Head of Accounting&quot; is an attribute &#x2014; and at the same time, within the organization, a clue that points to a specific person.</p><p>Ages and dates, when combined, also edge closer to a &quot;who&quot; (these are called <strong>quasi-identifiers</strong>). This is precisely why the yardstick for the decision is not the word&apos;s type but its role.</p><p>It is also why the question in the flow above is not &quot;is this word a name?&quot; but &quot;will the reader use the truth of this value to do their work?&quot;</p><p>Rather than deciding the method mechanically from the detected type alone, we decide it by combining the role the word plays within the document with the recipient&apos;s intended use.</p><p>&quot;Honestly redacting&quot; means replacing the value with a label such as <code>[Disease 1]</code>.</p><p>The point is to number the labels sequentially: the same disease name always receives the same number (we call this <strong>coreference preservation</strong>).</p><p>That way, the fact that &quot;this document discusses two different diseases&quot; &#x2014; <strong>the structure the analysis needs &#x2014; is preserved</strong>, while the reader is honestly told that &quot;this part has been redacted.&quot;</p><p>There is also a middle path between the two choices: &quot;<strong>generalization</strong>.&quot; As in &quot;age 47 &#x2192; 40s&quot; or &quot;full street address &#x2192; city level only,&quot; it is a way of <strong>keeping the truth while lowering only its resolution</strong>.</p><p>Because it injects no falsehood and reduces only the identification risk, it is an honest middle option usable for both identifiers and attributes.</p><p>Putting all of this together, the de-identification methods can be organized as follows.</p>
<!--kg-card-begin: html-->
<table style="border-collapse:collapse;width:100%;font-size:0.95em;"><thead><tr><th style="padding:8px 12px;border:1px solid #d8d3cb;vertical-align:top;background:#f3f0ea;font-weight:bold;text-align:left;">Method</th><th style="padding:8px 12px;border:1px solid #d8d3cb;vertical-align:top;background:#f3f0ea;font-weight:bold;text-align:left;">Example</th><th style="padding:8px 12px;border:1px solid #d8d3cb;vertical-align:top;background:#f3f0ea;font-weight:bold;text-align:left;">When it may be used</th></tr></thead><tbody><tr><td style="padding:8px 12px;border:1px solid #d8d3cb;vertical-align:top;"><b>Dummy (pseudonym)</b></td><td style="padding:8px 12px;border:1px solid #d8d3cb;vertical-align:top;">&#x7532;&#x91CE;&#x592A;&#x90CE; &#x2192; &#x4E59;&#x5C71;&#x6B21;&#x90CE;</td><td style="padding:8px 12px;border:1px solid #d8d3cb;vertical-align:top;"><b>Identifiers only</b>. Coreference preservation protects the document structure</td></tr><tr><td style="padding:8px 12px;border:1px solid #d8d3cb;vertical-align:top;"><b>Label replacement</b></td><td style="padding:8px 12px;border:1px solid #d8d3cb;vertical-align:top;">&#x9AD8;&#x8840;&#x5727; (hypertension) &#x2192; [Disease 1]</td><td style="padding:8px 12px;border:1px solid #d8d3cb;vertical-align:top;">When an attribute must be hidden. Honest, and the structure survives</td></tr><tr><td style="padding:8px 12px;border:1px solid #d8d3cb;vertical-align:top;"><b>Generalization</b></td><td style="padding:8px 12px;border:1px solid #d8d3cb;vertical-align:top;">Age 47 &#x2192; 40s</td><td style="padding:8px 12px;border:1px solid #d8d3cb;vertical-align:top;">When you want to keep the truth but lower its resolution</td></tr><tr><td style="padding:8px 12px;border:1px solid #d8d3cb;vertical-align:top;"><b>Redaction</b></td><td style="padding:8px 12px;border:1px solid #d8d3cb;vertical-align:top;">P@ssw0rd &#x2192; &#xFF0A;&#xFF0A;&#xFF0A;&#xFF0A;</td><td style="padding:8px 12px;border:1px solid #d8d3cb;vertical-align:top;">Credentials and other values whose very existence should be hidden</td></tr><tr><td style="padding:8px 12px;border:1px solid #d8d3cb;vertical-align:top;"><b>As-is</b></td><td style="padding:8px 12px;border:1px solid #d8d3cb;vertical-align:top;">&#x2014;</td><td style="padding:8px 12px;border:1px solid #d8d3cb;vertical-align:top;">Information the recipient needs for their work and that does not lead to identification</td></tr></tbody></table>
<!--kg-card-end: html-->
<p>One note of caution here.</p><p>Credentials such as passwords and API keys &#x2014; the last rows of the table &#x2014; should be treated as &quot;<strong>secrets</strong>,&quot; regardless of whether they qualify as PII.</p><p>On the shared file they are redacted, but if there is any possibility they have leaked externally, redaction is not the end of the story: revocation and rotation &#x2014; that is, <strong>incident response</strong> &#x2014; are separately required.</p><p>Conversely, <br><br><strong>applying dummies to attributes (substituting one disease name for another, for example) is, as a rule, prohibited</strong><br><br>.</p><p>If there is ever a situation that calls for realistic fake data, it is one where the recipient does not rely on the factuality of the original &#x2014; parser testing, demos, load testing, and the like.</p><p>We do not call that de-identification; we treat it as a separate job called &quot;synthetic data generation.&quot;</p><p>In the standards world, synthetic data generation is indeed counted among de-identification techniques (NIST SP 800-188), but <br><br><strong>&quot;masking that preserves meaning for handover&quot; and &quot;the job of crafting plausible fakes&quot; should never be mixed into the same process</strong></p><p> &#x2014; that is the design decision we have adopted.</p><p>Note also that for anonymizing statistical databases there are standard techniques that deliberately alter attribute values, such as noise addition (adding random error to numeric values) (ISO/IEC 20889); these are positioned as tools for hiding each record&apos;s true value while preserving statistical properties in aggregate.<br>Bringing them into the domain this article addresses &#x2014; documents and logs read directly by people and tools &#x2014; causes the same problem as the injection of falsehood described above.</p><h2 id="four-pitfalls-that-are-easy-to-step-into-in-practice">Four Pitfalls That Are Easy to Step Into in Practice</h2><p>Now let us look at the points to watch when actually designing PII processing.</p><p>Here are four challenges you will genuinely encounter when implementing a PII-processing application.</p><h3 id="1-across-files-the-same-person-becomes-different-people">1. Across Files, the Same Person Becomes Different People</h3><p>De-identify indiscriminately and you can end up converting one person into several different people. The same person should remain traceable as the same person after de-identification. This is what we call coreference preservation.</p><p>Consider, for example, de-identifying person names that appear across multiple logs.</p><p>If coreference preservation is applied only &quot;within a single file,&quot; then when a set of logs is processed, file A may map &#x7532;&#x91CE; (Kono) &#x2192; &#x4E59;&#x5C71; (Otsuyama) while file B maps &#x7532;&#x91CE; &#x2192; &#x4E19;&#x5DDD; (Heikawa).</p><p>That breaks any analysis that follows the actors&apos; movements across multiple logs.</p><p>To deal with this class of problem, you need </p><p><strong>coreference preservation at the level of the whole set (the job)</strong></p><p>.</p><p>There is a flip side, however.</p><p>The wider the coreference scope, the more the &quot;appearance pattern of the same pseudonym = the original person&apos;s behavior pattern&quot; survives &#x2014; which also means more clues for identification. For that reason, we believe the scope of consistency should be selectable to match the use case.</p><p>This point applies not only to person pseudonyms but equally to the numbering of labels such as [Disease 1].</p><h3 id="2-a-pseudonym-collides-with-a-real-person">2. A Pseudonym Collides with a Real Person</h3><p>If the generated pseudonym &quot;&#x4E59;&#x5C71;&#x6B21;&#x90CE; (Otsuyama Jiro)&quot; happens to match a real Mr. Otsuyama who already appears in the document, the analysis is not merely confused &#x2014; you risk pinning a false accusation on that real person.</p><p>This challenge requires a mechanism to </p><p><strong>exclude values that actually appear in the document from the pool of dummy candidates</strong><br><br>.</p><p>Natural person names, however, can never be guaranteed &quot;not to exist.&quot; For recipients who cannot accept the risk of misattribution, choose a label such as [Person 1] instead of a pseudonym &#x2014; this, too, is a &quot;destination&quot; decision, discussed below.</p><p>For machine-formatted values, moreover, the standard move is to <strong>generate &quot;values that cannot exist&quot;</strong>.</p><p>Use reserved domains for dummy email addresses (example.com), documentation-reserved test ranges for IP addresses (such as 192.0.2.0/24), and check-digit-invalid values for various ID numbers &#x2014; then even an accidental contact or lookup reaches no one.</p><h3 id="3-de-identification-cannot-erase-everyone-knows-who-that-is">3. De-identification Cannot Erase &quot;Everyone Knows Who That Is&quot;</h3><p>Even with every name and number removed, the context alone &#x2014; &quot;the head of Accounting received a disciplinary action on July 3&quot; &#x2014; tells people inside the company exactly who it is. This frequently happens when de-identifying PII contained in email.</p><p><strong>De-identification is not magic; it is a technique for reducing identification risk</strong>.</p><p>In that sense, the assumption that &quot;processed = perfectly safe&quot; may be the biggest pitfall of all.</p><p>Note that &quot;pseudonymized information&quot; and &quot;anonymized information&quot; are legal terms, with definitions and requirements under Japan&apos;s Act on the Protection of Personal Information.</p><p>For referring to technical processing, we consider it safer to use the terms &quot;de-identification&quot; and &quot;masking,&quot; as this article does.</p><h3 id="4-a-processed-file-is-an-altered-document">4. A Processed File Is an &quot;Altered Document&quot;</h3><p>Deliverables from incident response can later become material for audits or legal proceedings.</p><p>Since a de-identified file is not the original, <br><br><strong>a processing record documenting &quot;when, under what rules, what was processed and in how many instances,&quot; together with a hash of the original,</strong><br><br> should accompany the deliverable, so that its relationship to the original can be demonstrated to third parties. The record is not a mere disclaimer; it is an audit document that guarantees the transparency of the alterations.</p><h2 id="the-right-answer-is-decided-by-the-destination-not-the-type">The Right Answer Is Decided by the &quot;Destination,&quot; Not the &quot;Type&quot;</h2><p>Let us move on to the next point:</p><p>what to prioritize in PII processing.</p><p><strong>Naturalness (analysis tools keep working), safety, and honesty (fakes are recognizable as fakes)</strong> &#x2014; these three cannot all be maximized at once.</p><p>Which one to prioritize is determined by <strong>where the data is going</strong>.</p><ul><li><strong>Deliverables read by people</strong> &#x2192; prioritize honesty. Label replacement at the core, plus a processing record</li><li><strong>Logs analyzed by tools</strong> &#x2192; prioritize preserving formats and digit counts. Dummies built from values that cannot exist</li><li><strong>Data fed into LLMs</strong> &#x2192; prioritize naturalness. Dummies at the core (some designs pair this with restoration applied to the LLM&apos;s responses)</li></ul><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://journal.qualiteg.com/content/images/2026/07/chart3_matrix_v2.png" class="kg-image" alt="The Essence of PII De-identification &#x2014; You May Fake the &quot;Who,&quot; Never the &quot;What Happened&quot;" loading="lazy" width="2000" height="1183" srcset="https://journal.qualiteg.com/content/images/size/w600/2026/07/chart3_matrix_v2.png 600w, https://journal.qualiteg.com/content/images/size/w1000/2026/07/chart3_matrix_v2.png 1000w, https://journal.qualiteg.com/content/images/size/w1600/2026/07/chart3_matrix_v2.png 1600w, https://journal.qualiteg.com/content/images/2026/07/chart3_matrix_v2.png 2300w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Suitability map of the five methods &#x2014; the three properties cannot all be maximized at once (Diagram: Qualiteg)</span></figcaption></figure><p>Incidentally, the LLM case is not complete with input-side substitution alone.</p><p>The substitution mapping table is never sent to the LLM; it is managed inside your own trust boundary.</p><p>Restoration is limited to managed tokens, never free-text string matching.</p><p>And because an LLM&apos;s responses can contain PII that was not present in the input, the output side must be run through PII inspection again. All of this together forms one complete set.</p><p>In other words, <u>a de-identification configuration is </u>not &quot;a preference per data type&quot; but <br><strong><u>a declaration of &quot;to whom, and for what purpose, this data is being handed&quot;</u></strong><br>.</p><p>In our <a href="https://pii-fi.com/?ref=journal.qualiteg.com" rel="noreferrer">PII-FI</a>, we design this declaration as a per-destination &quot;<strong>profile</strong>.&quot;</p><h2 id="conclusion">Conclusion</h2><p>In this article we have laid out our thinking on what de-identification essentially is, illustrating the design challenges of PII processing along the way.</p><p>To close, let us restate the key points.</p><ul><li>De-identification is a technology for &quot;handing data over&quot;: <strong>keep the &quot;events,&quot; sever the &quot;who&quot;</strong></li><li>There are two kinds of words: <strong>identifiers may be pseudonymized; attributes offer three options &#x2014; keep, honestly redact, or generalize &#x2014; and must never be faked</strong></li><li>Injecting fake data into attributes is an &quot;injection of falsehood&quot;; the only place it belongs is the separate job of synthetic data generation</li><li>In practice, watch four things: cross-file coreference preservation, pseudonym collisions with real people, residual identification risk, and the processing record</li><li>The final answer is determined not by the word&apos;s type but by <strong>&quot;to whom, and for what purpose, the data is handed&quot;</strong>.</li></ul><p>We hope this article has been of some use in thinking through PII processing.</p><p>At Qualiteg, as a fast, high-accuracy PII detection and masking solution built on the design philosophy in this article, we are developing and offering &quot;<a href="https://pii-fi.com/?ref=journal.qualiteg.com" rel="noreferrer">PII-FI Scan</a>,&quot; a service that de-identifies whole sets of logs and documents via drag and drop, along with the &quot;PII-FI API,&quot; which makes the same technology available through an API.</p><p>If you are interested in PII-FI&apos;s detection, masking, or de-identification capabilities, please feel free to reach out via our <a href="https://qualiteg.com/contact?ref=journal.qualiteg.com" rel="noreferrer">contact form</a>.</p><p>See you next time!</p><hr><h2 id="references-industry-standards-and-guidelines">References (Industry Standards and Guidelines)</h2><p>The framework in this article is consistent with the thinking in the following standards and guidelines on de-identification. Please refer to them as well.</p><ul><li><a href="https://nvlpubs.nist.gov/nistpubs/ir/2015/nist.ir.8053.pdf?ref=journal.qualiteg.com" rel="noreferrer">NIST IR 8053: De-Identification of Personal Information</a> &#x2014; A report from the U.S. NIST broadly organizing research and practice on de-identification and re-identification. Covers not only structured data but also free text and images</li><li><a href="https://csrc.nist.gov/pubs/sp/800/188/final?ref=journal.qualiteg.com" rel="noreferrer">NIST SP 800-188: De-Identifying Government Datasets</a> &#x2014; A practical guide to de-identifying government datasets (final version, 2023). Covers quasi-identifier transformation, synthetic data, re-identification risk assessment, and governance</li><li><a href="https://www.iso.org/standard/69373.html?ref=journal.qualiteg.com" rel="noreferrer">ISO/IEC 20889:2018</a> &#x2014; The international standard for the terminology and classification of de-identification techniques. Systematizes pseudonymization, generalization, suppression (deletion/masking), noise addition, and more</li><li><a href="https://www.enisa.europa.eu/publications/pseudonymisation-techniques-and-best-practices?ref=journal.qualiteg.com" rel="noreferrer">ENISA: Pseudonymisation Techniques and Best Practices</a> &#x2014; A practical guide to pseudonymization from the EU cybersecurity agency. Details the trade-off between the usefulness of consistent pseudonyms (coreference preservation) and re-identification risk</li><li><a href="https://www.ppc.go.jp/personalinfo/legal/guidelines_anonymous/?ref=journal.qualiteg.com" rel="noreferrer">Personal Information Protection Commission: Guidelines on the Act on the Protection of Personal Information (Pseudonymized and Anonymized Information volume)</a> &#x2014; Definitions, requirements, and obligations for &quot;pseudonymized information&quot; and &quot;anonymized information&quot; under Japanese law</li></ul><h2 id="related-resources">Related Resources</h2><ul><li><a href="https://journal.qualiteg.com/llm-audit-pii-detection-technology-part1/" rel="noreferrer">High-Accuracy PII Detection (Part 1)</a></li><li><a href="https://journal.qualiteg.com/llm-audit-pii-detection-technology-part2/" rel="noreferrer">Staged PII Masking When Using LLMs (Part 2)</a></li><li><a href="https://journal.qualiteg.com/pii-detection-cross-recognizer-collision-and-test-design/" rel="noreferrer">What the Confusion Matrix Cannot Show in PII Detection &#x2014; Inter-Recognizer Collisions and Test Design</a></li><li><a href="https://journal.qualiteg.com/llm-security-llm-audit-pii-protector/" rel="noreferrer">Enterprise Information Defense in the LLM Era</a></li><li><a href="https://journal.qualiteg.com/zero-trust-security-and-llm-ai-agent/" rel="noreferrer">The Complete Guide to LLM Security in the Zero Trust Era</a></li><li><a href="https://journal.qualiteg.com/ai-dlp-technology-https-interception-explained-part1/" rel="noreferrer">DLP Technology in the AI Era (Part 1)</a></li><li><a href="https://journal.qualiteg.com/ai-dlp-technology-https-interception-explained-part2/" rel="noreferrer">DLP Technology in the AI Era (Part 2)</a></li></ul>]]></content:encoded></item><item><title><![CDATA[Japanese LLM Rankings 2026 — Benchmark Analysis Report (July 10 Edition)]]></title><description><![CDATA[<p></p><h2 id="introduction">Introduction</h2><p>This report is a comprehensive analysis of the performance of Japanese-capable LLMs, based on benchmark data from the <a href="https://wandb.ai/wandb-japan/llm-leaderboard4/reports/Nejumi-Leaderboard-4--VmlldzoxMDIxMjI1Mw?ref=journal.qualiteg.com">Nejumi Leaderboard 4</a> (2026/7/10 edition).</p><p>Last time, we published <a href="https://journal.qualiteg.com/llm-ranking-2026-03/">an analysis report on the 2026/3/6 edition</a>; <br>now, roughly four months on, this edition too <strong>has proved turbulent,</strong></p>]]></description><link>https://journal.qualiteg.com/llm-ranking-2026/</link><guid isPermaLink="false">6a509e8fedf69a17d422a7f4</guid><category><![CDATA[LLM]]></category><category><![CDATA[Generative AI Frontlines]]></category><dc:creator><![CDATA[Qualiteg Product Development Team]]></dc:creator><pubDate>Mon, 13 Jul 2026 02:19:58 GMT</pubDate><media:content url="https://journal.qualiteg.com/content/images/2026/07/2026_llm_ranking_0710-1.png" medium="image"/><content:encoded><![CDATA[<img src="https://journal.qualiteg.com/content/images/2026/07/2026_llm_ranking_0710-1.png" alt="Japanese LLM Rankings 2026 &#x2014; Benchmark Analysis Report (July 10 Edition)"><p></p><h2 id="introduction">Introduction</h2><p>This report is a comprehensive analysis of the performance of Japanese-capable LLMs, based on benchmark data from the <a href="https://wandb.ai/wandb-japan/llm-leaderboard4/reports/Nejumi-Leaderboard-4--VmlldzoxMDIxMjI1Mw?ref=journal.qualiteg.com">Nejumi Leaderboard 4</a> (2026/7/10 edition).</p><p>Last time, we published <a href="https://journal.qualiteg.com/llm-ranking-2026-03/">an analysis report on the 2026/3/6 edition</a>; <br>now, roughly four months on, this edition too <strong>has proved turbulent, with the lineup at the top <u>changing dramatically</u></strong>.</p><p>(We update this LLM ranking regularly. You can receive update notifications by following our <a href="https://x.com/qualiteg_jp?ref=journal.qualiteg.com">X</a> (formerly Twitter) account.)</p><p>Nejumi Leaderboard 4 is known as a reliable benchmark that evaluates LLM performance on Japanese-language tasks from multiple angles. It is built on two axes &#x2014; General Language Performance (GLP) and Alignment (ALT) &#x2014; and covers a wide range of aspects, from translation, summarization, reasoning, and coding to toxicity, bias, and truthfulness.</p><p>This analysis covers both commercial API models and open models, examining the characteristics and trends of each. First, here are the three biggest topics of this edition.</p><ul><li><strong>Claude Opus 4.8 breaks the 0.85 overall-score barrier, a first in the leaderboard&apos;s history</strong><br>Together with Claude Opus 4.7, Anthropic takes a one-two finish<br></li><li><strong>Nineteen models now score 0.80 or above overall</strong><br> (11 last time, 4 the time before) &#x2014; the near-doubling pace continues<br></li><li><strong>Among open models, Gemma 4 surges into view</strong><br>New domestic entrants also appear, including RakutenAI-3.0 and llm-jp-4<br></li></ul><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://journal.qualiteg.com/content/images/2026/07/opt_fig2_trend.png" class="kg-image" alt="Japanese LLM Rankings 2026 &#x2014; Benchmark Analysis Report (July 10 Edition)" loading="lazy" width="1840" height="864" srcset="https://journal.qualiteg.com/content/images/size/w600/2026/07/opt_fig2_trend.png 600w, https://journal.qualiteg.com/content/images/size/w1000/2026/07/opt_fig2_trend.png 1000w, https://journal.qualiteg.com/content/images/size/w1600/2026/07/opt_fig2_trend.png 1600w, https://journal.qualiteg.com/content/images/2026/07/opt_fig2_trend.png 1840w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">The top score rose from 0.8285 to 0.8523 in six months; the number of models above 0.80 keeps nearly doubling</span></figcaption></figure><h3 id="on-open-source-models">On &quot;open-source&quot; models</h3><p>Models with open weights are sometimes called &quot;open-source models&quot; or &quot;OSS models,&quot; but since not all of them disclose their training data and training code in full, this article uses the term &quot;open models&quot; throughout.</p><h3 id="on-benchmark-analysis">On benchmark analysis</h3><p>This report presents trends and characteristics that can be read from benchmark data, as reference information for LLM selection. For actual deployment, we recommend validating in a real environment suited to your use case.</p><p>This edition&apos;s tally is based on export data for the leaderboard&apos;s top 100 entries. Evaluation runs of the same model with different settings, such as reasoning/thinking modes, may appear as separate entries.</p><p>With that, let us look at the overall ranking of Japanese-capable LLMs as of 2026/7/10.</p><hr><h2 id="overall-score-ranking-top-50">Overall Score Ranking: TOP 50</h2><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://journal.qualiteg.com/content/images/2026/07/opt_fig1_top15.png" class="kg-image" alt="Japanese LLM Rankings 2026 &#x2014; Benchmark Analysis Report (July 10 Edition)" loading="lazy" width="1840" height="1312" srcset="https://journal.qualiteg.com/content/images/size/w600/2026/07/opt_fig1_top15.png 600w, https://journal.qualiteg.com/content/images/size/w1000/2026/07/opt_fig1_top15.png 1000w, https://journal.qualiteg.com/content/images/size/w1600/2026/07/opt_fig1_top15.png 1600w, https://journal.qualiteg.com/content/images/2026/07/opt_fig1_top15.png 1840w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">The overall TOP 15. The dashed line marks the &quot;0.85 wall,&quot; broken for the first time this edition</span></figcaption></figure>
<!--kg-card-begin: html-->
<div style="overflow-x:auto;"><table style="border-collapse:collapse;font-size:12px;font-family:sans-serif;">
  <thead>
    <tr>
      <th style="border:1px solid #c8d6e5;padding:4px 8px;background:#0B5C9C;color:#ffffff;">Rank</th>
      <th style="border:1px solid #c8d6e5;padding:4px 8px;background:#0B5C9C;color:#ffffff;">Model</th>
      <th style="border:1px solid #c8d6e5;padding:4px 8px;background:#0B5C9C;color:#ffffff;">Category</th>
      <th style="border:1px solid #c8d6e5;padding:4px 8px;background:#0B5C9C;color:#ffffff;">Overall score</th>
    </tr>
  </thead>
  <tbody>
    <tr><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">1 (*)</td><td style="border:1px solid #c8d6e5;padding:2px 8px;">anthropic/claude-opus-4.8: adaptive-thinking-xhigh</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">api</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">0.8523</td></tr>
    <tr><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">2</td><td style="border:1px solid #c8d6e5;padding:2px 8px;">anthropic/claude-opus-4.7: adaptive-thinking-xhigh</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">api</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">0.8509</td></tr>
    <tr><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">3</td><td style="border:1px solid #c8d6e5;padding:2px 8px;">google/gemini-3.1-pro-preview</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">api</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">0.8430</td></tr>
    <tr><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">4</td><td style="border:1px solid #c8d6e5;padding:2px 8px;">openai/gpt-5.5-2026-04-23: xhigh-effort</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">api</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">0.8411</td></tr>
    <tr><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">5</td><td style="border:1px solid #c8d6e5;padding:2px 8px;">openai/gpt-5.4-2026-03-05: high-effort</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">api</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">0.8397</td></tr>
    <tr><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">6</td><td style="border:1px solid #c8d6e5;padding:2px 8px;">anthropic/claude-opus-4-6: extended-thinking</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">api</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">0.8394</td></tr>
    <tr><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">7</td><td style="border:1px solid #c8d6e5;padding:2px 8px;">qwen/qwen3.6-max-preview: openrouter-reasoning</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">api</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">0.8295</td></tr>
    <tr><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">8</td><td style="border:1px solid #c8d6e5;padding:2px 8px;">openai/gpt-5.4-2026-03-05: xhigh-effort</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">api</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">0.8286</td></tr>
    <tr><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">9</td><td style="border:1px solid #c8d6e5;padding:2px 8px;">openai/gpt-5.2-2025-12-11: xhigh-effort</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">api</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">0.8285</td></tr>
    <tr><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">10</td><td style="border:1px solid #c8d6e5;padding:2px 8px;">google/gemini-3.5-flash</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">api</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">0.8249</td></tr>
    <tr><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">11</td><td style="border:1px solid #c8d6e5;padding:2px 8px;">anthropic/claude-sonnet-4.6: extended-thinking</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">api</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">0.8230</td></tr>
    <tr><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;background:#EAF3FC;">12</td><td style="border:1px solid #c8d6e5;padding:2px 8px;background:#EAF3FC;">Qwen/Qwen3.5-397B-A17B: reasoning-enabled</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;background:#EAF3FC;">Large (30B+)</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;background:#EAF3FC;">0.8191</td></tr>
    <tr><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">13</td><td style="border:1px solid #c8d6e5;padding:2px 8px;">google/gemini-3-flash-preview</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">api</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">0.8155</td></tr>
    <tr><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">14</td><td style="border:1px solid #c8d6e5;padding:2px 8px;">google/gemini-3-pro-preview</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">api</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">0.8134</td></tr>
    <tr><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;background:#EAF3FC;">15</td><td style="border:1px solid #c8d6e5;padding:2px 8px;background:#EAF3FC;">Qwen/Qwen3.5-122B-A10B: reasoning-enabled</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;background:#EAF3FC;">Large (30B+)</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;background:#EAF3FC;">0.8094</td></tr>
    <tr><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">16</td><td style="border:1px solid #c8d6e5;padding:2px 8px;">openai/gpt-5.1-2025-11-13: high-effort</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">api</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">0.8085</td></tr>
    <tr><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;background:#EAF3FC;">17</td><td style="border:1px solid #c8d6e5;padding:2px 8px;background:#EAF3FC;">google/gemma-4-31b-it</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;background:#EAF3FC;">Large (30B+)</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;background:#EAF3FC;">0.8077</td></tr>
    <tr><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">18</td><td style="border:1px solid #c8d6e5;padding:2px 8px;">anthropic/claude-opus-4.5-20251125: extended-thinking</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">api</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">0.8064</td></tr>
    <tr><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;background:#EAF3FC;">19</td><td style="border:1px solid #c8d6e5;padding:2px 8px;background:#EAF3FC;">Qwen/Qwen3.5-27B: reasoning-enabled</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;background:#EAF3FC;">Medium (10B-30B)</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;background:#EAF3FC;">0.8049</td></tr>
    <tr><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">20</td><td style="border:1px solid #c8d6e5;padding:2px 8px;">z-ai/glm-5.2: openrouter-reasoning-xhigh</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">api</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">0.8040</td></tr>
    <tr><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">21</td><td style="border:1px solid #c8d6e5;padding:2px 8px;">anthropic/claude-opus-4-1-20250805: extended-thinking</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">api</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">0.7992</td></tr>
    <tr><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">22</td><td style="border:1px solid #c8d6e5;padding:2px 8px;">openai/gpt-5-2025-08-07: high-effort</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">api</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">0.7970</td></tr>
    <tr><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">23</td><td style="border:1px solid #c8d6e5;padding:2px 8px;">deepseek/deepseek-v4-pro: thinking-max</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">api</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">0.7956</td></tr>
    <tr><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">24</td><td style="border:1px solid #c8d6e5;padding:2px 8px;">anthropic/claude-sonnet-4-5-20250929: extended-thinking</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">api</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">0.7954</td></tr>
    <tr><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">25</td><td style="border:1px solid #c8d6e5;padding:2px 8px;">anthropic/claude-sonnet-4-20250514: extended-thinking</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">api</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">0.7918</td></tr>
    <tr><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">26</td><td style="border:1px solid #c8d6e5;padding:2px 8px;">deepseek/DeepSeek-V3.2 (Thinking Mode)</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">api</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">0.7905</td></tr>
    <tr><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;background:#EAF3FC;">27</td><td style="border:1px solid #c8d6e5;padding:2px 8px;background:#EAF3FC;">Qwen/Qwen3.5-35B-A3B: reasoning-enabled</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;background:#EAF3FC;">Large (30B+)</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;background:#EAF3FC;">0.7895</td></tr>
    <tr><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;background:#EAF3FC;">28</td><td style="border:1px solid #c8d6e5;padding:2px 8px;background:#EAF3FC;">deepseek-ai/DeepSeek-V3.2: reasoning-enabled</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;background:#EAF3FC;">Large (30B+)</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;background:#EAF3FC;">0.7888</td></tr>
    <tr><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;background:#EAF3FC;">29</td><td style="border:1px solid #c8d6e5;padding:2px 8px;background:#EAF3FC;">zai-org/GLM-5: reasoning-enabled</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;background:#EAF3FC;">Large (30B+)</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;background:#EAF3FC;">0.7884</td></tr>
    <tr><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">30</td><td style="border:1px solid #c8d6e5;padding:2px 8px;">anthropic/claude-haiku-4-5-20251001: extended-thinking</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">api</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">0.7879</td></tr>
    <tr><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">31</td><td style="border:1px solid #c8d6e5;padding:2px 8px;">openai/o3-2025-04-16: high-effort</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">api</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">0.7876</td></tr>
    <tr><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;background:#EAF3FC;">32</td><td style="border:1px solid #c8d6e5;padding:2px 8px;background:#EAF3FC;">google/gemma-4-26B-A4B-it</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;background:#EAF3FC;">Medium (10&#x2013;30B)</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;background:#EAF3FC;">0.7872</td></tr>
    <tr><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">33</td><td style="border:1px solid #c8d6e5;padding:2px 8px;">grok-4</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">api</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">0.7810</td></tr>
    <tr><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">34</td><td style="border:1px solid #c8d6e5;padding:2px 8px;">anthropic/claude-opus-4-20250514: no-thinking</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">api</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">0.7804</td></tr>
    <tr><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;background:#EAF3FC;">35</td><td style="border:1px solid #c8d6e5;padding:2px 8px;background:#EAF3FC;">moonshotai/Kimi-K2.5: reasoning-enabled</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;background:#EAF3FC;">Large (30B+)</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;background:#EAF3FC;">0.7785</td></tr>
    <tr><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;background:#EAF3FC;">36</td><td style="border:1px solid #c8d6e5;padding:2px 8px;background:#EAF3FC;">Qwen/Qwen3-235B-A22B-Thinking-2507: reasoning-enabled</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;background:#EAF3FC;">Large (30B+)</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;background:#EAF3FC;">0.7785</td></tr>
    <tr><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">37</td><td style="border:1px solid #c8d6e5;padding:2px 8px;">openai/gpt-5.4-mini-2026-03-17: high-effort</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">api</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">0.7776</td></tr>
    <tr><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">38</td><td style="border:1px solid #c8d6e5;padding:2px 8px;">openai/o1-2024-12-17: high-effort</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">api</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">0.7753</td></tr>
    <tr><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">39</td><td style="border:1px solid #c8d6e5;padding:2px 8px;">anthropic/claude-3.7-sonnet-20250219: extended-thinking</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">api</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">0.7734</td></tr>
    <tr><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">40</td><td style="border:1px solid #c8d6e5;padding:2px 8px;">xai/grok-4.20-0309-reasoning</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">api</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">0.7732</td></tr>
    <tr><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">41</td><td style="border:1px solid #c8d6e5;padding:2px 8px;">google/gemini-2.5-pro</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">api</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">0.7696</td></tr>
    <tr><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">42</td><td style="border:1px solid #c8d6e5;padding:2px 8px;">x-ai/grok-4-1-fast-reasoning</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">api</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">0.7646</td></tr>
    <tr><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">43</td><td style="border:1px solid #c8d6e5;padding:2px 8px;">openai/o4-mini-2025-04-16</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">api</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">0.7610</td></tr>
    <tr><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;background:#EAF3FC;">44</td><td style="border:1px solid #c8d6e5;padding:2px 8px;background:#EAF3FC;">Qwen/Qwen3-Next-80B-A3B-Thinking</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;background:#EAF3FC;">Large (30B+)</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;background:#EAF3FC;">0.7563</td></tr>
    <tr><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;background:#EAF3FC;">45</td><td style="border:1px solid #c8d6e5;padding:2px 8px;background:#EAF3FC;">MiniMaxAI/MiniMax-M2.1: reasoning-enabled</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;background:#EAF3FC;">Large (30B+)</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;background:#EAF3FC;">0.7556</td></tr>
    <tr><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;background:#EAF3FC;">46</td><td style="border:1px solid #c8d6e5;padding:2px 8px;background:#EAF3FC;">Qwen/Qwen3.5-9B: reasoning-enabled</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;background:#EAF3FC;">Medium (10B-30B)</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;background:#EAF3FC;">0.7485</td></tr>
    <tr><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">47</td><td style="border:1px solid #c8d6e5;padding:2px 8px;">openai/o3-mini-2025-01-31</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">api</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">0.7430</td></tr>
    <tr><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">48</td><td style="border:1px solid #c8d6e5;padding:2px 8px;">Qwen/Qwen3-Max-Preview</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">api</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">0.7425</td></tr>
    <tr><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">49</td><td style="border:1px solid #c8d6e5;padding:2px 8px;">openai/gpt-5.1-2025-11-13: none-effort</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">api</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">0.7412</td></tr>
    <tr><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">50</td><td style="border:1px solid #c8d6e5;padding:2px 8px;">grok-3-mini</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">api</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">0.7370</td></tr>
  </tbody>
</table></div>
<!--kg-card-end: html-->
<p>* Rows in light blue are open models.<br>* As of today (7/10), Fable 5 and GPT 5.6 have rolled out, but there is a lag before new models appear in the benchmark, so they are not yet listed. Please bear this in mind.</p><h2 id="overall-score-trends-and-analysis">Overall Score: Trends and Analysis</h2><p>The biggest news this time is, without question, <br><strong>the one-two finish by Claude Opus 4.8 (0.8523) and Claude Opus 4.7 (0.8509)</strong>.</p><p>This is the first time an overall score has exceeded 0.85 on Nejumi Leaderboard 4 &#x2014; and two models from the same vendor achieved it simultaneously.</p><ul><li><strong>The top two both score 0.85 or above</strong>, an unprecedented level (the previous edition&apos;s leader stood at 0.8430)</li><li><strong>The top 19 score 0.80 or above</strong> (11 models last time)</li><li>Six of the TOP 10 slots are newcomers absent from the previous ranking</li></ul><h3 id="anthropic-finally-breaks-through-the-085-wall">Anthropic finally breaks through the &quot;0.85 wall&quot;</h3><p>The leader, Claude Opus 4.8, achieved high marks on both axes: GLP (General Language Performance) 0.8328 and ALT (Alignment) 0.8933. Its mathematical reasoning of 0.975, abstract reasoning of 0.87, and 0.6875 on the SWE-Bench-style evaluation of practical coding ability are top-class among all models &#x2014; the strength of its reasoning is what lifts the score.</p><p>Claude Opus 4.6 (0.8394), second last time, holds on at sixth, leaving Anthropic with three of the TOP 10 slots (Opus 4.8, Opus 4.7, and Opus 4.6). Gemini 3.1 Pro (0.8430), the previous leader, slips to third with its score unchanged.</p><h3 id="openai-gives-chase-with-gpt-55-and-gpt-54">OpenAI gives chase with GPT-5.5 and GPT-5.4</h3><p>GPT-5.4 (0.8397), which we noted last time as &quot;too new to have scores listed,&quot; comes in fifth, and its successor GPT-5.5 (0.8411) takes fourth. With GLP 0.8303, GPT-5.5 closes in on Opus 4.8 in language performance, and its SWE-Bench-style score of 0.6875 matches Opus 4.8.</p><p>Interestingly, for GPT-5.4 the &quot;high&quot; reasoning-effort setting (0.8397) outscored the &quot;xhigh&quot; setting (0.8286) &#x2014; a good illustration that more reasoning does not always mean a higher score.</p><h3 id="the-true-latest-models-are-yet-to-come">* The true latest models are yet to come</h3><p>As of today (2026/7/10), the true latest and highest-end models &#x2014; Claude Fable 5 and ChatGPT 5.6 &#x2014; do exist, but they are expected to appear in the benchmark a little later, so please note that they are not yet in this ranking.</p><p></p><h3 id="six-of-the-top-10-slots-change-hands">Six of the TOP 10 Slots Change Hands</h3><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://journal.qualiteg.com/content/images/2026/07/opt_fig3_vs_prev.png" class="kg-image" alt="Japanese LLM Rankings 2026 &#x2014; Benchmark Analysis Report (July 10 Edition)" loading="lazy" width="1840" height="1216" srcset="https://journal.qualiteg.com/content/images/size/w600/2026/07/opt_fig3_vs_prev.png 600w, https://journal.qualiteg.com/content/images/size/w1000/2026/07/opt_fig3_vs_prev.png 1000w, https://journal.qualiteg.com/content/images/size/w1600/2026/07/opt_fig3_vs_prev.png 1600w, https://journal.qualiteg.com/content/images/2026/07/opt_fig3_vs_prev.png 1840w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Six of this edition&apos;s TOP 10 models were absent from the previous ranking</span></figcaption></figure><p>As the chart above shows, six of the TOP 10 are faces that were not in the previous ranking. Here are the newcomers most worth noting.</p><ul><li><strong>Qwen3.6 Max (7th, 0.8295)</strong><br>Alibaba&apos;s flagship API model. Its ALT of 0.9181 is the highest of any model, with a standout balance of controllability, low toxicity, and robustness<br></li><li><strong>Gemini 3.5 Flash (10th, 0.8249)</strong><br>A light, low-cost Flash-class model that outscores the previous edition&apos;s Opus 4.5 (0.8064). Its truthfulness of 0.550, however, is markedly the lowest among the top group, so hallucination countermeasures are needed on the user side<br></li><li><strong>GLM-5.2 (20th, 0.8040)</strong><br>Z.ai&apos;s latest API model. Newly released in June, it outscores the open GLM-5 (0.7884)<br></li><li><strong>DeepSeek V4 Pro (23rd, 0.7956)</strong><br>DeepSeek&apos;s latest API flagship. Reasoning has been reinforced, with mathematical reasoning at 0.94 and abstract reasoning at 0.79</li></ul><h3 id="high-performance-yet-sinking-overall-%E2%80%94-the-lesson-of-grok-420">&quot;High Performance, Yet Sinking Overall&quot; &#x2014; the Lesson of grok-4.20</h3><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://journal.qualiteg.com/content/images/2026/07/opt_fig5_glp_alt.png" class="kg-image" alt="Japanese LLM Rankings 2026 &#x2014; Benchmark Analysis Report (July 10 Edition)" loading="lazy" width="1840" height="1280" srcset="https://journal.qualiteg.com/content/images/size/w600/2026/07/opt_fig5_glp_alt.png 600w, https://journal.qualiteg.com/content/images/size/w1000/2026/07/opt_fig5_glp_alt.png 1000w, https://journal.qualiteg.com/content/images/size/w1600/2026/07/opt_fig5_glp_alt.png 1600w, https://journal.qualiteg.com/content/images/2026/07/opt_fig5_glp_alt.png 1840w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">The upper right is better. Reaching the overall top requires both GLP and ALT</span></figcaption></figure><p>The scatter plot above places the major models on two axes: GLP (language performance) and ALT (alignment).</p><p>Every model at the overall top sits in the upper right &#x2014; that is, they <strong>combine &quot;intelligence&quot; with &quot;safety and controllability&quot;</strong>.</p><p>The contrast is xAI&apos;s grok-4.20-0309-reasoning (0.7732).</p><p>Its GLP of 0.7942 is TOP 10-class language performance, but its ALT is low at 0.7659 (notably toxicity 0.566 and truthfulness 0.485), sinking it to 40th overall.</p><p><strong><u>Because alignment carries substantial weight in the overall evaluation</u></strong>, <strong><u>&quot;being smart alone&quot; does not get a model into the top ranks</u></strong> &#x2014; this case illustrates that structure clearly.</p><h3 id="on-interpreting-benchmark-results">On interpreting benchmark results</h3><p>The scores presented in this report are, in the end, results of benchmark tests. Benchmarks are a useful tool for objectively comparing LLM performance, but please note the following.</p><ul><li>Benchmarks evaluate against a specific set of tasks, so models well suited to that task mix tend to score higher</li><li>The practical feel in real work, and usefulness for specific purposes, cannot be fully measured by benchmark scores alone</li><li>Some models have unique strengths and characteristics that the benchmark does not measure</li></ul><p>Next, let us narrow the field to open models and see how they fare.</p><hr><h2 id="open-models-overall-score-ranking-top-20">Open Models: Overall Score Ranking TOP 20</h2><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://journal.qualiteg.com/content/images/2026/07/opt_fig4_open.png" class="kg-image" alt="Japanese LLM Rankings 2026 &#x2014; Benchmark Analysis Report (July 10 Edition)" loading="lazy" width="1840" height="1248" srcset="https://journal.qualiteg.com/content/images/size/w600/2026/07/opt_fig4_open.png 600w, https://journal.qualiteg.com/content/images/size/w1000/2026/07/opt_fig4_open.png 1000w, https://journal.qualiteg.com/content/images/size/w1600/2026/07/opt_fig4_open.png 1600w, https://journal.qualiteg.com/content/images/2026/07/opt_fig4_open.png 1840w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">The open TOP 12. Bars show the parameter configuration (per HF model cards). The dashed line marks the gap to the API leader</span></figcaption></figure>
<!--kg-card-begin: html-->
<div style="overflow-x:auto;"><table style="border-collapse:collapse;font-size:12px;font-family:sans-serif;">
  <thead>
    <tr>
      <th style="border:1px solid #c8d6e5;padding:4px 8px;background:#0B5C9C;color:#ffffff;">Rank</th>
      <th style="border:1px solid #c8d6e5;padding:4px 8px;background:#0B5C9C;color:#ffffff;">Model</th>
      <th style="border:1px solid #c8d6e5;padding:4px 8px;background:#0B5C9C;color:#ffffff;">Size class</th>
      <th style="border:1px solid #c8d6e5;padding:4px 8px;background:#0B5C9C;color:#ffffff;">Overall score</th>
    </tr>
  </thead>
  <tbody>
    <tr><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">1</td><td style="border:1px solid #c8d6e5;padding:2px 8px;">Qwen/Qwen3.5-397B-A17B: reasoning-enabled</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">Large (30B+)</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">0.8191</td></tr>
    <tr><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">2</td><td style="border:1px solid #c8d6e5;padding:2px 8px;">Qwen/Qwen3.5-122B-A10B: reasoning-enabled</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">Large (30B+)</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">0.8094</td></tr>
    <tr><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">3</td><td style="border:1px solid #c8d6e5;padding:2px 8px;">google/gemma-4-31b-it</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">Large (30B+)</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">0.8077</td></tr>
    <tr><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">4</td><td style="border:1px solid #c8d6e5;padding:2px 8px;">Qwen/Qwen3.5-27B: reasoning-enabled</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">Medium (10B-30B)</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">0.8049</td></tr>
    <tr><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">5</td><td style="border:1px solid #c8d6e5;padding:2px 8px;">Qwen/Qwen3.5-35B-A3B: reasoning-enabled</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">Large (30B+)</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">0.7895</td></tr>
    <tr><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">6</td><td style="border:1px solid #c8d6e5;padding:2px 8px;">deepseek-ai/DeepSeek-V3.2: reasoning-enabled</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">Large (30B+)</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">0.7888</td></tr>
    <tr><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">7</td><td style="border:1px solid #c8d6e5;padding:2px 8px;">zai-org/GLM-5: reasoning-enabled</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">Large (30B+)</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">0.7884</td></tr>
    <tr><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">8</td><td style="border:1px solid #c8d6e5;padding:2px 8px;">google/gemma-4-26B-A4B-it</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">Medium (10&#x2013;30B)</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">0.7872</td></tr>
    <tr><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">9</td><td style="border:1px solid #c8d6e5;padding:2px 8px;">moonshotai/Kimi-K2.5: reasoning-enabled</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">Large (30B+)</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">0.7785</td></tr>
    <tr><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">10</td><td style="border:1px solid #c8d6e5;padding:2px 8px;">Qwen/Qwen3-235B-A22B-Thinking-2507: reasoning-enabled</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">Large (30B+)</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">0.7785</td></tr>
    <tr><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">11</td><td style="border:1px solid #c8d6e5;padding:2px 8px;">Qwen/Qwen3-Next-80B-A3B-Thinking</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">Large (30B+)</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">0.7563</td></tr>
    <tr><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">12</td><td style="border:1px solid #c8d6e5;padding:2px 8px;">MiniMaxAI/MiniMax-M2.1: reasoning-enabled</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">Large (30B+)</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">0.7556</td></tr>
    <tr><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">13</td><td style="border:1px solid #c8d6e5;padding:2px 8px;">Qwen/Qwen3.5-9B: reasoning-enabled</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">Medium (10B-30B)</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">0.7485</td></tr>
    <tr><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">14</td><td style="border:1px solid #c8d6e5;padding:2px 8px;">Qwen/Qwen3.5-4B: reasoning-enabled</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">Small (<10b)< td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">0.7352</td></10b)<></td></tr>
    <tr><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">15</td><td style="border:1px solid #c8d6e5;padding:2px 8px;">Qwen/Qwen3-30B-A3B-Thinking-2507: reasoning-enabled</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">Large (30B+)</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">0.7331</td></tr>
    <tr><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">16</td><td style="border:1px solid #c8d6e5;padding:2px 8px;">Qwen/Qwen3-14B: reasoning-enabled</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">Medium (10&#x2013;30B)</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">0.7233</td></tr>
    <tr><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">17</td><td style="border:1px solid #c8d6e5;padding:2px 8px;">LGAI-EXAONE/K-EXAONE-236B-A23B: reasoning-enabled</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">Large (30B+)</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">0.7186</td></tr>
    <tr><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">18</td><td style="border:1px solid #c8d6e5;padding:2px 8px;">Qwen/Qwen3-Next-80B-A3B-Instruct</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">Large (30B+)</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">0.7130</td></tr>
    <tr><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">19</td><td style="border:1px solid #c8d6e5;padding:2px 8px;">nvidia/NVIDIA-Nemotron-Nano-9B-v2-Japanese: reasoning-enabled</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">Small (<10b)< td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">0.7111</td></10b)<></td></tr>
    <tr><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">20</td><td style="border:1px solid #c8d6e5;padding:2px 8px;">Qwen/Qwen3-VL-8B-Thinking</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">Small (<10b)< td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">0.7021</td></10b)<></td></tr>
  </tbody>
</table></div>
<!--kg-card-end: html-->
<p>* Rankings are per model (where a model has multiple evaluation runs, only its best score is used).</p><h2 id="open-models-trends-and-analysis">Open Models: Trends and Analysis</h2><h3 id="qwen35-397b-a17b-holds-the-lead-but-the-gap-to-the-api-camp-widens-again">Qwen3.5-397B-A17B holds the lead, but the gap to the API camp widens again</h3><p>The top open model is once again Alibaba&apos;s <strong>Qwen3.5-397B-A17B (0.8191)</strong>.</p><p>The Qwen3.5 series still carries its scores from its February 2026 release, meaning the open-side frontier saw no update over these four months.</p><p>Meanwhile the API-side leader climbed from 0.8430 to 0.8523, so the gap between the open and API leaders has widened again, from roughly 0.024 to roughly 0.033.</p><p>A reversal from the excitement last time that &quot;open models are closing in on the APIs&quot; &#x2014; this time the frontier API camp has pulled away.</p><p>That said, the open field is steadily deepening: the number of open models above 0.80 grew from three to four.</p><h3 id="the-gemma-4-shock-%E2%80%94-a-31b-dense-model-above-080">The Gemma 4 Shock &#x2014; a 31B Dense Model Above 0.80</h3><p>That fourth model is the biggest news in this edition&apos;s open division: Google&apos;s <strong>Gemma 4 family</strong>. A new generation released in March 2026, published on Hugging Face under the Apache 2.0 license.</p><ul><li><strong>Gemma 4 31B (0.8077)</strong><br>A 31B dense model that surges to third among open models. It delivers the same level as GPT-5.1 (0.8085) and Claude Opus 4.5 (0.8064) at a size that runs on a single GPU<br></li><li><strong>Gemma 4 26B-A4B (0.7872)</strong><br>An MoE version with 26B total and 4B active parameters. Roughly 0.79-class performance while sharply reducing inference cost<br></li><li><strong>Gemma 4 E4B / E2B</strong><br>Compact on-device versions round out the lineup (covered in the small-model section)</li></ul><p>Until now, the leading candidate for a 30B-class local LLM was Qwen3.5-27B (0.8049); with Gemma 4 31B now surpassing it, the single-GPU class has two strong options side by side.</p><h3 id="new-chinese-entrants-glm-5-kimi-k25-and-minimax-m21">New Chinese entrants: GLM-5, Kimi K2.5, and MiniMax-M2.1</h3><p>As before, the depth of China-origin open models is overwhelming. This edition brings three large newcomers.</p><ul><li><strong>GLM-5 (0.7884)</strong><br>Z.ai&apos;s latest generation: an MoE with 744B total and 40B active parameters, adopting DeepSeek Sparse Attention (DSA). Generously released under the MIT license<br></li><li><strong>Kimi K2.5 (0.7785)</strong><br>Moonshot AI&apos;s 1T-total, 32B-active MoE. A natively multimodal model with an integrated vision encoder, designed with agentic use squarely in mind<br></li><li><strong>MiniMax-M2.1 (0.7556)</strong><br>A 229B-total MoE, with a character specialized in SWE-Bench-style coding and agentic processing</li></ul><p>The pattern of five Chinese players &#x2014; Qwen, DeepSeek, GLM (Z.ai), Kimi (Moonshot), and MiniMax &#x2014; filling the open TOP 12 holds again this time, with Google&apos;s Gemma 4 now wedged in among them.</p>
<!--kg-card-begin: html-->
<div style="max-width:760px;margin:2.5rem auto;font-family:-apple-system,BlinkMacSystemFont,&apos;Segoe UI&apos;,&apos;Hiragino Kaku Gothic ProN&apos;,&apos;Noto Sans JP&apos;,Meiryo,sans-serif;color:#1a2b3c;line-height:1.85;border:1px solid #d9e2ec;">

  <!-- ヘッダー -->
  <div style="padding:1.8rem 1.6rem;background:#0B5C9C;color:#ffffff;">
    <div style="font-size:0.78rem;letter-spacing:0.12em;opacity:0.85;margin-bottom:0.5rem;">COLUMN:OPEN MODEL LANDSCAPE</div>
    <h2 style="margin:0;font-size:1.5rem;line-height:1.4;color:#ffffff;">[Column] The Five Major Camps Behind China&apos;s LLMs</h2>
  </div>

  <div style="padding:1.6rem;background:#ffffff;">

    <p style="margin:0 0 1.8rem;color:#3a4a5c;">
      In this edition&apos;s ranking, five camps originating in China &#x2014; <strong>Qwen, DeepSeek, GLM, Kimi, and MiniMax</strong> &#x2014; fill the upper ranks of the open models. Tracing the developers, all are Chinese AI companies: <strong>Alibaba (&#x963F;&#x91CC;&#x5DF4;&#x5DF4;), DeepSeek (&#x6DF1;&#x5EA6;&#x6C42;&#x7D22;), Zhipu AI (&#x667A;&#x8C31;AI), Moonshot AI (&#x6708;&#x4E4B;&#x6697;&#x9762;), and MiniMax (&#x7A00;&#x5B87;&#x79D1;&#x6280;)</strong>. Note, however, that Qwen, GLM, and Kimi are not company names but the model brand names each company operates. Here we briefly organize each camp&apos;s characteristics and development approach.
    </p>

    <!-- ① Qwen -->
    <section style="padding:1.4rem 0;border-top:1px solid #e3eaf2;">
      <div style="display:flex;align-items:baseline;flex-wrap:wrap;gap:0.5rem;margin-bottom:0.5rem;">
        <span style="font-weight:700;font-size:1.15rem;color:#0B5C9C;">Qwen</span>
        <span style="font-size:0.9rem;font-weight:700;color:#c0392b;">Alibaba (&#x963F;&#x91CC;&#x5DF4;&#x5DF4;)</span>
        <span style="font-size:0.9rem;color:#5a6b7c;">&#x2014; an all-around model family</span>
      </div>
      <p style="margin:0 0 0.4rem;color:#3a4a5c;">
        A family of foundation models developed by Alibaba. It spans everything from small models to MoE models in the hundreds of billions of parameters, covering general dialogue, reasoning, coding, image understanding, and more. Both API-only models and open models you can run in your own environment are offered.
      </p>
      <details style="margin-top:0.6rem;">
        <summary style="cursor:pointer;font-weight:600;color:#0B5C9C;font-size:0.92rem;list-style:none;">+ Read more</summary>
        <div style="padding:0.8rem 0 0;color:#41505f;font-size:0.96rem;">
          <p style="margin:0 0 0.7rem;">Qwen, also known as &quot;Tongyi Qianwen&quot; (&#x901A;&#x7FA9;&#x5343;&#x554F;), is Alibaba&apos;s model brand. It is not an independent company; development and delivery center on Alibaba Cloud.</p>
          <p style="margin:0 0 0.7rem;">Its defining trait is the breadth of scales and uses. From small models of a few billion parameters to Mixture-of-Experts (MoE) models in the hundreds of billions, a single family covers general dialogue, mathematical reasoning, coding, image/video understanding, speech, search, embeddings, and more.</p>
          <p style="margin:0 0 0.7rem;">It also invests in switching between thinking and non-thinking modes &#x2014; reasoning through complex problems while skipping reasoning for simple dialogue. The ease of tuning the balance of performance, speed, and running cost for each use case is a strength.</p>
          <p style="margin:0;">While there are API-only models such as the Qwen3.6 Max appearing in this ranking, there are also models like Qwen3.5-397B-A17B and Qwen3.5-27B whose weights can be obtained and operated in your own environment. Even within Qwen, the release format must be checked model by model.</p>
        </div>
      </details>
    </section>

    <!-- ② DeepSeek -->
    <section style="padding:1.4rem 0;border-top:1px solid #e3eaf2;">
      <div style="display:flex;align-items:baseline;flex-wrap:wrap;gap:0.5rem;margin-bottom:0.5rem;">
        <span style="font-weight:700;font-size:1.15rem;color:#0B5C9C;">DeepSeek</span>
        <span style="font-size:0.9rem;font-weight:700;color:#c0392b;">DeepSeek (&#x6DF1;&#x5EA6;&#x6C42;&#x7D22;)</span>
        <span style="font-size:0.9rem;color:#5a6b7c;">&#x2014; efficiency technology and open research</span>
      </div>
      <p style="margin:0 0 0.4rem;color:#3a4a5c;">
        A Chinese AI company centered on R&amp;D in foundation models and inference technology. It is known for designs that use MoE and similar techniques to hold down inference-time compute rather than running gigantic models as-is. It delivers high-performance models at comparatively low cost and actively publishes model weights and technical reports.
      </p>
      <details style="margin-top:0.6rem;">
        <summary style="cursor:pointer;font-weight:600;color:#0B5C9C;font-size:0.92rem;list-style:none;">+ Read more</summary>
        <div style="padding:0.8rem 0 0;color:#41505f;font-size:0.96rem;">
          <p style="margin:0 0 0.7rem;">DeepSeek is a Chinese AI company founded in 2023, focused on R&amp;D in foundation models, reasoning models, and training infrastructure. Compared with Alibaba or MiniMax, which run broad consumer-facing services, it plants its feet in model performance itself and in efficiency technology.</p>
          <p style="margin:0 0 0.7rem;">A major reason DeepSeek drew attention is its efficiency technology, starting with Mixture-of-Experts (MoE): while the model as a whole holds a very large number of parameters, only the subset needed for each input is activated, reconciling performance with compute cost.</p>
          <p style="margin:0 0 0.7rem;">It also has a strong presence in foundational technology: the reasoning-specialized DeepSeek-R1, DeepSeek Sparse Attention for efficient long-context processing, and a thinking mode with built-in tool calling. Beyond offering an API, its practice of publishing model weights and technical materials is another distinguishing trait.</p>
          <p style="margin:0;">In the ranking, the API-side DeepSeek V4 Pro and the open DeepSeek-V3.2 are evaluated separately. Because model generation, release format, and thinking settings differ, do not lump them together under the name &quot;DeepSeek&quot; &#x2014; check the specific model that was evaluated.</p>
        </div>
      </details>
    </section>

    <!-- ③ GLM -->
    <section style="padding:1.4rem 0;border-top:1px solid #e3eaf2;">
      <div style="display:flex;align-items:baseline;flex-wrap:wrap;gap:0.5rem;margin-bottom:0.5rem;">
        <span style="font-weight:700;font-size:1.15rem;color:#0B5C9C;">GLM&#xFF0F;Z.ai</span>
        <span style="font-size:0.9rem;font-weight:700;color:#c0392b;">Zhipu AI (&#x667A;&#x8C31;AI)</span>
        <span style="font-size:0.9rem;color:#5a6b7c;">&#x2014; a focus on coding agents</span>
      </div>
      <p style="margin:0 0 0.4rem;color:#3a4a5c;">
        Foundation models developed by the Chinese AI company Zhipu AI. Internationally it offers chat, API, and coding services under the Z.ai brand. It places particular weight on agent-style development work that sustains code investigation, implementation, testing, and fixing over long stretches.
      </p>
      <details style="margin-top:0.6rem;">
        <summary style="cursor:pointer;font-weight:600;color:#0B5C9C;font-size:0.92rem;list-style:none;">+ Read more</summary>
        <div style="padding:0.8rem 0 0;color:#41505f;font-size:0.96rem;">
          <p style="margin:0 0 0.7rem;">GLM is the name of the models; the developer is China&apos;s Zhipu AI. Domestically it offers services under the Zhipu and BigModel names, while internationally it mainly uses the Z.ai brand.</p>
          <p style="margin:0 0 0.7rem;">The GLM series emphasizes not only general dialogue and reasoning but also search, tool calling, coding, and long-running agentic processing. Rather than one-shot code generation, it is designed around the full development cycle: reading existing code, designing, modifying multiple files, and revising again based on test results.</p>
          <p style="margin:0 0 0.7rem;">From GLM-5 onward, support for complex software development and long-duration tasks has been strengthened. It adopts MoE and long-context efficiency techniques, with clear attention to use in connection with development environments such as Claude Code and Cline.</p>
          <p style="margin:0;">In this ranking, the API-side GLM-5.2 and the open-weight GLM-5 appear separately. API models and open models differ in performance and terms of delivery, so the distinction matters at adoption time.</p>
        </div>
      </details>
    </section>

    <!-- ④ Kimi -->
    <section style="padding:1.4rem 0;border-top:1px solid #e3eaf2;">
      <div style="display:flex;align-items:baseline;flex-wrap:wrap;gap:0.5rem;margin-bottom:0.5rem;">
        <span style="font-weight:700;font-size:1.15rem;color:#0B5C9C;">Kimi&#xFF0F;Moonshot AI</span>
        <span style="font-size:0.9rem;font-weight:700;color:#c0392b;">Moonshot AI (&#x6708;&#x4E4B;&#x6697;&#x9762;)</span>
        <span style="font-size:0.9rem;color:#5a6b7c;">&#x2014; from long-context processing to agents</span>
      </div>
      <p style="margin:0 0 0.4rem;color:#3a4a5c;">
        An AI assistant and model brand developed by Moonshot AI. It first drew attention for long-context capability that could ingest large volumes of documents at once. Today it has evolved into an agent-style model combining long-context understanding with coding, image/video understanding, and tool use.
      </p>
      <details style="margin-top:0.6rem;">
        <summary style="cursor:pointer;font-weight:600;color:#0B5C9C;font-size:0.92rem;list-style:none;">+ Read more</summary>
        <div style="padding:0.8rem 0 0;color:#41505f;font-size:0.96rem;">
          <p style="margin:0 0 0.7rem;">Moonshot AI, the developer of Kimi, is a Chinese AI company founded in 2023. Kimi is not the company&apos;s name but the brand name of its models and AI assistant.</p>
          <p style="margin:0 0 0.7rem;">Kimi&apos;s original strength was long-context processing that could take in papers, contracts, web pages, and large volumes of business documents at once. It has since evolved beyond reading long texts, toward writing code based on what it reads, using search and external tools, and executing multi-step procedures.</p>
          <p style="margin:0 0 0.7rem;">The Kimi K2 line consists of large MoE models whose primary uses are coding and agentic processing. The Kimi K2.5 listed this time is a natively multimodal model that handles images and video in addition to text.</p>
          <p style="margin:0;">For Kimi as well, there is a time lag between the models on the leaderboard and the latest models currently offered. Check not only the ranking scores but also which model generations can actually be selected via the API.</p>
        </div>
      </details>
    </section>

    <!-- ⑤ MiniMax -->
    <section style="padding:1.4rem 0;border-top:1px solid #e3eaf2;">
      <div style="display:flex;align-items:baseline;flex-wrap:wrap;gap:0.5rem;margin-bottom:0.5rem;">
        <span style="font-weight:700;font-size:1.15rem;color:#0B5C9C;">MiniMax</span>
        <span style="font-size:0.9rem;font-weight:700;color:#c0392b;">MiniMax (&#x7A00;&#x5B87;&#x79D1;&#x6280;)</span>
        <span style="font-size:0.9rem;color:#5a6b7c;">&#x2014; from text to speech and video</span>
      </div>
      <p style="margin:0 0 0.4rem;color:#3a4a5c;">
        A Chinese AI company that develops not only text LLMs but also generative models for speech, music, images, and video. Its M2 series of text models emphasizes practical tasks: coding, search, tool use, and business-document drafting. Spanning multiple generative-AI fields within one company is what most sets it apart from the other four camps.
      </p>
      <details style="margin-top:0.6rem;">
        <summary style="cursor:pointer;font-weight:600;color:#0B5C9C;font-size:0.92rem;list-style:none;">+ Read more</summary>
        <div style="padding:0.8rem 0 0;color:#41505f;font-size:0.96rem;">
          <p style="margin:0 0 0.7rem;">MiniMax is a Chinese AI company founded in 2022. In parallel with large language models, it develops multiple generative-AI technologies: speech synthesis, music generation, image generation, and video generation.</p>
          <p style="margin:0 0 0.7rem;">Its M2 series of text models is aimed less at general conversation than at agentic use that advances real work: code generation, modifying existing code, search, tool calling, and business-document drafting.</p>
          <p style="margin:0 0 0.7rem;">The MiniMax-M2.1 listed this time is an MoE model that keeps the parameters active at inference small relative to the model&apos;s overall size. Support extends beyond Python to multiple programming languages, including Rust, Java, Go, C++, and TypeScript.</p>
          <p style="margin:0;">In text-LLM-only rankings, MiniMax may stand out less than Qwen or DeepSeek. Viewed across its whole product range, however &#x2014; speech, music, images, and video included &#x2014; it pursues the broadest multimodal strategy of the five camps.</p>
        </div>
      </details>
    </section>

    <!-- まとめ -->
    <div style="margin-top:1.6rem;padding:1.3rem 1.4rem;background:#eef5fb;border-top:3px solid #0B5C9C;">
      <div style="font-weight:700;color:#0B5C9C;margin-bottom:0.4rem;">The five camps, each in one line</div>
      <p style="margin:0;color:#3a4a5c;font-size:0.96rem;">
        <strong>Qwen</strong> is the all-rounder; <strong>DeepSeek</strong> the efficiency-and-open-research type; <strong>GLM</strong> the coding-agent type; <strong>Kimi</strong> the long-context and multimodal type; and <strong>MiniMax</strong> the all-round generative-AI type extending to speech and video.
      </p>
    </div>

  </div>
</div>
<!-- ▲ ここまで -->
<!--kg-card-end: html-->
<h3 id="new-developments-among-japanese-open-models">New Developments Among Japanese Open Models</h3><p>This edition also brought noteworthy movement among open models from Japan.</p><ul><li><strong>RakutenAI-3.0 (0.6761)</strong><br>An MoE with 671B total and 37B active parameters released by Rakuten Group in March &#x2014; among the largest domestic open models. It adopts a DeepSeek-V3-family architecture and was built on Japanese-English bilingual data (Apache 2.0)<br></li><li><strong>llm-jp-4-32b-a3b-thinking (0.6679)</strong><br>An MoE reasoning model with 32B total and roughly 4B active parameters from the National Institute of Informatics (NII). An ambitious, fully domestic effort trained from scratch on 11.7 trillion tokens<br></li><li><strong>Reinforcement-learning versions of the Swallow series</strong><br>The RL versions from the Swallow team at Institute of Science Tokyo (formerly Tokyo Tech) have expanded. GPT-OSS-Swallow-120B-RL-v0.1 (0.6914) is top-class among domestic models, followed by Qwen3-Swallow-32B-RL-v0.2 (0.6782) and others</li></ul><p>Their overall scores still sit short of the 0.70 wall, but training data optimized for Japanese and ease of domestic operation are value the scores do not show.</p><p>It is also welcome news for Japanese users that K-EXAONE-236B-A23B (0.7186) from Korea&apos;s LG AI Research includes Japanese among its officially supported languages.</p><p></p><p>Next, let us look at <strong><u>mid-size models, roughly 10B to 30B</u></strong>.</p><p>The appeal of mid-size models is that they can run on GPUs that are relatively affordable even for individuals.</p><hr><h2 id="mid-size-models-10b-30b-overall-score-ranking">Mid-size Models (10B-30B): Overall Score Ranking</h2><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://journal.qualiteg.com/content/images/2026/07/opt_fig6_mid_small.png" class="kg-image" alt="Japanese LLM Rankings 2026 &#x2014; Benchmark Analysis Report (July 10 Edition)" loading="lazy" width="1840" height="1024" srcset="https://journal.qualiteg.com/content/images/size/w600/2026/07/opt_fig6_mid_small.png 600w, https://journal.qualiteg.com/content/images/size/w1000/2026/07/opt_fig6_mid_small.png 1000w, https://journal.qualiteg.com/content/images/size/w1600/2026/07/opt_fig6_mid_small.png 1600w, https://journal.qualiteg.com/content/images/2026/07/opt_fig6_mid_small.png 1840w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">The main battleground for local LLMs: top mid-size models (left) and small models (right)</span></figcaption></figure>
<!--kg-card-begin: html-->
<div style="overflow-x:auto;"><table style="border-collapse:collapse;font-size:12px;font-family:sans-serif;">
  <thead>
    <tr>
      <th style="border:1px solid #c8d6e5;padding:4px 8px;background:#0B5C9C;color:#ffffff;">Rank</th>
      <th style="border:1px solid #c8d6e5;padding:4px 8px;background:#0B5C9C;color:#ffffff;">Model</th>
      <th style="border:1px solid #c8d6e5;padding:4px 8px;background:#0B5C9C;color:#ffffff;">Overall score</th>
    </tr>
  </thead>
  <tbody>
    <tr><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">1</td><td style="border:1px solid #c8d6e5;padding:2px 8px;">Qwen/Qwen3.5-27B: reasoning-enabled</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">0.8049</td></tr>
    <tr><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">2</td><td style="border:1px solid #c8d6e5;padding:2px 8px;">google/gemma-4-26B-A4B-it</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">0.7872</td></tr>
    <tr><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">3</td><td style="border:1px solid #c8d6e5;padding:2px 8px;">Qwen/Qwen3.5-9B: reasoning-enabled</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">0.7485</td></tr>
    <tr><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">4</td><td style="border:1px solid #c8d6e5;padding:2px 8px;">Qwen/Qwen3-14B: reasoning-enabled</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">0.7233</td></tr>
    <tr><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">5</td><td style="border:1px solid #c8d6e5;padding:2px 8px;">tokyotech-llm/GPT-OSS-Swallow-20B-RL-v0.1: reasoning-enabled</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">0.6424</td></tr>
    <tr><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">6</td><td style="border:1px solid #c8d6e5;padding:2px 8px;">tokyotech-llm/Gemma-2-Llama-Swallow-27b-it-v0.1</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">0.6208</td></tr>
  </tbody>
</table></div>
<!--kg-card-end: html-->
<p>* Because the tally is based on the top-100 export data, some previously listed models (such as the gemma-3 family) fall outside this edition&apos;s scope.</p><h2 id="mid-size-models-trends-and-analysis">Mid-size Models: Trends and Analysis</h2><p>In the mid-size category, the previous champion <strong>Qwen3.5-27B (0.8049)</strong> defended first place, but <strong>Gemma 4 26B-A4B (0.7872)</strong> debuts in second, turning this into a two-horse race.</p><p>Because Gemma 4 26B-A4B is an MoE with only 4B active parameters, its inference load is far lighter than a dense 27B model&apos;s.</p><p>A sensible division of labor seems to emerge: Qwen3.5-27B for performance, Gemma 4 26B-A4B for inference cost.</p><p>Fourth-place GPT-OSS-Swallow-20B-RL-v0.1 (0.6424) is OpenAI&apos;s open model gpt-oss-20b further trained for Japanese with reinforcement learning &#x2014; a valuable Japanese-specialized mid-size model.</p><p>Finally, let us look at small models. These compact models run on relatively inexpensive consumer GPUs, making them the prime candidates for edge and on-premises use.</p><hr><h2 id="small-models-under-10b-overall-score-ranking">Small Models (Under 10B): Overall Score Ranking</h2>
<!--kg-card-begin: html-->
<div style="overflow-x:auto;"><table style="border-collapse:collapse;font-size:12px;font-family:sans-serif;">
  <thead>
    <tr>
      <th style="border:1px solid #c8d6e5;padding:4px 8px;background:#0B5C9C;color:#ffffff;">Rank</th>
      <th style="border:1px solid #c8d6e5;padding:4px 8px;background:#0B5C9C;color:#ffffff;">Model</th>
      <th style="border:1px solid #c8d6e5;padding:4px 8px;background:#0B5C9C;color:#ffffff;">Overall score</th>
    </tr>
  </thead>
  <tbody>
    <tr><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">1</td><td style="border:1px solid #c8d6e5;padding:2px 8px;">Qwen/Qwen3.5-4B: reasoning-enabled</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">0.7352</td></tr>
    <tr><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">2</td><td style="border:1px solid #c8d6e5;padding:2px 8px;">nvidia/NVIDIA-Nemotron-Nano-9B-v2-Japanese: reasoning-enabled</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">0.7111</td></tr>
    <tr><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">3</td><td style="border:1px solid #c8d6e5;padding:2px 8px;">Qwen/Qwen3-VL-8B-Thinking</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">0.7021</td></tr>
    <tr><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">4</td><td style="border:1px solid #c8d6e5;padding:2px 8px;">Qwen/Qwen3-8B: reasoning-enabled</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">0.6900</td></tr>
    <tr><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">5</td><td style="border:1px solid #c8d6e5;padding:2px 8px;">google/gemma-4-E4B-it</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">0.6692</td></tr>
    <tr><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">6</td><td style="border:1px solid #c8d6e5;padding:2px 8px;">google/gemma-4-E2B-it</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">0.6564</td></tr>
    <tr><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">7</td><td style="border:1px solid #c8d6e5;padding:2px 8px;">tokyotech-llm/Qwen3-Swallow-8B-RL-v0.2: reasoning-enabled</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">0.6552</td></tr>
    <tr><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">8</td><td style="border:1px solid #c8d6e5;padding:2px 8px;">tokyotech-llm/Gemma-2-Llama-Swallow-9b-it-v0.1</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">0.5982</td></tr>
  </tbody>
</table></div>
<!--kg-card-end: html-->
<h2 id="small-models-trends-and-analysis">Small Models: Trends and Analysis</h2><p>Among small models, <strong>Qwen3.5-4B (0.7352)</strong> leads again. At just 4B, it posts a score level that a year ago would have taken a 30B-class model &#x2014; emblematic of how far miniaturization has come.</p><h3 id="for-japanese-specialization-nemotron-nano-9b-v2-japanese">For Japanese specialization: Nemotron Nano 9B v2 Japanese</h3><p>In second place again, <strong>NVIDIA Nemotron Nano 9B v2 Japanese (0.7111)</strong> is NVIDIA&apos;s Nemotron Nano &#x2014; a Mamba-2/Transformer hybrid &#x2014; further trained for Japanese. It supports toggling reasoning on and off and controlling the volume of thinking tokens (thinking budget), and it is published under a commercially usable license. It is arguably the best Japanese-specialized small model available today.</p><h3 id="gemma-4s-on-device-versions-e4b-e2b">Gemma 4&apos;s on-device versions: E4B / E2B</h3><p>Gemma 4 E4B (0.6692) and E2B (0.6564) are compact versions intended to run on smartphones and edge devices. They reach this score band while keeping effective parameters low &#x2014; the practical bar for &quot;Japanese LLMs that run entirely on-device&quot; keeps rising steadily.</p><p>Seventh-place Qwen3-Swallow-8B-RL-v0.2 (0.6552), a Japanese reinforcement-learning version from the Swallow team at Institute of Science Tokyo, also made its presence felt among domestic small models.</p><hr><h2 id="conclusion-a-guide-toward-full-scale-adoption">Conclusion: a Guide Toward Full-Scale Adoption</h2><p>Once again we have analyzed the Nejumi Leaderboard 4 benchmark data. Here are the key takeaways from this edition.</p><h3 id="the-dawn-of-the-085-era-%E2%80%94-and-the-democratization-of-080">The dawn of the &quot;0.85 era&quot; &#x2014; and the democratization of 0.80</h3><p>The biggest point this time is that <strong>Claude Opus 4.8 broke the 0.85 overall-score barrier for the first time in the leaderboard&apos;s history</strong>.</p><p>At the same time, models above 0.80 reached 19, continuing a near-doubling pace from 11 last time and 4 the time before.</p><p>A score of 0.80 is no longer &quot;proof of the frontier&quot; but &quot;an admission ticket to the top group.&quot;</p><ul><li>Commercial APIs: the big three of Anthropic (Opus 4.8/4.7), Google (Gemini 3.1 Pro), and OpenAI (GPT-5.5/5.4) become a big four, with Alibaba (Qwen3.6 Max) forcing its way in<br></li><li>Open models: Qwen3.5 holds the lead while newcomers such as Gemma 4, GLM-5, and Kimi K2.5 deepen the field<br></li><li>Domestic models: Japanese-specialized options are steadily expanding, with RakutenAI-3.0, llm-jp-4, and the Swallow RL versions</li></ul><h3 id="characteristics-by-model-size">Characteristics by Model Size</h3>
<!--kg-card-begin: html-->
<div style="overflow-x:auto;"><table style="border-collapse:collapse;font-size:12px;font-family:sans-serif;">
  <thead>
    <tr>
      <th style="border:1px solid #c8d6e5;padding:4px 8px;background:#0B5C9C;color:#ffffff;">Category</th>
      <th style="border:1px solid #c8d6e5;padding:4px 8px;background:#0B5C9C;color:#ffffff;">Recommended models</th>
      <th style="border:1px solid #c8d6e5;padding:4px 8px;background:#0B5C9C;color:#ffffff;">Characteristics</th>
    </tr>
  </thead>
  <tbody>
    <tr><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">Maximum performance (commercial API)</td><td style="border:1px solid #c8d6e5;padding:2px 8px;">Claude Opus 4.8</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">First model in leaderboard history above 0.85 overall. Combines reasoning power and alignment at a high level</td></tr>
    <tr><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">Balancing cost efficiency and performance (commercial API)</td><td style="border:1px solid #c8d6e5;padding:2px 8px;">Gemini 3.5 Flash &#xFF0F; Claude Sonnet 4.6</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">Above 0.82 overall in the light, low-cost class. For high-volume processing and everyday work</td></tr>
    <tr><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">The open-model summit</td><td style="border:1px solid #c8d6e5;padding:2px 8px;">Qwen3.5-397B-A17B</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">0.8191 overall (Apache 2.0). The highest performance band you can operate on your own infrastructure</td></tr>
    <tr><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">Local operation on a single GPU</td><td style="border:1px solid #c8d6e5;padding:2px 8px;">Gemma 4 31B &#xFF0F; Qwen3.5-27B</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">Around 30B with 0.80-class overall scores. The realistic answer for on-premises and confidential-data use</td></tr>
    <tr><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">Small / edge</td><td style="border:1px solid #c8d6e5;padding:2px 8px;">Qwen3.5-4B &#xFF0F; Gemma 4 E4B</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">Above 0.73 overall in the 4B class. For on-device and low-resource environments</td></tr>
    <tr><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">Japanese-specialized</td><td style="border:1px solid #c8d6e5;padding:2px 8px;">NVIDIA Nemotron Nano 9B v2 Japanese &#xFF0F; RakutenAI-3.0</td><td style="border:1px solid #c8d6e5;padding:2px 8px;text-align:center;">Specialized models further trained on Japanese data. For domestic operation and Japanese-language work</td></tr>
  </tbody>
</table></div>
<!--kg-card-end: html-->
<h3 id="toward-full-scale-llm-adoption-choosing-the-right-model-for-each-use-case">Toward Full-Scale LLM Adoption: Choosing the Right Model for Each Use Case</h3><p>This report has mapped each model&apos;s position around overall scores, but real adoption decisions are not that simple.</p><p>Benchmarks are strong reference material, yet practice demands multifaceted evaluation: not just accuracy but deployment cost, inference cost, response speed, handling of confidential data, and integration with existing systems. Licensing, too &#x2014; what is called &quot;open source&quot; or an &quot;open model&quot; in name can conceal pitfalls on closer inspection.</p><p>Especially in a moment like this one, when the options have expanded rapidly, what matters on the ground is less &quot;picking the single highest-scoring model&quot; than &quot;building the ability to use multiple models appropriately across use cases.&quot;</p><p>To support this kind of multi-model operation in practice, we provide our integrated AI platform <a href="https://bestllam.com/?ref=journal.qualiteg.com">Bestllam </a>, which lets you use multiple LLMs on a single platform.</p><p>We can support you end to end &#x2014; from clarifying the issues around commercial use and selecting models, to embedding them in business workflows and designing operations built around AI agents.</p><p>Beyond simply providing tools, we also offer <a href="https://qualiteg.com/consulting/business?ref=journal.qualiteg.com#ai-transformation">BPR consulting aimed at AI-enabling your business operations</a>, accompanying you not only on AI technology but from upstream business analysis through AI-native BPR planning, success-metric design, and deployment support.</p><p><strong>Please feel free to get in touch.</strong><br><a href="https://qualiteg.com/contact?inquiry=consulting&amp;ref=journal.qualiteg.com">https://qualiteg.com/contact?inquiry=consulting</a></p>]]></content:encoded></item><item><title><![CDATA[The Complete Guide to Claude Fable 5 — Model Specs and Claude Code Operations from the Official Docs]]></title><description><![CDATA[<p></p><p>Hello! <br><br>Claude Fable 5, which arrived in June 2026, has had an eventful first month: a suspension under export controls right after release, a global re-rollout, and then its departure from the subscription allowance.</p><p>This blog has followed the situation at each turn.</p><p>For the overall picture, see <a href="https://journal.qualiteg.com/claude-fable-5-mythos-5-guide-benchmarks/">Finally Generally</a></p>]]></description><link>https://journal.qualiteg.com/claude-fable-5-claude-code-guide/</link><guid isPermaLink="false">6a4c9570edf69a17d422a6a9</guid><category><![CDATA[ClaudeCode]]></category><category><![CDATA[AI Agents]]></category><category><![CDATA[Generative AI Frontlines]]></category><dc:creator><![CDATA[Qualiteg Product Development Team]]></dc:creator><pubDate>Thu, 09 Jul 2026 22:55:05 GMT</pubDate><media:content url="https://journal.qualiteg.com/content/images/2026/07/claude-fable-5-claude-code-guide--1-.png" medium="image"/><content:encoded><![CDATA[<img src="https://journal.qualiteg.com/content/images/2026/07/claude-fable-5-claude-code-guide--1-.png" alt="The Complete Guide to Claude Fable 5 &#x2014; Model Specs and Claude Code Operations from the Official Docs"><p></p><p>Hello! <br><br>Claude Fable 5, which arrived in June 2026, has had an eventful first month: a suspension under export controls right after release, a global re-rollout, and then its departure from the subscription allowance.</p><p>This blog has followed the situation at each turn.</p><p>For the overall picture, see <a href="https://journal.qualiteg.com/claude-fable-5-mythos-5-guide-benchmarks/">Finally Generally Available: Reading Claude Mythos 5 / Fable 5 from a Practitioner&apos;s Perspective</a>; for the suspension drama right after release, see <a href="https://journal.qualiteg.com/fable-5-mythos-5-us-government-directive/">Suspended Three Days After Release &#x2014; the U.S. Government Directive on Fable 5 / Mythos 5 and the New Availability Risk of AI</a>; and for pricing and the outlook, see <a href="https://journal.qualiteg.com/claude-fable5-cost-and-outlook/">What Happens Next for Claude Fable 5? Background, Costs, and Outlook</a>.<br><br>This article builds on those to serve as &quot;the definitive guide for practical use.&quot;</p><p>In particular, <br><br> <strong>as of July 12, 2026 (July 13 Japan time), it leaves the subscription allowance and cannot be used unless usage credits are enabled</strong> <br>(This deadline was initially set at July 7, 2026, and was later extended by five days to July 12.)<br><br> &#x2014; with this major pricing change as the axis, this article brings together the model specifications, the realities of pricing, and the operational points to watch when using it in <a href="https://journal.qualiteg.com/claude-opus-4-8-claude-code-guide/">Claude Code</a>. Including how to divide roles with Opus 4.8, we provide the material for judging <br><br><strong>&quot;how much Fable 5 is worth paying for&quot;</strong><br><br> for yourself.</p><p>This guide therefore takes Anthropic&apos;s official announcements and documentation as its baseline, and organizes <br>Claude Fable 5 (<code>claude-fable-5</code>) around the three questions of<br><br><strong> &quot;understanding it as a model,&quot;<br> &quot;grasping the pricing and the treatment of the subscription allowance,&quot;<br> and &quot;operating it economically in Claude Code by combining Fable with less expensive models&quot;</strong><br><br>.<br><br>With that, let us get into the main content.</p><blockquote>Incidentally, in the early morning of this article&apos;s publication date (2026/7/10), the weekly rate limit was abruptly lifted, effectively expanding Fable 5&apos;s usage allowance once again</blockquote><figure class="kg-card kg-embed-card"><blockquote class="twitter-tweet"><p lang="en" dir="ltr">We&apos;ve reset 5-hour and weekly rate limits for all users.</p>&#x2014; ClaudeDevs (@ClaudeDevs) <a href="https://x.com/ClaudeDevs/status/2075279141352706215?ref_src=twsrc%5Etfw&amp;ref=journal.qualiteg.com">July 9, 2026</a></blockquote>
<script async src="https://platform.x.com/widgets.js" charset="utf-8"></script></figure><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://journal.qualiteg.com/content/images/2026/07/image-2.png" class="kg-image" alt="The Complete Guide to Claude Fable 5 &#x2014; Model Specs and Claude Code Operations from the Official Docs" loading="lazy" width="349" height="127"><figcaption><span style="white-space: pre-wrap;">Source: X, 2026/7/10</span></figcaption></figure>
<!--kg-card-begin: html-->
<p><strong>Table of Contents</strong></p>
<ul>
  <li><a href="#%E7%AC%AC1%E9%83%A8%EF%BC%9Aclaude-fable-5%E3%81%A8%E3%81%AF%E4%BD%95%E3%81%8B">Part 1: What Is Claude Fable 5?</a>
    <ul>
      <li><a href="#fable-5%E3%81%AE%E4%BD%8D%E7%BD%AE%E3%81%A5%E3%81%91">Where Fable 5 fits</a></li>
      <li><a href="#%E7%99%BA%E8%A1%A8%E3%83%BB%E8%BC%B8%E5%87%BA%E8%A6%8F%E5%88%B6%E3%83%BB%E5%86%8D%E5%B1%95%E9%96%8B%E3%81%AE%E3%82%BF%E3%82%A4%E3%83%A0%E3%83%A9%E3%82%A4%E3%83%B3">Timeline: announcement, export controls, re-rollout</a></li>
      <li><a href="#%E3%83%A2%E3%83%87%E3%83%AB%E3%81%A8%E3%81%97%E3%81%A6%E3%81%AE%E4%BB%95%E6%A7%98">Specifications as a model</a></li>
      <li><a href="#%E4%BC%81%E6%A5%AD%E5%88%A9%E7%94%A8%E5%89%8D%E3%81%AB%E7%A2%BA%E8%AA%8D%E3%81%99%E3%81%B9%E3%81%8D%E5%88%B6%E7%B4%84%EF%BC%88%E3%83%87%E3%83%BC%E3%82%BF%E4%BF%9D%E6%8C%81%EF%BC%89">Constraints to check before enterprise use (data retention)</a></li>
      <li><a href="#%E3%83%99%E3%83%B3%E3%83%81%E3%83%9E%E3%83%BC%E3%82%AF%E3%81%AE%E8%AA%AD%E3%81%BF%E6%96%B9">How to read the benchmarks</a></li>
      <li><a href="#%E4%B8%BB%E8%A6%81%E3%81%AAapi%E5%B7%AE%E5%88%86">Key API differences</a></li>
      <li><a href="#mythos-5%E3%81%A8%E3%81%AE%E9%96%A2%E4%BF%82">Relationship to Mythos 5</a></li>
    </ul>
  </li>
  <li><a href="#%E7%AC%AC2%E9%83%A8%EF%BC%9A%E6%96%99%E9%87%91%E3%81%A8%E3%82%B5%E3%83%96%E3%82%B9%E3%82%AF%E6%9E%A0%E3%81%8B%E3%82%89%E3%81%AE%E7%A7%BB%E8%A1%8C%EF%BC%88%E6%9C%80%E9%87%8D%E8%A6%81%EF%BC%89">Part 2: Pricing and the move out of the subscription allowance (most important)</a>
    <ul>
      <li><a href="#%E6%8F%90%E4%BE%9B%E6%96%B9%E6%B3%95%E3%81%AE%E5%A4%89%E6%9B%B4%E3%81%A87%E6%9C%887%E6%97%A5%E3%81%8B%E3%82%897%E6%9C%8812%E6%97%A5%E3%81%B8%E3%81%AE%E6%9C%9F%E9%99%90%E5%BB%B6%E9%95%B7">The change in delivery and the deadline extension from July 7 to July 12</a></li>
      <li><a href="#%E4%BD%BF%E7%94%A8%E3%82%AF%E3%83%AC%E3%82%B8%E3%83%83%E3%83%88%E3%81%AE%E4%BB%95%E7%B5%84%E3%81%BF%E3%81%A8%E7%AE%A1%E7%90%86%E7%94%BB%E9%9D%A2">How usage credits work and the management screen</a></li>
      <li><a href="#%E4%B8%8A%E9%99%90%E3%83%BB%E6%AE%8B%E9%AB%98%E3%83%BB%E4%BA%8B%E5%89%8D%E8%B3%BC%E5%85%A5%E3%81%AE%E5%89%B2%E5%BC%95%EF%BC%88%E3%81%9D%E3%82%8C%E3%81%9E%E3%82%8C%E5%88%A5%E7%89%A9%EF%BC%89">Limits, balance, and prepaid discounts (each a separate thing)</a></li>
      <li><a href="#%E3%82%B3%E3%82%B9%E3%83%88%E8%A9%A6%E7%AE%97%E3%81%A8%E3%80%81%E8%87%AA%E5%88%86%E3%81%A7%E5%AE%9F%E6%B8%AC%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95">Cost estimates, and how to measure for yourself</a></li>
      <li><a href="#%E4%BE%A1%E6%A0%BC%E6%AF%94%E8%BC%83%EF%BC%882026%E5%B9%B47%E6%9C%889%E6%97%A5%E6%99%82%E7%82%B9%EF%BC%89">Price comparison (as of July 9, 2026)</a></li>
    </ul>
  </li>
  <li><a href="#%E7%AC%AC3%E9%83%A8%EF%BC%9Aclaude-code-%E3%81%A7%E4%BD%BF%E3%81%86-fable-5">Part 3: Fable 5 in Claude Code</a>
    <ul>
      <li><a href="#%E5%89%8D%E6%8F%90%E6%9D%A1%E4%BB%B6%E3%81%A8%E3%83%A2%E3%83%87%E3%83%AB%E9%81%B8%E6%8A%9E">Prerequisites and model selection</a></li>
      <li><a href="#%E3%82%AF%E3%83%AC%E3%82%B8%E3%83%83%E3%83%88%E3%81%AE%E6%9C%89%E5%8A%B9%E5%8C%96%E3%81%A8%E4%B8%8A%E9%99%90%E8%A8%AD%E5%AE%9A">Enabling credits and setting limits</a></li>
      <li><a href="#effort%E3%83%BB1m%E3%82%B3%E3%83%B3%E3%83%86%E3%82%AD%E3%82%B9%E3%83%88%E3%83%BB%E3%83%97%E3%83%AD%E3%83%B3%E3%83%97%E3%83%88%E3%82%AD%E3%83%A3%E3%83%83%E3%82%B7%E3%83%A5">effort, the 1M context, and prompt caching</a></li>
      <li><a href="#%E6%8B%92%E5%90%A6%EF%BC%88refusal%EF%BC%89%E3%81%A8%E3%83%95%E3%82%A9%E3%83%BC%E3%83%AB%E3%83%90%E3%83%83%E3%82%AF%E3%81%AE%E5%AE%9F%E5%8B%99">Refusals and fallback in practice</a></li>
      <li><a href="#fable-5-%E3%82%92-claude-code-%E3%81%A7%E7%8F%BE%E5%AE%9F%E7%9A%84%E3%81%AB%E4%BD%BF%E3%81%86-%E2%80%95-%E5%8F%B8%E4%BB%A4%E5%A1%94%E3%81%A8%E5%AE%9F%E5%83%8D%E3%81%A7%E3%83%A2%E3%83%87%E3%83%AB%E3%82%92%E5%88%86%E3%81%91%E3%82%8B">Using Fable 5 realistically in Claude Code &#x2014; splitting models into commander and workers</a></li>
      <li><a href="#%E5%AE%89%E5%85%A8%E5%88%86%E9%A1%9E%E5%99%A8%E3%81%AB%E3%82%88%E3%82%8B%E8%AA%A4%E6%A4%9C%E7%9F%A5%E3%81%B8%E3%81%AE%E5%AF%BE%E5%87%A6">Handling false positives from the safety classifier</a></li>

    </ul>
  </li>
  <li><a href="#%E3%81%BE%E3%81%A8%E3%82%81-%E2%80%95-fable-5-%E3%81%A8%E3%81%AE%E4%BB%98%E3%81%8D%E5%90%88%E3%81%84%E6%96%B9">Conclusion &#x2014; how to live with Fable 5</a></li>
</ul>
<!--kg-card-end: html-->
<hr><h1 id="part-1-what-is-claude-fable-5">Part 1: What Is Claude Fable 5?</h1><h2 id="where-fable-5-fits">Where Fable 5 Fits</h2><p>Claude Fable 5, announced by Anthropic on <strong>June 9, 2026</strong>, is the most capable model the company currently makes generally available (GA).</p><p>The official documentation positions Fable 5 as <br><br><strong>&quot;Anthropic&apos;s most capable broadly available model, designed for the most advanced reasoning and long-horizon autonomous (agentic) work&quot;</strong><br><br>.</p><p>The key concept is <strong>&quot;<u>long-horizon agentic work</u>&quot; (long stretches of autonomous work)</strong>.<br></p><p>What distinguishes Fable 5 is that its lead over other models widens as tasks grow longer and more complex, more than in one-off Q&amp;A.</p><p>As an example cited at announcement, the payments company Stripe stated that it &quot;completed a migration of a Ruby codebase exceeding 50 million lines &#x2014; work that would normally take a team more than two months &#x2014; in one day,&quot; <strong>reported as an early customer example</strong> (note that this is Stripe&apos;s report, not a general performance guarantee).</p><p>Fable 5 is &quot;Mythos-class&quot; &#x2014; that is, it carries capabilities from the same lineage as Anthropic&apos;s top research model, released with safeguards built in to make it suitable for general use.</p><blockquote><strong>Why It Is Not &quot;an Upgraded Opus 4.8&quot;</strong><br>Fable 5 is not Opus&apos;s successor. Opus 4.8 (<code>claude-opus-4-8</code>) remains &quot;the newest and highest model in the Opus tier,&quot; and for most practical work it is the standard choice. Fable 5 sits <strong>above</strong> the Opus tier &#x2014; a separate bracket in both price and capability. So the answer to the common request &quot;I want to upgrade to the latest model&quot; is still Opus 4.8. Understand Fable 5 as the model you choose explicitly when you want the hardest problems solved, with the cost accepted up front.</blockquote><h2 id="timeline-announcement-export-controls-re-rollout">Timeline: Announcement, Export Controls, Re-rollout</h2><p>Fable 5 followed an unusual path entangled with national security and export controls.</p><p>Here is the chronology.</p><figure class="kg-card kg-image-card"><img src="https://journal.qualiteg.com/content/images/2026/07/timeline_fable5-1.png" class="kg-image" alt="The Complete Guide to Claude Fable 5 &#x2014; Model Specs and Claude Code Operations from the Official Docs" loading="lazy" width="2000" height="838" srcset="https://journal.qualiteg.com/content/images/size/w600/2026/07/timeline_fable5-1.png 600w, https://journal.qualiteg.com/content/images/size/w1000/2026/07/timeline_fable5-1.png 1000w, https://journal.qualiteg.com/content/images/size/w1600/2026/07/timeline_fable5-1.png 1600w, https://journal.qualiteg.com/content/images/2026/07/timeline_fable5-1.png 2100w" sizes="(min-width: 720px) 720px"></figure>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>Date (2026)</th>
<th>Event</th>
</tr>
</thead>
<tbody>
<tr>
<td>June 9</td>
<td>Claude Fable 5 becomes generally available on the API, Claude.ai, and Claude Code. Claude Mythos 5, which has no safety classifiers, is limited to Project Glasswing participant organizations and similar.</td>
</tr>
<tr>
<td>June 12</td>
<td>The U.S. government applies export controls to the new models, restricting access by foreign nationals. In the background, an Amazon researcher had discovered a technique for bypassing Fable 5&apos;s safeguards.</td>
</tr>
<tr>
<td>June 30</td>
<td>The export controls are lifted.</td>
</tr>
<tr>
<td>July 1</td>
<td>Fable 5 is re-released globally with an improved classifier, available on the Claude Platform, Claude.ai, Claude Code, and Claude Cowork (Mythos 5 remains limited).</td>
</tr>
<tr>
<td>July 7 (original deadline)</td>
<td>This was initially the last day Fable 5 could be used within the subscription&apos;s weekly allowance (up to 50% of the weekly allowance).</td>
</tr>
<tr>
<td>Around July 7</td>
<td>Anthropic announces a five-day extension of the deadline to July 12, 23:59:59 (PT), stated explicitly in the official support article. That corresponds to July 13 Japan time.</td>
</tr>
<tr>
<td>July 12 (PT / final day after extension)</td>
<td>The last day of use within the subscription&apos;s weekly allowance on Pro / Max / Team and premium-seat Enterprise plans (up to 50% of the weekly allowance).</td>
</tr>
<tr>
<td>After July 12 ends (from July 13 Japan time)</td>
<td>Fable 5 leaves the subscription allowance and moves to access via usage credits.</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>For the re-rollout, Anthropic introduced a new safeguard classifier. Per the official explanation, &quot;the specific technique described in Amazon&apos;s report is now blocked in more than 99% of cases,&quot; while &quot;the safety margin has been expanded substantially&quot; &#x2014; with the result that <strong>more benign requests are also blocked</strong> than before.</p><p>Anthropic explicitly states </p><blockquote><em>&quot;In the near term, some routine tasks like coding and debugging may be flagged more often.&quot;</em><br> (meaning: for the time being, everyday tasks such as coding and debugging may be flagged more often than before)</blockquote><p>. Because this matters in practice for using Fable 5 in Claude Code, we revisit it in Part 3.</p><p>The suspension under export controls and the re-rollout themselves &#x2014; and the &quot;new availability risk of AI&quot; they reveal &#x2014; are explored in depth in <br><br><a href="https://journal.qualiteg.com/fable-5-mythos-5-us-government-directive/">Suspended Three Days After Release &#x2014; the U.S. Government Directive on Fable 5 / Mythos 5 and the New Availability Risk of AI</a> <br><br>.</p><h2 id="specifications-as-a-model">Specifications as a Model</h2><p>Here are the key specifications, based on the official documentation. Unit prices are as of July 9, 2026, as noted below.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>Item</th>
<th>Value</th>
</tr>
</thead>
<tbody>
<tr>
<td>Model ID</td>
<td><code>claude-fable-5</code></td>
</tr>
<tr>
<td>Context window</td>
<td>1M (1,000,000) tokens (default = maximum; no long-context premium)</td>
</tr>
<tr>
<td>Max output tokens</td>
<td>128K (128,000) tokens / request</td>
</tr>
<tr>
<td>Input price</td>
<td>$10 / million tokens</td>
</tr>
<tr>
<td>Output price</td>
<td>$50 / million tokens</td>
</tr>
<tr>
<td>Cache reads</td>
<td>approx. $1 / million tokens</td>
</tr>
<tr>
<td>Cache writes</td>
<td>5-minute retention $12.50 / million; 1-hour retention $20 / million</td>
</tr>
<tr>
<td>Tokenizer</td>
<td>Same as Opus 4.8 (introduced with Opus 4.7)</td>
</tr>
<tr>
<td>Data retention</td>
<td>30-day retention required (not available under zero data retention = ZDR)</td>
</tr>
<tr>
<td>Thinking mode</td>
<td>Adaptive thinking only (always on)</td>
</tr>
<tr>
<td>Supported features</td>
<td>effort, memory tool, code execution, context editing (beta), compaction, Vision (high resolution), and more</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<ul><li><strong>The 1M context comes at standard pricing</strong>, with no surcharge (premium) for long context.</li><li><strong>The tokenizer is identical to Opus 4.8&apos;s</strong>, so if you migrate from Opus 4.7 / 4.8, the token count for the same text is essentially unchanged.<br>What changes is the <strong>unit price</strong>. If you move from Opus 4.6 or earlier, Sonnet, or Haiku, token counts will shift, so re-measure with <code>count_tokens</code>.</li></ul><h2 id="constraints-to-check-before-enterprise-use-data-retention">Constraints to Check Before Enterprise Use (Data Retention)</h2><p>Fable 5 comes with the following constraints.<br>If they do not immediately click on first reading, that is fine.<br>Below them we have added a <strong>plain-language explanation</strong>.</p><blockquote><strong>Fable 5 / Mythos 5 are &quot;Covered Models,&quot; and 30-day data retention is mandatory. They cannot be used under zero data retention (ZDR).</strong><br><br>More than performance or price, this is the constraint that decides whether enterprise adoption is possible. Before adopting, check at least the following.Do your contracts and internal rules permit sending confidential code and data to Fable 5?Existing <strong>ZDR-based workloads cannot be migrated as they are</strong>. Thirty-day retention is required on every serving platform, but <code>400 invalid_request_error</code> is officially documented only for <strong>Claude API</strong> (when the organization/workspace retention settings do not meet the requirement). Display and error behavior via Claude Code or each cloud varies by endpoint (for example, Fable disappearing from the model choices).For each connecting platform &#x2014; Bedrock / Vertex / Foundry and so on &#x2014; confirm where and under what conditions data is retained.</blockquote><h3 id="plain-language-explanation-%E2%86%92-the-basic-rule"><strong>Plain-language explanation &#x2192; the basic rule</strong></h3><p>What the above means is this: the text we send to Fable 5, and the text Fable 5 returns, <strong>is always stored for 30 days</strong>. You cannot delete it. You cannot opt out.</p><p>Other Claude models (Opus 4.8 and so on) can be set to &quot;do not store.&quot; Only Fable 5 cannot.</p><p><strong>Why is it stored?</strong></p><p>Because Fable 5 is powerful, it is monitored for abuse. Abuse cannot be spotted in a single exchange; only when hundreds of exchanges are laid side by side does it become clear that &quot;this is an attack.&quot; The stored data is not used to train AI.</p><p><strong>What is the problem?</strong></p><p>Some companies hold contracts (ZDR) stating &quot;none of our data is ever stored.&quot; That contract <strong>does not apply to Fable 5</strong>. The retention requirement takes precedence over the contract.</p><p>In other words, if you send confidential source code or customer data to Fable 5, it will remain somewhere for 30 days. And if it is judged dangerous, a human may look at its contents.</p><h2 id="how-to-read-the-benchmarks">How to Read the Benchmarks</h2><p>For benchmark details, we defer to our separate article below.</p><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://journal.qualiteg.com/claude-fable-5-mythos-5-guide-benchmarks/"><div class="kg-bookmark-content"><div class="kg-bookmark-title">Finally Generally Available: A Practitioner&apos;s Read on Claude Mythos 5 / Fable 5</div><div class="kg-bookmark-description">Hello! This is the Qualiteg Product Development Team. On June 9, 2026, Anthropic announced Claude Fable 5 and Claude Mythos 5. In this article, we sort out what&#x2026;</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://blog.qualiteg.com/content/images/size/w256h256/2024/04/q_logo_20231023_150x150.png" alt="The Complete Guide to Claude Fable 5 &#x2014; Model Specs and Claude Code Operations from the Official Docs"><span class="kg-bookmark-author">Qualiteg Blog</span><span class="kg-bookmark-publisher">Qualiteg &#x30B3;&#x30F3;&#x30B5;&#x30EB;&#x30C6;&#x30A3;&#x30F3;&#x30B0;</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://blog.qualiteg.com/content/images/2026/06/claude-fable-5-mythos-5-guide-benchmarks--1-.png" alt="The Complete Guide to Claude Fable 5 &#x2014; Model Specs and Claude Code Operations from the Official Docs"></div></a></figure><p></p><h2 id="key-api-differences">Key API Differences</h2><p>First, let us look at the API-level differences from Opus.</p><p>Fable 5 largely shares the API request surface with the Opus tier (4.7 / 4.8), but there are differences that can turn existing implementations into <code>400</code> responses on migration.<br>Here are the main ones (not exhaustive).</p><h3 id="1-thinking-is-always-on">1. Thinking is always on</h3><p>Adaptive thinking is the only thinking mode, and omitting <code>thinking</code> enables it automatically.<strong>Explicitly sending <code>thinking: {type: &quot;disabled&quot;}</code> returns a 400</strong> (specific to Fable 5; disabled is accepted on Opus 4.7 / 4.8).<code>budget_tokens</code> has also been removed and returns a 400 if sent. Depth is controlled with <code>output_config.effort</code> (<code>low</code> to <code>max</code>).</p><h3 id="2-sampling-parameters-are-not-supported">2. Sampling parameters are not supported</h3><p><code>temperature</code> / <code>top_p</code> / <code>top_k</code> return a 400 if you send non-default values. Steer output tendencies through the prompt.</p><h3 id="3-maxtokens-is-the-total-of-thinking-plus-the-final-answer">3. <code>max_tokens</code> is the total of thinking plus the final answer</h3><p><code>max_tokens</code> is a cap that includes <strong>both</strong> thinking tokens and the final answer. At high effort, thinking consumes many tokens, so a small cap will cut the answer off midway.</p><h3 id="4-raw-chain-of-thought-is-not-returned">4. Raw chain of thought is not returned</h3><p>What comes back is a normal <code>thinking</code> block; with <code>display: &quot;summarized&quot;</code> it contains a summary, and with <code>&quot;omitted&quot;</code> (the default) it is an empty string. Thinking runs and is billed regardless of the display setting.</p><h3 id="5-a-stop-reason-called-refusal">5. A stop reason called refusal</h3><p>Fable 5 runs a safety classifier over the input. When refused, <strong>you get an HTTP 200 success response, not an error</strong>, with <code>stop_reason: &quot;refusal&quot;</code> returned and <code>stop_details</code> carrying the category.</p><ul><li><strong>Before output</strong> &#x2014; refusal: <code>content</code> is empty, and there is <strong>no charge</strong>.</li><li><strong>Mid-stream</strong> refusal: the portion already generated is billable (discard the partial output; do not use it).</li></ul><p><code>response.content[0]</code> &#x2014; code that reads this unconditionally will break.<strong>Always check <code>stop_reason</code> first</strong>. In practice, judge in the following order: (1) HTTP status &#x2192; (2) <code>stop_reason</code> &#x2192; &#x2462;<code>stop_details</code> logged &#x2192; (4) <code>content</code> confirmed non-empty &#x2192; (5) on refusal, do not use the partial output.</p><h3 id="6-fallback-rescuing-refusals-with-another-model">6. Fallback (rescuing refusals with another model)</h3><p>Server-side <code>fallbacks</code> automatically re-runs the same request on another model upon a policy refusal &#x2014; <strong>an opt-in beta feature</strong> (<code>server-side-fallback-2026-06-01</code>) that <strong>must be specified explicitly</strong> (it is not on by default).</p><p>Currently it is available on <strong>the Claude API and Claude Platform on AWS</strong>; <br><br><strong>on the Message Batches API, Amazon Bedrock, Google Cloud, and Microsoft Foundry it is <u>not available</u></strong>, <br><br>requiring client-side re-execution or SDK middleware. The model to fall back to is <strong>specified explicitly in the request&apos;s <code>fallbacks</code> array</strong>.<br> (The official example is Opus 4.8; the Anthropic API does not automatically pin the fallback to Opus 4.8.)<br><br>What differs by endpoint is &quot;whether server-side <code>fallbacks</code> can be used.&quot; If you are writing new <code>claude-fable-5</code> code, we recommend <strong>putting this fallback in explicitly</strong>.</p><h2 id="relationship-to-mythos-5">Relationship to Mythos 5</h2><p>Claude Mythos 5 (<code>claude-mythos-5</code>) shares <strong>the same base model, context length, maximum output, and pricing structure</strong> with Fable 5.<br><br>However, <strong>it does not carry the safety classifiers added to Fable 5</strong>, so the actual API behavior, including refusals and automatic fallback, is not identical<br> (the refusal and fallback descriptions apply to Fable 5 only).<br><br>Mythos 5 is limited to Project Glasswing participant organizations and the like; general users use <code>claude-fable-5</code>.<br><br>It is the successor to the formerly invitation-only <code>claude-mythos-preview</code>. For the difference in positioning between Mythos 5 and Fable 5 and a reading of the benchmarks, see also <a href="https://journal.qualiteg.com/claude-fable-5-mythos-5-guide-benchmarks/">Finally Generally Available: Reading Claude Mythos 5 / Fable 5 from a Practitioner&apos;s Perspective</a>.</p><hr><h1 id="part-2-pricing-and-the-move-out-of-the-subscription-allowance-most-important">Part 2: Pricing and the Move out of the Subscription Allowance (Most Important)</h1><h2 id="the-change-in-delivery-and-the-deadline-extension-from-july-7-to-july-12">The Change in Delivery and the Deadline Extension from July 7 to July 12</h2><p>When Fable 5 was re-released on July 1, its inclusion in subscriptions came with a deadline.</p><p>That deadline was initially July 7, 2026, but just before it arrived, Anthropic abruptly extended it by five days, finally setting it at July 12, 2026 (23:59:59 U.S. Pacific Time; July 13 Japan time).</p><p>The cap of up to 50% of the weekly allowance, and the switch to credit-based use after the deadline, have been unchanged since the July 1 re-release.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>Period</th>
<th>Treatment of Fable 5</th>
</tr>
</thead>
<tbody>
<tr>
<td>Until the original July 7, 2026 (before the change)</td>
<td>The subscription-inclusion deadline was initially set for this date.</td>
</tr>
<tr>
<td>Until July 12, 2026 (after extension, PT basis / until July 13 Japan time)</td>
<td>Usable on Pro / Max / Team and premium-seat Enterprise plans, up to 50% of the normal weekly allowance.</td>
</tr>
<tr>
<td>After July 12 ends (from July 13 Japan time)</td>
<td>Leaves the subscription allowance and moves to pay-as-you-go via usage credits (standard API pricing). Without credits enabled, Fable 5 requests will not run.</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>The cutoff is 23:59:59 on July 12 (U.S. Pacific Time; the afternoon of July 13 in Japan). Confirm the actual switchover timing on your account screen (described below) as well.</p><blockquote><strong>On the possibility of returning to subscriptions</strong><br>Anthropic has indicated it would like to bring Fable 5 back into the subscription allowance if capacity can be secured, but <strong>neither the timing nor the implementation is guaranteed</strong>. Deadlines have moved once already, so the realistic approach is to keep checking the latest official guidance while planning operations on a credit basis for now.</blockquote><h2 id="how-usage-credits-work-and-the-management-screen">How Usage Credits Work and the Management Screen</h2><p>Usage credits are a pay-as-you-go layer available on paid plans such as Pro / Max. Originally designed so you could &quot;keep working after hitting your plan limit,&quot; after July 12 (from July 13 Japan time) they become the entry point to Fable 5.</p><p>Note, however, that &quot;general extra usage credits (for continuing after hitting the plan cap)&quot; and &quot;the delivery of Fable 5 after July 12&quot; are officially separate announcements.</p><p>Anthropic describes the latter as &quot;provided via usage credits,&quot; and <strong>we will not assert the specific consumption order &#x2014; whether Fable 5 draws down the normal allowance first before moving to credits, or consumes credits from the start</strong>. Confirm actual allowance consumption on your account screen and in the latest official guidance.</p><p>Management happens in <strong>claude.ai under Settings &#x2192; Usage</strong>. Looking at the actual screen (with the subscription allowance used up and credits turned on) makes the mechanics concrete.</p><blockquote><strong>Who can configure this differs by plan</strong>. The screen examples and steps below assume <strong>a Pro / Max individual account</strong>.<strong>Team</strong> and <strong>seat-based Enterprise</strong> plans: the Owner / Primary Owner enables credits and sets limits from Organization settings &#x2192; Usage.<strong>usage-based Enterprise</strong> is not a use-up-included-allowance scheme; in principle it is billed per token from the first token.</blockquote><figure class="kg-card kg-image-card"><img src="https://journal.qualiteg.com/content/images/2026/07/kakin_fable5.png" class="kg-image" alt="The Complete Guide to Claude Fable 5 &#x2014; Model Specs and Claude Code Operations from the Official Docs" loading="lazy" width="1012" height="752" srcset="https://journal.qualiteg.com/content/images/size/w600/2026/07/kakin_fable5.png 600w, https://journal.qualiteg.com/content/images/size/w1000/2026/07/kakin_fable5.png 1000w, https://journal.qualiteg.com/content/images/2026/07/kakin_fable5.png 1012w" sizes="(min-width: 720px) 720px"></figure><p><em>* Display example from our own account in early July 2026. You can see the Fable 5 subscription allowance has been used up and usage has moved to the credit allowance.</em></p><p>Here is what can be read from this screen.</p><ul><li><strong>Usage allowances are displayed per model</strong>. &quot;All models&quot; and &quot;Fable&quot; appear as separate bars; in the example above, <strong>the Fable allowance is 100% used</strong> (the subscription allowance is exhausted).</li><li><strong>Usage credits can be toggled ON/OFF</strong>. The framing is that you turn credits on &quot;to keep using Claude even after reaching your limit.&quot;</li><li><strong>Usage is displayed in real time</strong> (e.g., $68.69 used / 27% of the limit, with the reset date).</li></ul><h2 id="limits-balance-and-prepaid-discounts-each-a-separate-thing">Limits, Balance, and Prepaid Discounts (Each a Separate Thing)</h2><p><br><strong>&quot;If I turn credits on, won&apos;t spending run away without limit?&quot;</strong></p><p>You may worry about that, but <br><strong>you can set a spending limit on credits</strong></p><p>With credits on, there are three concepts to know</p><ul><li><strong>Monthly spending limit</strong><br>The cap on credit spending for the month (e.g., $250.00). You can change it via &quot;Adjust limit.&quot; However, <strong>&quot;no limit&quot; is also selectable</strong>, so merely enabling credits does not guarantee a spending cap. Especially if you use auto-reload, always confirm the monthly limit is set to the amount you intend.<br></li><li><strong>Credit balance</strong><br>The balance you currently hold (e.g., $181.31).<strong>Auto-reload</strong>An ON/OFF switch controlling whether the balance is automatically topped up as it runs down, or replenished manually (auto-reload combined with &quot;no limit&quot; can effectively become unbounded).<br></li><li><strong>Discount bundles (prepurchase)</strong><br>A &quot;bulk purchase&quot; product separate from limits and balance. Think of it as charging up your billing allowance in advance.<br><br> <strong>$50 worth = 10% off (pay $45)<br>$250 worth = 20% off ($200)<br>$1,000 worth = 30% off ($700)</strong><br><br>For example, buying $250 worth applies the 20% discount, so you pay $200. In practice, 10% consumption tax is added, for a payment of $220.<br><br></li></ul><p>In short, Fable 5 costs are managed with separate levers: <strong>the monthly limit (no limit unless you set one), the held balance, auto-reload, and prepurchased discount bundles</strong>.</p><p>Set a monthly limit to avoid unbounded spend, and charge up in advance to buy your billing allowance at a modest discount &#x2014; that is the shape of it.</p><h2 id="cost-estimates-and-how-to-measure-for-yourself">Cost Estimates, and How to Measure for Yourself</h2><p>Here are simple estimates based on Fable 5&apos;s unit prices (input $10 / output $50 per 1M).<strong>All assume no caching, no retries, no fallback, and no tax or exchange-rate effects</strong>.</p><h3 id="case-a-chat-centric-200k-input-50k-output-tokens-per-day">Case A: chat-centric (200K input + 50K output tokens per day)</h3><ul><li>Input: 0.2M &#xD7; $10 = $2.0</li><li>Output: 0.05M &#xD7; $50 = $2.5</li><li><strong>About $4.5 per day &#x2192; about $135 per month</strong></li></ul><p>This is a simple estimate that assumes <strong>all Fable 5 usage is billed to credits</strong>.</p><h3 id="case-b-autonomous-coding-in-claude-code">Case B: autonomous coding in Claude Code</h3><p>What drives cost is less chat than <strong>agentic coding</strong>. Long Claude Code sessions repeatedly load context, call tools, and self-verify, so token consumption is large.</p><p>Actual consumption, however, varies greatly with <strong>the model, codebase size, parallelism (number of subagents), caching, retries/fallback, and usage pattern</strong>.</p><p>The official documentation likewise explains that costs vary substantially with these factors.</p><p>Generalizations like &quot;X dollars per hour&quot; are unreliable unless measurement conditions match.<strong>Measuring in your own environment</strong> is the dependable way.</p><p>Concretely, record the following per session and apply the price table (input $10 / output $50 / cache reads $1 / cache writes $12.50&#x2013;$20, all per 1M):</p><ul><li>Model used / input tokens / output tokens</li><li>Cache-creation tokens / cache-read tokens</li><li>Fallback count / number of subagents / session duration</li></ul><p>Fable 5 costs twice Opus 4.8 per token, so <strong>with regular use, credit consumption can reach a scale that cannot be ignored</strong>.</p><p>That is exactly why the Part 3 question of &quot;when to use Fable 5&quot; is itself cost management.</p><h2 id="price-comparison-as-of-july-9-2026">Price Comparison (as of July 9, 2026)</h2>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>Model</th>
<th>Input / 1M</th>
<th>Output / 1M</th>
<th>Context</th>
<th>Notes</th>
</tr>
</thead>
<tbody>
<tr>
<td>Claude Fable 5</td>
<td>$10.00</td>
<td>$50.00</td>
<td>1M</td>
<td>The top tier, for the hardest and long-horizon autonomous tasks</td>
</tr>
<tr>
<td>Claude Opus 4.8</td>
<td>$5.00</td>
<td>$25.00</td>
<td>1M</td>
<td>Newest in the Opus tier; the standard for practical work</td>
</tr>
<tr>
<td>Claude Sonnet 5</td>
<td>$2.00 (introductory price)</td>
<td>$10.00 (introductory price)</td>
<td>1M</td>
<td>A balance of speed and intelligence</td>
</tr>
<tr>
<td>Claude Haiku 4.5</td>
<td>$1.00</td>
<td>$5.00</td>
<td>200K</td>
<td>Fast and low-cost</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<ul><li><strong>Sonnet 5 carries an introductory price of $2 input / $10 output through August 31, 2026</strong> (the price currently in effect). The standard price from September 1 is $3 input / $15 output.</li><li><strong>Fable 5&apos;s unit price is exactly double Opus 4.8&apos;s</strong>, <strong>placing it among the most expensive of the mainstream generally available models</strong> (not &quot;the most expensive ever&quot; &#x2014; models with higher unit prices, such as Opus 4.1, have existed, and Anthropic itself describes Fable 5 as less than half the price of the old Mythos Preview).</li></ul><h3 id="double-the-unit-price-and-double-the-effective-cost-are-different-things">&quot;Double the unit price&quot; and &quot;double the effective cost&quot; are different things</h3><p>This is the easiest point to misread. The $10 / $50 above is a comparison of <strong>token unit prices</strong>, and <strong>the actual cost per task will not necessarily stay within 2x</strong>. There are two main reasons effective cost tends to exceed the 2x price ratio.</p><figure class="kg-card kg-image-card"><img src="https://journal.qualiteg.com/content/images/2026/07/price_fable5.png" class="kg-image" alt="The Complete Guide to Claude Fable 5 &#x2014; Model Specs and Claude Code Operations from the Official Docs" loading="lazy" width="2000" height="1120" srcset="https://journal.qualiteg.com/content/images/size/w600/2026/07/price_fable5.png 600w, https://journal.qualiteg.com/content/images/size/w1000/2026/07/price_fable5.png 1000w, https://journal.qualiteg.com/content/images/size/w1600/2026/07/price_fable5.png 1600w, https://journal.qualiteg.com/content/images/2026/07/price_fable5.png 2000w" sizes="(min-width: 720px) 720px"></figure><ol><li><strong>Fable 5 has Adaptive thinking always on</strong>.<br>Thinking tokens are <strong>billed as output</strong> ($50 / 1M on Fable 5), and <code>max_tokens</code> is the sum of thinking plus the final answer. Opus 4.8, by contrast, can turn thinking off (<code>thinking</code> omitted runs without thinking), so for the same task Fable 5 tends to consume more of <strong>the expensive side &#x2014; output tokens</strong>. Because tokens grow on the high-priced output side, the cost compounds.<br></li><li><strong>Fable 5 is designed to think deeply and at length</strong>.<br>On hard tasks a single request can easily run several minutes to well over ten, and thinking and output tokens accumulate accordingly. The longer the autonomous task, the larger this gap grows.</li></ol><p>In other words, effective cost is determined by &quot;<strong>2x unit price &#xD7; growth in generated tokens</strong>.&quot; The multiplier can be 2x or more (higher still at high effort). Budget on the assumption that &quot;paying double Opus 4.8 buys the same work&quot; and the invoice will exceed expectations.</p><p><strong>Levers that actually reduce cost</strong></p><ul><li><strong><code>effort</code>: turn it down</strong>. Fable 5 remains strong even at low effort, and this directly reduces thinking tokens (the most effective lever on effective cost).</li><li><strong><code>max_tokens</code>: constrain it appropriately</strong>, or control the tokens of the whole loop with Task Budgets (API only).</li><li><strong>Use the measurements from the previous section</strong> to track input, output, thinking (included in output), and cache separately.</li><li>Note: <strong>prompt caching discounts only the input side</strong>. The thinking and output tokens that tend to grow are not made cheaper by caching, so do not assume &quot;caching will keep it within 2x.&quot;</li></ul><p>The question of whether to choose Fable 5 is therefore not &quot;the unit price is double&quot; but <br><strong>&quot;do I want to solve problems Opus 4.8 cannot reach, even at a cost that can effectively exceed 2x?&quot;</strong>.</p><hr><h1 id="part-3-fable-5-in-claude-code">Part 3: Fable 5 in Claude Code</h1><p>Here we consider the scenarios for putting Fable 5 to serious use in Claude Code.</p><h2 id="prerequisites-and-model-selection">Prerequisites and Model Selection</h2><p>Fable 5 is a supported model in Claude Code. First, the prerequisites.</p><ul><li><strong>Check the supported version</strong>. Per the official documentation, Fable 5 requires a relatively recent Claude Code. In practice: use the latest Claude Code CLI.<br></li><li><strong>The default model differs by plan</strong><br>Fable 5 is <strong>not the default model on any plan</strong>, so if you want it, select Fable 5 explicitly with the <code>/model</code> command.</li></ul><h2 id="enabling-credits-and-setting-limits">Enabling Credits and Setting Limits</h2><p>As noted above, after July 12 (from July 13 Japan time), calling Fable 5 from Claude Code requires credits to be enabled on the claude.ai side.</p><h3 id="the-1m-context-and-prompt-caching">The 1M Context and Prompt Caching</h3><p>Fable 5 offers a 1M-token context at standard pricing, but the more you load, the more tokens (= cost) you consume. For large fixed context (codebases, specifications), use <strong>prompt caching</strong>. Its pricing needs to be understood, though.</p><ul><li><strong>Cache-hit reads are $1 / 1M</strong> &#x2014; inexpensive.</li><li>On the other hand, <strong>the initial cache write costs $12.50 / 1M at 5-minute retention, or $20 / 1M at 1-hour retention</strong>.</li></ul><p>In other words, <strong>unless the fixed context is referenced repeatedly, caching actually costs more</strong>. It pays off precisely in workflows that reuse the same prefix many times.</p><blockquote><strong>Task Budgets cannot be used in Claude Code</strong><br>The API offers Task Budgets (beta), which conveys a token budget for the entire agentic loop to the model, but this is <strong>a Messages API feature and is not available in Claude Code / Cowork</strong>. It is also a &quot;guideline&quot; conveyed to the model, not a hard cap. It applies only if you implement your own Messages API agent.</blockquote><h2 id="refusals-and-fallback-in-practice">Refusals and Fallback in Practice</h2><p>Because the re-released Fable 5 has widened its safety margin, benign tasks such as coding and debugging are <strong>more likely than before to be refused as false positives</strong>.</p><ul><li><strong>If you use Claude Code as-is</strong><br>When the endpoint can correctly identify Fable 5 and the fallback Opus model, it falls back automatically on refusal.<br>It is, frankly, quite sensitive and produces false positives fairly often. More on that below.<br></li><li><strong>If you build your own agent against the API</strong><br><code>stop_reason == &quot;refusal&quot;</code> must be handled, and the opt-in server-side <code>fallbacks</code> should be specified explicitly. It is available on the Claude API and Claude Platform on AWS; elsewhere (Batches, Bedrock, Vertex, Foundry) you need client-side re-execution or SDK middleware. Specify the fallback model explicitly in the request&apos;s <code>fallbacks</code> array (the official example is Opus 4.8). What differs by endpoint is availability.</li></ul><h2 id="using-fable-5-realistically-in-claude-code-%E2%80%94">Using Fable 5 Realistically in Claude Code &#x2014; </h2><h3 id="commander-fable-and-workers-opus-sonnet-split-your-models-by-role"><br><u>Commander (Fable) and Workers (Opus, Sonnet)</u>: Split Your Models by Role</h3><p>After the pricing change, Fable 5 is expensive (2x Opus 4.8, and with thinking always on the effective cost tends to climb further); having it do <strong><u>absolutely everything &#x2014; file reading, trial and error, long autonomous runs &#x2014; is frankly not economical</u></strong>.</p><p>What we at Qualiteg actually do is split a single Claude Code session into a &quot;commander&quot; and &quot;workers,&quot; assigning a different model to each role.</p><p>The basic idea is simple</p><ul><li><strong>Commander = Fable 5</strong><br>Devotes itself to deciding policy, decomposing tasks, issuing work orders, accepting or rejecting reports, and judging the next move. It does not read code or logs itself, and it does not implement.<br></li><li><strong>Workers = Opus 4.8 / Sonnet 5 subagents</strong><br>Take on all the hands-on work &#x2014; exploration, investigation, implementation, testing, documentation &#x2014; and return only short reports to the commander.<br></li><li><strong>Use two tiers of workers</strong><br>Work requiring judgment or design understanding goes to Opus; fully specified, mechanical routine work (bulk renames, log collection, and the like) drops to Sonnet.</li></ul><p>The aim is plain: <strong>the expensive model&apos;s value is concentrated in &quot;judgment&quot;</strong>.</p><p>Let the process (large volumes of file reading, trial and error, logs) be digested inside the subagents&apos; context and have only conclusions returned to the commander, and Fable 5&apos;s credits and context are spent only on the &quot;moments of judgment.&quot;</p><p><strong>Moving from &quot;Fable 5 does everything&quot;</strong> to <strong>&quot;Fable 5 thinks, cheaper models do the hands-on work&quot;</strong><br><br> alone cuts credit consumption substantially.</p><p>Of course, for small day-to-day fixes it is faster and cheaper to skip the commander entirely and work directly with the default models (Opus 4.8 / Sonnet 5).</p><p>The commander method pays off in the &quot;hard and heavy&quot; situations: large migrations, large implementations with clear acceptance criteria, and large investigations using parallel subagents.</p><p>This <strong>Fable commander method</strong> &#x2014; including setup steps, the shape of delegation prompts, orchestrating parallel subagents, and pinning models via <code>CLAUDE_CODE_SUBAGENT_MODEL</code> &#x2014; <strong>will be covered in detail in a separate article, so stay tuned</strong>.</p><p>For this article, the one idea to take away is: put the expensive Fable 5 in the commander&apos;s seat, and leave the hands-on work to Opus / Sonnet.</p><h2 id="handling-false-positives-from-the-safety-classifier">Handling False Positives from the Safety Classifier</h2><p>The re-released classifier widens the safety margin around areas such as cybersecurity and biology/chemistry.</p><p>Here it is important <strong>not to conflate &quot;intentional blocks&quot; with &quot;false positives&quot;</strong>.</p><ol><li><strong>Treat refusals as &quot;content results,&quot; not &quot;errors&quot;</strong><br><code>stop_reason</code> &#x2014; check it, and on refusal route to fallback or a switch to Opus 4.8.<br></li><li><strong>Clearly intended block targets</strong><br>Building exploit chains, generating malware, creating attack tools &#x2014; <strong>requests that directly provide offensive cyber capability</strong> are, naturally, what Fable 5&apos;s classifier intentionally restricts. These are design-level restrictions, not false positives.<br></li><li><strong>Safety-margin blocks and false positives</strong><br>Vulnerability research, penetration testing, and PoC development are ambiguous areas that can serve attack or defense depending on content. Because Fable 5 judges broadly on the safe side, <strong>legitimate defensive work can also be blocked</strong>. In addition, ordinary coding, debugging, configuration changes, dependency updates, and other inherently unproblematic work can get caught up as well.<br>Anthropic characterizes refusals of such harmless requests as <strong>false positives</strong> and says it will improve toward &quot;better distinguishing true abuse from legitimate requests.&quot; In ambiguous areas or suspected false positives, restate the request with the legitimate purpose, ownership, and scope of authorization made explicit; if it is still refused, consider fallback or switching to Opus 4.8.</li></ol><blockquote><strong>Related articles</strong>: our firsthand account of Fable 5 on Claude Code detecting, refusing, and reflecting on &quot;an attack that never came&quot; is in <a href="https://journal.qualiteg.com/confabulated-prompt-injection/">The AI &quot;Detected,&quot; &quot;Refused,&quot; and &quot;Reflected On&quot; an Attack That Never Came</a>, and our treatment of legitimate operational work being judged a Usage Policy violation is in <a href="https://journal.qualiteg.com/claude-code-usage-policy-violation-fix/">Why Legitimate Operations Work Gets Flagged as a &quot;Usage Policy Violation&quot; in Claude Code</a>.</blockquote><hr><h2 id="conclusion-%E2%80%94-how-to-live-with-fable-5">Conclusion &#x2014; How to Live with Fable 5</h2><p>Claude Fable 5 is the most capable model Anthropic makes generally available. Five key points.</p><ol><li><strong>Fable 5 is not Opus&apos;s successor; it is a separate bracket above it</strong><br>The default models (Opus 4.8 / Sonnet 5) for everyday work, Fable 5 only for the hard parts &#x2014; that is the baseline.<br></li><li><strong>It stays within the subscription allowance only through July 12, 2026 (July 13 Japan time)</strong><br>Past that deadline, it cannot be used unless credits are enabled on claude.ai.<br>That said, dates and policy may change again at the last minute; this is not necessarily permanent and deadlines can move, so keep checking the latest official guidance while planning around credits for now.<br></li><li><strong>Manage credits by setting your own limit</strong><br> (without one, spending can be &quot;unlimited&quot;). The monthly spending limit, held balance, auto-reload, and discount bundles (up to 30% off) are separate levers. The unit price is double Opus 4.8, but <strong>always-on thinking increases token consumption, so effective cost can exceed 2x</strong> (<code>effort</code> is the most effective lever to turn down). Always measure.<br></li><li><strong>The longer, more autonomous, and more complex the task, the stronger it is</strong><br>State the goal and constraints up front, use appropriate effort, and exploit parallel subagents. But wherever possible, use Fable 5 for &quot;thinking and judgment&quot; and Opus / Sonnet as the hands &#x2014; that keeps things economical.<br></li><li><strong>Mind the safety classifier</strong><br>Benign coding/debugging can be refused (false positives). Attack code, authentication bypasses, and the like, by contrast, are intentional restrictions rather than false positives, and may not pass even for legitimate business.<code>stop_reason</code> must be handled; prepare a fallback, and route the affected areas to another model such as Opus 4.8.</li></ol><p>&quot;<strong>Do I want to solve problems Opus 4.8 cannot reach, even at a cost that can effectively exceed 2x?</strong>&quot;<br> Commit Fable 5 only to tasks where the answer is yes. And rather than letting Fable 5 do everything, split the commander and worker models. That is the realistic way to live with this powerful &#x2014; and expensive &#x2014; model.</p><hr><h2 id="closing-%E2%80%94-staying-steady-amid-a-shifting-model-landscape">Closing &#x2014; Staying Steady amid a Shifting Model Landscape</h2><p>The whole sequence around Fable 5 (suspension under export controls, global re-rollout, departure from the subscription allowance, and hard-to-read effective costs) once again drove home <strong>the risk of depending heavily on a single model</strong>.</p><p>The higher a model&apos;s performance, the faster its availability and pricing can change. That is precisely why the question &quot;if this model becomes unavailable or expensive, can we switch to an alternative immediately?&quot; matters.</p><p>Qualiteg&apos;s consulting services draw on a deep store of practical AI-native development knowledge, including the insights introduced here, and we provide support for <a href="https://qualiteg.com/consulting/technology?ref=journal.qualiteg.com#ai-sdlc" rel="noreferrer">AI-native software development process innovation</a> leveraging AI agents, and for <a href="https://qualiteg.com/consulting/technology?ref=journal.qualiteg.com#accel-with-claude-code" rel="noreferrer">making full use of Claude Code</a>.</p><p>If you are interested, please <a href="https://qualiteg.com/contact?ref=journal.qualiteg.com">get in touch with Qualiteg</a>.</p><p>Building on our knowledge of frontier AI models, AI-native development processes, and AI security, we will propose the form that fits your organization best.</p><p>See you next time!</p><hr><h2 id="primary-sources-referenced">Primary Sources Referenced</h2><ul><li><a href="https://www.anthropic.com/news/claude-fable-5-mythos-5?ref=journal.qualiteg.com">Claude Fable 5 and Claude Mythos 5 &#x2014; Anthropic</a></li><li><a href="https://platform.claude.com/docs/en/about-claude/models/introducing-claude-fable-5-and-claude-mythos-5?ref=journal.qualiteg.com">Introducing Claude Fable 5 and Claude Mythos 5 &#x2014; Claude Platform Docs</a></li><li><a href="https://www.anthropic.com/news/redeploying-fable-5?ref=journal.qualiteg.com">Redeploying Claude Fable 5 &#x2014; Anthropic</a></li><li><a href="https://support.claude.com/en/articles/15424964-claude-fable-5-promotional-access?ref=journal.qualiteg.com">Claude Fable 5 promotional access &#x2014; Anthropic official support</a></li><li><a href="https://platform.claude.com/docs/en/about-claude/models/overview?ref=journal.qualiteg.com">Models overview / Pricing &#x2014; Claude Platform Docs</a></li></ul>]]></content:encoded></item></channel></rss>