<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Browser AI on Programmer.ie: Modern AI programming</title>
    <link>http://programmer.ie/tags/browser-ai/</link>
    <description>Recent content in Browser AI on Programmer.ie: Modern AI programming</description>
    <generator>Hugo</generator>
    <language>en-us</language>
    <lastBuildDate>Wed, 02 Sep 2026 16:45:00 +0100</lastBuildDate>
    <atom:link href="http://programmer.ie/tags/browser-ai/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>The Browser Stops Being Just a Client</title>
      <link>http://programmer.ie/books/browser-ai-from-first-principles/01-chapter/</link>
      <pubDate>Wed, 02 Sep 2026 12:00:00 +0100</pubDate>
      <guid>http://programmer.ie/books/browser-ai-from-first-principles/01-chapter/</guid>
      <description>&lt;p&gt;For most of the web&amp;rsquo;s history, the browser has been the place where computation ends up, not the place where intelligence begins.&lt;/p&gt;&#xA;&lt;p&gt;It renders documents.&lt;/p&gt;&#xA;&lt;p&gt;It executes JavaScript.&lt;/p&gt;&#xA;&lt;p&gt;It stores local state.&lt;/p&gt;&#xA;&lt;p&gt;It turns user actions into requests and server responses into interfaces.&lt;/p&gt;&#xA;&lt;p&gt;When language models first entered web applications, they fitted that architecture neatly. The page gathered a prompt, sent it to an application server, the server called a model provider, and the answer travelled back through the same chain.&lt;/p&gt;</description>
    </item>
    <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>Writing, Rewriting and Proofreading Are Different Operations</title>
      <link>http://programmer.ie/books/browser-ai-from-first-principles/07-chapter/</link>
      <pubDate>Wed, 02 Sep 2026 14:10:00 +0100</pubDate>
      <guid>http://programmer.ie/books/browser-ai-from-first-principles/07-chapter/</guid>
      <description>&lt;p&gt;Writer, Rewriter and Proofreader all accept text and return text-related results.&lt;/p&gt;&#xA;&lt;p&gt;That surface similarity makes it tempting to place them behind one function:&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;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;improveText&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;input&lt;/span&gt;);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The name hides the most important property of the operation.&lt;/p&gt;&#xA;&lt;p&gt;How much is it allowed to change?&lt;/p&gt;&#xA;&lt;p&gt;A writer may create content that did not exist. A rewriter may change expression while preserving the underlying message. A proofreader should correct a bounded class of errors while leaving correct content alone.&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>
  </channel>
</rss>
