<?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/categories/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 18:45:00 +0100</lastBuildDate>
    <atom:link href="http://programmer.ie/categories/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>Build the Smallest Browser AI Observatory</title>
      <link>http://programmer.ie/books/browser-ai-from-first-principles/03-chapter/</link>
      <pubDate>Wed, 02 Sep 2026 12:10:00 +0100</pubDate>
      <guid>http://programmer.ie/books/browser-ai-from-first-principles/03-chapter/</guid>
      <description>&lt;p&gt;We are ready to make the browser&amp;rsquo;s AI lifecycle visible.&lt;/p&gt;&#xA;&lt;p&gt;The first version will be deliberately small. It will not inspect every page, intercept arbitrary prompts, call tools, diagnose quality or persist a history. It will do five things:&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;create a panel inside Chrome DevTools;&lt;/li&gt;&#xA;&lt;li&gt;report whether the Prompt API is exposed and available;&lt;/li&gt;&#xA;&lt;li&gt;create a browser-managed language-model session with visible download progress;&lt;/li&gt;&#xA;&lt;li&gt;stream a prompt with cancellation;&lt;/li&gt;&#xA;&lt;li&gt;display an event trace that separates each phase.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;That is already more useful than a chat demo.&lt;/p&gt;</description>
    </item>
    <item>
      <title>From Prompt Demo to AI Debugger</title>
      <link>http://programmer.ie/books/browser-ai-from-first-principles/04-chapter/</link>
      <pubDate>Wed, 02 Sep 2026 12:15:00 +0100</pubDate>
      <guid>http://programmer.ie/books/browser-ai-from-first-principles/04-chapter/</guid>
      <description>&lt;p&gt;Our first DevTools panel can run a prompt and display its lifecycle.&lt;/p&gt;&#xA;&lt;p&gt;That makes it a useful experiment console.&lt;/p&gt;&#xA;&lt;p&gt;It does not yet make it a debugger.&lt;/p&gt;&#xA;&lt;p&gt;A debugger must help explain a failure that occurred in the application under inspection. It needs to connect model activity to application context, preserve events long enough to compare them, and distinguish facts it observed from inferences it derived. It must do this without quietly capturing every prompt, response and page the user visits.&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>
    <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>
    <item>
      <title>Untrusted Text Meets Executable Authority</title>
      <link>http://programmer.ie/books/browser-ai-from-first-principles/20-chapter/</link>
      <pubDate>Wed, 02 Sep 2026 17:45:00 +0100</pubDate>
      <guid>http://programmer.ie/books/browser-ai-from-first-principles/20-chapter/</guid>
      <description>&lt;p&gt;Before tools, malicious page text could mislead a model&amp;rsquo;s answer.&lt;/p&gt;&#xA;&lt;p&gt;After tools, the same text may influence an action.&lt;/p&gt;&#xA;&lt;p&gt;Prompt injection becomes an authority problem when untrusted content shares a reasoning context with executable capabilities.&lt;/p&gt;&#xA;&lt;hr&gt;&#xA;&lt;h2 id=&#34;1-identify-the-trust-domains&#34;&gt;1. Identify the trust domains&lt;/h2&gt;&#xA;&lt;p&gt;A browser agent may combine:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;user instructions;&lt;/li&gt;&#xA;&lt;li&gt;developer policy;&lt;/li&gt;&#xA;&lt;li&gt;page content;&lt;/li&gt;&#xA;&lt;li&gt;tool descriptions;&lt;/li&gt;&#xA;&lt;li&gt;tool results;&lt;/li&gt;&#xA;&lt;li&gt;prior session state.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;They are all text to the model. They are not equally authoritative.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Put a Human at the Authority Boundary</title>
      <link>http://programmer.ie/books/browser-ai-from-first-principles/21-chapter/</link>
      <pubDate>Wed, 02 Sep 2026 18:00:00 +0100</pubDate>
      <guid>http://programmer.ie/books/browser-ai-from-first-principles/21-chapter/</guid>
      <description>&lt;p&gt;“Ask the user before doing anything dangerous” sounds like a safety design.&lt;/p&gt;&#xA;&lt;p&gt;It is only a slogan until we define what the user sees, when approval occurs and exactly what the approval authorizes.&lt;/p&gt;&#xA;&lt;p&gt;A useful authority boundary turns a model&amp;rsquo;s proposal into a concrete, validated effect. The user approves that effect—not a vague intention and not the model in general.&lt;/p&gt;&#xA;&lt;hr&gt;&#xA;&lt;h2 id=&#34;1-classify-effects-before-requesting-permission&#34;&gt;1. Classify effects before requesting permission&lt;/h2&gt;&#xA;&lt;p&gt;Not every tool call deserves the same interruption. Begin with effect classes:&lt;/p&gt;</description>
    </item>
    <item>
      <title>The Browser as a Personal Policy Engine</title>
      <link>http://programmer.ie/books/browser-ai-from-first-principles/22-chapter/</link>
      <pubDate>Wed, 02 Sep 2026 18:15:00 +0100</pubDate>
      <guid>http://programmer.ie/books/browser-ai-from-first-principles/22-chapter/</guid>
      <description>&lt;p&gt;So far, the browser has supplied models, sessions, context and tools. We used them to inspect applications and constrain agent actions.&lt;/p&gt;&#xA;&lt;p&gt;There is another direction the same architecture can travel.&lt;/p&gt;&#xA;&lt;p&gt;Instead of asking only, “What can an agent do to a website?”, ask:&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;What should the website be allowed to do to the user&amp;rsquo;s attention?&lt;/p&gt;&lt;/blockquote&gt;&#xA;&lt;p&gt;A personal policy engine observes the page, evaluates content under rules chosen by the user and changes presentation locally. It is not the site&amp;rsquo;s moderation system. It is the user&amp;rsquo;s mediation layer.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Build an AI-Origin Content Filter</title>
      <link>http://programmer.ie/books/browser-ai-from-first-principles/23-chapter/</link>
      <pubDate>Wed, 02 Sep 2026 18:30:00 +0100</pubDate>
      <guid>http://programmer.ie/books/browser-ai-from-first-principles/23-chapter/</guid>
      <description>&lt;p&gt;Suppose a user says:&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Exclude AI-generated content from my browser experience.&lt;/p&gt;&lt;/blockquote&gt;&#xA;&lt;p&gt;The request is clear. The underlying fact often is not.&lt;/p&gt;&#xA;&lt;p&gt;Once text has been copied, edited, translated, mixed with human work or stripped of metadata, its origin may be impossible to establish from the content alone. A serious filter must therefore manage evidence and uncertainty rather than pretend to possess an infallible detector.&lt;/p&gt;&#xA;&lt;hr&gt;&#xA;&lt;h2 id=&#34;1-define-the-claim-precisely&#34;&gt;1. Define the claim precisely&lt;/h2&gt;&#xA;&lt;p&gt;“AI-generated” can mean several things:&lt;/p&gt;</description>
    </item>
    <item>
      <title>The User, Not the Platform, Controls the Interface</title>
      <link>http://programmer.ie/books/browser-ai-from-first-principles/24-chapter/</link>
      <pubDate>Wed, 02 Sep 2026 18:45:00 +0100</pubDate>
      <guid>http://programmer.ie/books/browser-ai-from-first-principles/24-chapter/</guid>
      <description>&lt;p&gt;A platform decides what enters a feed, how it is ranked, which controls are prominent and which forms of automation are available.&lt;/p&gt;&#xA;&lt;p&gt;The user may select among the settings the platform offers. That is not the same as controlling the interface.&lt;/p&gt;&#xA;&lt;p&gt;Browser AI creates the possibility of another layer: software acting locally, under rules the user can inspect, across sites and independently of one model provider.&lt;/p&gt;&#xA;&lt;p&gt;This chapter assembles the system we have built and defines the limits of that claim.&lt;/p&gt;</description>
    </item>
  </channel>
</rss>
