<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Giorgio Boa</title>
    <description>The latest articles on DEV Community by Giorgio Boa (@gioboa).</description>
    <link>https://dev.to/gioboa</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F892161%2Ff7bb8d77-6568-4576-b4e5-715d424afabd.jpeg</url>
      <title>DEV Community: Giorgio Boa</title>
      <link>https://dev.to/gioboa</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/gioboa"/>
    <language>en</language>
    <item>
      <title>Untyped Python? Let Antigravity /goal Do the Cleanup</title>
      <dc:creator>Giorgio Boa</dc:creator>
      <pubDate>Thu, 09 Jul 2026 14:49:44 +0000</pubDate>
      <link>https://dev.to/gioboa/untyped-python-let-antigravity-goal-do-the-cleanup-10mh</link>
      <guid>https://dev.to/gioboa/untyped-python-let-antigravity-goal-do-the-cleanup-10mh</guid>
      <description>&lt;p&gt;Python projects have a special way of aging.&lt;/p&gt;

&lt;p&gt;At first, everything feels light and fast. A few scripts, some helper functions, maybe a small API. Then six months pass. The project grows. Functions start returning "whatever works." Dictionaries become informal data models. Tests still pass, mostly, but every refactor feels like walking through a dark room full of furniture.&lt;/p&gt;

&lt;p&gt;That is exactly where &lt;a href="https://antigravity.google/product/antigravity-cli" rel="noopener noreferrer"&gt;Antigravity CLI&lt;/a&gt;'s new &lt;code&gt;/goal&lt;/code&gt; command becomes useful.&lt;/p&gt;

&lt;p&gt;The idea behind &lt;code&gt;/goal&lt;/code&gt; is simple: instead of giving the agent one instruction and waiting for a single pass, you define an end state. Antigravity keeps working until that goal is reached, or until it has a clear reason to stop. For refactoring, this is a very natural fit, because cleanup work is rarely one-and-done. You fix one issue, run the toolchain, uncover ten more, repeat.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fl87otqhfjppf6v76q0fz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fl87otqhfjppf6v76q0fz.png" alt="goal-command" width="766" height="46"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A great example is taking an older Python project with little or no type discipline and moving it toward a cleaner, more maintainable baseline.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;My preferred first step is not "add perfect typing everywhere." That is usually too big, too vague, and too easy to derail. Instead, start with formatting and linting. Install &lt;a href="https://docs.astral.sh/ruff/" rel="noopener noreferrer"&gt;Ruff&lt;/a&gt;, let it enforce consistency, and use Antigravity's &lt;code&gt;/goal&lt;/code&gt; command to loop until the codebase is clean.&lt;/p&gt;

&lt;p&gt;First, add Ruff:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;uv add &lt;span class="nt"&gt;--dev&lt;/span&gt; ruff
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;or, if the project still uses pip:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;ruff
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Then configure a basic &lt;code&gt;pyproject.toml&lt;/code&gt; if one does not exist:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="nn"&gt;[tool.ruff]&lt;/span&gt;
&lt;span class="py"&gt;line-length&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;
&lt;span class="py"&gt;target-version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"py314"&lt;/span&gt;

&lt;span class="nn"&gt;[tool.ruff.lint]&lt;/span&gt;
&lt;span class="py"&gt;select&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"E"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"F"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"I"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"UP"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"B"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Now the useful part: give Antigravity a measurable goal.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/goal Refactor this Python project toward a clean Ruff baseline. Run `ruff check --fix; ruff format;` repeatedly, inspect remaining errors, and update the code until Ruff reports no errors. Preserve behaviour and avoid broad rewrites unless required.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;That prompt works because the finish line is concrete: Ruff must pass. The agent is not guessing what "clean up the project" means. It has a command to run, feedback to read, and a clear loop: fix, format, check, repeat.&lt;/p&gt;

&lt;p&gt;This is where Antigravity CLI feels different from a normal chat-style coding session. The asynchronous workflow lets the agent keep running commands and iterating without turning every lint error into a manual back-and-forth. You can stay focused on the higher-level direction while the tool handles the mechanical cleanup.&lt;/p&gt;

&lt;p&gt;For untyped Python projects, Ruff is a good first refactor gate because it catches high-signal problems without requiring a full typing migration. Unused imports disappear. Import order becomes consistent. Risky patterns get flagged. Old syntax can be modernised. Formatting stops being a debate.&lt;/p&gt;

&lt;p&gt;After Ruff passes, you can raise the bar:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/goal Add lightweight type hints to the public functions in this project. Keep changes minimal, run tests after each batch, and stop when tests and Ruff both pass.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;That second goal is much safer after the first cleanup. The code is already formatted, obvious lint issues are gone, and the agent has less noise to fight through.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The most important lesson: &lt;code&gt;/goal&lt;/code&gt; works best when paired with verifiable commands. "Make this better" is weak. "Run Ruff until it passes" is strong. "Add types while tests keep passing" is strong. "Refactor without changing behavior" becomes much more realistic when the agent has tests, linters, and formatters as feedback.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For me, this is the real value of Antigravity CLI's &lt;code&gt;/goal&lt;/code&gt;: it turns refactoring from a single fragile prompt into a controlled loop. The agent is not just editing code. It is working against a measurable definition of done and for messy Python projects, that is exactly what you want.&lt;/p&gt;



&lt;p&gt;You can&amp;nbsp;&lt;a href="https://github.com/gioboa" rel="noopener noreferrer"&gt;follow me on GitHub&lt;/a&gt;, where I'm creating cool projects.&lt;/p&gt;

&lt;p&gt;I hope you enjoyed this article, until next time 👋&lt;/p&gt;


&lt;div class="ltag__user ltag__user__id__892161"&gt;
    &lt;a href="/gioboa" class="ltag__user__link profile-image-link"&gt;
      &lt;div class="ltag__user__pic"&gt;
        &lt;img src="https://media2.dev.to/dynamic/image/width=150,height=150,fit=cover,gravity=auto,format=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F892161%2Ff7bb8d77-6568-4576-b4e5-715d424afabd.jpeg" alt="gioboa image"&gt;
      &lt;/div&gt;
    &lt;/a&gt;
  &lt;div class="ltag__user__content"&gt;
    &lt;h2&gt;
&lt;a class="ltag__user__link" href="/gioboa"&gt;Giorgio Boa&lt;/a&gt;Follow
&lt;/h2&gt;
    &lt;div class="ltag__user__summary"&gt;
      &lt;a class="ltag__user__link" href="/gioboa"&gt;Giorgio Boa is a full stack developer and the front-end ecosystem is his passion. He is also international public speaker, active in open source ecosystem, he loves learn and studies new things.&lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;



</description>
      <category>antigravity</category>
      <category>agenticarchitect</category>
      <category>google</category>
      <category>python</category>
    </item>
    <item>
      <title>Moving Fast Without Losing Track: My antigravity-cli Changelog Habit</title>
      <dc:creator>Giorgio Boa</dc:creator>
      <pubDate>Thu, 09 Jul 2026 14:29:04 +0000</pubDate>
      <link>https://dev.to/gioboa/moving-fast-without-losing-track-my-antigravity-cli-changelog-habit-4h1a</link>
      <guid>https://dev.to/gioboa/moving-fast-without-losing-track-my-antigravity-cli-changelog-habit-4h1a</guid>
      <description>&lt;p&gt;As a consultant, I am used to working at different speeds.&lt;/p&gt;

&lt;p&gt;At the beginning of a project, especially when preparing the first proof of concept, the pace is fast. Very fast. It feels close to startup mode: short feedback loops, quick decisions, and a strong focus on delivering something usable in the shortest possible time. The goal is not to build the final version immediately. The goal is to test an idea, reduce uncertainty, and put something concrete in front of people.&lt;/p&gt;

&lt;p&gt;In that phase, speed matters more than ceremony. A proof of concept gives the team real evidence: does the workflow make sense, does the model answer correctly, does the tool integration work, does the user understand the value?&lt;/p&gt;

&lt;p&gt;But after the POC works, things change.&lt;/p&gt;

&lt;p&gt;Once the first version is tested and released to production, the project enters a different rhythm. The code is no longer only an experiment. It becomes something users depend on. Every change can affect a real workflow, so the team needs more control over what will go live.&lt;/p&gt;

&lt;p&gt;This is why, with &lt;code&gt;atigravity-cli&lt;/code&gt;, I usually add a skill that updates the changelog after every modification. It is a small habit, but it creates a useful control layer. Each code change leaves a written trace.&lt;/p&gt;

&lt;p&gt;Here is a simple example from my &lt;a href="https://github.com/gioboa/typescript-adk" rel="noopener noreferrer"&gt;Google ADK TypeScript project&lt;/a&gt;. The root agent is a sequential &lt;a href="https://adk.dev/" rel="noopener noreferrer"&gt;ADK&lt;/a&gt; workflow: first it converts currency, then it estimates how many LEGO pieces could be bought.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;SequentialAgent&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@google/adk&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;currencyAgent&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./sub-agents/currencyAgent.ts&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;legoPiecesAgent&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./sub-agents/legoPiecesAgent.ts&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;rootAgent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;SequentialAgent&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;currency_pipeline&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Converts currency, then calculates LEGO pieces needed for the converted amount.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;subAgents&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;currencyAgent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;legoPiecesAgent&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This is still a small project, but it already has a structure that can grow: a root agent, sub-agents, tools, a README, and a changelog. The currency agent is focused on one job only.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;currencyAgent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;LlmAgent&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;currency_agent&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;gemini-3.5-flash&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;An agent that can help with currency conversions.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;instruction&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;SYSTEM_INSTRUCTION&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; When converting an amount, clearly include the final converted amount and target currency in your response.`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;tools&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;getExchangeRate&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;outputKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;currencyResult&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The tool itself calls the Frankfurter API and keeps the external integration isolated.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`https://api.frankfurter.app/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;currency_date&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;searchParams&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;from&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;currency_from&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toUpperCase&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;searchParams&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;to&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;currency_to&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toUpperCase&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Then another agent reads the conversion result and calculates a LEGO estimate. In the example, the logic supports USD and EUR.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;If&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;target&lt;/span&gt; &lt;span class="nx"&gt;currency&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="nx"&gt;EUR&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="nx"&gt;estimate&lt;/span&gt; &lt;span class="nx"&gt;LEGO&lt;/span&gt; &lt;span class="nx"&gt;pieces&lt;/span&gt; &lt;span class="nx"&gt;using&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;average&lt;/span&gt; &lt;span class="nx"&gt;retail&lt;/span&gt; &lt;span class="nx"&gt;price&lt;/span&gt; &lt;span class="nx"&gt;range&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;LEGO&lt;/span&gt; &lt;span class="nx"&gt;piece&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="nx"&gt;EUR0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;EUR0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;13&lt;/span&gt; &lt;span class="nx"&gt;EUR&lt;/span&gt; &lt;span class="nx"&gt;per&lt;/span&gt; &lt;span class="nx"&gt;piece&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This kind of change may look small. But in production, even small changes matter. Supporting EUR in the LEGO estimation changes the behavior users see. With a changelog, it becomes visible.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fv5tiapmaemnvvgwdr543.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fv5tiapmaemnvvgwdr543.png" alt="prompt" width="800" height="140"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The project includes a custom rule:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;After you modify, add, or delete any files in the workspace,
trigger and follow the update-changelog skill.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;And the skill defines the process:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;Check which files were modified, read package.json,
read CHANGELOG.md, then write clear user-facing bullet points.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The result is simple but powerful:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fp2zx70v5zu15mwh4pd11.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fp2zx70v5zu15mwh4pd11.png" alt="changelog-result" width="800" height="188"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For me, this is the difference between moving fast and moving blind. During the POC, I want maximum speed. After production, I still want speed, but with memory.&lt;/p&gt;

&lt;p&gt;That context helps consultants, developers, stakeholders, and future maintainers. It turns an AI-assisted workflow into something easier to review, easier to release, and easier to trust.&lt;/p&gt;



&lt;p&gt;You can&amp;nbsp;&lt;a href="https://github.com/gioboa" rel="noopener noreferrer"&gt;follow me on GitHub&lt;/a&gt;, where I'm creating cool projects.&lt;/p&gt;

&lt;p&gt;I hope you enjoyed this article, until next time 👋&lt;/p&gt;


&lt;div class="ltag__user ltag__user__id__892161"&gt;
    &lt;a href="/gioboa" class="ltag__user__link profile-image-link"&gt;
      &lt;div class="ltag__user__pic"&gt;
        &lt;img src="https://media2.dev.to/dynamic/image/width=150,height=150,fit=cover,gravity=auto,format=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F892161%2Ff7bb8d77-6568-4576-b4e5-715d424afabd.jpeg" alt="gioboa image"&gt;
      &lt;/div&gt;
    &lt;/a&gt;
  &lt;div class="ltag__user__content"&gt;
    &lt;h2&gt;
&lt;a class="ltag__user__link" href="/gioboa"&gt;Giorgio Boa&lt;/a&gt;Follow
&lt;/h2&gt;
    &lt;div class="ltag__user__summary"&gt;
      &lt;a class="ltag__user__link" href="/gioboa"&gt;Giorgio Boa is a full stack developer and the front-end ecosystem is his passion. He is also international public speaker, active in open source ecosystem, he loves learn and studies new things.&lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;



</description>
      <category>agenticarchitect</category>
      <category>antigravity</category>
      <category>google</category>
      <category>adk</category>
    </item>
    <item>
      <title>Stop Giving AI Agents Your Whole Laptop: Secure Them with Dev Containers</title>
      <dc:creator>Giorgio Boa</dc:creator>
      <pubDate>Wed, 08 Jul 2026 09:31:07 +0000</pubDate>
      <link>https://dev.to/gioboa/stop-giving-ai-agents-your-whole-laptop-secure-them-with-dev-containers-k4m</link>
      <guid>https://dev.to/gioboa/stop-giving-ai-agents-your-whole-laptop-secure-them-with-dev-containers-k4m</guid>
      <description>&lt;p&gt;I recently started using Visual Studio Code Dev Containers with LLM coding agents and I thought to share it because, in my opinion, it is one of the simplest ways to make agentic development safer.&lt;/p&gt;




&lt;p&gt;LLM agents are incredibly useful, but the first time you run one with full access to your laptop you may have the same thought I had:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Do I really want this thing to see my whole filesystem, my SSH keys, my cloud credentials, and all the random projects I have locally?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Developer Experience
&lt;/h3&gt;

&lt;p&gt;The best developer experience is not only about speed.&lt;/p&gt;

&lt;p&gt;It is also about having an environment where you can experiment without constantly worrying about what the tool can touch.&lt;/p&gt;

&lt;p&gt;This is where Dev Containers are very useful: you can give the agent a clean workspace, the exact dependencies it needs, and nothing else.&lt;/p&gt;

&lt;h3&gt;
  
  
  Visual Studio Code Dev Containers
&lt;/h3&gt;

&lt;p&gt;The &lt;a href="https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers" rel="noopener noreferrer"&gt;Visual Studio Code Dev Containers extension&lt;/a&gt; lets you use a Docker container as a full-featured development environment. It allows you to open any folder or repository inside a container and take advantage of Visual Studio Code's full feature set.&lt;/p&gt;

&lt;p&gt;For LLM agents, this means you can run the editor, terminal, tools, and agent inside a container instead of directly on your machine.&lt;/p&gt;

&lt;p&gt;The agent can still edit files, run tests, install packages, and execute commands, but only inside the environment you prepared for it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why This Matters For LLM Agents
&lt;/h3&gt;

&lt;p&gt;When you run an agent locally, the risk is not only that it writes bad code.&lt;/p&gt;

&lt;p&gt;The bigger concern is access.&lt;/p&gt;

&lt;p&gt;If your whole home directory is available, the agent may accidentally read files that are unrelated to the project. If your shell has access to credentials, tokens, cloud CLIs, SSH config, or production scripts, the blast radius is much bigger.&lt;/p&gt;

&lt;p&gt;With a Dev Container you can avoid sharing all your system and credentials. You mount only the project folders you want to work on, install only the tools needed for that environment, and decide explicitly which secrets, if any, are available.&lt;/p&gt;

&lt;h3&gt;
  
  
  YOLO Mode
&lt;/h3&gt;

&lt;p&gt;Many LLM coding tools have a mode where the agent can run commands and edit files without asking for confirmation every time.&lt;/p&gt;

&lt;p&gt;Sometimes people call this "YOLO mode".&lt;/p&gt;

&lt;p&gt;It is convenient, but on your host machine it can be scary.&lt;/p&gt;

&lt;p&gt;Inside a Dev Container, it becomes much more reasonable: if the agent installs the wrong package, breaks the environment, or creates a mess, you can rebuild the container and start again.&lt;/p&gt;

&lt;p&gt;You are not giving it your entire laptop.&lt;/p&gt;

&lt;p&gt;You are giving it a disposable development box.&lt;/p&gt;

&lt;h3&gt;
  
  
  My Setup
&lt;/h3&gt;

&lt;p&gt;Instead of adding a &lt;code&gt;.devcontainer&lt;/code&gt; folder to every project, I keep one separate folder that only describes the agent environment.&lt;/p&gt;

&lt;p&gt;Something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.
|-- devcontainer
|   |-- devcontainer.json
|   `-- Dockerfile
|-- project-a
|-- project-b
`-- project-c
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;I build and start the container from the &lt;code&gt;devcontainer&lt;/code&gt; folder.&lt;/p&gt;

&lt;p&gt;Then, when I want to work on a project, I attach that project folder into the running container and connect VS Code to the container.&lt;/p&gt;

&lt;p&gt;This gives me one reusable environment for LLM agents, without having to copy the same Dev Container configuration into every repository.&lt;/p&gt;
&lt;h3&gt;
  
  
  Configuration
&lt;/h3&gt;
&lt;h4&gt;
  
  
  devcontainer.json
&lt;/h4&gt;

&lt;p&gt;The &lt;code&gt;devcontainer.json&lt;/code&gt; file describes the reusable container environment.&lt;/p&gt;

&lt;p&gt;Here is a simple example:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"agent-safe-workspace"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"build"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"dockerfile"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Dockerfile"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"workspaceFolder"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/workspaces"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"remoteUser"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"node"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The important idea is that this folder describes the agent box, not a specific application.&lt;/p&gt;

&lt;p&gt;Your projects can stay separate, and you decide which ones are attached to the running container.&lt;/p&gt;
&lt;h4&gt;
  
  
  Dockerfile
&lt;/h4&gt;

&lt;p&gt;The Dockerfile defines what is installed inside the container.&lt;/p&gt;

&lt;p&gt;For example, for a Node.js based environment:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; mcr.microsoft.com/devcontainers/javascript-node:1-22-bookworm&lt;/span&gt;

&lt;span class="k"&gt;RUN &lt;/span&gt;apt-get update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; apt-get &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;    ripgrep &lt;span class="se"&gt;\
&lt;/span&gt;    jq &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; /var/lib/apt/lists/&lt;span class="k"&gt;*&lt;/span&gt;

&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /workspaces&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;You can adapt this depending on your stack: Python, Go, Rust, Java, or anything else.&lt;/p&gt;

&lt;p&gt;The important part is that the dependencies are installed in the container, not directly on your host machine.&lt;/p&gt;
&lt;h3&gt;
  
  
  Starting The Container
&lt;/h3&gt;

&lt;p&gt;From the folder that contains the Dev Container configuration, you start the container separately.&lt;/p&gt;

&lt;p&gt;For example, you can use the Dev Containers extension to open only that &lt;code&gt;devcontainer&lt;/code&gt; folder, or you can build and run the Docker image yourself.&lt;/p&gt;

&lt;p&gt;After the container is running, attach VS Code to it with:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Dev Containers: Attach to Running Container&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;At that point you are inside the isolated environment.&lt;/p&gt;

&lt;p&gt;Then you attach or mount the project folder you want to work on into the container and open it from there.&lt;/p&gt;

&lt;p&gt;The workflow becomes:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1. Start the reusable agent container
2. Attach your project to the running container with VS Code
3. Run the LLM agent inside the container
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This is different from the usual flow where each project owns its own &lt;code&gt;.devcontainer&lt;/code&gt; folder.&lt;/p&gt;

&lt;p&gt;In this setup, the container is the stable tool environment, and the project folders are the inputs you choose to expose to it.&lt;/p&gt;
&lt;h3&gt;
  
  
  Credentials
&lt;/h3&gt;

&lt;p&gt;Be intentional with secrets.&lt;/p&gt;

&lt;p&gt;Do not mount your entire &lt;code&gt;~/.ssh&lt;/code&gt;, &lt;code&gt;~/.aws&lt;/code&gt;, &lt;code&gt;~/.config&lt;/code&gt;, or home directory by default.&lt;/p&gt;

&lt;p&gt;If the agent needs a token, create a limited token for that task. If it needs GitHub access, prefer a token with the smallest useful scope. If it does not need credentials, do not provide them.&lt;/p&gt;

&lt;p&gt;The point of the container is to make access explicit.&lt;/p&gt;
&lt;h3&gt;
  
  
  Docker
&lt;/h3&gt;

&lt;p&gt;Obviously, you need Docker up and running on your machine.&lt;/p&gt;

&lt;p&gt;After that, VS Code can connect to the container and give you the usual editor experience inside the isolated environment.&lt;/p&gt;
&lt;h3&gt;
  
  
  VS Code Extension
&lt;/h3&gt;

&lt;p&gt;To use this workflow, install the &lt;a href="https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers" rel="noopener noreferrer"&gt;Dev Containers&lt;/a&gt; extension.&lt;/p&gt;

&lt;p&gt;The command I use most in this setup is:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Dev Containers: Attach to Running Container&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This lets me keep the container lifecycle separate from the project lifecycle.&lt;/p&gt;
&lt;h3&gt;
  
  
  Ready To Go
&lt;/h3&gt;

&lt;p&gt;Once the container is running and the project folder is attached, start your LLM agent from the VS Code terminal inside the container.&lt;/p&gt;

&lt;p&gt;Now the agent sees the project workspace and the tools you installed there.&lt;/p&gt;

&lt;p&gt;That is the main advantage: you can let the agent move faster, even in YOLO mode, while keeping a clear boundary between the experiment and the rest of your machine.&lt;/p&gt;

&lt;p&gt;It is not a magic security solution, but it is a very practical improvement. The only tedious part is writing the correct Dockerfile, but once it is done, the environment becomes reusable, predictable, and safe to use.&lt;/p&gt;

&lt;p&gt;For day-to-day agentic coding, a reusable disposable Dev Container is one of the easiest ways to reduce risk without making the workflow painful.&lt;/p&gt;



&lt;p&gt;You can&amp;nbsp;&lt;a href="https://github.com/gioboa" rel="noopener noreferrer"&gt;follow me on GitHub&lt;/a&gt;, where I'm creating cool projects.&lt;/p&gt;

&lt;p&gt;I hope you enjoyed this article, until next time 👋&lt;/p&gt;


&lt;div class="ltag__user ltag__user__id__892161"&gt;
    &lt;a href="/gioboa" class="ltag__user__link profile-image-link"&gt;
      &lt;div class="ltag__user__pic"&gt;
        &lt;img src="https://media2.dev.to/dynamic/image/width=150,height=150,fit=cover,gravity=auto,format=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F892161%2Ff7bb8d77-6568-4576-b4e5-715d424afabd.jpeg" alt="gioboa image"&gt;
      &lt;/div&gt;
    &lt;/a&gt;
  &lt;div class="ltag__user__content"&gt;
    &lt;h2&gt;
&lt;a class="ltag__user__link" href="/gioboa"&gt;Giorgio Boa&lt;/a&gt;Follow
&lt;/h2&gt;
    &lt;div class="ltag__user__summary"&gt;
      &lt;a class="ltag__user__link" href="/gioboa"&gt;Giorgio Boa is a full stack developer and the front-end ecosystem is his passion. He is also international public speaker, active in open source ecosystem, he loves learn and studies new things.&lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;



</description>
      <category>discuss</category>
      <category>ai</category>
      <category>vscode</category>
      <category>programming</category>
    </item>
    <item>
      <title>Scalable Micro-Frontends on Cloudflare</title>
      <dc:creator>Giorgio Boa</dc:creator>
      <pubDate>Mon, 06 Jul 2026 14:49:20 +0000</pubDate>
      <link>https://dev.to/gioboa/scalable-micro-frontends-on-cloudflare-28in</link>
      <guid>https://dev.to/gioboa/scalable-micro-frontends-on-cloudflare-28in</guid>
      <description>&lt;p&gt;In a traditional monolithic front-end, coordinating releases across multiple teams introduces significant organisational friction. Teams often find themselves bottlenecked by shared deployment pipelines, where a single bug in one feature can block unrelated updates from shipping to production. Additionally, managing massive merge conflicts, coordinating deployment windows, and aligning testing cycles across disparate product areas frequently lead to slower release cadences and diluted domain ownership. Micro-frontends address these challenges by decoupling the frontend into autonomous modules, enabling each team to deploy updates on their own schedule without requiring cross-organisational synchronisation.&lt;/p&gt;

&lt;p&gt;However, traditional micro-frontend setups often introduce latency, complex Cross-Origin Resource Sharing (CORS) configurations, and complicated deployment pipelines. &lt;/p&gt;

&lt;p&gt;By combining &lt;strong&gt;Module Federation (&lt;code&gt;@module-federation/vite&lt;/code&gt;)&lt;/strong&gt; with &lt;strong&gt;Cloudflare Workers&lt;/strong&gt;—utilizing &lt;strong&gt;Service Bindings&lt;/strong&gt;, &lt;strong&gt;&lt;code&gt;@cloudflare/vite-plugin&lt;/code&gt;&lt;/strong&gt;, and &lt;strong&gt;Wrangler&lt;/strong&gt;—you can create a scalable, performant micro-frontend monorepo.&lt;/p&gt;

&lt;p&gt;This approach resolves remote micro-frontends (MFEs) via a same-origin proxy mechanism directly on Cloudflare’s edge network, completely avoiding CORS issues in production while preserving a native development experience locally.&lt;/p&gt;




&lt;h2&gt;
  
  
  Architecture Overview
&lt;/h2&gt;

&lt;p&gt;In this example of monorepo architecture, we split our system into a single &lt;strong&gt;Host Shell&lt;/strong&gt; and multiple &lt;strong&gt;Remote micro-frontends&lt;/strong&gt; (&lt;code&gt;remote-a&lt;/code&gt; and &lt;code&gt;remote-b&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;├── apps/
│   └── host/     # Host shell (Vite + Cloudflare Worker)
└── mfes/
    ├── remote-a/ # Exposed Micro-Frontend A (Assets-only Worker)
    └── remote-b/ # Exposed Micro-Frontend B (Assets-only Worker)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  The Production Same-Origin Proxy Pattern
&lt;/h3&gt;

&lt;p&gt;In production, the host worker acts as an API gateway and static asset router. When a user requests &lt;code&gt;/remote-a/remoteEntry.js&lt;/code&gt;, the host worker intercepts the route and proxies the request to the &lt;code&gt;remote-a&lt;/code&gt; Worker via &lt;strong&gt;Cloudflare Service Bindings&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;This offers several operational, performance, and cost advantages:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Zero CORS Issues&lt;/strong&gt;: Because all micro-frontends are served under the host’s primary domain, the browser views them as same-origin. This removes the need for complex, fragile, and potentially insecure cross-origin HTTP header management.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Minimal Latency&lt;/strong&gt;: Cloudflare Service Bindings allow Workers to execute within the same thread on the same physical edge server [1.2.2]. This allows them to pass requests internally with near-zero network overhead, routing traffic instantly without going back out to the public internet.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No Request Duplication Costs (Free Subrequests)&lt;/strong&gt;: On Cloudflare Workers, you only pay for the initial user request hitting the Host Worker. The subsequent internal calls to the remote Workers via &lt;code&gt;env.REMOTE_A&lt;/code&gt; or &lt;code&gt;env.REMOTE_B&lt;/code&gt; are treated as internal subrequests, which carry &lt;strong&gt;zero additional request fees&lt;/strong&gt;. This allows you to split your application into as many micro-frontends as required without multiplying your Cloudflare request charges.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Elimination of Gateway Infrastructure Overhead&lt;/strong&gt;: Historically, avoiding CORS in a micro-frontend architecture required provisioning, patching, and maintaining a cluster of dedicated reverse-proxy servers (e.g., NGINX running on virtual machines) or configuring expensive cloud load balancers. Cloudflare Workers scale to zero, eliminating the maintenance effort and baseline idle-VM costs associated with dedicated routing infrastructure.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Robust Environment Isolation&lt;/strong&gt;: The host can map service bindings dynamically across environments (e.g., routing &lt;code&gt;/remote-a/*&lt;/code&gt; to &lt;code&gt;remote-a-qa&lt;/code&gt; in the staging environment and &lt;code&gt;remote-a-prod&lt;/code&gt; in production). This permits deployment pipelines to deliver changes safely without running separate physical infrastructure stacks for each target environment.&lt;/li&gt;
&lt;/ol&gt;


&lt;h2&gt;
  
  
  1. Configuring the Remote Micro-Frontends
&lt;/h2&gt;

&lt;p&gt;Each remote MFE functions as an assets-only Worker. It builds its static files—including the Module Federation container entrypoint (&lt;code&gt;remoteEntry.js&lt;/code&gt;)—and serves them directly.&lt;/p&gt;
&lt;h3&gt;
  
  
  Vite Configuration (&lt;code&gt;mfes/remote-a/vite.config.ts&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;The remote uses the &lt;code&gt;@module-federation/vite&lt;/code&gt; plugin to bundle components and expose them. It also declares shared dependencies like &lt;code&gt;react&lt;/code&gt; and &lt;code&gt;react-dom&lt;/code&gt; as singletons to prevent multiple React runtimes from loading in the browser.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;defineConfig&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vite&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;react&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@vitejs/plugin-react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;federation&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@module-federation/vite&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;defineConfig&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nf"&gt;react&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="nf"&gt;federation&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;dts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;remoteA&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;remoteEntry.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Emitted container entrypoint&lt;/span&gt;
      &lt;span class="na"&gt;exposes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./Widget&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./src/Widget.tsx&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Exposed remote component&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="na"&gt;shared&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;react&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;singleton&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-dom&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;singleton&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;}),&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Module Federation relies on top-level await; esnext target is required&lt;/span&gt;
    &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;esnext&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;server&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5174&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;strictPort&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;cors&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;origin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;*&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="c1"&gt;// Required for local cross-origin loading in dev&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Wrangler Configuration (&lt;code&gt;mfes/remote-a/wrangler.jsonc&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;For the remote micro-frontends, we configure them as assets-only deployments. A crucial setting is &lt;code&gt;"not_found_handling": "none"&lt;/code&gt;. Unlike single-page applications (SPAs) which fallback to &lt;code&gt;index.html&lt;/code&gt; on missing assets, MFE chunk directories must strictly return a &lt;code&gt;404 Not Found&lt;/code&gt; if a chunk is missing to prevent the federated runtime from swallowing errors.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json-doc"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"$schema"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"node_modules/wrangler/config-schema.json"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"cloudflare-react-remote-a"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"compatibility_date"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2026-06-16"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"assets"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"directory"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./dist"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"not_found_handling"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"none"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// Crucial: return 404s for missing asset chunks&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"workers_dev"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"env"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"qa"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"prod"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  2. Configuring the Host Worker
&lt;/h2&gt;

&lt;p&gt;The host application consists of a React SPA built with Vite, run inside the Workers environment locally and in production via the official &lt;code&gt;@cloudflare/vite-plugin&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  Vite Configuration (&lt;code&gt;apps/host/vite.config.ts&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;The host references the &lt;code&gt;@cloudflare/vite-plugin&lt;/code&gt; to run worker-level code locally in a &lt;code&gt;workerd&lt;/code&gt; environment.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;defineConfig&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vite&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;react&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@vitejs/plugin-react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;cloudflare&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@cloudflare/vite-plugin&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;federation&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@module-federation/vite&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;defineConfig&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nf"&gt;react&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="nf"&gt;cloudflare&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="nf"&gt;federation&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;dts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;host&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;remotes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt; &lt;span class="c1"&gt;// Configured dynamically at runtime instead of statically&lt;/span&gt;
      &lt;span class="na"&gt;shared&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;react&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;singleton&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-dom&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;singleton&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="na"&gt;shareStrategy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;loaded-first&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}),&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;esnext&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Wrangler Configuration (&lt;code&gt;apps/host/wrangler.jsonc&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;The host wrangler config binds the remote Workers using &lt;code&gt;services&lt;/code&gt; and sets up &lt;code&gt;run_worker_first&lt;/code&gt; routing. The &lt;code&gt;run_worker_first&lt;/code&gt; configuration routes the matching path prefixes to the worker code instead of attempting to look them up inside the host’s static asset bucket.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json-doc"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"$schema"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"node_modules/wrangler/config-schema.json"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"cloudflare-react"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"main"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"worker/index.ts"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"compatibility_date"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2026-06-16"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"assets"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"binding"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ASSETS"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"not_found_handling"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"single-page-application"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"run_worker_first"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"/remote-a/*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"/remote-b/*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"/api/*"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"services"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"binding"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"REMOTE_A"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"service"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"cloudflare-react-remote-a"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"binding"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"REMOTE_B"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"service"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"cloudflare-react-remote-b"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"env"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"qa"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"services"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"binding"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"REMOTE_A"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"service"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"cloudflare-react-remote-a-qa"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"binding"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"REMOTE_B"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"service"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"cloudflare-react-remote-b-qa"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"prod"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"services"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"binding"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"REMOTE_A"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"service"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"cloudflare-react-remote-a-prod"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"binding"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"REMOTE_B"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"service"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"cloudflare-react-remote-b-prod"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  3. Implementing the Host Worker Entrypoint
&lt;/h2&gt;

&lt;p&gt;The host worker’s router handles routing for local assets, remote proxy routing, and server-side logic APIs. When a route begins with &lt;code&gt;/remote-a/*&lt;/code&gt; or &lt;code&gt;/remote-b/*&lt;/code&gt;, the request is modified and forwarded via Service Bindings to the correct remote worker.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// apps/host/worker/index.ts&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Env&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;ASSETS&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Fetcher&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;REMOTE_A&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Fetcher&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;REMOTE_B&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Fetcher&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;withAssetCache&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;pathname&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;Response&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;out&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="c1"&gt;// Immutable caching for content-hashed production asset bundles&lt;/span&gt;
  &lt;span class="nx"&gt;out&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Cache-Control&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;pathname&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;startsWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/assets/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;public, max-age=31536000, immutable&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;no-cache&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;out&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Dynamic routing maps to remote service bindings&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;remoteRoutes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;prefix&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/remote-a&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;service&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;REMOTE_A&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;prefix&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/remote-b&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;service&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;REMOTE_B&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;];&lt;/span&gt;

    &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;prefix&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;service&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;remoteRoutes&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pathname&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;prefix&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pathname&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;startsWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;prefix&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;target&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="c1"&gt;// Strip the path prefix so the remote worker receives its root path&lt;/span&gt;
        &lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pathname&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pathname&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;prefix&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;service&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pathname&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;startsWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/api/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Cloudflare Workers Edge API&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Default: Serve static front-end assets for the host SPA&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;withAssetCache&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ASSETS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pathname&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;satisfies&lt;/span&gt; &lt;span class="nx"&gt;ExportedHandler&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Env&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  4. Resolving Micro-Frontends Dynamically at Runtime
&lt;/h2&gt;

&lt;p&gt;Statically defining remote URLs in &lt;code&gt;vite.config.ts&lt;/code&gt; forces a rebundling step for every distinct environment deployment. To achieve a &lt;strong&gt;single-build deployment model&lt;/strong&gt;, register your remotes programmatically using &lt;code&gt;@module-federation/runtime&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  Endpoint Mapping (&lt;code&gt;apps/host/src/moduleFederation/mfeUrls.ts&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;The remote resolution strategy shifts based on whether the code executes in local development or a production Worker. Vite's standard &lt;code&gt;import.meta.env.DEV&lt;/code&gt; variable determines the target origin.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;devRemoteEntry&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;envOverride&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;fallback&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;origin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;envOverride&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="nx"&gt;fallback&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\/&lt;/span&gt;&lt;span class="sr"&gt;$/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;origin&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/remoteEntry.js`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mfeUrls&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Record&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;remoteA&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DEV&lt;/span&gt;
    &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nf"&gt;devRemoteEntry&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;VITE_REMOTE_A_URL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http://localhost:5174&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/remote-a/remoteEntry.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;remoteB&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DEV&lt;/span&gt;
    &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nf"&gt;devRemoteEntry&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;VITE_REMOTE_B_URL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http://localhost:5175&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/remote-b/remoteEntry.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Initializing the Runtime (&lt;code&gt;apps/host/src/moduleFederation/moduleFederationRuntime.ts&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;Before importing any remote React code, initialize the federation container.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;registerRemotes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;loadRemote&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@module-federation/runtime&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;mfeUrls&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./mfeUrls&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;initialized&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;initializeModuleFederationRuntime&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;initialized&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nf"&gt;registerRemotes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;entries&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mfeUrls&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(([&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;module&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;})),&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;force&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;initialized&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;loadRemoteComponent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;TProps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Record&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;never&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;remoteId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ComponentType&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;TProps&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;initializeModuleFederationRuntime&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;remoteModule&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;loadRemote&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ComponentType&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;TProps&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;remoteId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;remoteModule&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Remote "&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;remoteId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;" failed to resolve.`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;remoteModule&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  5. Integrating Remote Components in React
&lt;/h2&gt;

&lt;p&gt;To handle potential loading failures gracefully (such as network drops or remote MFE redeployments), load the federated components dynamically using &lt;code&gt;React.lazy&lt;/code&gt; and enclose them in a &lt;strong&gt;React Error Boundary&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// apps/host/src/moduleFederation/RemoteWidget.tsx&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;lazy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Suspense&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ReactNode&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;loadRemoteComponent&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./moduleFederationRuntime&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;WidgetProps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;greeting&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;lazyByRemoteId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getRemoteWidget&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;remoteId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;component&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;lazyByRemoteId&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;remoteId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;component&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;component&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;lazy&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;loadRemoteComponent&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;WidgetProps&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;remoteId&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="nx"&gt;lazyByRemoteId&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;remoteId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;component&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;component&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;RemoteErrorBoundary&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Component&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;children&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ReactNode&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="nf"&gt;getDerivedStateFromError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;error-card&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h4&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Failed&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;load&lt;/span&gt; &lt;span class="nx"&gt;Remote&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h4&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/p&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;RemoteWidget&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;remoteId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;greeting&lt;/span&gt; &lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;remoteId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;greeting&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Widget&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getRemoteWidget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;remoteId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;RemoteErrorBoundary&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Suspense&lt;/span&gt; &lt;span class="nx"&gt;fallback&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Loading&lt;/span&gt; &lt;span class="nx"&gt;remote&lt;/span&gt; &lt;span class="nx"&gt;MFE&lt;/span&gt; &lt;span class="nx"&gt;components&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&amp;gt;}&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Widget&lt;/span&gt; &lt;span class="nx"&gt;greeting&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;greeting&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Suspense&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/RemoteErrorBoundary&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;By deploying your monorepo micro-frontends with &lt;strong&gt;Module Federation&lt;/strong&gt;, &lt;strong&gt;&lt;code&gt;@cloudflare/vite-plugin&lt;/code&gt;&lt;/strong&gt;, and &lt;strong&gt;Wrangler&lt;/strong&gt;, you combine the agility of modern UI composition with the performance profile of Cloudflare's edge network. Using same-origin proxying via Service Bindings avoids complex client CORS setups entirely. When combined with dynamic runtime federation entry resolution, this setup simplifies local development workflows and provides robust routing capabilities in production environments.&lt;/p&gt;



&lt;p&gt;Special thanks to &lt;a href="https://github.com/Sultanyaron" rel="noopener noreferrer"&gt;Sultanyaron&lt;/a&gt; for your amazing example &lt;a href="https://github.com/Sultanyaron/vite-module-federation-cloudflare-deployment" rel="noopener noreferrer"&gt;https://github.com/Sultanyaron/vite-module-federation-cloudflare-deployment&lt;/a&gt;. You inspired this article.&lt;/p&gt;



&lt;p&gt;You can&amp;nbsp;&lt;a href="https://github.com/gioboa" rel="noopener noreferrer"&gt;follow me on GitHub&lt;/a&gt;, where I'm creating cool projects.&lt;/p&gt;

&lt;p&gt;I hope you enjoyed this article, until next time 👋&lt;/p&gt;


&lt;div class="ltag__user ltag__user__id__892161"&gt;
    &lt;a href="/gioboa" class="ltag__user__link profile-image-link"&gt;
      &lt;div class="ltag__user__pic"&gt;
        &lt;img src="https://media2.dev.to/dynamic/image/width=150,height=150,fit=cover,gravity=auto,format=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F892161%2Ff7bb8d77-6568-4576-b4e5-715d424afabd.jpeg" alt="gioboa image"&gt;
      &lt;/div&gt;
    &lt;/a&gt;
  &lt;div class="ltag__user__content"&gt;
    &lt;h2&gt;
&lt;a class="ltag__user__link" href="/gioboa"&gt;Giorgio Boa&lt;/a&gt;Follow
&lt;/h2&gt;
    &lt;div class="ltag__user__summary"&gt;
      &lt;a class="ltag__user__link" href="/gioboa"&gt;Giorgio Boa is a full stack developer and the front-end ecosystem is his passion. He is also international public speaker, active in open source ecosystem, he loves learn and studies new things.&lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;



</description>
      <category>webdev</category>
      <category>cloudflare</category>
      <category>microfrontend</category>
      <category>vite</category>
    </item>
    <item>
      <title>Reason, Act, Remember: Advanced AI with Microsoft Agent Framework</title>
      <dc:creator>Giorgio Boa</dc:creator>
      <pubDate>Thu, 19 Feb 2026 09:15:01 +0000</pubDate>
      <link>https://dev.to/gioboa/reason-act-remember-advanced-ai-with-microsoft-agent-framework-1p80</link>
      <guid>https://dev.to/gioboa/reason-act-remember-advanced-ai-with-microsoft-agent-framework-1p80</guid>
      <description>&lt;p&gt;Artificial Intelligence has moved beyond simple chatbots and into the realm of intelligent agents. These agents are not just passive responders; they are capable of reasoning, acting, and remembering. The &lt;a href="https://learn.microsoft.com/en-us/agent-framework/get-started/" rel="noopener noreferrer"&gt;Microsoft Agent Framework&lt;/a&gt; provides a comprehensive set of tools and libraries that empower developers to build these sophisticated AI systems.&lt;/p&gt;

&lt;p&gt;The first step in this journey is installing the dependency.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;agent-framework &lt;span class="nt"&gt;--pre&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Now that we have the right package, let's start by understanding what an agent actually is. In the simplest terms, an agent is a piece of software that uses a Large Language Model (LLM) to understand and generate human language. &lt;/p&gt;

&lt;p&gt;The framework makes it incredibly easy to bring such an entity to life. With just a few lines of code, a developer can connect to Azure's powerful AI infrastructure. You can give your agent a name and a set of instructions. For instance, you might tell it to be a friendly assistant or a technical expert. The framework handles all the complex communication with the AI model, allowing you to focus on what you want the agent to do.&lt;/p&gt;

&lt;p&gt;You can interact with this agent in two ways: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;ask a question and wait for the complete answer, which is great for short queries&lt;/li&gt;
&lt;li&gt;for longer responses, you can use streaming, where the agent "types" the answer out in real-time, making the experience feel much more interactive and responsive, just like a human typing a message.
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;agent_framework.azure&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;AzureOpenAIResponsesClient&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;azure.identity&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;AzureCliCredential&lt;/span&gt;

&lt;span class="c1"&gt;# Create an agent
&lt;/span&gt;&lt;span class="n"&gt;credential&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;AzureCliCredential&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;AzureOpenAIResponsesClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;project_endpoint&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;AZURE_AI_PROJECT_ENDPOINT&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="n"&gt;deployment_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;AZURE_OPENAI_RESPONSES_DEPLOYMENT_NAME&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="n"&gt;credential&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;credential&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;agent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;as_agent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;HelloAgent&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;instructions&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;You are a friendly assistant. Keep your answers brief.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Run agent (non-streaming)
&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;agent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;What is the capital of France?&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Agent: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Run agent (streaming)
&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Agent (streaming): &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;flush&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;chunk&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;agent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Tell me a one-sentence fun fact.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;flush&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Expanding Capabilities with Tools
&lt;/h2&gt;

&lt;p&gt;However, an AI that can only talk is limited. The real magic happens when you give your agent the ability to interact with the world. This is where the concept of "Tools" comes into play. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Imagine you want your agent to know the current weather. A standard language model only knows what it was trained on and cannot know if it is raining outside right now. You can define standard Python functions and attaching them to your agent. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You could write a simple function that checks a weather API. When you ask the agent about the weather, it analyses your request, the system intelligently decides to call the function you provided. It then takes the result from that function and uses it to formulate a natural language response.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;typing&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Annotated&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;agent_framework&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;tool&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;pydantic&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Field&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;random&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;randint&lt;/span&gt;

&lt;span class="nd"&gt;@tool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;approval_mode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;never_require&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_weather&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;location&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Annotated&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;The location to get the weather for.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)],&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Get the weather for a given location.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;conditions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sunny&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cloudy&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;rainy&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;stormy&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;The weather in &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;location&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; is &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;conditions&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;randint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; with a high of &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;randint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;°C.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="c1"&gt;# Create agent with tools
&lt;/span&gt;&lt;span class="n"&gt;agent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;as_agent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;WeatherAgent&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;instructions&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;You are a helpful weather agent. Use the get_weather tool to answer questions.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;get_weather&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;--&lt;/span&gt; &lt;span class="n"&gt;here&lt;/span&gt; &lt;span class="n"&gt;you&lt;/span&gt; &lt;span class="n"&gt;have&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;define&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;tool&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;agent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;What&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;s the weather like in Seattle?&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Agent: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Multi-Turn Interactions with Sessions
&lt;/h2&gt;

&lt;p&gt;If you tell an agent your name at the start of a chat, you expect it to remember that name five minutes later. The framework solves this through "Sessions". &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A session acts as a container for the conversation history. When you talk to the agent within a session, the framework automatically keeps track of what has been said. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This allows for multi-turn conversations where the agent maintains context. This creates an experience that feels personal and coherent rather than robotic.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Create a session to maintain conversation history
&lt;/span&gt;&lt;span class="n"&gt;session&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;agent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create_session&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;# First turn
&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;agent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;My name is Alice and I love hiking.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Agent: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Second turn — the agent should remember the user's name and hobby
&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;agent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;What do you remember about me?&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Agent: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




&lt;p&gt;The Microsoft Agent Framework provides a comprehensive toolkit for building intelligent AI agents that reason, act, and remember. Key features include core agent interaction via LLMs, dynamic tool integration for real-world tasks, and session-based conversation persistence. Finally&amp;nbsp;the journey for building an AI agent is both accessible and powerful.&lt;/p&gt;



&lt;p&gt;You can&amp;nbsp;&lt;a href="https://github.com/gioboa" rel="noopener noreferrer"&gt;follow me on GitHub&lt;/a&gt;, where I'm creating cool projects.&lt;/p&gt;

&lt;p&gt;I hope you enjoyed this article, until next time 👋&lt;/p&gt;

&lt;p&gt;

&lt;/p&gt;
&lt;div class="ltag__user ltag__user__id__892161"&gt;
    &lt;a href="/gioboa" class="ltag__user__link profile-image-link"&gt;
      &lt;div class="ltag__user__pic"&gt;
        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F892161%2Ff7bb8d77-6568-4576-b4e5-715d424afabd.jpeg" alt="gioboa image"&gt;
      &lt;/div&gt;
    &lt;/a&gt;
  &lt;div class="ltag__user__content"&gt;
    &lt;h2&gt;
&lt;a class="ltag__user__link" href="/gioboa"&gt;Giorgio Boa&lt;/a&gt;Follow
&lt;/h2&gt;
    &lt;div class="ltag__user__summary"&gt;
      &lt;a class="ltag__user__link" href="/gioboa"&gt;Giorgio Boa is a full stack developer and the front-end ecosystem is his passion. He is also international public speaker, active in open source ecosystem, he loves learn and studies new things.&lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;





</description>
      <category>microsoft</category>
      <category>ai</category>
      <category>python</category>
      <category>programming</category>
    </item>
    <item>
      <title>Copilot: Secret Tip to Troubleshooting Your GitHub Actions</title>
      <dc:creator>Giorgio Boa</dc:creator>
      <pubDate>Thu, 12 Feb 2026 08:16:04 +0000</pubDate>
      <link>https://dev.to/gioboa/copilot-secret-tip-to-troubleshooting-your-github-actions-30cd</link>
      <guid>https://dev.to/gioboa/copilot-secret-tip-to-troubleshooting-your-github-actions-30cd</guid>
      <description>&lt;p&gt;GitHub Actions have become an indispensable tool for automating software development workflows, enabling continuous integration and delivery directly within your repositories. However, even the most meticulously crafted pipelines can encounter issues, leading to frustrating debugging sessions. This is where GitHub Copilot emerges as a powerful assistant, offering intelligent insights and streamlining the troubleshooting process for your GitHub Actions workflows.&lt;/p&gt;

&lt;p&gt;Traditionally, pinpointing the root cause of a failed GitHub Actions run involves sifting through extensive logs, meticulously checking syntax, and understanding the intricate interplay of various actions and conditions. This can be a time-consuming, especially for intricate workflows or those managed by multiple contributors. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Copilot aims to transform this experience, acting as an intelligent partner that can quickly analyse failures and suggest solutions.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Here is an example:
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1n0g9s7dwm9fmpivslbn.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1n0g9s7dwm9fmpivslbn.gif" alt="Copilot-helper"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;One of Copilot's most compelling features for GitHub Actions troubleshooting is its ability to provide immediate explanations for failed checks. You no longer need to manually navigate through layers of logs to understand what went wrong. With a simple click on the "Explain error" option next to a failed check in the merge box or on the workflow run summary page, Copilot springs into action. It opens a chat window, where it will analyze the context of the failure and offer actionable instructions to resolve the issue. This direct and contextual guidance significantly reduces the time and effort required to diagnose problems.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This kind of intelligent assistance can be invaluable for understanding the flow of your workflow and identifying logic errors more efficiently.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;It acts as an intelligent accelerator, helping you navigate complex scenarios and quickly pinpoint solutions. By leveraging Copilot as a helper in your GitHub Actions pipelines you can spend more time building and less time debugging.&lt;/p&gt;




&lt;p&gt;You can&amp;nbsp;&lt;a href="https://github.com/gioboa" rel="noopener noreferrer"&gt;follow me on GitHub&lt;/a&gt;, where I'm creating cool projects.&lt;/p&gt;

&lt;p&gt;I hope you enjoyed this article, until next time 👋&lt;/p&gt;

&lt;p&gt;

&lt;/p&gt;
&lt;div class="ltag__user ltag__user__id__892161"&gt;
    &lt;a href="/gioboa" class="ltag__user__link profile-image-link"&gt;
      &lt;div class="ltag__user__pic"&gt;
        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F892161%2Ff7bb8d77-6568-4576-b4e5-715d424afabd.jpeg" alt="gioboa image"&gt;
      &lt;/div&gt;
    &lt;/a&gt;
  &lt;div class="ltag__user__content"&gt;
    &lt;h2&gt;
&lt;a class="ltag__user__link" href="/gioboa"&gt;Giorgio Boa&lt;/a&gt;Follow
&lt;/h2&gt;
    &lt;div class="ltag__user__summary"&gt;
      &lt;a class="ltag__user__link" href="/gioboa"&gt;Giorgio Boa is a full stack developer and the front-end ecosystem is his passion. He is also international public speaker, active in open source ecosystem, he loves learn and studies new things.&lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;




</description>
      <category>microsoft</category>
      <category>github</category>
      <category>githubcopilot</category>
      <category>ai</category>
    </item>
    <item>
      <title>Hooks are here: Now you can intercept and direct the path of the Gemini CLI</title>
      <dc:creator>Giorgio Boa</dc:creator>
      <pubDate>Thu, 29 Jan 2026 09:11:47 +0000</pubDate>
      <link>https://dev.to/gioboa/hooks-are-here-now-you-can-intercept-and-direct-the-path-of-the-gemini-cli-oeh</link>
      <guid>https://dev.to/gioboa/hooks-are-here-now-you-can-intercept-and-direct-the-path-of-the-gemini-cli-oeh</guid>
      <description>&lt;p&gt;The &lt;a href="https://geminicli.com/" rel="noopener noreferrer"&gt;Gemini Command Line Interface&lt;/a&gt; (CLI) is a powerful tool, and with the introduction of its "hooks" feature, users can now significantly extend and customise its behaviour without ever touching the core source code. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Hooks are essentially scripts or programs that the Gemini CLI executes at specific, predefined points within its agentic loop, offering unparalleled control and flexibility.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Use Cases
&lt;/h2&gt;

&lt;p&gt;Imagine being able to inject crucial context before your AI model even sees a request, validate potentially risky actions before they execute, or even enforce company-wide compliance policies directly within your development workflow. This is precisely the power that Gemini CLI hooks bring to the table. By running synchronously as part of the agent loop, hooks ensure that the CLI waits for their completion before proceeding, guaranteeing that your custom logic is always applied.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting Started
&lt;/h2&gt;

&lt;p&gt;Hooks communicate with the CLI via strict JSON requirements over &lt;code&gt;stdin&lt;/code&gt; and &lt;code&gt;stdout&lt;/code&gt; – the "Golden Rule" dictates that your script must only print the final JSON object to &lt;code&gt;stdout&lt;/code&gt;, reserving &lt;code&gt;stderr&lt;/code&gt; for all debugging and logging. Exit codes play a crucial role, with &lt;code&gt;0&lt;/code&gt; signifying success and allowing &lt;code&gt;stdout&lt;/code&gt; to be parsed, while &lt;code&gt;2&lt;/code&gt; indicates a "System Block," aborting the target action and using &lt;code&gt;stderr&lt;/code&gt; as the rejection reason. Hooks can also be selectively triggered using "matchers," which are regular expressions for tool events and exact strings for lifecycle events.&lt;/p&gt;

&lt;h2&gt;
  
  
  Real Case Scenario
&lt;/h2&gt;

&lt;p&gt;Consider a scenario where you want to prevent the &lt;code&gt;delete_file&lt;/code&gt; tool from being executed if a specific environment variable isn't set. You could configure an hook with a matcher for &lt;code&gt;delete_file&lt;/code&gt;. This hook script would check for the environment variable. If it's missing, the script would print a JSON object like &lt;code&gt;{"decision": "deny", "reason": "Environment variable 'ALLOW_DELETIONS' not set."}&lt;/code&gt; to &lt;code&gt;stdout&lt;/code&gt; and exit with code &lt;code&gt;0&lt;/code&gt;. The Gemini CLI would then parse this and block the delete operation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Configuration
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://geminicli.com/docs/hooks/" rel="noopener noreferrer"&gt;Here is&lt;/a&gt; the official announcement with all the possibile configurations.&lt;/p&gt;

&lt;p&gt;The configuration is handled in &lt;code&gt;settings.json&lt;/code&gt;, with a clear hierarchy of precedence from project to system settings. This allows for granular control, from project-specific security checks to global compliance policies. The configuration schema defines fields like &lt;code&gt;type&lt;/code&gt; (currently only "command" is supported), the &lt;code&gt;command&lt;/code&gt; to execute, a friendly &lt;code&gt;name&lt;/code&gt;, and an optional &lt;code&gt;timeout&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;e.g.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "hooks": {
    "BeforeTool": [
      {
        "matcher": "write_file|replace",
        "hooks": [
          {
            "name": "security-check",
            "type": "command",
            "command": "$GEMINI_PROJECT_DIR/.gemini/hooks/security.sh",
            "timeout": 5000
          }
        ]
      }
    ]
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;blockquote&gt;
&lt;p&gt;Hooks execute arbitrary code with your user privileges. Therefore, caution is advised, especially with project-level hooks in untrusted projects.&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;Mastering these hooks means gaining control over your AI interactions, ensuring that the Gemini CLI operates exactly as you intend, securely and efficiently, across all your projects.&lt;/p&gt;



&lt;p&gt;You can&amp;nbsp;&lt;a href="https://github.com/gioboa" rel="noopener noreferrer"&gt;follow me on GitHub&lt;/a&gt;, where I'm creating cool projects.&lt;/p&gt;

&lt;p&gt;I hope you enjoyed this article, until next time 👋&lt;/p&gt;

&lt;p&gt;

&lt;/p&gt;
&lt;div class="ltag__user ltag__user__id__892161"&gt;
    &lt;a href="/gioboa" class="ltag__user__link profile-image-link"&gt;
      &lt;div class="ltag__user__pic"&gt;
        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F892161%2Ff7bb8d77-6568-4576-b4e5-715d424afabd.jpeg" alt="gioboa image"&gt;
      &lt;/div&gt;
    &lt;/a&gt;
  &lt;div class="ltag__user__content"&gt;
    &lt;h2&gt;
&lt;a class="ltag__user__link" href="/gioboa"&gt;Giorgio Boa&lt;/a&gt;Follow
&lt;/h2&gt;
    &lt;div class="ltag__user__summary"&gt;
      &lt;a class="ltag__user__link" href="/gioboa"&gt;Giorgio Boa is a full stack developer and the front-end ecosystem is his passion. He is also international public speaker, active in open source ecosystem, he loves learn and studies new things.&lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;





</description>
      <category>ai</category>
      <category>gemini</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
    <item>
      <title>Senior Developer's Secret: AI-Driven Iteration with VSCode, Cline &amp; Playwright</title>
      <dc:creator>Giorgio Boa</dc:creator>
      <pubDate>Mon, 26 Jan 2026 14:23:09 +0000</pubDate>
      <link>https://dev.to/gioboa/senior-developers-secret-ai-driven-iteration-with-vscode-cline-playwright-38ee</link>
      <guid>https://dev.to/gioboa/senior-developers-secret-ai-driven-iteration-with-vscode-cline-playwright-38ee</guid>
      <description>&lt;p&gt;The integration of &lt;a href="https://code.visualstudio.com/" rel="noopener noreferrer"&gt;VSCode&lt;/a&gt;, &lt;a href="https://cline.bot/" rel="noopener noreferrer"&gt;Cline&lt;/a&gt;, and the &lt;a href="https://playwright.dev/" rel="noopener noreferrer"&gt;Playwright&lt;/a&gt; Model Context Protocol (MCP) Server marks a significant leap forward in frontend application development, testing, and refinement. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This powerful combination empowers developers to iterate with browsers more effectively, streamlining workflows and accelerating the delivery of high-quality web experiences.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  The New Frontend Development Workflow
&lt;/h2&gt;

&lt;p&gt;This integration creates a seamless and highly efficient feedback loop for frontend developers. With Cline embedded in VSCode, developers can leverage AI to generate code snippets, refactor existing code, and understand complex codebases. Cline can even execute commands directly in the terminal, adapting to the development environment and toolchain. This dramatically speeds up the initial coding phase and helps maintain code quality.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi19vm1sd0bx44vwzzkn1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi19vm1sd0bx44vwzzkn1.png" alt="Cline-integration"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Playwright MCP Server is the bridge that connects the AI capabilities of Cline (or other LLMs) with actual browser environments. It exposes Playwright's browser automation functionalities, such as navigating pages, clicking elements, and filling forms, as structured tools that an AI can utilize. Instead of manually scripting every interaction, developers can use natural language prompts to instruct the AI to perform complex browser actions.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This is where the integration truly shines. The AI, powered by Playwright MCP, can open a browser and validate changes made to the application.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa8cynzx73dd18xy8r4so.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa8cynzx73dd18xy8r4so.png" alt="MCP"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Developers can ask the AI to verify specific UI behaviors, generate automated tests based on natural language descriptions, and even suggest fixes for failing tests. Playwright's inherent capabilities, like auto-waiting for elements, web-first assertions, and detailed tracing, further enhance the reliability and debuggability of these AI-driven tests.&lt;/p&gt;

&lt;p&gt;Cline can explore the application, suggest new test cases, and automatically generate tests, significantly reducing the manual effort in quality assurance. This rapid iteration cycle means that frontend issues can be identified and resolved much faster, leading to a more robust and polished user experience.&lt;/p&gt;

&lt;h2&gt;
  
  
  Real Use Case
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs7bagfuqs8iovz5muhhw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs7bagfuqs8iovz5muhhw.png" alt="Carousel-Component"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I stumbled upon a fantastic UI component on the web and, without missing a beat, grabbed a screenshot. Then, the magic happened. I pasted that image directly into Cline.&lt;br&gt;
What followed was an incredible display of AI power.&lt;br&gt;
Through just a few iterative "AI loops" within Cline, the platform intelligently analysed the screenshot, understood its structure and styling, and then, almost effortlessly, translated it into functional code. After few minutes, that stylish component was not just an image on my screen, but a live, interactive part of my own application. This seamless transition from a visual idea to a working element, all powered by AI, truly felt like the future of development.&lt;/p&gt;



&lt;p&gt;In conclusion, the sophisticated integration of VSCode, Cline, and the Playwright MCP Server is transforming the landscape of frontend development. Developers can now build, test, and refine frontend applications with unprecedented speed and accuracy, thanks to a new era of intelligent, efficient, and highly effective workflows, leading to superior web experiences for users.&lt;/p&gt;



&lt;p&gt;You can&amp;nbsp;&lt;a href="https://github.com/gioboa" rel="noopener noreferrer"&gt;follow me on GitHub&lt;/a&gt;, where I'm creating cool projects.&lt;/p&gt;

&lt;p&gt;I hope you enjoyed this article, until next time 👋&lt;/p&gt;

&lt;p&gt;

&lt;/p&gt;
&lt;div class="ltag__user ltag__user__id__892161"&gt;
    &lt;a href="/gioboa" class="ltag__user__link profile-image-link"&gt;
      &lt;div class="ltag__user__pic"&gt;
        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F892161%2Ff7bb8d77-6568-4576-b4e5-715d424afabd.jpeg" alt="gioboa image"&gt;
      &lt;/div&gt;
    &lt;/a&gt;
  &lt;div class="ltag__user__content"&gt;
    &lt;h2&gt;
&lt;a class="ltag__user__link" href="/gioboa"&gt;Giorgio Boa&lt;/a&gt;Follow
&lt;/h2&gt;
    &lt;div class="ltag__user__summary"&gt;
      &lt;a class="ltag__user__link" href="/gioboa"&gt;Giorgio Boa is a full stack developer and the front-end ecosystem is his passion. He is also international public speaker, active in open source ecosystem, he loves learn and studies new things.&lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;




</description>
      <category>microsoft</category>
      <category>playwright</category>
      <category>mcp</category>
      <category>ai</category>
    </item>
    <item>
      <title>Agent Flows At Scale with Google’s ADK for TypeScript</title>
      <dc:creator>Giorgio Boa</dc:creator>
      <pubDate>Sat, 20 Dec 2025 22:08:47 +0000</pubDate>
      <link>https://dev.to/gioboa/agent-flows-at-scale-with-googles-adk-for-typescript-b8k</link>
      <guid>https://dev.to/gioboa/agent-flows-at-scale-with-googles-adk-for-typescript-b8k</guid>
      <description>&lt;p&gt;The landscape of Artificial Intelligence is undergoing a seismic shift. We are moving rapidly beyond simple, single-purpose chatbots toward autonomous, intelligent multi-agent systems capable of complex reasoning and task orchestration.&lt;/p&gt;

&lt;p&gt;To empower developers in this new era, Google has officially introduced the &lt;a href="https://developers.googleblog.com/introducing-agent-development-kit-for-typescript-build-ai-agents-with-the-power-of-a-code-first-approach/" rel="noopener noreferrer"&gt;Agent Development Kit (ADK) for TypeScript&lt;/a&gt;. This open-source framework marks a pivotal moment for the JavaScript ecosystem, bringing a strict "code-first" philosophy to AI development.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Code-First Revolution
&lt;/h2&gt;

&lt;p&gt;For too long, building AI agents felt like an exercise in abstract prompt engineering. The ADK changes this paradigm by allowing developers to define logic, tools, and orchestration directly in TypeScript. As highlighted in &lt;a href="https://developers.googleblog.com/introducing-agent-development-kit-for-typescript-build-ai-agents-with-the-power-of-a-code-first-approach/" rel="noopener noreferrer"&gt;Google’s December 2025 announcement&lt;/a&gt;, this approach enables engineers to apply standard software development best practices—such as version control, automated testing, and CI/CD integration—to their AI workflows.&lt;/p&gt;

&lt;p&gt;The framework offers end-to-end type safety, meaning developers can build their agent backend and application frontend in a cohesive language, drastically reducing integration errors. By utilising modular components like &lt;code&gt;Agents&lt;/code&gt;, &lt;code&gt;Instructions&lt;/code&gt;, and &lt;code&gt;Tools&lt;/code&gt;, the ADK transforms complex AI behaviours into clean, readable, and scalable code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Case Study: The "Chef &amp;amp; Sommelier" Multi-Agent System
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://github.com/gioboa/chef-agent-adk-typescript" rel="noopener noreferrer"&gt;Here&lt;/a&gt; you can find the working project, you only need to add your Gemini API Key.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To demonstrate the power of the ADK, let’s explore a practical implementation: a hierarchical &lt;strong&gt;Chef Agent&lt;/strong&gt;. This project uses the latest &lt;a href="https://gemini.google.com/" rel="noopener noreferrer"&gt;Gemini 3&lt;/a&gt; model &lt;code&gt;gemini-3-pro-preview&lt;/code&gt; model to create a culinary experience that goes beyond simple recipe generation.&lt;/p&gt;

&lt;p&gt;The project structure is clean and modular, a hallmark of the ADK methodology:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;chef-agent/
├── agent.ts (The Head Chef)
└── sommelier-agent/
    └── agent.ts (The Wine Expert)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  The Hierarchical Architecture
&lt;/h2&gt;

&lt;p&gt;The core of this application lies in &lt;code&gt;chef-agent/agent.ts&lt;/code&gt;. Here, the root agent is defined as the "Chef," whose instruction is to take a single ingredient input and generate a masterpiece dish, complete with a name, description, recipe, and plating instructions.&lt;/p&gt;

&lt;p&gt;However, the true power of the ADK is showcased in how it handles sub-agents. The Chef isn't working alone.&lt;/p&gt;

&lt;p&gt;The code explicitly defines a &lt;code&gt;subAgents&lt;/code&gt; array:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;LlmAgent&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@google/adk&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;sommelierAgent&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./sommelier-agent/agent&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;rootAgent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;LlmAgent&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;chef_agent&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;gemini-3-pro-preview&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;A chef that creates amazing food based on a single ingredient.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;instruction&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`You are a world-renowned Chef with a passion for creating culinary masterpieces.
Your specialty is taking a SINGLE INGREDIENT provided by the user and designing a complete, delicious, and amazing dish around it.

When you receive an input (which will be an ingredient):
1.  **Conceive a Dish**: Create a unique name for a dish highlighting that ingredient.
2.  **Description**: Write a mouth-watering description.
3.  **Recipe**: Provide a detailed recipe including:
    *   Ingredients list (quantities and items).
    *   Step-by-step cooking instructions.
4.  **Presentation**: Suggest how to plate the dish for maximum visual appeal.

Be enthusiastic, professional, and creative.
You also have a colleague, "sommelier_agent", who must suggest wine pairings for the dish you create.`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;subAgents&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;sommelierAgent&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This configuration tells the Chef agent that it has access to a colleague. When the Chef generates a recipe, it can automatically consult the &lt;code&gt;sommelier_agent&lt;/code&gt;. defined in &lt;code&gt;sommelier-agent/agent.ts&lt;/code&gt;. This sub-agent has a specific, narrow scope: suggesting the perfect wine pairing based on the flavour profile of the dish the Chef just created.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;sommelier_agent&lt;/code&gt; code:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;LlmAgent&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@google/adk&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;instruction&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`You are an expert Sommelier.
Your goal is to suggest the perfect wine pairing for a given dish.
When provided with a dish name or description:
1. Suggest a specific type of wine (e.g., Cabernet Sauvignon, Chardonnay).
2. Explain why it pairs well with the dish (flavor profile, acidity, etc.).
3. Recommend a specific region if applicable.`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sommelierAgent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;LlmAgent&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sommelier_agent&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;gemini-3-pro-preview&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;A sommelier that suggests wine pairings for a given dish.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;instruction&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  The Developer Experience
&lt;/h2&gt;

&lt;p&gt;The project leverages the &lt;code&gt;@google/adk&lt;/code&gt; library and offers a seamless developer experience. Looking at the &lt;code&gt;package.json&lt;/code&gt;, we see built-in scripts that use the ADK devtools:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Terminal Mode:&lt;/strong&gt; &lt;code&gt;pnpm run run:terminal&lt;/code&gt; allows the developer to interact with the Chef directly in the command line for rapid testing.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F964sfd6npxmc9x7do5hs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F964sfd6npxmc9x7do5hs.png" alt="ADK Terminal"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Web Interface:&lt;/strong&gt; &lt;code&gt;pnpm run run:web&lt;/code&gt; launches a local server (&lt;code&gt;localhost:8000&lt;/code&gt;), providing a chat interface to visualize the interaction between the user, the Chef, and the hidden Sommelier sub-agent.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F11yappsus6y7xy2wsvcr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F11yappsus6y7xy2wsvcr.png" alt="ADK Web"&gt;&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;The Chef Agent project perfectly illustrates why the ADK for TypeScript is a game-changer. It creates a structured environment where distinct AI personalities (the Chef and the Sommelier) interact through typed contracts rather than vague prompts.&lt;/p&gt;

&lt;p&gt;By combining the reasoning capabilities of the new Gemini 3 models with the reliability of TypeScript, Google’s ADK provides the foundation for the next generation of software—where code doesn't just execute commands, but thinks, creates, and collaborates.&lt;/p&gt;



&lt;p&gt;You can&amp;nbsp;&lt;a href="https://github.com/gioboa" rel="noopener noreferrer"&gt;follow me on GitHub&lt;/a&gt;, where I'm creating cool projects.&lt;/p&gt;

&lt;p&gt;I hope you enjoyed this article, until next time 👋&lt;/p&gt;

&lt;p&gt;

&lt;/p&gt;
&lt;div class="ltag__user ltag__user__id__892161"&gt;
    &lt;a href="/gioboa" class="ltag__user__link profile-image-link"&gt;
      &lt;div class="ltag__user__pic"&gt;
        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F892161%2Ff7bb8d77-6568-4576-b4e5-715d424afabd.jpeg" alt="gioboa image"&gt;
      &lt;/div&gt;
    &lt;/a&gt;
  &lt;div class="ltag__user__content"&gt;
    &lt;h2&gt;
&lt;a class="ltag__user__link" href="/gioboa"&gt;Giorgio Boa&lt;/a&gt;Follow
&lt;/h2&gt;
    &lt;div class="ltag__user__summary"&gt;
      &lt;a class="ltag__user__link" href="/gioboa"&gt;Giorgio Boa is a full stack developer and the front-end ecosystem is his passion. He is also international public speaker, active in open source ecosystem, he loves learn and studies new things.&lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;





</description>
      <category>ai</category>
      <category>gemini</category>
      <category>programming</category>
      <category>typescript</category>
    </item>
    <item>
      <title>Agent Development in Hours, Not Weeks: Accelerating with Gemini 3 and Google ADK</title>
      <dc:creator>Giorgio Boa</dc:creator>
      <pubDate>Thu, 18 Dec 2025 18:13:04 +0000</pubDate>
      <link>https://dev.to/gioboa/agent-development-in-hours-not-weeks-accelerating-with-gemini-3-and-google-adk-4h0l</link>
      <guid>https://dev.to/gioboa/agent-development-in-hours-not-weeks-accelerating-with-gemini-3-and-google-adk-4h0l</guid>
      <description>&lt;p&gt;In the rapidly evolving landscape of artificial intelligence, the ability to iterate and deploy intelligent agents with speed is no longer a luxury – it's a critical competitive advantage. Traditionally, bringing a sophisticated AI agent from concept to production could take weeks, bogged down by complex model training, intricate API integrations, and the laborious process of building robust applications around the core AI.&lt;/p&gt;

&lt;p&gt;However, a revolutionary shift is underway, largely thanks to the potent synergy between &lt;strong&gt;&lt;a href="https://antigravity.google/" rel="noopener noreferrer"&gt;Gemini 3&lt;/a&gt;'s advanced capabilities&lt;/strong&gt; and the streamlined tooling provided by the &lt;a href="https://google.github.io/adk-docs/" rel="noopener noreferrer"&gt;Google Agent Development Kit (ADK)&lt;/a&gt;. This powerful combination isn't just about incremental improvements; it represents a paradigm shift, compressing development timelines from weeks of effort down to mere hours.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Powerhouse: Gemini 3
&lt;/h2&gt;

&lt;p&gt;At the heart of this acceleration lies Gemini 3, Google's next-generation multimodal AI model.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Gemini 3 is not just an incremental update; it's engineered for enhanced reasoning, complex task understanding, and superior performance across a vast array of modalities, including text, image, audio, and video.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Gemini 3 excels at understanding complex instructions and performing multi-step reasoning. This means less hand-holding and explicit programming for the agent's logic, as Gemini 3 can often infer intent and execute sophisticated workflows based on high-level prompts.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Accelerator: Google Agent Development Kit (ADK)
&lt;/h2&gt;

&lt;p&gt;While Gemini 3 provides the brain, the Google ADK provides the entire nervous system and skeletal structure, making it incredibly easy to connect that brain to the real world. The ADK is more than just a library; it's a comprehensive ecosystem designed specifically for rapid agent prototyping and deployment.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Features of ADK
&lt;/h2&gt;

&lt;p&gt;The ADK offers a &lt;a href="https://github.com/google/adk-samples" rel="noopener noreferrer"&gt;rich collection&lt;/a&gt; of pre-built components, templates, and example agents that demonstrate common use cases. This allows developers to start from a solid foundation rather than building everything from scratch.&lt;br&gt;
ADK provides seamless, abstracted interfaces for interacting with LLMs, allowing developers to focus on the agent's behaviour rather than the intricacies of API calls.&lt;br&gt;
It is designed to work hand-in-hand with &lt;a href="https://cloud.google.com/" rel="noopener noreferrer"&gt;Google Cloud&lt;/a&gt;'s robust infrastructure, offering simple paths to deploy agents as scalable, production-ready services.&lt;/p&gt;
&lt;h2&gt;
  
  
  Amazing Developer Experience
&lt;/h2&gt;

&lt;p&gt;Features like interactive playgrounds, debugging tools, and quick deployment options massively reduce the iteration cycle. Developers can test, refine, and redeploy their agents in minutes, not hours.&lt;/p&gt;

&lt;p&gt;With ADK is easy to orchestrate complex agent behaviours, managing state, memory, and interactions with various external tools and systems. e.g. logging tools, safety&amp;nbsp;security tools.&lt;/p&gt;



&lt;p&gt;In a world where AI innovation moves at an unprecedented pace, the combination of Gemini 3 and the Google ADK isn't just a development advantage; it's the new standard for building the intelligent agents of tomorrow, today. Start building and watch your project development time drop from weeks to hours.&lt;/p&gt;



&lt;p&gt;You can&amp;nbsp;&lt;a href="https://github.com/gioboa" rel="noopener noreferrer"&gt;follow me on GitHub&lt;/a&gt;, where I'm creating cool projects.&lt;/p&gt;

&lt;p&gt;I hope you enjoyed this article, until next time 👋&lt;/p&gt;

&lt;p&gt;

&lt;/p&gt;
&lt;div class="ltag__user ltag__user__id__892161"&gt;
    &lt;a href="/gioboa" class="ltag__user__link profile-image-link"&gt;
      &lt;div class="ltag__user__pic"&gt;
        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F892161%2Ff7bb8d77-6568-4576-b4e5-715d424afabd.jpeg" alt="gioboa image"&gt;
      &lt;/div&gt;
    &lt;/a&gt;
  &lt;div class="ltag__user__content"&gt;
    &lt;h2&gt;
&lt;a class="ltag__user__link" href="/gioboa"&gt;Giorgio Boa&lt;/a&gt;Follow
&lt;/h2&gt;
    &lt;div class="ltag__user__summary"&gt;
      &lt;a class="ltag__user__link" href="/gioboa"&gt;Giorgio Boa is a full stack developer and the front-end ecosystem is his passion. He is also international public speaker, active in open source ecosystem, he loves learn and studies new things.&lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;




</description>
      <category>ai</category>
      <category>development</category>
      <category>programming</category>
      <category>agents</category>
    </item>
    <item>
      <title>Thinking, Planning, Executing: Gemini 3's Agentic Core in the Antigravity Sandbox</title>
      <dc:creator>Giorgio Boa</dc:creator>
      <pubDate>Thu, 18 Dec 2025 16:06:24 +0000</pubDate>
      <link>https://dev.to/gioboa/thinking-planning-executing-gemini-3s-agentic-core-in-the-antigravity-sandbox-1g9p</link>
      <guid>https://dev.to/gioboa/thinking-planning-executing-gemini-3s-agentic-core-in-the-antigravity-sandbox-1g9p</guid>
      <description>&lt;p&gt;In the ever-accelerating landscape of artificial intelligence, the promise of true agency, where systems not only perform tasks but proactively think, plan, and execute, has long been the holy grail. &lt;/p&gt;

&lt;p&gt;Today, we stand on the precipice of that realisation with the advent of &lt;a href="https://gemini.google.com/" rel="noopener noreferrer"&gt;Gemini 3&lt;/a&gt;’s revolutionary agentic core, particularly as its capabilities unfold within the controlled yet expansive environment of the Antigravity Sandbox.&lt;/p&gt;

&lt;p&gt;This isn't just about faster computation; it's about fundamentally reshaping how we approach complex problems, entrusting their lifecycle management from conceptualisation to completion to an intelligent system.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;At the heart of Gemini 3 lies a sophisticated architecture designed to mirror human cognitive processes, yet unbound by human limitations.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Its agentic core is not a collection of isolated functionalities, but rather an interconnected suite of modules enabling seamless transitions between ideation and action.&lt;/p&gt;

&lt;p&gt;This integration manifests in three critical phases: &lt;br&gt;
&lt;strong&gt;thinking, planning, and executing.&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Thinking
&lt;/h2&gt;

&lt;p&gt;The "thinking" phase in a Gemini 3 agent is where the magic begins. When presented with a goal or a problem within the &lt;a href="https://antigravity.google/" rel="noopener noreferrer"&gt;Antigravity&lt;/a&gt; Sandbox, the agent doesn't immediately jump to the most obvious solution. Instead, it engages in a deep analysis of the context, drawing upon its vast knowledge base and learned patterns. This involves interpreting ambiguities, identifying underlying constraints, and even hypothesising potential causal relationships.&lt;/p&gt;
&lt;h2&gt;
  
  
  Planning
&lt;/h2&gt;

&lt;p&gt;This detailed understanding then seamlessly transitions into the "planning" phase. This isn't just about generating a linear sequence of steps; it's about dynamic, adaptive strategy formulation. Gemini 3 agents in the Antigravity Sandbox are capable of generating intricate workflow diagrams, complete with contingencies and alternative pathways. They anticipate potential roadblocks, perhaps a database dependency that might impact downtime, or a security policy that could bottleneck deployment. Crucially, the planning phase is iterative and self-correcting.&lt;/p&gt;
&lt;h2&gt;
  
  
  Executing
&lt;/h2&gt;

&lt;p&gt;Finally, we arrive at "execution", where the carefully crafted plans are brought to life. Within the Antigravity Sandbox, Gemini 3 agents aren't merely observers of the execution process. It leverages its ongoing monitoring capabilities to detect anomalies, analyse the deviation against its planned state, and then initiate an intelligent re-planning or recovery sequence.&lt;/p&gt;



&lt;p&gt;We are moving beyond simply &lt;em&gt;tooling&lt;/em&gt; intelligence, to truly &lt;em&gt;partnering&lt;/em&gt; with it. The precipice has been crossed; the landscape of possibility is now immeasurably wider, inviting us to dream with an intelligence that doesn't just assist, but truly, profoundly, leads the way.&lt;/p&gt;



&lt;p&gt;You can&amp;nbsp;&lt;a href="https://github.com/gioboa" rel="noopener noreferrer"&gt;follow me on GitHub&lt;/a&gt;, where I'm creating cool projects.&lt;/p&gt;

&lt;p&gt;I hope you enjoyed this article, until next time 👋&lt;/p&gt;

&lt;p&gt;

&lt;/p&gt;
&lt;div class="ltag__user ltag__user__id__892161"&gt;
    &lt;a href="/gioboa" class="ltag__user__link profile-image-link"&gt;
      &lt;div class="ltag__user__pic"&gt;
        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F892161%2Ff7bb8d77-6568-4576-b4e5-715d424afabd.jpeg" alt="gioboa image"&gt;
      &lt;/div&gt;
    &lt;/a&gt;
  &lt;div class="ltag__user__content"&gt;
    &lt;h2&gt;
&lt;a class="ltag__user__link" href="/gioboa"&gt;Giorgio Boa&lt;/a&gt;Follow
&lt;/h2&gt;
    &lt;div class="ltag__user__summary"&gt;
      &lt;a class="ltag__user__link" href="/gioboa"&gt;Giorgio Boa is a full stack developer and the front-end ecosystem is his passion. He is also international public speaker, active in open source ecosystem, he loves learn and studies new things.&lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;




</description>
      <category>webdev</category>
      <category>programming</category>
      <category>ai</category>
      <category>development</category>
    </item>
    <item>
      <title>Antigravity for Developers: Lifting the Burden with Gemini 3 Agents</title>
      <dc:creator>Giorgio Boa</dc:creator>
      <pubDate>Tue, 16 Dec 2025 09:05:57 +0000</pubDate>
      <link>https://dev.to/gioboa/antigravity-for-developers-lifting-the-burden-with-gemini-3-agents-3o9c</link>
      <guid>https://dev.to/gioboa/antigravity-for-developers-lifting-the-burden-with-gemini-3-agents-3o9c</guid>
      <description>&lt;p&gt;The constant pressure to innovate and deliver faster is a familiar burden for every developer. Days are often consumed by repetitive tasks, debugging, and navigating complex workflows, leaving little room for the creative problem-solving that truly fuels progress.&lt;/p&gt;

&lt;p&gt;What if developers could experience a form of "antigravity," liberating them from these tedious constraints? The answer might lie in &lt;a href="https://gemini.google.com/" rel="noopener noreferrer"&gt;Gemini 3&lt;/a&gt; Agents.&lt;/p&gt;

&lt;p&gt;These intelligent agents, powered by the cutting-edge reasoning capabilities of Gemini 3, promise to revolutionise the development landscape by automating complex, multi-step tasks.&lt;/p&gt;

&lt;p&gt;They act as tireless assistants, capable of understanding intricate instructions and executing them with precision and efficiency. Imagine offloading tasks like code generation, bug fixing, documentation creation, and even complex refactoring to a dedicated agent. This is the potential unlocked by Gemini 3 Agents.&lt;/p&gt;

&lt;h2&gt;
  
  
  Automate Impossible Tasks
&lt;/h2&gt;

&lt;p&gt;Unlike simple scripts that follow rigid instructions, Gemini 3 Agents can interpret natural language requests, reason about the underlying code, and dynamically adjust their strategies based on the context of the project. This level of intelligence allows them to tackle tasks that were previously impossible to automate, freeing up developers to focus on higher-level challenges.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The key to their transformative power lies in their ability to understand and adapt to the nuances of the development process.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  How do Gemini 3 Agents work in practice?
&lt;/h2&gt;

&lt;p&gt;Consider a scenario where a developer needs to implement a new feature. Instead of manually writing all the code, they can instruct a Gemini 3 Agent to generate the initial code structure, including necessary functions and classes, based on a brief description of the feature's requirements. The agent can then integrate this code into the existing codebase, ensuring compatibility and adherence to coding standards. Furthermore, it can even write unit tests to verify the functionality of the newly implemented feature.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The benefits extend beyond simple code generation. Gemini 3 Agents can also play a crucial role in debugging and error resolution.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;By analysing error logs and code snippets, they can identify potential causes of bugs and suggest solutions. They can even automatically implement fixes, significantly reducing the time spent on tedious debugging sessions.&lt;/p&gt;

&lt;h2&gt;
  
  
  The advantages
&lt;/h2&gt;

&lt;p&gt;Automating repetitive tasks frees up developers to focus on more complex and creative aspects of their work, leading to a significant boost in overall productivity. This streamlined workflows and automated tasks contribute to faster development cycles, allowing teams to deliver projects more quickly. By removing the burden of tedious tasks, Gemini 3 Agents can improve developer satisfaction and create a more engaging and fulfilling work environment.&lt;/p&gt;




&lt;p&gt;The introduction of Gemini 3 Agents marks a paradigm shift in software development. It's &lt;strong&gt;not about replacing developers&lt;/strong&gt;, but about augmenting their capabilities and empowering them to achieve more. As these agents become more sophisticated and integrated into the development ecosystem, the potential for unlocking unprecedented levels of productivity and innovation in the software industry is truly limitless. The future of development is here, and it's lighter than ever before.&lt;/p&gt;




&lt;p&gt;You can&amp;nbsp;&lt;a href="https://github.com/gioboa" rel="noopener noreferrer"&gt;follow me on GitHub&lt;/a&gt;, where I'm creating cool projects.&lt;/p&gt;

&lt;p&gt;I hope you enjoyed this article, until next time 👋&lt;/p&gt;

&lt;p&gt;

&lt;/p&gt;
&lt;div class="ltag__user ltag__user__id__892161"&gt;
    &lt;a href="/gioboa" class="ltag__user__link profile-image-link"&gt;
      &lt;div class="ltag__user__pic"&gt;
        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F892161%2Ff7bb8d77-6568-4576-b4e5-715d424afabd.jpeg" alt="gioboa image"&gt;
      &lt;/div&gt;
    &lt;/a&gt;
  &lt;div class="ltag__user__content"&gt;
    &lt;h2&gt;
&lt;a class="ltag__user__link" href="/gioboa"&gt;Giorgio Boa&lt;/a&gt;Follow
&lt;/h2&gt;
    &lt;div class="ltag__user__summary"&gt;
      &lt;a class="ltag__user__link" href="/gioboa"&gt;Giorgio Boa is a full stack developer and the front-end ecosystem is his passion. He is also international public speaker, active in open source ecosystem, he loves learn and studies new things.&lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;




</description>
      <category>gemini</category>
      <category>google</category>
      <category>ai</category>
      <category>development</category>
    </item>
  </channel>
</rss>
