<?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: Nicola Mastromarino</title>
    <description>The latest articles on DEV Community by Nicola Mastromarino (@nicolamastromarino).</description>
    <link>https://dev.to/nicolamastromarino</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%2F4060145%2F3f2e1b38-0a47-4c64-aaeb-a6b4b51339d4.jpg</url>
      <title>DEV Community: Nicola Mastromarino</title>
      <link>https://dev.to/nicolamastromarino</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/nicolamastromarino"/>
    <language>en</language>
    <item>
      <title>Why JSON tool calling is breaking your agents (and how MCP Code Mode fixes it)</title>
      <dc:creator>Nicola Mastromarino</dc:creator>
      <pubDate>Mon, 09 Nov 2026 11:06:23 +0000</pubDate>
      <link>https://dev.to/nicolamastromarino/why-json-tool-calling-is-breaking-your-agents-and-how-mcp-code-mode-fixes-it-h1m</link>
      <guid>https://dev.to/nicolamastromarino/why-json-tool-calling-is-breaking-your-agents-and-how-mcp-code-mode-fixes-it-h1m</guid>
      <description>&lt;p&gt;Standard tool calling looks great when your agent has three tools. You pass the JSON schemas in the system prompt, the model emits a tool_call payload, your backend executes it, and you feed the result back.&lt;/p&gt;

&lt;p&gt;Then you connect your agent to real enterprise infrastructure.&lt;/p&gt;

&lt;p&gt;Suddenly you have 4 MCP servers, 150+ endpoints, and complex multi-step workflows. Before the user even types a prompt, you are burning 80,000 tokens just to load tool definitions into the context window. And when the agent actually needs to do something nontrivial, it gets stuck in a slow, expensive ping-pong loop of sequential JSON calls.&lt;/p&gt;

&lt;p&gt;Enter Code Mode—a pattern popularized across Cloudflare Agents, FastMCP, and the Vercel AI SDK that replaces chatty JSON tool-calling chains with single-shot, sandboxed code execution.&lt;/p&gt;

&lt;p&gt;Here is why standard JSON tool calling hits a wall in production, and how switching to Code Mode changes the math on latency, tokens, and reliability.&lt;/p&gt;




&lt;h3&gt;
  
  
  1. The Upfront Context Tax (1M tokens vs. 1,000 tokens)
&lt;/h3&gt;

&lt;p&gt;In standard Model Context Protocol (MCP) or native function calling, the model needs to see the schema of every tool upfront.&lt;/p&gt;

&lt;p&gt;To give a concrete benchmark: exposing the full Cloudflare API natively via MCP (around 2,500+ endpoints) consumes roughly 1.17 million tokens of schema definitions. Even stripping it down to required parameters still burns ~244,000 tokens.&lt;/p&gt;

&lt;p&gt;Beyond the sheer cost, attention degrades as context grows. When an LLM has to choose between 200 similarly named tools, hallucinated parameters and wrong tool selections spike.&lt;/p&gt;

&lt;p&gt;How Code Mode fixes it: Instead of dumping every schema into the prompt, you expose a typed SDK (TypeScript or Python) inside a sandbox and give the model just two meta-tools: search_spec and execute_code (around 1,000 tokens total). The agent discovers only the exact types it needs on the fly and writes code against them.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Death by 10 Sequential Round-Trips
&lt;/h3&gt;

&lt;p&gt;Suppose a user asks: "Find all failed deployments from the last 24 hours, check their error logs, and open a ticket for any 5xx database timeout."&lt;/p&gt;

&lt;p&gt;With standard JSON tool calling, the execution looks like this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Model calls list_deployments(status="failed") -&amp;gt; waits for network + inference.&lt;/li&gt;
&lt;li&gt;Backend dumps 50 deployment objects into the context window.&lt;/li&gt;
&lt;li&gt;Model calls get_logs(deployment_id) 10 separate times -&amp;gt; 10 round-trips, 10x token re-ingestion of the entire conversation history.&lt;/li&gt;
&lt;li&gt;Model parses the text in-context and calls create_ticket().&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You are paying for full-context prefill on every single hop, and the user is staring at a spinner for 45 seconds.&lt;/p&gt;

&lt;p&gt;How Code Mode fixes it: The LLM writes a single script that loops, filters, and aggregates inside the execution environment, returning only the final outcome to the context window:&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;# Instead of 12 JSON round-trips, the LLM generates and runs this in a sandbox:
&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;triage_failed_deployments&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sdk&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;deployments&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;sdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;deployments&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;failed&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;hours&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;created_tickets&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;dep&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;deployments&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;logs&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;sdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;logs&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="n"&gt;dep&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;504 Gateway Timeout&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;logs&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;DBConnectionError&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;logs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;ticket&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;sdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tickets&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&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;DB Timeout on deployment &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;dep&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;id&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="n"&gt;priority&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;high&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;snippet&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;logs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;:]&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;created_tickets&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ticket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;id&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;triaged&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;deployments&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tickets_opened&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;created_tickets&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;One LLM generation. Zero intermediate JSON payloads polluting the context window.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. LLMs are better at writing code than chaining JSON
&lt;/h3&gt;

&lt;p&gt;Frontier models have been trained on billions of lines of Python and TypeScript—not on bespoke, deeply nested JSON-RPC tool-calling trajectories.&lt;/p&gt;

&lt;p&gt;When you force an agent to orchestrate logic through the conversation history, you are asking the attention mechanism to act as a CPU and RAM simultaneously. When you let the agent write code, you offload control flow (loops, conditionals, retries, parallel calls) to a deterministic runtime.&lt;/p&gt;

&lt;p&gt;If you use Python with FastMCP, enabling this pattern over an existing server takes three lines:&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;fastmcp&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;FastMCP&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;fastmcp.experimental.transforms.code_mode&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;CodeMode&lt;/span&gt;

&lt;span class="c1"&gt;# Wraps registered tools into a programmatic sandbox interface
&lt;/span&gt;&lt;span class="n"&gt;mcp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;FastMCP&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;EnterpriseOps&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;transforms&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;CodeMode&lt;/span&gt;&lt;span class="p"&gt;()])&lt;/span&gt;

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. Where Code Mode breaks (The Red Team view)
&lt;/h3&gt;

&lt;p&gt;Code Mode isn't a silver bullet, and treating it as one introduces a different class of production failures:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sandbox Security is non-negotiable: You are executing LLM-generated code. exec() on your host container is an incident waiting to happen. You need strict isolation: V8 isolates (Cloudflare Workers), QuickJS WebAssembly sandboxes, MicroVMs (Firecracker / E2B), or gVisor-backed containers with zero ambient network access.&lt;/li&gt;
&lt;li&gt;Opaque Mid-Script Failures: If step 4 of a 6-step generated script throws an unhandled exception, you lose the granular step-by-step state visibility you get from standard agent graphs (like LangGraph). Your sandbox must return structured tracebacks and partial execution state so the agent can self-heal without re-running non-idempotent mutations (like double-charging a payment API).&lt;/li&gt;
&lt;li&gt;Overkill for Simple Routing: If your agent only has 4 tools and performs single-hop lookups (like a standard RAG retriever), spinning up a sandbox and compiling TypeScript adds unnecessary overhead.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  The Architecture Rule of Thumb
&lt;/h3&gt;

&lt;p&gt;Use Direct Tool Calling when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You have &amp;lt; 15 tools with small, flat schemas.&lt;/li&gt;
&lt;li&gt;Calls are single-hop or require human-in-the-loop approval between every individual step.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Use Code Mode when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You are exposing large APIs or multiple MCP servers where schema tokens exceed 10k+.&lt;/li&gt;
&lt;li&gt;Workflows involve loops, data filtering, joins across endpoints, or parallel requests.&lt;/li&gt;
&lt;li&gt;You want to keep large intermediate API payloads out of the LLM's context window.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Are you still relying on native JSON tool calling for multi-step agents, or have you started moving orchestration into sandboxed code execution? Let me know what sandboxing stack you're running in the comments.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>mcp</category>
      <category>llm</category>
      <category>architecture</category>
    </item>
    <item>
      <title>5 RAG mistakes that looked fine in the demo and broke in production</title>
      <dc:creator>Nicola Mastromarino</dc:creator>
      <pubDate>Sat, 03 Oct 2026 05:06:32 +0000</pubDate>
      <link>https://dev.to/nicolamastromarino/5-rag-mistakes-that-looked-fine-in-the-demo-and-broke-in-production-cp9</link>
      <guid>https://dev.to/nicolamastromarino/5-rag-mistakes-that-looked-fine-in-the-demo-and-broke-in-production-cp9</guid>
      <description>&lt;p&gt;Every RAG demo works. You pick five questions, the system answers them beautifully, and everyone nods.&lt;/p&gt;

&lt;p&gt;I've built RAG pipelines over clinical notes and over a knowledge graph, and the gap between "works in the demo" and "works on real questions" is bigger than you'd expect. Real users ask messy questions, use acronyms nobody documented, and expect answers from documents that changed last Tuesday.&lt;/p&gt;

&lt;p&gt;Here are five mistakes that pass the demo and fail on real data.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Judging quality by vibes
&lt;/h3&gt;

&lt;p&gt;The demo set is five questions &lt;em&gt;you&lt;/em&gt; wrote, about documents &lt;em&gt;you&lt;/em&gt; know. Of course it works.&lt;/p&gt;

&lt;p&gt;Without an evaluation set you can't tell whether a change to chunking or embeddings made things better or just different. On a clinical QA project (about 40K MIMIC-III notes) I tracked Token F1 and hallucination rate against a baseline. That's the only reason I can say QLoRA fine-tuning cut hallucinations by roughly 40% and lifted Token F1 by 190%, instead of "the answers felt better."&lt;/p&gt;

&lt;p&gt;The same applies to retrieval. Build a golden set of 30-50 real questions, each mapped to the document that should answer it, and measure retrieval &lt;strong&gt;separately&lt;/strong&gt; from generation. If the right chunk never reaches the model, no prompt will save you.&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="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;hit_rate_at_k&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;eval_set&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;retriever&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;hits&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;eval_set&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;docs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;retriever&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;question&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;any&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;relevant_ids&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;docs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="n"&gt;hits&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;hits&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;eval_set&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Twenty lines of code, and it changes how you work.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Fixed-size chunking
&lt;/h3&gt;

&lt;p&gt;Splitting every document into 500-token blocks is fast and wrong. It cuts tables in half, separates a list from its heading, and ends chunks mid-sentence. The chunk that says "the limit is 10,000" no longer says &lt;em&gt;what&lt;/em&gt; limit.&lt;/p&gt;

&lt;p&gt;Chunk along the document's structure (sections, headings, paragraphs), keep the section title attached as metadata, and consider retrieving small chunks but passing the larger parent section to the model.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Vector search only
&lt;/h3&gt;

&lt;p&gt;Embeddings are great at meaning and mediocre at exact strings. Error codes, product IDs, contract numbers, internal acronyms: this is exactly what users search for, and exactly where pure semantic search is weakest.&lt;/p&gt;

&lt;p&gt;The retriever in my clinical system combines BM25 with a biomedical embedding model, fused with Reciprocal Rank Fusion. Medical text is full of abbreviations and drug names, exactly the kind of string where keyword matching earns its place next to embeddings. Add a reranker on top and you get one of the cheapest upgrades with one of the biggest effects.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Letting the model answer no matter what
&lt;/h3&gt;

&lt;p&gt;When retrieval returns nothing useful, most systems still pass the top-k chunks to the LLM, and the LLM still produces a fluent answer. That's the worst failure mode, because it looks like success.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Set a relevance threshold and let the system say "I couldn't find this in the documents."&lt;/li&gt;
&lt;li&gt;Require citations, so a wrong answer is at least checkable.&lt;/li&gt;
&lt;li&gt;Don't stuff the context with 20 chunks "just in case." More context often means more noise, not more accuracy.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;My clinical QA system keeps a human in the loop (it was designed with the EU AI Act in mind). When the domain is medical, a fluent wrong answer isn't a UX bug, it's a risk.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Treating the index as finished
&lt;/h3&gt;

&lt;p&gt;The demo index was built once. Real documents change, get deleted, get replaced by newer versions, and some of them shouldn't be visible to every user.&lt;/p&gt;

&lt;p&gt;You need an ingestion pipeline, not a script: updates and deletions handled, versions tracked, metadata filters for permissions, and a plan for re-embedding when you change the embedding model. An answer based on a policy that was withdrawn two months ago is worse than no answer.&lt;/p&gt;

&lt;h3&gt;
  
  
  The pattern behind all five
&lt;/h3&gt;

&lt;p&gt;Every one of these is invisible in a demo and obvious on real data. The demo tests whether the &lt;em&gt;pipeline runs&lt;/em&gt;. Real usage tests whether it &lt;em&gt;retrieves the right thing, says no when it should, and stays correct over time&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Build the evaluation set first. Everything else gets easier once you can measure it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What's the worst RAG failure you've seen that passed the demo? I'd love to hear the war stories in the comments.&lt;/strong&gt;&lt;/p&gt;




</description>
      <category>ai</category>
      <category>rag</category>
      <category>llm</category>
      <category>machinelearning</category>
    </item>
    <item>
      <title>I build LLMs for a living. Here's why I wrote a book about slowing down.</title>
      <dc:creator>Nicola Mastromarino</dc:creator>
      <pubDate>Mon, 03 Aug 2026 13:30:00 +0000</pubDate>
      <link>https://dev.to/nicolamastromarino/i-build-llms-for-a-living-heres-why-i-wrote-a-book-about-slowing-down-3196</link>
      <guid>https://dev.to/nicolamastromarino/i-build-llms-for-a-living-heres-why-i-wrote-a-book-about-slowing-down-3196</guid>
      <description>&lt;p&gt;My job is to make machines think faster.&lt;/p&gt;

&lt;p&gt;I work daily with large language models and generative AI systems. I fine-tune, optimize, reduce latency, eliminate friction. My entire professional value is measured in throughput, tokens per second, inference speed.&lt;/p&gt;

&lt;p&gt;And then one evening I noticed something: it was 11 PM. I had been "productive" for 14 hours straight. My thumb was scrolling through my phone — screen off. Just muscle memory. My brain was too fried to even choose what to look at, but it kept reaching for stimulation anyway.&lt;/p&gt;

&lt;p&gt;That was the moment I realized something was deeply wrong. Not just with me — with how we, as people who build fast systems, have started treating ourselves like fast systems.&lt;/p&gt;

&lt;h2&gt;
  
  
  The paradox nobody talks about in tech
&lt;/h2&gt;

&lt;p&gt;We spend our careers removing friction, automating repetitive tasks, optimizing pipelines. The promise is always the same: "this will save you time."&lt;/p&gt;

&lt;p&gt;But somehow, the more time-saving tools we build and adopt, the less time we feel we have. We're busier than ever. More anxious than ever. More connected than ever, and more exhausted than ever.&lt;/p&gt;

&lt;p&gt;I started digging into the neuroscience behind this. What I found changed how I think about work, attention, and time.&lt;/p&gt;

&lt;p&gt;The ancient Greeks had two completely different words for time:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Kronos&lt;/strong&gt; — chronological, measurable, ticking time. The kind you track in Jira tickets and calendar blocks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Kairos&lt;/strong&gt; — qualitative, dense, meaningful time. The kind where an hour feels like a minute because you're fully present.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Modern knowledge work, and especially tech culture, has become obsessed with Kronos. We fill every second. We context-switch 50 times a day. We treat rest as wasted clock cycles.&lt;/p&gt;

&lt;p&gt;But here's what the neuroscience actually says: &lt;strong&gt;your brain does its most important work — creativity, memory consolidation, emotional regulation — precisely when you stop optimizing it.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The Default Mode Network (the part of your brain that activates during rest and "mind wandering") is not idle. It's processing. It's connecting dots you couldn't connect while you were sprinting.&lt;/p&gt;

&lt;p&gt;We've been so busy optimizing Kronos that we've completely destroyed our Kairos.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I did about it
&lt;/h2&gt;

&lt;p&gt;I started writing down protocols for myself. Not productivity hacks. Not "wake up at 5 AM" routines. Just practical, neuroscience-backed ways to protect my attention and reclaim some sense of pace in a job that constantly demands more speed.&lt;/p&gt;

&lt;p&gt;Things like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Monotasking blocks&lt;/strong&gt;: single-context work sessions where notifications don't exist&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cognitive cooldowns&lt;/strong&gt;: intentional transition rituals between deep work and shallow work&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Digital friction by design&lt;/strong&gt;: making the default action the slow one, not the fast one&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The notes grew. I kept refining them. Eventually they became a short book: &lt;em&gt;The Art of Slowing Down in the Age of Hyper-Speed&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Writing it felt deeply ironic — an AI engineer writing a manifesto against the very culture his work accelerates. But that's exactly the point. We're the ones building the machines. We're the ones who should understand, better than anyone, why the human brain can't run like one.&lt;/p&gt;

&lt;h2&gt;
  
  
  The one thing I'd leave you with
&lt;/h2&gt;

&lt;p&gt;If you work in AI, ML, or any fast-moving area of tech, you probably already feel this tension. The industry screams FASTER every single day. New model, new framework, new benchmark every week.&lt;/p&gt;

&lt;p&gt;You don't have to opt out of all of it. But you do have to protect some space for Kairos. Otherwise, you're just a very expensive server running at 99% CPU with no garbage collection.&lt;/p&gt;

&lt;p&gt;And we all know what happens to systems with no garbage collection.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Thanks for reading. If this resonated, I'd love to hear how you deal with the pressure to optimize everything — including yourself.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>productivity</category>
      <category>career</category>
      <category>machinelearning</category>
    </item>
  </channel>
</rss>
