<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Chrome Built-in AI on Programmer.ie: Modern AI programming</title>
    <link>http://programmer.ie/tags/chrome-built-in-ai/</link>
    <description>Recent content in Chrome Built-in AI on Programmer.ie: Modern AI programming</description>
    <generator>Hugo</generator>
    <language>en-us</language>
    <lastBuildDate>Wed, 02 Sep 2026 17:30:00 +0100</lastBuildDate>
    <atom:link href="http://programmer.ie/tags/chrome-built-in-ai/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>What Does Built-In Actually Mean?</title>
      <link>http://programmer.ie/books/browser-ai-from-first-principles/02-chapter/</link>
      <pubDate>Wed, 02 Sep 2026 12:05:00 +0100</pubDate>
      <guid>http://programmer.ie/books/browser-ai-from-first-principles/02-chapter/</guid>
      <description>&lt;p&gt;The word &lt;em&gt;built-in&lt;/em&gt; suggests permanence.&lt;/p&gt;&#xA;&lt;p&gt;A built-in function is present when the program starts. A built-in browser feature is expected to work without an installer, account or deployment. If a web developer hears that AI is built into the browser, the obvious mental model is a global function waiting to be called.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;answer&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;await&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;browserAI&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;prompt&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Explain this page&amp;#34;&lt;/span&gt;);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;That is not the system we actually have.&lt;/p&gt;&#xA;&lt;p&gt;The API may be absent. The device may be ineligible. The requested language or modality may be unsupported. A model may need to be downloaded. Downloading may require a user action. The bytes can arrive before extraction and loading finish. A session can be created and later exhaust its context. The same interface can be backed by a changed implementation after a browser update.&lt;/p&gt;</description>
    </item>
    <item>
      <title>One Runtime, Several Interfaces</title>
      <link>http://programmer.ie/books/browser-ai-from-first-principles/05-chapter/</link>
      <pubDate>Wed, 02 Sep 2026 14:00:00 +0100</pubDate>
      <guid>http://programmer.ie/books/browser-ai-from-first-principles/05-chapter/</guid>
      <description>&lt;p&gt;The first Browser AI Observatory knew about one global object: &lt;code&gt;LanguageModel&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;p&gt;That was enough to expose the common lifecycle. We could inspect availability, create a session, monitor model acquisition, stream output, cancel a request and record what happened.&lt;/p&gt;&#xA;&lt;p&gt;Chrome also exposes narrower built-in AI capabilities. Instead of asking a general language-model session to perform an arbitrary task, an application can create a summarizer, writer, rewriter, proofreader, translator or language detector.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Summarization Is a Contract</title>
      <link>http://programmer.ie/books/browser-ai-from-first-principles/06-chapter/</link>
      <pubDate>Wed, 02 Sep 2026 14:05:00 +0100</pubDate>
      <guid>http://programmer.ie/books/browser-ai-from-first-principles/06-chapter/</guid>
      <description>&lt;p&gt;Summarization looks like the ideal local AI feature.&lt;/p&gt;&#xA;&lt;p&gt;The input is already in the browser. The desired output is smaller than the input. The task is useful for articles, documentation, conversations, reviews and support content. Sending the entire source to a remote provider can feel disproportionate when a browser-managed model can operate on the device.&lt;/p&gt;&#xA;&lt;p&gt;So the implementation seems obvious:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;summarizer&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;await&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Summarizer&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;create&lt;/span&gt;();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;result&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;await&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;summarizer&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;summarize&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;text&lt;/span&gt;);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The code is correct.&lt;/p&gt;&#xA;&lt;p&gt;The feature is unspecified.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Language Detection Is a Decision, Not an Answer</title>
      <link>http://programmer.ie/books/browser-ai-from-first-principles/08-chapter/</link>
      <pubDate>Wed, 02 Sep 2026 14:15:00 +0100</pubDate>
      <guid>http://programmer.ie/books/browser-ai-from-first-principles/08-chapter/</guid>
      <description>&lt;p&gt;Translation appears to be a two-step browser-AI pipeline:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;text&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ↓&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;detect language&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ↓&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;translate to target language&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The implementation is short enough to fit inside one event handler.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;candidates&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;await&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;detector&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;detect&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;text&lt;/span&gt;);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;sourceLanguage&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;candidates&lt;/span&gt;[&lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;].&lt;span style=&#34;color:#a6e22e&#34;&gt;detectedLanguage&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;translator&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;await&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Translator&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;create&lt;/span&gt;({&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#a6e22e&#34;&gt;sourceLanguage&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#a6e22e&#34;&gt;targetLanguage&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;en&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;});&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;output&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;await&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;translator&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;translate&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;text&lt;/span&gt;);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The dangerous line is not the model call.&lt;/p&gt;&#xA;&lt;p&gt;It is the array index.&lt;/p&gt;&#xA;&lt;p&gt;&lt;code&gt;candidates[0]&lt;/code&gt; is the highest-ranked language returned by the detector. That does not make it correct, supported for translation, or confident enough to justify an automatic action.&lt;/p&gt;</description>
    </item>
    <item>
      <title>A Session Is Not a Stateless Function</title>
      <link>http://programmer.ie/books/browser-ai-from-first-principles/09-chapter/</link>
      <pubDate>Wed, 02 Sep 2026 15:00:00 +0100</pubDate>
      <guid>http://programmer.ie/books/browser-ai-from-first-principles/09-chapter/</guid>
      <description>&lt;p&gt;A remote model API often encourages a simple mental model:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;answer&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;await&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;complete&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;prompt&lt;/span&gt;);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Input goes in. Output comes back. Any conversation state is reconstructed by the application and sent again.&lt;/p&gt;&#xA;&lt;p&gt;A browser-managed Prompt API session is a different kind of object. It owns resources, may retain conversational state, reports a finite input budget, supports branching in some implementations, and should be destroyed when its work is finished.&lt;/p&gt;&#xA;&lt;p&gt;The correct abstraction is not a stateless function.&lt;/p&gt;</description>
    </item>
    <item>
      <title>When the Context Window Fills</title>
      <link>http://programmer.ie/books/browser-ai-from-first-principles/10-chapter/</link>
      <pubDate>Wed, 02 Sep 2026 15:15:00 +0100</pubDate>
      <guid>http://programmer.ie/books/browser-ai-from-first-principles/10-chapter/</guid>
      <description>&lt;p&gt;A stateful session eventually encounters a physical limit.&lt;/p&gt;&#xA;&lt;p&gt;Prompts, initial instructions, examples, conversation history and model outputs all compete for a finite context budget. Once the budget is exhausted, the application cannot solve the problem by pretending the next message is independent.&lt;/p&gt;&#xA;&lt;p&gt;The difficult question is not how to delete text.&lt;/p&gt;&#xA;&lt;p&gt;It is how to preserve the right state.&lt;/p&gt;&#xA;&lt;hr&gt;&#xA;&lt;h2 id=&#34;1-the-context-window-is-a-budget&#34;&gt;1. The context window is a budget&lt;/h2&gt;&#xA;&lt;p&gt;When a session exposes usage and quota, context pressure becomes observable:&lt;/p&gt;</description>
    </item>
    <item>
      <title>Cold Starts, Warm Runs and Real Latency</title>
      <link>http://programmer.ie/books/browser-ai-from-first-principles/11-chapter/</link>
      <pubDate>Wed, 02 Sep 2026 15:30:00 +0100</pubDate>
      <guid>http://programmer.ie/books/browser-ai-from-first-principles/11-chapter/</guid>
      <description>&lt;p&gt;“Local AI is faster” is not a measurement.&lt;/p&gt;&#xA;&lt;p&gt;It compresses several different waiting periods into one adjective. A browser-native feature can avoid network round trips and still make a user wait for model acquisition, process startup, session creation, context ingestion or slow generation.&lt;/p&gt;&#xA;&lt;p&gt;To understand latency, we have to take the lifecycle apart.&lt;/p&gt;&#xA;&lt;hr&gt;&#xA;&lt;h2 id=&#34;1-one-duration-hides-several-clocks&#34;&gt;1. One duration hides several clocks&lt;/h2&gt;&#xA;&lt;p&gt;For one interaction, useful timestamps include:&lt;/p&gt;&#xA;&lt;table&gt;&#xA;  &lt;thead&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;th&gt;Phase&lt;/th&gt;&#xA;          &lt;th&gt;Starts&lt;/th&gt;&#xA;          &lt;th&gt;Ends&lt;/th&gt;&#xA;          &lt;th&gt;User-visible?&lt;/th&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/thead&gt;&#xA;  &lt;tbody&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Capability inspection&lt;/td&gt;&#xA;          &lt;td&gt;&lt;code&gt;availability()&lt;/code&gt; call&lt;/td&gt;&#xA;          &lt;td&gt;state returned&lt;/td&gt;&#xA;          &lt;td&gt;Usually not&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Acquisition&lt;/td&gt;&#xA;          &lt;td&gt;session request requires assets&lt;/td&gt;&#xA;          &lt;td&gt;assets ready&lt;/td&gt;&#xA;          &lt;td&gt;Yes, if it blocks&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Session creation&lt;/td&gt;&#xA;          &lt;td&gt;&lt;code&gt;create()&lt;/code&gt; called&lt;/td&gt;&#xA;          &lt;td&gt;session returned&lt;/td&gt;&#xA;          &lt;td&gt;Often&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Prompt startup&lt;/td&gt;&#xA;          &lt;td&gt;prompt called&lt;/td&gt;&#xA;          &lt;td&gt;first chunk&lt;/td&gt;&#xA;          &lt;td&gt;Yes&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Generation&lt;/td&gt;&#xA;          &lt;td&gt;first chunk&lt;/td&gt;&#xA;          &lt;td&gt;final chunk&lt;/td&gt;&#xA;          &lt;td&gt;Yes&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Validation&lt;/td&gt;&#xA;          &lt;td&gt;output complete&lt;/td&gt;&#xA;          &lt;td&gt;feature accepted/rejected&lt;/td&gt;&#xA;          &lt;td&gt;Sometimes&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;p&gt;The perceived wait for a streaming feature is often dominated by time to first output:&lt;/p&gt;</description>
    </item>
    <item>
      <title>The Browser Manages the Model</title>
      <link>http://programmer.ie/books/browser-ai-from-first-principles/12-chapter/</link>
      <pubDate>Wed, 02 Sep 2026 15:45:00 +0100</pubDate>
      <guid>http://programmer.ie/books/browser-ai-from-first-principles/12-chapter/</guid>
      <description>&lt;p&gt;The central promise of built-in AI is an abstraction boundary:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;application&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ↓&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;browser AI API&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ↓&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;browser-managed runtime&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ↓&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;current model and execution strategy&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The application asks for a capability. The browser chooses how to provide it.&lt;/p&gt;&#xA;&lt;p&gt;That separation is powerful, but it does not make the lower layers irrelevant. Changes beneath the API can alter availability, accepted options, performance and behavior.&lt;/p&gt;&#xA;&lt;p&gt;We encountered that fact before completing our first prompt experiment.&lt;/p&gt;</description>
    </item>
    <item>
      <title>A Resolved Promise Is Not a Correct Answer</title>
      <link>http://programmer.ie/books/browser-ai-from-first-principles/13-chapter/</link>
      <pubDate>Wed, 02 Sep 2026 16:00:00 +0100</pubDate>
      <guid>http://programmer.ie/books/browser-ai-from-first-principles/13-chapter/</guid>
      <description>&lt;p&gt;The following code has only one definition of success:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;try&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;output&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;await&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;session&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;prompt&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;input&lt;/span&gt;);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#a6e22e&#34;&gt;show&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;output&lt;/span&gt;);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;} &lt;span style=&#34;color:#66d9ef&#34;&gt;catch&lt;/span&gt; (&lt;span style=&#34;color:#a6e22e&#34;&gt;error&lt;/span&gt;) {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#a6e22e&#34;&gt;showFailure&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;error&lt;/span&gt;);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If the promise resolves, the interface displays the result.&lt;/p&gt;&#xA;&lt;p&gt;That is sufficient for a deterministic lookup whose return value is authoritative. It is not sufficient for a probabilistic system that can return fluent, well-formed and incorrect text.&lt;/p&gt;&#xA;&lt;p&gt;A resolved promise proves that an operation completed according to the runtime contract. It does not prove that the feature did its job.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Evaluate the Feature, Not the Demo</title>
      <link>http://programmer.ie/books/browser-ai-from-first-principles/14-chapter/</link>
      <pubDate>Wed, 02 Sep 2026 16:15:00 +0100</pubDate>
      <guid>http://programmer.ie/books/browser-ai-from-first-principles/14-chapter/</guid>
      <description>&lt;p&gt;A demo asks whether one carefully chosen example can work.&lt;/p&gt;&#xA;&lt;p&gt;A feature evaluation asks how often the product contract holds across the inputs, states and failures users will actually encounter.&lt;/p&gt;&#xA;&lt;p&gt;Both have value. Confusing them is the problem.&lt;/p&gt;&#xA;&lt;hr&gt;&#xA;&lt;h2 id=&#34;1-the-unit-of-evaluation-is-the-feature&#34;&gt;1. The unit of evaluation is the feature&lt;/h2&gt;&#xA;&lt;p&gt;“Evaluate Gemma 4” is too broad for our application. “Evaluate this prompt” is too narrow.&lt;/p&gt;&#xA;&lt;p&gt;The useful unit is something a user attempts:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;summarize selected documentation&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;rewrite permission copy without changing authority&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;detect language and decide whether to translate&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;produce structured arguments for a read-only tool&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Each feature includes input preparation, capability selection, model output, validation, fallback and UI behavior.&lt;/p&gt;</description>
    </item>
    <item>
      <title>When Local Is Not Available</title>
      <link>http://programmer.ie/books/browser-ai-from-first-principles/15-chapter/</link>
      <pubDate>Wed, 02 Sep 2026 16:30:00 +0100</pubDate>
      <guid>http://programmer.ie/books/browser-ai-from-first-principles/15-chapter/</guid>
      <description>&lt;p&gt;A browser-native AI feature cannot assume that its preferred local capability exists everywhere.&lt;/p&gt;&#xA;&lt;p&gt;The API may be absent. Hardware may be ineligible. A language pair may be unsupported. Model assets may need acquisition. Session options may be rejected. Storage pressure or a browser update may change a state that worked yesterday.&lt;/p&gt;&#xA;&lt;p&gt;Reliability begins by treating local availability as a runtime condition, not an installation promise.&lt;/p&gt;&#xA;&lt;hr&gt;&#xA;&lt;h2 id=&#34;1-unavailable-is-not-one-state&#34;&gt;1. Unavailable is not one state&lt;/h2&gt;&#xA;&lt;p&gt;A useful feature distinguishes:&lt;/p&gt;</description>
    </item>
    <item>
      <title>Structured Output Is Still Model Output</title>
      <link>http://programmer.ie/books/browser-ai-from-first-principles/16-chapter/</link>
      <pubDate>Wed, 02 Sep 2026 16:45:00 +0100</pubDate>
      <guid>http://programmer.ie/books/browser-ai-from-first-principles/16-chapter/</guid>
      <description>&lt;p&gt;JSON feels safer than prose because software can parse it.&lt;/p&gt;&#xA;&lt;p&gt;That is a real advantage. It is not a guarantee that the values are correct, permitted or useful.&lt;/p&gt;&#xA;&lt;p&gt;A model can produce perfectly valid JSON containing a nonexistent file, an unsupported operation, a reversed date range or an action the user never authorized.&lt;/p&gt;&#xA;&lt;p&gt;Structured output is still model output.&lt;/p&gt;&#xA;&lt;hr&gt;&#xA;&lt;h2 id=&#34;1-structure-removes-one-class-of-ambiguity&#34;&gt;1. Structure removes one class of ambiguity&lt;/h2&gt;&#xA;&lt;p&gt;Suppose we ask a model to choose a fixture and repetition count. Prose might return:&lt;/p&gt;</description>
    </item>
    <item>
      <title>From Buttons to Capabilities</title>
      <link>http://programmer.ie/books/browser-ai-from-first-principles/17-chapter/</link>
      <pubDate>Wed, 02 Sep 2026 17:00:00 +0100</pubDate>
      <guid>http://programmer.ie/books/browser-ai-from-first-principles/17-chapter/</guid>
      <description>&lt;p&gt;A browser agent can operate software by looking at a page, guessing which control matters and simulating a click.&lt;/p&gt;&#xA;&lt;p&gt;That is sometimes necessary. It should not be the preferred contract between two pieces of software.&lt;/p&gt;&#xA;&lt;p&gt;The alternative is a capability: an operation the application exposes deliberately, with a name, description, input schema, result and authority boundary.&lt;/p&gt;&#xA;&lt;hr&gt;&#xA;&lt;h2 id=&#34;1-a-button-is-evidence-not-an-interface-contract&#34;&gt;1. A button is evidence, not an interface contract&lt;/h2&gt;&#xA;&lt;p&gt;The text “Book” may represent a purchase, reservation, navigation link or decorative heading. Position and colour help a human infer meaning, but none provides a stable machine contract.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Expose the First WebMCP Tool</title>
      <link>http://programmer.ie/books/browser-ai-from-first-principles/18-chapter/</link>
      <pubDate>Wed, 02 Sep 2026 17:15:00 +0100</pubDate>
      <guid>http://programmer.ie/books/browser-ai-from-first-principles/18-chapter/</guid>
      <description>&lt;p&gt;Our first WebMCP tool should not send a message, edit a document or buy anything.&lt;/p&gt;&#xA;&lt;p&gt;It should read from the book we control.&lt;/p&gt;&#xA;&lt;p&gt;We will expose &lt;code&gt;search_book&lt;/code&gt;: a bounded operation that finds relevant chapters and passages.&lt;/p&gt;&#xA;&lt;hr&gt;&#xA;&lt;h2 id=&#34;1-start-with-a-narrow-contract&#34;&gt;1. Start with a narrow contract&lt;/h2&gt;&#xA;&lt;p&gt;Conceptually, the page registers:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-javascript&#34; data-lang=&#34;javascript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;navigator&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;modelContext&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;registerTool&lt;/span&gt;({&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#a6e22e&#34;&gt;name&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;search_book&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#a6e22e&#34;&gt;description&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;Search this book for passages related to a query.&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#a6e22e&#34;&gt;inputSchema&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;type&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;object&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;properties&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#a6e22e&#34;&gt;query&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; { &lt;span style=&#34;color:#a6e22e&#34;&gt;type&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;string&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;minLength&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;2&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;maxLength&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;300&lt;/span&gt; },&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#a6e22e&#34;&gt;limit&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; { &lt;span style=&#34;color:#a6e22e&#34;&gt;type&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;integer&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;minimum&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;maximum&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;10&lt;/span&gt; }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    },&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;required&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; [&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;query&amp;#34;&lt;/span&gt;],&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;additionalProperties&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;false&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  },&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#a6e22e&#34;&gt;execute&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; ({ &lt;span style=&#34;color:#a6e22e&#34;&gt;query&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;limit&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;5&lt;/span&gt; }) =&amp;gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;searchIndex&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;query&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;limit&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;});&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;WebMCP is evolving, so the exact registration surface must be checked against the browser version used for an experiment. The durable architecture is name, description, schema and implementation.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Tool Choice Is a Behavioral Problem</title>
      <link>http://programmer.ie/books/browser-ai-from-first-principles/19-chapter/</link>
      <pubDate>Wed, 02 Sep 2026 17:30:00 +0100</pubDate>
      <guid>http://programmer.ie/books/browser-ai-from-first-principles/19-chapter/</guid>
      <description>&lt;p&gt;A tool can be perfectly implemented and never used correctly.&lt;/p&gt;&#xA;&lt;p&gt;Once an agent sees several capabilities, success depends on a behavioral pipeline:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;discover → select → construct arguments → invoke → interpret result&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;A single “task passed” score cannot tell us which stage failed.&lt;/p&gt;&#xA;&lt;hr&gt;&#xA;&lt;h2 id=&#34;1-discovery-precedes-choice&#34;&gt;1. Discovery precedes choice&lt;/h2&gt;&#xA;&lt;p&gt;If the tool never enters the agent&amp;rsquo;s effective context, it cannot be selected. Record which registrations were available, filtered, truncated or rejected.&lt;/p&gt;</description>
    </item>
  </channel>
</rss>
