<?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: Marc Newstead</title>
    <description>The latest articles on DEV Community by Marc Newstead (@icentric).</description>
    <link>https://dev.to/icentric</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%2F3929651%2Ffa7f595b-8a59-45da-b8be-ee66e3feab4d.png</url>
      <title>DEV Community: Marc Newstead</title>
      <link>https://dev.to/icentric</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/icentric"/>
    <language>en</language>
    <item>
      <title>We built a GB-first Maps &amp; Places API because the mapping bill stopped making sense</title>
      <dc:creator>Marc Newstead</dc:creator>
      <pubDate>Tue, 04 Aug 2026 09:11:20 +0000</pubDate>
      <link>https://dev.to/icentric/we-built-a-gb-first-maps-places-api-because-the-mapping-bill-stopped-making-sense-39h1</link>
      <guid>https://dev.to/icentric/we-built-a-gb-first-maps-places-api-because-the-mapping-bill-stopped-making-sense-39h1</guid>
      <description>&lt;h2&gt;
  
  
  The bill nobody budgeted for
&lt;/h2&gt;

&lt;p&gt;If you've shipped anything with a map in it lately, you've had a version of this conversation with your finance person.&lt;/p&gt;

&lt;p&gt;The short history: in March 2025 Google Maps Platform retired the flat $200 monthly credit and replaced it with much smaller per-SKU allowances. Subscription tiers followed. The practical effect is that workloads which used to vanish under the credit now bill from a low threshold — and place search sits at the expensive end. Text Search on the Places API (New) runs around $32 per 1,000 calls above a 5,000-call monthly allowance. Request a &lt;code&gt;rating&lt;/code&gt; field and the call moves up an SKU tier. Request reviews and it moves up again.&lt;/p&gt;

&lt;p&gt;None of that is unreasonable for what Google provides. It's an excellent global dataset and you're paying global-dataset prices.&lt;/p&gt;

&lt;p&gt;But plenty of us aren't building for the globe. We're building a UK checkout. A UK store locator. A UK field-service dispatcher. And we're paying for planet-scale coverage, a consumer-search-optimised ranking model, and a session-token billing abstraction we then have to reverse-engineer to forecast next month's spend.&lt;/p&gt;

&lt;p&gt;So we built the thing we wanted instead.&lt;/p&gt;

&lt;h2&gt;
  
  
  Goggle Places
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://www.goggleplaces.com" rel="noopener noreferrer"&gt;Goggle Places&lt;/a&gt;&lt;/strong&gt; is a Maps &amp;amp; Places API for Great Britain: predictive search, unified place search, nearby lookup, hosted vector maps and routing, behind one key, priced per request.&lt;/p&gt;

&lt;p&gt;GB-first is the whole design constraint, and it buys things a global provider can't easily give you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Postcodes are first-class&lt;/strong&gt;, not a special case bolted onto a generic geocoder. Full and partial input, typo-tolerant, ranked sensibly.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Full national coverage&lt;/strong&gt; — every GB postcode, street, town and landmark, plus amenities, in one index.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Real GB public transport&lt;/strong&gt; — National Rail plus London bus/tube/DLR/ferry, on live timetables.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sub-50ms typeahead from the edge&lt;/strong&gt;, because autocomplete that lands after the user stops typing isn't autocomplete.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Two search endpoints, and the difference matters
&lt;/h2&gt;

&lt;p&gt;This is the bit worth reading properly, because picking the wrong one is the most likely way to have a bad time.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;GET /predict&lt;/code&gt; is the addresses-only typeahead — postcodes, streets, towns, landmarks. It's what you want behind a checkout address field.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="s2"&gt;"https://api.goggleplaces.com/predict?q=York"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"x-api-key: gk_live_pk_..."&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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;"hits"&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;"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;"York"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"town"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"geo_point"&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;"lat"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;53.96&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"lon"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;-1.08&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;p&gt;&lt;code&gt;GET /search&lt;/code&gt; is the single-field façade. It fans out server-side to the gazetteer &lt;em&gt;and&lt;/em&gt; the amenity index, then blends both into one ranked list. So &lt;code&gt;Premier Inn York&lt;/code&gt;, &lt;code&gt;Nando's&lt;/code&gt; and &lt;code&gt;Pizza Express&lt;/code&gt; resolve here — where &lt;code&gt;/predict&lt;/code&gt; returns nothing, because they aren't addresses.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="s2"&gt;"https://api.goggleplaces.com/search?q=premier%20inn%20york&amp;amp;mode=all&amp;amp;key=gk_live_pk_..."&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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;"q"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"premier inn york"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"mode"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"all"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"total"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"hits"&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;"display_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;"Premier Inn York South West, York"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"kind"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"place"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"lodging"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"locality"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"York"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"geo_point"&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;"lat"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;53.93&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"lon"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;-1.13&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;"display_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;"York, North Yorkshire"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"kind"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"address"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"town"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"geo_point"&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;"lat"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;53.96&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"lon"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;-1.08&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;p&gt;&lt;code&gt;mode&lt;/code&gt; takes &lt;code&gt;all&lt;/code&gt; (default), &lt;code&gt;addresses&lt;/code&gt; (gazetteer only — identical to &lt;code&gt;/predict&lt;/code&gt;) or &lt;code&gt;places&lt;/code&gt; (amenities only, for a store locator). Pass &lt;code&gt;lat&lt;/code&gt;/&lt;code&gt;lng&lt;/code&gt; as a location bias and the amenity half gets a distance decay, so typing &lt;code&gt;travelodge&lt;/code&gt; with the map over Manchester surfaces Manchester branches first.&lt;/p&gt;

&lt;p&gt;One gotcha, documented but easy to miss: businesses are matched &lt;strong&gt;by name&lt;/strong&gt;. &lt;code&gt;Nando's Manchester&lt;/code&gt; won't match, because amenities aren't named with their city. Bias by coordinates instead.&lt;/p&gt;

&lt;h2&gt;
  
  
  Nearby lookup
&lt;/h2&gt;

&lt;p&gt;Proximity and category rather than typed name — anchored on a point, or on the map viewport so you load exactly what's on screen as the user pans.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# around a point (radius in km, default 5, max 25)&lt;/span&gt;
curl &lt;span class="s2"&gt;"https://api.goggleplaces.com/nearby?lat=53.4808&amp;amp;lng=-2.2426&amp;amp;radius=2&amp;amp;categories=restaurant,bar&amp;amp;key=gk_live_pk_..."&lt;/span&gt;

&lt;span class="c"&gt;# within a viewport (bbox = minLng,minLat,maxLng,maxLat)&lt;/span&gt;
curl &lt;span class="s2"&gt;"https://api.goggleplaces.com/nearby?bbox=-2.26,53.46,-2.20,53.50&amp;amp;categories=lodging,charging&amp;amp;key=gk_live_pk_..."&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Categories: &lt;code&gt;restaurant&lt;/code&gt;, &lt;code&gt;bar&lt;/code&gt;, &lt;code&gt;attraction&lt;/code&gt;, &lt;code&gt;transport&lt;/code&gt;, &lt;code&gt;hospital&lt;/code&gt;, &lt;code&gt;parking&lt;/code&gt;, &lt;code&gt;lodging&lt;/code&gt;, &lt;code&gt;charging&lt;/code&gt;. Hits come back nearest-first with &lt;code&gt;distance&lt;/code&gt;, plus &lt;code&gt;opening_hours&lt;/code&gt;, &lt;code&gt;website&lt;/code&gt;, &lt;code&gt;phone&lt;/code&gt;, &lt;code&gt;cuisine&lt;/code&gt; and &lt;code&gt;wheelchair&lt;/code&gt; where we have them. Coverage on those secondary fields varies by area, so don't build a UI that assumes opening hours are always present.&lt;/p&gt;

&lt;h2&gt;
  
  
  Routing
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;POST /directions&lt;/code&gt;, self-hosted over GB data, engine-normalised so the response shape is stable regardless of which engine served it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="s2"&gt;"https://api.goggleplaces.com/directions"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"x-api-key: gk_live_sk_..."&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"content-type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "origin": [-2.2426, 53.4808],
    "destination": [-1.8904, 52.4862],
    "mode": "auto",
    "alternatives": true
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Modes are &lt;code&gt;auto&lt;/code&gt;, &lt;code&gt;bicycle&lt;/code&gt;, &lt;code&gt;pedestrian&lt;/code&gt; and &lt;code&gt;transit&lt;/code&gt; (with the obvious aliases). Up to 25 waypoints, &lt;code&gt;optimize&lt;/code&gt; to reorder them as a TSP, GeoJSON &lt;code&gt;LineString&lt;/code&gt; geometry, turn-by-turn legs. Set &lt;code&gt;mode=transit&lt;/code&gt; and each leg carries the service name, board/alight stops and live times.&lt;/p&gt;

&lt;p&gt;Points accept &lt;code&gt;[lon, lat]&lt;/code&gt; arrays or &lt;code&gt;{lat, lon}&lt;/code&gt; / &lt;code&gt;{lat, lng}&lt;/code&gt; objects, so a &lt;code&gt;geo_point&lt;/code&gt; from &lt;code&gt;/search&lt;/code&gt; drops straight in — you can route to a hotel, not just to an address.&lt;/p&gt;

&lt;p&gt;There's a convenience GET for simple two-point routes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="s2"&gt;"https://api.goggleplaces.com/directions?from=53.4808,-2.2426&amp;amp;to=52.4862,-1.8904"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"x-api-key: gk_live_sk_..."&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Maps
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&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;map&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;@goggleplaces/sdk&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;container&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;map&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;gk_live_pk_...&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A full UK vector map in your &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt;. Tiles stream from our API — nothing to self-host, no tile server to operate, no per-tile line item on the invoice.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keys
&lt;/h2&gt;

&lt;p&gt;Publishable (&lt;code&gt;gk_live_pk_…&lt;/code&gt;) are safe to ship in a browser but &lt;strong&gt;must&lt;/strong&gt; be origin-locked; anything else is rejected at the edge with a 403. Secret (&lt;code&gt;gk_live_sk_…&lt;/code&gt;) are server-side only. Both are scoped per service, rotatable and metered.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pricing
&lt;/h2&gt;

&lt;p&gt;Free allowance on every service, then a flat per-1,000 rate. Priced per service, no bundles to decode.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Service&lt;/th&gt;
&lt;th&gt;Free / month&lt;/th&gt;
&lt;th&gt;Rate&lt;/th&gt;
&lt;th&gt;Above 5M*&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/predict&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;30,000&lt;/td&gt;
&lt;td&gt;£1.68 / 1k&lt;/td&gt;
&lt;td&gt;£1.34 / 1k&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/nearby&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;30,000&lt;/td&gt;
&lt;td&gt;£2.96 / 1k&lt;/td&gt;
&lt;td&gt;£2.37 / 1k&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/tiles&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;30,000&lt;/td&gt;
&lt;td&gt;£4.15 / 1k&lt;/td&gt;
&lt;td&gt;£3.32 / 1k&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/directions&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;10,000&lt;/td&gt;
&lt;td&gt;£2.96 / 1k&lt;/td&gt;
&lt;td&gt;£2.37 / 1k&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;*Directions steps down above 1M rather than 5M. Rates as at August 2026 — check &lt;a href="https://www.goggleplaces.com/pricing" rel="noopener noreferrer"&gt;/pricing&lt;/a&gt; for current figures.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A card is required to activate the account.&lt;/strong&gt; You aren't charged unless you exceed the free allowance.&lt;/p&gt;

&lt;h3&gt;
  
  
  Worked example
&lt;/h3&gt;

&lt;p&gt;The Google comparison depends on your field profile, but a checkout session terminating in a Place Details Pro request is commonly cited around $17 per 1,000 sessions — so ~$1,700 (c £1,260) for 100,000 sessions, against our pricing which would (at an average of 4 debounced calls per session and including the free tier) would work out at £621.60 for the same number of sessions.&lt;/p&gt;

&lt;p&gt;Add a map to that page and Google's dynamic map loads run around $7/1,000 against our £4.15/1,000 with 30,000 free — that gap is wider and more straightforward.&lt;/p&gt;

&lt;h2&gt;
  
  
  When you should &lt;em&gt;not&lt;/em&gt; use this
&lt;/h2&gt;

&lt;p&gt;Worth saying plainly, because you'd find out in week three otherwise:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;You need coverage outside Great Britain.&lt;/strong&gt; We don't have it. Use Google, HERE or Mapbox.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;You depend on ratings and review text.&lt;/strong&gt; We don't return either. If your UI shows star ratings, this isn't a swap you can make.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;You need Street View or equivalent imagery.&lt;/strong&gt; Not something we offer.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Your POI depth requirement is high in long-tail commercial categories.&lt;/strong&gt; Coverage is strongest on transport, infrastructure, hospitality and chains, and thinner on small independents in some areas.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;p&gt;The search box on &lt;a href="https://www.goggleplaces.com" rel="noopener noreferrer"&gt;goggleplaces.com&lt;/a&gt; hits the live predictive endpoint on every keystroke — same endpoint your app would call, no demo mode. Open the network tab and throw real queries at it before you sign up for anything.&lt;/p&gt;

&lt;p&gt;Docs: &lt;a href="https://www.goggleplaces.com/docs" rel="noopener noreferrer"&gt;goggleplaces.com/docs&lt;/a&gt;. Keys: &lt;a href="https://app.goggleplaces.com" rel="noopener noreferrer"&gt;app.goggleplaces.com&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If predictive search mis-ranks somewhere you know well, or the router sends you a stupid way round, put it in the comments. GB coverage &lt;em&gt;is&lt;/em&gt; the product, so local knowledge is the most useful bug report we can get.&lt;/p&gt;

</description>
      <category>api</category>
      <category>webdev</category>
      <category>javascript</category>
      <category>showdev</category>
    </item>
    <item>
      <title>Your AI Integration Just Got Deprecated: A Developer's Guide to Vendor Stability</title>
      <dc:creator>Marc Newstead</dc:creator>
      <pubDate>Mon, 03 Aug 2026 09:05:04 +0000</pubDate>
      <link>https://dev.to/icentric/your-ai-integration-just-got-deprecated-a-developers-guide-to-vendor-stability-563j</link>
      <guid>https://dev.to/icentric/your-ai-integration-just-got-deprecated-a-developers-guide-to-vendor-stability-563j</guid>
      <description>&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;You've just spent three sprints integrating a shiny new AI API. Your pull request is merged, monitoring is green, and the product team is already planning the next feature that builds on it. Then you open your inbox:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Important Update: [Feature Name] Deprecated"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The capability you built around? It's being "refined". Translation: it didn't work as advertised, and now you're rewriting code.&lt;/p&gt;

&lt;p&gt;This isn't a hypothetical. Google, OpenAI, and Anthropic have all shipped features, branded them, and then quietly walked them back. &lt;a href="https://www.icentricagency.com/insights/ai-retractions-why-labs-ship-before-they-know-what-they-ve-built" rel="noopener noreferrer"&gt;Why labs ship&lt;/a&gt; before they fully understand what they've built is a systemic issue, and as developers, we're the ones left holding the technical debt.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why This Hits Developers Harder Than Anyone Else
&lt;/h2&gt;

&lt;p&gt;When marketing changes messaging, they update a deck. When a vendor retracts a feature, &lt;em&gt;you&lt;/em&gt; rewrite the code.&lt;/p&gt;

&lt;p&gt;Here's what actually happens:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Contract breakage disguised as iteration.&lt;/strong&gt; A model that was "multimodal" becomes "optimised for text-primary workflows". Your image processing pipeline now throws errors in production.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Versioning theatre.&lt;/strong&gt; The model version number increments, but the behaviour changes fundamentally. Your integration tests pass, but user-facing accuracy drops 20%.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Documentation drift.&lt;/strong&gt; The API docs still reference capabilities that have been soft-deprecated. You only find out when you hit rate limits or unexpected error codes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Consumer apps can pivot. Enterprise systems can't. And the codebase you maintain sits somewhere in between, absorbing every breaking change.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to Check Before You Integrate
&lt;/h2&gt;

&lt;p&gt;You can't eliminate risk, but you can avoid the worst landmines. Here's what I look at now:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. &lt;strong&gt;Version Stability Track Record&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Don't trust the roadmap. Check the changelog:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How often do minor versions introduce breaking changes?&lt;/li&gt;
&lt;li&gt;Are deprecations announced with a migration window, or do they appear retroactively in release notes?&lt;/li&gt;
&lt;li&gt;Is there a public issue tracker where behavioural regressions are discussed?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If a vendor has quietly changed model behaviour three times in six months, assume that's the cadence you'll be dealing with.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. &lt;strong&gt;SLA Reality Check&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Read the actual SLA, not the marketing site:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;❌ "Enterprise-grade reliability"
✅ 99.9% uptime on inference endpoints, 30-day notice on deprecations
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the SLA doesn't mention API stability or behavioural consistency, you don't have one.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. &lt;strong&gt;Escape Hatch Architecture&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Design for replaceability from day one:&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;# Bad: Tight coupling to vendor SDK
&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;openai&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ChatCompletion&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;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gpt-4&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;# Better: Abstraction layer
&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;LLMProvider&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Protocol&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;complete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;prompt&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="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="bp"&gt;...&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;OpenAIProvider&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LLMProvider&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;complete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;prompt&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="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="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;openai&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ChatCompletion&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="c1"&gt;# Swap providers without touching business logic
&lt;/span&gt;&lt;span class="n"&gt;provider&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;LLMProvider&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_provider&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;  &lt;span class="c1"&gt;# Config-driven
&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;provider&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;complete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If swapping the vendor would mean rewriting half your application, you've already lost.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. &lt;strong&gt;Feature Flag Everything&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Treat AI features like you'd treat any experimental third-party dependency:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Wrap calls in feature flags so you can disable them instantly&lt;/li&gt;
&lt;li&gt;Log inputs, outputs, and latency separately from your core metrics&lt;/li&gt;
&lt;li&gt;Have a fallback path that doesn't depend on the AI being available or correct&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This isn't paranoia. This is treating external APIs like the network calls they are.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Naming Game
&lt;/h2&gt;

&lt;p&gt;One of the subtler issues: vendors brand capabilities before they've proven them at scale. A feature called "Advanced Reasoning" or "Extended Context" sounds like a contract, but legally and technically, it's marketing.&lt;/p&gt;

&lt;p&gt;As developers, we need to push back:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If a capability is critical, get the behaviour in writing (SLA, API contract, regression tests)&lt;/li&gt;
&lt;li&gt;If the vendor won't commit to specific accuracy or consistency metrics, treat it as experimental&lt;/li&gt;
&lt;li&gt;If a feature has been in "beta" for a year, it's not becoming stable — that &lt;em&gt;is&lt;/em&gt; the stable state&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What This Means for Your Next Sprint
&lt;/h2&gt;

&lt;p&gt;If you're integrating AI tooling — especially in systems that can't tolerate surprise breakage — apply the same scrutiny you would to any other third-party dependency:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Treat model outputs as untrusted input&lt;/li&gt;
&lt;li&gt;Version your integrations so you can roll back&lt;/li&gt;
&lt;li&gt;Monitor behavioural drift, not just uptime&lt;/li&gt;
&lt;li&gt;Budget time for re-integration work, because it's coming&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The competitive advantages of AI tooling are real, and adoption does create a moat. But only if you build on stable ground. Firms specialising in &lt;a href="https://www.icentricagency.com" rel="noopener noreferrer"&gt;AI automation and software development&lt;/a&gt; often see teams trip over this exact issue: brilliant proof-of-concept, fragile production deployment.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Thought
&lt;/h2&gt;

&lt;p&gt;AI vendors are shipping fast because the market rewards speed over stability. That's not changing. What &lt;em&gt;can&lt;/em&gt; change is how we integrate: with scepticism, abstraction layers, and an escape plan.&lt;/p&gt;

&lt;p&gt;Because the next retraction email is already being drafted.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>api</category>
      <category>architecture</category>
      <category>devops</category>
    </item>
    <item>
      <title>Stop Writing One-Shot Prompts: Why Your AI Feature Needs a Loop</title>
      <dc:creator>Marc Newstead</dc:creator>
      <pubDate>Mon, 03 Aug 2026 09:02:23 +0000</pubDate>
      <link>https://dev.to/icentric/stop-writing-one-shot-prompts-why-your-ai-feature-needs-a-loop-45ci</link>
      <guid>https://dev.to/icentric/stop-writing-one-shot-prompts-why-your-ai-feature-needs-a-loop-45ci</guid>
      <description>&lt;h2&gt;
  
  
  Stop Writing One-Shot Prompts: Why Your AI Feature Needs a Loop
&lt;/h2&gt;

&lt;p&gt;If you're building AI features the same way you call a REST API — fire a request, get a response, parse the output — you've probably hit the reliability wall. One-shot prompts work brilliantly for demos and narrow tasks, but the moment you need consistency, validation, or multi-step reasoning, they fall apart.&lt;/p&gt;

&lt;p&gt;The answer isn't bigger models or more prompt engineering. It's &lt;strong&gt;agentic loops&lt;/strong&gt;: structured, deterministic systems that let AI reason, validate, and course-correct in a controlled cycle.&lt;/p&gt;

&lt;p&gt;Here's what that actually looks like in practice.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem with One-Shot Thinking
&lt;/h2&gt;

&lt;p&gt;Let's say you're building a feature that generates SQL from natural language. A one-shot implementation looks like this:&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="n"&gt;query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;llm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;generate&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;Convert to SQL: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;user_input&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;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Simple. Clean. And completely brittle.&lt;/p&gt;

&lt;p&gt;What happens when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The LLM hallucinates a table name?&lt;/li&gt;
&lt;li&gt;The query has a syntax error?&lt;/li&gt;
&lt;li&gt;The user asks for something ambiguous?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You could add validation logic &lt;em&gt;after&lt;/em&gt; the call, but you're still stuck with a single attempt. The model doesn't get to learn from its mistakes, and you can't build guardrails into the reasoning process itself.&lt;/p&gt;

&lt;p&gt;This is where &lt;a href="https://www.icentricagency.com/insights/agentic-loops-the-engineering-discipline-behind-reliable-ai-features" rel="noopener noreferrer"&gt;agentic loops&lt;/a&gt; come in.&lt;/p&gt;

&lt;h2&gt;
  
  
  What an Agentic Loop Actually Is
&lt;/h2&gt;

&lt;p&gt;An agentic loop is a &lt;strong&gt;structured cycle&lt;/strong&gt; where an AI system:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Attempts a task&lt;/li&gt;
&lt;li&gt;Evaluates its own output&lt;/li&gt;
&lt;li&gt;Decides whether to return, retry, or escalate&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Think of it as a &lt;code&gt;while&lt;/code&gt; loop with intelligence:&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="n"&gt;max_iterations&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;
&lt;span class="n"&gt;attempts&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;while&lt;/span&gt; &lt;span class="n"&gt;attempts&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;max_iterations&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;llm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;generate&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;Convert to SQL: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;user_input&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;validation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;validate_sql&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;schema&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;validation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_valid&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;query&lt;/span&gt;

    &lt;span class="n"&gt;user_input&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="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;user_input&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="s"&gt;Previous attempt failed: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;validation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;attempts&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;raise&lt;/span&gt; &lt;span class="nc"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Failed to generate valid SQL after 5 attempts&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;Now the model gets &lt;strong&gt;feedback&lt;/strong&gt;. It can see why it failed and adjust. You've turned a fragile one-shot into a self-correcting system.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Three Non-Negotiables
&lt;/h2&gt;

&lt;p&gt;If you're building agentic loops in production, three things need to be explicit and deterministic:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Exit Conditions
&lt;/h3&gt;

&lt;p&gt;Every loop must have clear success and failure criteria. "The model seems happy" is not an exit condition. "Query passes schema validation" is.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Iteration Limits
&lt;/h3&gt;

&lt;p&gt;Never build an unbounded loop. Set a hard cap (usually 3–7 iterations). If the agent can't succeed by then, escalate or fail gracefully.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. State Management
&lt;/h3&gt;

&lt;p&gt;The agent needs context across iterations. That means passing conversation history, error messages, and intermediate outputs back into the loop. If you're not tracking state, you're not building an agent — you're just retrying.&lt;/p&gt;

&lt;h2&gt;
  
  
  Real-World Patterns
&lt;/h2&gt;

&lt;p&gt;Two architectures have emerged as practical starting points:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Supervisor-worker&lt;/strong&gt;: One agent plans, multiple agents execute. The supervisor breaks a task into subtasks, delegates to specialist workers (e.g. one for SQL generation, one for validation), and synthesises the results.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Chain-of-thought validation&lt;/strong&gt;: The agent generates a solution, then explicitly reasons about whether it meets the requirements. This "thinking step" is logged and used to decide whether to iterate.&lt;/p&gt;

&lt;p&gt;Both patterns share a common trait: &lt;strong&gt;the agent's reasoning is observable and debuggable&lt;/strong&gt;. You're not staring at a black box hoping it works.&lt;/p&gt;

&lt;h2&gt;
  
  
  Observability Is Not Optional
&lt;/h2&gt;

&lt;p&gt;Here's the part that surprises teams: once you ship an agentic loop, you've shipped a &lt;strong&gt;runtime decision-making system&lt;/strong&gt;. That means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Every iteration should be logged with inputs, outputs, and reasoning&lt;/li&gt;
&lt;li&gt;You need metrics on loop convergence (how many iterations to success?)&lt;/li&gt;
&lt;li&gt;Failed loops need structured error states, not just stack traces&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you're treating this as a dev concern rather than an ops/governance one, you're in for a rough production incident.&lt;/p&gt;

&lt;p&gt;For teams building this infrastructure from scratch, partnering with specialists in &lt;a href="https://www.icentricagency.com" rel="noopener noreferrer"&gt;AI automation and software development&lt;/a&gt; can accelerate time-to-production significantly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Start Small, Build Deliberately
&lt;/h2&gt;

&lt;p&gt;You don't need to rewrite your entire AI stack overnight. Start with one feature where reliability matters:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Wrap a flaky prompt in a validation loop&lt;/li&gt;
&lt;li&gt;Add iteration limits and logging&lt;/li&gt;
&lt;li&gt;Track convergence rates and failure modes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once you see the difference in reliability, you'll never go back to one-shot prompts.&lt;/p&gt;

&lt;p&gt;Agentic loops aren't magic. They're structured engineering. And they're the difference between an AI feature that works in demos and one that works in production.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>architecture</category>
      <category>softwaredevelopment</category>
      <category>engineering</category>
    </item>
    <item>
      <title>Your Agentic AI Pilot Is Probably Measuring the Wrong Things</title>
      <dc:creator>Marc Newstead</dc:creator>
      <pubDate>Mon, 27 Jul 2026 09:07:20 +0000</pubDate>
      <link>https://dev.to/icentric/your-agentic-ai-pilot-is-probably-measuring-the-wrong-things-3hi8</link>
      <guid>https://dev.to/icentric/your-agentic-ai-pilot-is-probably-measuring-the-wrong-things-3hi8</guid>
      <description>&lt;h2&gt;
  
  
  Your Agentic AI Pilot Is Probably Measuring the Wrong Things
&lt;/h2&gt;

&lt;p&gt;You've built an agentic AI system. It's working. It's doing real work autonomously—chaining API calls, making decisions, handling edge cases. Now you need to prove it's worth the infrastructure spend.&lt;/p&gt;

&lt;p&gt;So you pull up the metrics dashboard: tokens consumed, average response time, cost per interaction. Clean numbers. Finance-friendly.&lt;/p&gt;

&lt;p&gt;Except these metrics were designed for chatbots, not agents. And that mismatch is quietly killing your business case.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Chatbot Metric Trap
&lt;/h2&gt;

&lt;p&gt;Most teams inherit their AI metrics from RAG systems and support bots. Those systems were evaluated on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Cost per query&lt;/strong&gt; – How much does one Q&amp;amp;A interaction cost?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Response accuracy&lt;/strong&gt; – Did it retrieve the right answer?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;User satisfaction scores&lt;/strong&gt; – Did the human like the response?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These made sense when you were replacing a glorified search box. But agentic systems don't work like that.&lt;/p&gt;

&lt;p&gt;An agent doesn't answer a question. It &lt;em&gt;executes a workflow&lt;/em&gt;. It might:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Call three different APIs to gather context&lt;/li&gt;
&lt;li&gt;Make a decision based on business rules&lt;/li&gt;
&lt;li&gt;Write data back to your CRM&lt;/li&gt;
&lt;li&gt;Trigger a follow-up task in Slack&lt;/li&gt;
&lt;li&gt;Handle failures and retry with backoff&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you measure that with "cost per query", you're comparing apples to entire fruit salads. The unit of work isn't comparable. Your ROI case falls apart under scrutiny.&lt;/p&gt;

&lt;h2&gt;
  
  
  What You Should Actually Be Measuring
&lt;/h2&gt;

&lt;p&gt;Start with the &lt;em&gt;workflow&lt;/em&gt;, not the AI. Map out what the agent is replacing:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Before (manual process):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1. Support agent receives escalation email
2. Looks up customer in CRM (avg 2 mins)
3. Checks order history in legacy system (avg 3 mins)
4. Evaluates refund eligibility (avg 5 mins)
5. Updates CRM and sends response (avg 3 mins)

Total: ~13 minutes per escalation
Cost: £X per hour × time spent
Throughput: Limited by team capacity
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;After (agentic system):&lt;/strong&gt;&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;# Pseudocode for agentic refund workflow
&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;handle_refund_escalation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;customer&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;crm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lookup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;from_address&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;orders&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;legacy_system&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_orders&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;customer&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="n"&gt;decision&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;evaluate_refund&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;customer_tier&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;customer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tier&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;order_history&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;orders&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;request_details&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;body&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;decision&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;approved&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;payments&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;process_refund&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;decision&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;crm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log_interaction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;customer&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="n"&gt;decision&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send_response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;decision&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;template&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Measure this:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;End-to-end completion time&lt;/strong&gt; (13 mins → 45 seconds)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Throughput increase&lt;/strong&gt; (8/hour/person → 80/hour)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Error rate&lt;/strong&gt; (manual data entry errors vs. agent failures)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Escalation rate&lt;/strong&gt; (what % still needs human review)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cost per completed workflow&lt;/strong&gt; (not per API call)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now you have numbers that map to business outcomes. You can show that your agent handles 72 more escalations per hour than a human, with 99.2% accuracy and £2.30 per workflow vs. £4.80 for manual processing.&lt;/p&gt;

&lt;p&gt;That's a business case. "We saved 40,000 tokens" is not.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Pilots Hide the Real Wins
&lt;/h2&gt;

&lt;p&gt;Most agentic pilots run &lt;em&gt;in parallel&lt;/em&gt; with existing processes. You're comparing outputs, but not capturing the actual cost savings because the old process is still running.&lt;/p&gt;

&lt;p&gt;This creates three problems:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;No cost reduction shows up&lt;/strong&gt; – You're paying for both systems&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Throughput gains are invisible&lt;/strong&gt; – The agent could handle 10× more volume, but you're not sending it 10× more work&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The comparison is artificial&lt;/strong&gt; – You're cherry-picking tasks instead of measuring real production load&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you want credible numbers, you need to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Route a &lt;em&gt;percentage&lt;/em&gt; of production traffic to the agent&lt;/li&gt;
&lt;li&gt;Measure actual time/cost saved on those workflows&lt;/li&gt;
&lt;li&gt;Track what happens when you scale up the percentage&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Don't run a science experiment. Run a production rollout with rollback capability.&lt;/p&gt;

&lt;h2&gt;
  
  
  Making Finance Actually Listen
&lt;/h2&gt;

&lt;p&gt;Your CFO doesn't care about your model architecture. They care about:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Unit economics&lt;/strong&gt; – Cost per workflow completed&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Payback period&lt;/strong&gt; – When does cumulative saving exceed build cost?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Risk&lt;/strong&gt; – What happens if it breaks?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Build your metrics around those questions. If you're serious about getting this right, treating &lt;a href="https://www.icentricagency.com/insights/measuring-agentic-ai-why-your-roi-framework-is-broken" rel="noopener noreferrer"&gt;your ROI framework as broken&lt;/a&gt; is the starting point.&lt;/p&gt;

&lt;p&gt;And if you're building agentic systems in a larger digital transformation context, working with teams experienced in &lt;a href="https://www.icentricagency.com" rel="noopener noreferrer"&gt;AI automation and software development&lt;/a&gt; helps you avoid the common structural mistakes that sink pilots before they reach production.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Practical Takeaway
&lt;/h2&gt;

&lt;p&gt;Before you write another line of agentic code, map the workflow it's replacing. Define:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Time saved per workflow&lt;/li&gt;
&lt;li&gt;Error rate comparison&lt;/li&gt;
&lt;li&gt;Throughput ceiling (old vs. new)&lt;/li&gt;
&lt;li&gt;Total cost per completed unit of work&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then instrument your agent to capture those metrics from day one. Not token counts. Not inference latency. &lt;em&gt;Business outcomes.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Because the best agentic system in the world is worthless if you can't prove it's worth running.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>devops</category>
      <category>architecture</category>
      <category>automation</category>
    </item>
    <item>
      <title>Your RAG system can't answer "why" questions. Here's what you're missing.</title>
      <dc:creator>Marc Newstead</dc:creator>
      <pubDate>Mon, 27 Jul 2026 09:04:44 +0000</pubDate>
      <link>https://dev.to/icentric/your-rag-system-cant-answer-why-questions-heres-what-youre-missing-29f1</link>
      <guid>https://dev.to/icentric/your-rag-system-cant-answer-why-questions-heres-what-youre-missing-29f1</guid>
      <description>&lt;h2&gt;
  
  
  The problem with semantic search
&lt;/h2&gt;

&lt;p&gt;You've built a RAG system. User asks a question, you embed it, run a vector similarity search, retrieve the top 5 chunks, shove them into context, and let the LLM answer. Works brilliantly for simple lookup queries.&lt;/p&gt;

&lt;p&gt;Then someone asks: &lt;em&gt;"Why did the deployment fail after the database migration?"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Your agent retrieves a chunk about the deployment error. Maybe another about the migration. But it completely misses that the migration changed a column type, which broke a dependency in the service layer, which caused the deployment to fail. That's three hops of reasoning your vector store can't connect.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The gap between 32% and 86% accuracy on multi-hop questions isn't a prompt engineering problem. It's an architecture problem.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What vector search actually gives you
&lt;/h2&gt;

&lt;p&gt;Vector embeddings are phenomenal at semantic similarity. They'll find documents &lt;em&gt;about&lt;/em&gt; the same topic, even if the words differ. But they're terrible at representing &lt;strong&gt;relationships between facts&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;When you embed a sentence like "Service A depends on Service B", that directional relationship gets flattened into a 1536-dimensional float array. The embedding knows these services are related, but it doesn't know &lt;em&gt;how&lt;/em&gt; or &lt;em&gt;which direction&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Ask "what services depend on Service B?" and you might retrieve chunks mentioning both services. Ask "what does Service A depend on?" and you'll get similar chunks. The vector store can't distinguish between these queries because the relationship isn't preserved—just the proximity.&lt;/p&gt;

&lt;h2&gt;
  
  
  The retrieval gap in production
&lt;/h2&gt;

&lt;p&gt;Here's where it breaks in real systems:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Scenario&lt;/strong&gt;: Your AI agent manages a microservices architecture. Documentation lives in Notion, incident reports in Jira, config in GitHub.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Query&lt;/strong&gt;: "What's the blast radius if we take down the auth service?"&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What vector retrieval gets you&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Chunks about the auth service&lt;/li&gt;
&lt;li&gt;Maybe some chunks about services that mention auth&lt;/li&gt;
&lt;li&gt;Possibly incident reports that mention auth failures&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;What you actually need&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Services that directly call auth&lt;/li&gt;
&lt;li&gt;Services that depend on &lt;em&gt;those&lt;/em&gt; services (second hop)&lt;/li&gt;
&lt;li&gt;Downstream effects on user-facing features (third hop)&lt;/li&gt;
&lt;li&gt;Historical incidents showing actual impact patterns&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Vector search retrieves &lt;em&gt;documents&lt;/em&gt;. But reasoning about systems requires traversing a &lt;strong&gt;graph of relationships&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why hybrid retrieval matters
&lt;/h2&gt;

&lt;p&gt;The solution isn't to abandon vector search—it's to stop treating it as your only retrieval mechanism.&lt;/p&gt;

&lt;p&gt;Graph-based memory stores information as &lt;strong&gt;entities and edges&lt;/strong&gt;. When your agent processes documentation, it extracts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Entities: services, APIs, databases, teams, incidents&lt;/li&gt;
&lt;li&gt;Relationships: depends_on, calls, deploys, owns, caused_by&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now that "blast radius" query becomes a graph traversal:&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;# Pseudocode for hybrid retrieval
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;answer_query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# Step 1: Use vector search for initial recall
&lt;/span&gt;    &lt;span class="n"&gt;candidate_entities&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;vector_search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;top_k&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Step 2: Expand via graph traversal
&lt;/span&gt;    &lt;span class="n"&gt;related_nodes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;traverse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;start_nodes&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;candidate_entities&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;relationships&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;depends_on&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;calls&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;impacts&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="n"&gt;max_depth&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Step 3: Retrieve detailed content for final context
&lt;/span&gt;    &lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;fetch_content&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;related_nodes&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;llm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;generate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You use vectors for semantic recall ("find anything related to auth service"), then use the graph to expand outward along explicit relationships.&lt;/p&gt;

&lt;h2&gt;
  
  
  When you actually need this
&lt;/h2&gt;

&lt;p&gt;Not every agent needs a graph. If you're building a documentation Q&amp;amp;A bot that answers "how do I configure X?", vector search is probably fine.&lt;/p&gt;

&lt;p&gt;You need hybrid retrieval when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Questions require connecting multiple facts ("why did X happen?")&lt;/li&gt;
&lt;li&gt;You're reasoning about systems with explicit relationships (dependencies, hierarchies, workflows)&lt;/li&gt;
&lt;li&gt;Accuracy on complex queries is more valuable than simplicity&lt;/li&gt;
&lt;li&gt;You're seeing high retrieval scores but wrong final answers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Quick diagnostic&lt;/strong&gt;: Ask your agent three questions that require connecting information from different documents. If it can retrieve all relevant chunks but still gives incomplete answers, you have a relationship problem, not a retrieval problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  What this looks like in practice
&lt;/h2&gt;

&lt;p&gt;Implementing hybrid retrieval isn't trivial, but it's not exotic either:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Extract entities and relationships&lt;/strong&gt; during document ingestion (use an LLM or NLP pipeline)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Store vectors in your existing vector DB&lt;/strong&gt; (Pinecone, Weaviate, etc.)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Store the graph separately&lt;/strong&gt; (Neo4j, or even a relational DB with recursive CTEs)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Query both&lt;/strong&gt; during retrieval and merge results&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The teams seeing that 86% accuracy boost on multi-hop reasoning aren't using magic—they're just stopped expecting embeddings to preserve information they were never designed to capture. The research on &lt;a href="https://www.icentricagency.com/insights/agent-memory-why-vector-only-retrieval-is-failing-your-ai-stack" rel="noopener noreferrer"&gt;vector-only retrieval&lt;/a&gt; makes this gap clear.&lt;/p&gt;

&lt;p&gt;If you're building production AI systems that need to reason about relationships, not just retrieve similar text, you'll eventually hit this wall. Graph memory isn't a nice-to-have—it's how you bridge the gap between semantic similarity and actual reasoning.&lt;/p&gt;

&lt;p&gt;For more on building robust agent architectures, check out resources on &lt;a href="https://www.icentricagency.com" rel="noopener noreferrer"&gt;AI automation and software development&lt;/a&gt; that cover these hybrid approaches in depth.&lt;/p&gt;

&lt;h2&gt;
  
  
  The bottom line
&lt;/h2&gt;

&lt;p&gt;Vector search is brilliant at finding relevant documents. Terrible at understanding how facts connect. If your agent needs to answer "why" or "what happens if", you need more than cosine similarity. You need a graph.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>rag</category>
      <category>architecture</category>
      <category>machinelearning</category>
    </item>
    <item>
      <title>Stop Measuring Your AI Agent Like It's a Microservice</title>
      <dc:creator>Marc Newstead</dc:creator>
      <pubDate>Mon, 20 Jul 2026 09:10:04 +0000</pubDate>
      <link>https://dev.to/icentric/stop-measuring-your-ai-agent-like-its-a-microservice-4gbi</link>
      <guid>https://dev.to/icentric/stop-measuring-your-ai-agent-like-its-a-microservice-4gbi</guid>
      <description>&lt;h2&gt;
  
  
  Stop Measuring Your AI Agent Like It's a Microservice
&lt;/h2&gt;

&lt;p&gt;You've built an AI agent. It works. It's handling real tasks. Your manager asks: "What's the ROI?"&lt;/p&gt;

&lt;p&gt;You pull up latency metrics, error rates, cost per API call. The same dashboard you'd show for any service. And that's exactly why your pilot is about to die in committee.&lt;/p&gt;

&lt;p&gt;I've watched too many technically successful AI projects get axed because we measured them wrong. Here's what I learned about making agentic AI survive past the pilot phase.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Microservice Trap
&lt;/h2&gt;

&lt;p&gt;When you build a REST API or a background worker, you measure it like infrastructure:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Requests per second&lt;/li&gt;
&lt;li&gt;P99 latency&lt;/li&gt;
&lt;li&gt;Error rate&lt;/li&gt;
&lt;li&gt;Cost per transaction&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These metrics make sense for deterministic systems. You know exactly what each transaction does, and you optimise for doing it cheaper and faster.&lt;/p&gt;

&lt;p&gt;But agentic AI doesn't work like that. Your agent might:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Handle a customer query in 30 seconds that would take a human 15 minutes&lt;/li&gt;
&lt;li&gt;Fail gracefully and route to a human&lt;/li&gt;
&lt;li&gt;Resolve an issue completely, preventing three follow-up tickets&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you're measuring "cost per transaction" at £0.20 per agent interaction versus £0.05 for a traditional form submission, you've already lost the argument. You're comparing apples to entire orchards.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Actually Matters: Task Deflection Rate
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Task deflection rate&lt;/strong&gt; is the percentage of tasks your agent completes without human intervention. Not "handled" or "touched" — actually &lt;strong&gt;completed&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This is your primary metric. Everything else is secondary.&lt;/p&gt;

&lt;p&gt;Here's why it matters: if your agent deflects 60% of tier-1 support tickets, and you're processing 10,000 tickets monthly, you've just recaptured 6,000 human interactions. Each of those has a fully loaded cost (salary, overhead, management time).&lt;/p&gt;

&lt;p&gt;Let's get concrete:&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;# Traditional metric (wrong)
&lt;/span&gt;&lt;span class="n"&gt;cost_per_agent_call&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.20&lt;/span&gt;  &lt;span class="c1"&gt;# £0.20 LLM + infrastructure
&lt;/span&gt;&lt;span class="n"&gt;monthly_agent_calls&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;6000&lt;/span&gt;
&lt;span class="n"&gt;monthly_cost&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cost_per_agent_call&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;monthly_agent_calls&lt;/span&gt;  &lt;span class="c1"&gt;# £1,200
&lt;/span&gt;
&lt;span class="c1"&gt;# This looks expensive. But watch:
&lt;/span&gt;
&lt;span class="c1"&gt;# Task deflection metric (correct)
&lt;/span&gt;&lt;span class="n"&gt;avg_human_handle_time&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;  &lt;span class="c1"&gt;# minutes
&lt;/span&gt;&lt;span class="n"&gt;deflection_rate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.60&lt;/span&gt;
&lt;span class="n"&gt;monthly_tickets&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10000&lt;/span&gt;

&lt;span class="n"&gt;deflected_tickets&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;monthly_tickets&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;deflection_rate&lt;/span&gt;  &lt;span class="c1"&gt;# 6,000
&lt;/span&gt;&lt;span class="n"&gt;human_hours_recaptured&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;deflected_tickets&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;avg_human_handle_time&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt;  &lt;span class="c1"&gt;# 1,500 hours
&lt;/span&gt;
&lt;span class="n"&gt;fully_loaded_cost_per_hour&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;35&lt;/span&gt;  &lt;span class="c1"&gt;# £35/hour (salary + overhead)
&lt;/span&gt;&lt;span class="n"&gt;monthly_value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;human_hours_recaptured&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;fully_loaded_cost_per_hour&lt;/span&gt;  &lt;span class="c1"&gt;# £52,500
&lt;/span&gt;
&lt;span class="n"&gt;net_value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;monthly_value&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;monthly_cost&lt;/span&gt;  &lt;span class="c1"&gt;# £51,300/month
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Suddenly your "expensive" agent is generating £51k of monthly value. That's the business case.&lt;/p&gt;

&lt;h2&gt;
  
  
  Measuring Deflection in Practice
&lt;/h2&gt;

&lt;p&gt;You need to instrument this &lt;strong&gt;before&lt;/strong&gt; you finish your pilot. Here's the minimum viable tracking:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AgentInteraction&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ticketId&lt;/span&gt;&lt;span class="p"&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;ticketId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ticketId&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;startTime&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&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;humanHandoffRequired&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;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resolutionConfirmed&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="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;requiresHandoff&lt;/span&gt;&lt;span class="p"&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;humanHandoffRequired&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="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;logMetric&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;task_deflection&lt;/span&gt;&lt;span class="dl"&gt;'&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="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;confirmResolution&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="o"&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;humanHandoffRequired&lt;/span&gt;&lt;span class="p"&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;resolutionConfirmed&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="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;logMetric&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;task_deflection&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&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="nf"&gt;logMetric&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;time_saved_minutes&lt;/span&gt;&lt;span class="dl"&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;estimatedHumanTime&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The key is tracking &lt;strong&gt;complete resolution&lt;/strong&gt; versus &lt;strong&gt;partial assistance&lt;/strong&gt;. Your agent might help with 90% of tickets, but only fully resolve 60%. That 60% is your deflection rate.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Human-Hour Recapture Angle
&lt;/h2&gt;

&lt;p&gt;When &lt;a href="https://www.icentricagency.com/insights/measuring-agentic-ai-why-task-deflection-rate-changes-everything" rel="noopener noreferrer"&gt;task deflection rate changes everything&lt;/a&gt;, it's because you're no longer arguing about infrastructure costs. You're talking about capacity.&lt;/p&gt;

&lt;p&gt;Those 1,500 recaptured hours monthly? That's nearly a full FTE. Your business case isn't "we made customer service 3% cheaper" — it's "we created capacity equivalent to one senior engineer without hiring."&lt;/p&gt;

&lt;p&gt;For teams working on &lt;a href="https://www.icentricagency.com" rel="noopener noreferrer"&gt;AI automation and software development&lt;/a&gt;, this reframing is essential. You're not optimising a process. You're multiplying human capability.&lt;/p&gt;

&lt;h2&gt;
  
  
  Before You Ship to Production
&lt;/h2&gt;

&lt;p&gt;Build your measurement framework &lt;strong&gt;during&lt;/strong&gt; the pilot:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Baseline human performance&lt;/strong&gt; — average handle time, escalation rate, resolution rate&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Track deflection explicitly&lt;/strong&gt; — not just "agent engaged" but "human avoided"&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Validate with spot checks&lt;/strong&gt; — random sample of "deflected" tasks to confirm quality&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Calculate fully loaded costs&lt;/strong&gt; — don't use base salary; include overhead&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;When you go to production review, lead with deflection rate and human-hour recapture. Show the capacity you've created. The cost-per-transaction comparison comes last, if at all.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Real Win
&lt;/h2&gt;

&lt;p&gt;The best AI agents don't just save money. They give your team time back to do work that actually requires human judgement. Measure &lt;strong&gt;that&lt;/strong&gt; capability, and you'll get your production budget.&lt;/p&gt;

&lt;p&gt;Your agent isn't a microservice. Stop measuring it like one.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>devops</category>
      <category>productivity</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Your RAG Pipeline Is Probably Failing Multi-Hop Questions (Here's Why)</title>
      <dc:creator>Marc Newstead</dc:creator>
      <pubDate>Mon, 20 Jul 2026 09:07:23 +0000</pubDate>
      <link>https://dev.to/icentric/your-rag-pipeline-is-probably-failing-multi-hop-questions-heres-why-5hnh</link>
      <guid>https://dev.to/icentric/your-rag-pipeline-is-probably-failing-multi-hop-questions-heres-why-5hnh</guid>
      <description>&lt;h2&gt;
  
  
  The Problem You're Not Measuring
&lt;/h2&gt;

&lt;p&gt;If you've built a RAG system in the last year, you've probably reached for a vector database. Pinecone, Weaviate, Qdrant—doesn't matter which. You chunk your docs, generate embeddings, toss them in, and suddenly your LLM can "remember" things. Shipped.&lt;/p&gt;

&lt;p&gt;But here's the uncomfortable truth: &lt;strong&gt;vector-only RAG falls apart the moment queries require reasoning across multiple pieces of information.&lt;/strong&gt; We're talking 32% accuracy on multi-hop questions. That's not a tuning problem—it's an architectural one.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Vector Search Isn't Enough
&lt;/h2&gt;

&lt;p&gt;Vector databases are brilliant at semantic similarity. Ask "What's our refund policy?" and they'll surface the right doc chunk every time. But ask something like:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Which projects led by engineers who reported to Sarah are now blocked by infrastructure issues?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now you need:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Find engineers reporting to Sarah&lt;/li&gt;
&lt;li&gt;Find projects led by those engineers
&lt;/li&gt;
&lt;li&gt;Filter for blocked status&lt;/li&gt;
&lt;li&gt;Check blocking reason is infrastructure&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Vector search treats each chunk independently. There's no concept of "reports to" or "blocks" as &lt;strong&gt;traversable relationships&lt;/strong&gt;. You're hoping the right context happens to land in the same embedding neighbourhood. Sometimes it does. Often it doesn't.&lt;/p&gt;

&lt;p&gt;This is precisely why &lt;a href="https://www.icentricagency.com/insights/agent-memory-is-the-real-bottleneck-in-enterprise-ai" rel="noopener noreferrer"&gt;the real bottleneck&lt;/a&gt; isn't compute or model size—it's how we structure memory.&lt;/p&gt;

&lt;h2&gt;
  
  
  Graph Memory: Relationships as First-Class Citizens
&lt;/h2&gt;

&lt;p&gt;Graph-based memory stores knowledge as &lt;strong&gt;nodes&lt;/strong&gt; (entities) and &lt;strong&gt;edges&lt;/strong&gt; (relationships). Think Neo4j, but purpose-built for agentic systems.&lt;/p&gt;

&lt;p&gt;Instead of:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Chunk 437: "Sarah manages the Platform team..."
Chunk 891: "Project Apollo is blocked due to..."
Chunk 1203: "The Platform team owns..."
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You get:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cypher"&gt;&lt;code&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="py"&gt;sarah:&lt;/span&gt;&lt;span class="n"&gt;Person&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="ss"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;:MANAGES&lt;/span&gt;&lt;span class="ss"&gt;]&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="py"&gt;platform:&lt;/span&gt;&lt;span class="n"&gt;Team&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;
&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="py"&gt;alice:&lt;/span&gt;&lt;span class="n"&gt;Engineer&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="ss"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;:MEMBER_OF&lt;/span&gt;&lt;span class="ss"&gt;]&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="n"&gt;platform&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;
&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="n"&gt;alice&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="ss"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;:LEADS&lt;/span&gt;&lt;span class="ss"&gt;]&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="py"&gt;apollo:&lt;/span&gt;&lt;span class="n"&gt;Project&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;
&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="n"&gt;apollo&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="ss"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;:BLOCKED_BY&lt;/span&gt;&lt;span class="ss"&gt;]&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="py"&gt;infra:&lt;/span&gt;&lt;span class="n"&gt;Issue&lt;/span&gt; &lt;span class="ss"&gt;{&lt;/span&gt;&lt;span class="py"&gt;type:&lt;/span&gt; &lt;span class="s2"&gt;"infrastructure"&lt;/span&gt;&lt;span class="ss"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that multi-hop query becomes a graph traversal. You're not praying the embeddings align—you're following explicit paths through structured knowledge.&lt;/p&gt;

&lt;h3&gt;
  
  
  What This Looks Like in Practice
&lt;/h3&gt;

&lt;p&gt;For a Python agent using something like LangGraph or a custom orchestrator:&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;answer_complex_query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;question&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="c1"&gt;# LLM extracts entities and relationships from question
&lt;/span&gt;    &lt;span class="n"&gt;query_graph&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;llm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse_to_graph_query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;question&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Execute graph traversal
&lt;/span&gt;    &lt;span class="n"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;graph_db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;traverse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;start_nodes&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;query_graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;entities&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;relationships&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;query_graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;relations&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;constraints&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;query_graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;filters&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# LLM synthesises answer from structured results
&lt;/span&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;llm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;generate_answer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;question&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The key difference: your retrieval layer now understands &lt;strong&gt;structure&lt;/strong&gt;, not just semantics.&lt;/p&gt;

&lt;h2&gt;
  
  
  Multi-Agent Systems Amplify the Problem
&lt;/h2&gt;

&lt;p&gt;Single-agent RAG is one thing. But enterprise workflows increasingly involve &lt;strong&gt;multiple specialised agents&lt;/strong&gt; coordinating:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Agent A researches customer context
&lt;/li&gt;
&lt;li&gt;Agent B pulls relevant contract terms
&lt;/li&gt;
&lt;li&gt;Agent C generates a response draft
&lt;/li&gt;
&lt;li&gt;Agent D validates against compliance rules&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If each agent is independently fumbling with vector search over the same corpus, you're compounding retrieval errors at every step. Graph memory gives agents a &lt;strong&gt;shared, queryable mental model&lt;/strong&gt; of the domain.&lt;/p&gt;

&lt;p&gt;For teams working on &lt;a href="https://www.icentricagency.com" rel="noopener noreferrer"&gt;AI automation and software development&lt;/a&gt;, this isn't theoretical—it's the difference between a demo that impresses and a system that ships.&lt;/p&gt;

&lt;h2&gt;
  
  
  Hybrid Is the Pragmatic Play
&lt;/h2&gt;

&lt;p&gt;Don't rip out your vector DB tomorrow. &lt;strong&gt;Hybrid architectures&lt;/strong&gt; are where the smart money is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Vector search&lt;/strong&gt; for broad semantic retrieval ("find documents about billing")&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Graph traversal&lt;/strong&gt; for structured reasoning ("find Sarah's team's blocked projects")&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;LLM orchestration&lt;/strong&gt; to decide which retrieval mode to use&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can even use vector embeddings as &lt;strong&gt;initial filtering&lt;/strong&gt; before graph traversal—shrink the search space, then reason precisely.&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;# Hybrid retrieval pattern
&lt;/span&gt;&lt;span class="n"&gt;candidates&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;vector_db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;top_k&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# Cast wide net
&lt;/span&gt;&lt;span class="n"&gt;entities&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;extract_entities&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;candidates&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;          &lt;span class="c1"&gt;# Identify key nodes
&lt;/span&gt;&lt;span class="n"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;graph_db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;traverse_from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;entities&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;       &lt;span class="c1"&gt;# Reason through relationships
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What to Do Next
&lt;/h2&gt;

&lt;p&gt;If you're building agentic systems today:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Audit your queries.&lt;/strong&gt; How many actually require multi-hop reasoning? If it's &amp;gt;20%, you need structure.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Start small.&lt;/strong&gt; Build a domain graph for one use case—customer support tickets, project dependencies, org structure.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Instrument retrieval.&lt;/strong&gt; Log when your RAG system fails. You'll spot the pattern fast.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prototype hybrid.&lt;/strong&gt; Keep your vector pipeline, add graph traversal for complex queries.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The architecture shift isn't about chasing novelty. It's about building systems that &lt;strong&gt;actually reason&lt;/strong&gt; instead of just pattern-match.&lt;/p&gt;

&lt;p&gt;Because 32% accuracy doesn't ship.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>rag</category>
      <category>architecture</category>
      <category>llm</category>
    </item>
    <item>
      <title>Why Your RAG Agent Can't Connect the Dots (And How to Fix It)</title>
      <dc:creator>Marc Newstead</dc:creator>
      <pubDate>Mon, 13 Jul 2026 09:13:29 +0000</pubDate>
      <link>https://dev.to/icentric/why-your-rag-agent-cant-connect-the-dots-and-how-to-fix-it-39da</link>
      <guid>https://dev.to/icentric/why-your-rag-agent-cant-connect-the-dots-and-how-to-fix-it-39da</guid>
      <description>&lt;h2&gt;
  
  
  The Problem You've Probably Hit
&lt;/h2&gt;

&lt;p&gt;You've built a RAG agent. It answers questions from your docs brilliantly... until someone asks something that requires connecting information across multiple sources. Then it falls apart.&lt;/p&gt;

&lt;p&gt;"Who worked on projects related to the component that failed in production last week?"&lt;/p&gt;

&lt;p&gt;Your vector-based agent returns documents about the failure, documents about team members, and documents about projects. But it can't &lt;em&gt;connect&lt;/em&gt; them. That's multi-hop reasoning, and it's where vector embeddings hit their ceiling.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Multi-Hop Actually Looks Like in Code
&lt;/h2&gt;

&lt;p&gt;Let's be concrete. Single-hop reasoning is straightforward:&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;# Single hop: "What does the auth service do?"
&lt;/span&gt;&lt;span class="n"&gt;query_embedding&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;embed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;auth service functionality&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;vector_db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;similarity_search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query_embedding&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="c1"&gt;# Returns relevant docs about auth service ✓
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Multi-hop reasoning chains multiple steps:&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;# Multi-hop: "Which engineer should fix the auth service bug?"
# Step 1: What is the auth service?
# Step 2: Who maintains it?
# Step 3: Who's currently available?
# Step 4: Who has fixed similar bugs before?
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With vectors alone, you're either:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Hoping all that context lives in one chunk (unlikely)&lt;/li&gt;
&lt;li&gt;Re-querying multiple times and losing the thread&lt;/li&gt;
&lt;li&gt;Jamming everything into the LLM context window and burning tokens&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;None of these scale.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why We Defaulted to Vectors
&lt;/h2&gt;

&lt;p&gt;Vectors were the pragmatic choice in 2023. The tooling was mature, implementation was straightforward, and for 80% of use cases—document retrieval, FAQ matching, semantic search—they worked brilliantly.&lt;/p&gt;

&lt;p&gt;Pinecone, Weaviate, Chroma: all excellent tools. The problem isn't the technology; it's the architectural assumption that &lt;em&gt;every&lt;/em&gt; knowledge retrieval problem is a similarity search problem.&lt;/p&gt;

&lt;p&gt;It isn't.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Graphs Do Differently
&lt;/h2&gt;

&lt;p&gt;Graph databases store knowledge as entities and relationships:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cypher"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Neo4j example&lt;/span&gt;
&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="py"&gt;Alice:&lt;/span&gt;&lt;span class="n"&gt;Engineer&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="ss"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;:MAINTAINS&lt;/span&gt;&lt;span class="ss"&gt;]&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="py"&gt;AuthService:&lt;/span&gt;&lt;span class="n"&gt;Component&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;
&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AuthService&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="ss"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;:DEPENDS_ON&lt;/span&gt;&lt;span class="ss"&gt;]&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="py"&gt;UserDB:&lt;/span&gt;&lt;span class="n"&gt;Database&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;
&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="n"&gt;UserDB&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="ss"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;:HOSTED_ON&lt;/span&gt;&lt;span class="ss"&gt;]&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="py"&gt;ProdServer:&lt;/span&gt;&lt;span class="n"&gt;Infrastructure&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;
&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="py"&gt;Bob:&lt;/span&gt;&lt;span class="n"&gt;Engineer&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="ss"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;:ON_CALL_FOR&lt;/span&gt;&lt;span class="ss"&gt;]&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ProdServer&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that multi-hop query becomes traversable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cypher"&gt;&lt;code&gt;&lt;span class="k"&gt;MATCH&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="py"&gt;bug:&lt;/span&gt;&lt;span class="n"&gt;Issue&lt;/span&gt; &lt;span class="ss"&gt;{&lt;/span&gt;&lt;span class="py"&gt;component:&lt;/span&gt; &lt;span class="s2"&gt;"AuthService"&lt;/span&gt;&lt;span class="ss"&gt;})&lt;/span&gt;
      &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="ss"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;:AFFECTS&lt;/span&gt;&lt;span class="ss"&gt;]&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="py"&gt;service:&lt;/span&gt;&lt;span class="n"&gt;Component&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="ss"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;:MAINTAINS&lt;/span&gt;&lt;span class="ss"&gt;]&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="py"&gt;engineer:&lt;/span&gt;&lt;span class="n"&gt;Engineer&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;
      &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="ss"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;:FIXED&lt;/span&gt;&lt;span class="ss"&gt;]&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="py"&gt;similar:&lt;/span&gt;&lt;span class="n"&gt;Issue&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;similar.type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;bug.type&lt;/span&gt;
&lt;span class="k"&gt;RETURN&lt;/span&gt; &lt;span class="n"&gt;engineer.name&lt;/span&gt;&lt;span class="ss"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;COUNT&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="n"&gt;similar&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;experience&lt;/span&gt;
&lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;experience&lt;/span&gt; &lt;span class="k"&gt;DESC&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The graph &lt;em&gt;encodes the connections&lt;/em&gt;. You're not asking an LLM to infer relationships from unstructured text—you're traversing explicit edges.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Practical Hybrid Architecture
&lt;/h2&gt;

&lt;p&gt;Here's what's actually working in production:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use vectors for:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Initial document retrieval&lt;/li&gt;
&lt;li&gt;Semantic similarity matching&lt;/li&gt;
&lt;li&gt;Unstructured content search&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Use graphs for:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Entity relationships&lt;/li&gt;
&lt;li&gt;Multi-hop queries&lt;/li&gt;
&lt;li&gt;Traversing connected data&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Implementation pattern:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Ingest:&lt;/strong&gt; Extract entities and relationships from your documents (using NER, LLMs, or structured parsers)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Store:&lt;/strong&gt; Documents as vectors, entities and relationships in a graph&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Query:&lt;/strong&gt; Use vectors to find &lt;em&gt;candidate documents&lt;/em&gt;, use graphs to find &lt;em&gt;connected context&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Combine:&lt;/strong&gt; Pass both to your LLM as enriched context&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This isn't theoretical. Teams have measured 40%+ accuracy improvements on multi-hop tasks by adding graph memory to existing vector pipelines. The research on &lt;a href="https://www.icentricagency.com/insights/agent-memory-why-graph-beats-vectors-for-multi-hop-reasoning" rel="noopener noreferrer"&gt;why graph beats vectors&lt;/a&gt; shows the performance gap clearly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Actually Building This
&lt;/h2&gt;

&lt;p&gt;You don't need to rip out your existing stack. Start small:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Identify multi-hop queries&lt;/strong&gt; in your logs (anything requiring "and then" logic)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Extract key entities&lt;/strong&gt; from those query domains&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Add a graph layer&lt;/strong&gt; (Neo4j, Amazon Neptune, or even PostgreSQL with recursive CTEs)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Build a hybrid retriever&lt;/strong&gt; that queries both systems&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you're working with a team that specialises in &lt;a href="https://www.icentricagency.com" rel="noopener noreferrer"&gt;AI automation and software development&lt;/a&gt;, they'll likely be working through similar architectural decisions right now.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Real Tradeoff
&lt;/h2&gt;

&lt;p&gt;Graphs add complexity. You need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Entity extraction pipelines&lt;/li&gt;
&lt;li&gt;Relationship modelling&lt;/li&gt;
&lt;li&gt;Graph database expertise&lt;/li&gt;
&lt;li&gt;More complex query logic&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But if your agent needs to reason across connected information—and most interesting agents do—the accuracy gains justify the overhead.&lt;/p&gt;

&lt;p&gt;Vectors are brilliant for similarity. Graphs are brilliant for connectivity. Use both.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>rag</category>
      <category>architecture</category>
      <category>database</category>
    </item>
    <item>
      <title>Stop Measuring AI Agent ROI Like It's a Chatbot: A Developer's Guide</title>
      <dc:creator>Marc Newstead</dc:creator>
      <pubDate>Mon, 13 Jul 2026 09:10:51 +0000</pubDate>
      <link>https://dev.to/icentric/stop-measuring-ai-agent-roi-like-its-a-chatbot-a-developers-guide-4bl1</link>
      <guid>https://dev.to/icentric/stop-measuring-ai-agent-roi-like-its-a-chatbot-a-developers-guide-4bl1</guid>
      <description>&lt;h2&gt;
  
  
  Stop Measuring AI Agent ROI Like It's a Chatbot: A Developer's Guide
&lt;/h2&gt;

&lt;p&gt;If you've recently shipped an AI agent or are being asked to build one, you've probably been handed a spreadsheet that calculates ROI based on "hours saved" or "tickets deflected." These metrics made sense for traditional automation—but they're killing your agentic AI projects before they start.&lt;/p&gt;

&lt;p&gt;Here's why, and what to measure instead.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem: Traditional Metrics Miss the Point
&lt;/h2&gt;

&lt;p&gt;Most organisations are still measuring AI agents like they're measuring a search bar upgrade or a new help desk widget. The conversation goes something like this:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"If the agent handles 1,000 queries per month and saves 5 minutes per query, that's 83 hours saved. Times hourly rate, minus infrastructure cost... ROI positive in 18 months!"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Sounds reasonable. Except agentic AI doesn't just &lt;em&gt;answer questions&lt;/em&gt;—it makes decisions and takes actions. A procurement agent doesn't just look up vendor details; it evaluates quotes, flags compliance risks, and routes approvals. A triage agent doesn't just categorise tickets; it assesses severity, assigns priority, and sometimes resolves the issue outright.&lt;/p&gt;

&lt;p&gt;When you measure these systems purely on cost savings, you're optimising for the wrong thing. You end up building glorified FAQ bots with extra steps.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Better Metric: Decisions Automated Per Hour
&lt;/h2&gt;

&lt;p&gt;Instead of "how much did we save?", ask: &lt;strong&gt;"How many decisions is this system making per hour?"&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This reframes the entire conversation. Suddenly you're thinking about:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Throughput&lt;/strong&gt;: Can this agent handle 10 routing decisions per hour, or 1,000?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scope&lt;/strong&gt;: What categories of decisions can it own end-to-end?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Latency&lt;/strong&gt;: How quickly does it move from input to action?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scale&lt;/strong&gt;: What happens when load doubles?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are questions developers instinctively ask about any production system. Treating your agent as a decision-making service—not a cost-centre—makes architectural choices clearer.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example: Deployment Approval Agent
&lt;/h3&gt;

&lt;p&gt;Let's say you build an agent that reviews deployment requests for a platform team:&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;# Traditional ROI thinking:
# "Saves 10 minutes per manual review, ~200 reviews/month"
# = 33 hours saved, ~£1,500/month
&lt;/span&gt;
&lt;span class="c1"&gt;# Decisions-per-hour thinking:
# "Handles 50 deployment approvals/hour during peak"
# "Automatically clears 80% with no human in loop"
# "Escalates 20% with full context and risk assessment"
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The second framing makes it obvious this isn't about saving 33 hours—it's about &lt;strong&gt;removing a bottleneck&lt;/strong&gt;. You can now deploy 50 times per hour instead of queuing for manual review. The value isn't the time saved; it's the velocity unlocked.&lt;/p&gt;

&lt;p&gt;This shift in perspective influences everything: how you design the agent, what data it needs, how you monitor it, and how you sell it to stakeholders. The &lt;a href="https://www.icentricagency.com/insights/measuring-agentic-ai-roi-why-decisions-matter-more-than-cost-savings" rel="noopener noreferrer"&gt;decisions matter more&lt;/a&gt; article covers the strategic side of this in detail.&lt;/p&gt;

&lt;h2&gt;
  
  
  What This Changes for You as a Developer
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. &lt;strong&gt;You'll Prioritise Different Features&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Cost-reduction logic says: "Make the agent handle the simplest 80% of queries."&lt;/p&gt;

&lt;p&gt;Decisions-per-hour logic says: "Make the agent handle the highest-volume decision paths end-to-end."&lt;/p&gt;

&lt;p&gt;Very different backlogs.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. &lt;strong&gt;Observability Becomes Central&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;You need to instrument decision quality, not just uptime. Think:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Decision confidence scores&lt;/li&gt;
&lt;li&gt;Escalation rates by decision type&lt;/li&gt;
&lt;li&gt;Feedback loops from humans who review edge cases&lt;/li&gt;
&lt;li&gt;Drift detection on decision patterns&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Your agent is now a service with SLOs. Treat it like one.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. &lt;strong&gt;You'll Design for Throughput, Not Coverage&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;A chatbot optimises for "Can it answer this question?"&lt;/p&gt;

&lt;p&gt;An agent optimises for "Can it close the loop on this workflow?"&lt;/p&gt;

&lt;p&gt;That means thinking about state management, rollback strategies, and idempotency from day one. Your agent isn't read-only.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Quality Trap (and How to Avoid It)
&lt;/h2&gt;

&lt;p&gt;Obviously, "decisions per hour" is meaningless if those decisions are rubbish. The key is to &lt;strong&gt;instrument quality from the start&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Shadow mode first: Run the agent in parallel, compare to human decisions&lt;/li&gt;
&lt;li&gt;Confidence thresholds: Auto-execute high-confidence decisions, escalate the rest&lt;/li&gt;
&lt;li&gt;Continuous evaluation: Sample and audit decisions regularly&lt;/li&gt;
&lt;li&gt;Feedback signals: Did the human override? Did downstream systems reject it?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you're working with teams focused on &lt;a href="https://www.icentricagency.com" rel="noopener noreferrer"&gt;AI automation and software development&lt;/a&gt;, these feedback loops should be baked into your delivery process, not bolted on later.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Thought
&lt;/h2&gt;

&lt;p&gt;If your current AI project is being measured purely on "cost per query" or "FTE avoided," push back. Ask what decisions the system could own, how many per hour, and what good looks like.&lt;/p&gt;

&lt;p&gt;You'll build better systems—and you'll have a much easier time explaining why they matter.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>devops</category>
      <category>architecture</category>
      <category>automation</category>
    </item>
    <item>
      <title>MCP and A2A: Two Protocols Every Multi-Agent Dev Should Know</title>
      <dc:creator>Marc Newstead</dc:creator>
      <pubDate>Mon, 06 Jul 2026 09:11:56 +0000</pubDate>
      <link>https://dev.to/icentric/mcp-and-a2a-two-protocols-every-multi-agent-dev-should-know-2hcl</link>
      <guid>https://dev.to/icentric/mcp-and-a2a-two-protocols-every-multi-agent-dev-should-know-2hcl</guid>
      <description>&lt;h2&gt;
  
  
  The Two-Layer Problem Nobody Saw Coming
&lt;/h2&gt;

&lt;p&gt;If you're building anything with AI agents right now, you've probably hit the same wall I did: how do you wire multiple agents together without creating a brittle mess of custom integrations?&lt;/p&gt;

&lt;p&gt;Turns out, two protocols are emerging to split this problem cleanly down the middle. &lt;strong&gt;MCP (Model Context Protocol)&lt;/strong&gt; handles the vertical—how a single agent talks to its tools and data sources. &lt;strong&gt;A2A (Agent-to-Agent)&lt;/strong&gt; handles the horizontal—how agents discover and communicate with each other.&lt;/p&gt;

&lt;p&gt;Understanding this split early saves you from architectural regret later. Let me show you why.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Vertical Layer: MCP
&lt;/h2&gt;

&lt;p&gt;Think of MCP as the standardised plumbing between your agent and everything it needs to do actual work. Before MCP, every LLM framework had its own way of wrapping API calls, database queries, or file system access.&lt;/p&gt;

&lt;p&gt;Here's what MCP standardises:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Tool definitions&lt;/strong&gt; — A consistent schema for describing what a function does and what parameters it needs&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Resource access&lt;/strong&gt; — How agents read from databases, file systems, or external APIs&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prompts and context&lt;/strong&gt; — A protocol-level way to inject context and instructions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In practice, this means you can write an MCP server once and plug it into Claude, custom LangChain agents, or any other MCP-compatible runtime:&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;# Pseudocode: MCP server exposing a tool
&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;WeatherMCPServer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nd"&gt;@mcp_tool&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_forecast&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="nb"&gt;str&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;dict&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;fetch_weather_api&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Anthropie drives MCP, and adoption is growing fast. If you're building agents that need reliable tool access, MCP is becoming the safe default.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Horizontal Layer: A2A
&lt;/h2&gt;

&lt;p&gt;A2A solves a different problem: &lt;strong&gt;how do agents find each other and coordinate?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Imagine you're building a customer support system with three specialised agents:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;An intake agent that routes requests&lt;/li&gt;
&lt;li&gt;A technical agent that handles product queries&lt;/li&gt;
&lt;li&gt;A billing agent that processes refunds&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Without A2A, you'd hard-code those connections. With A2A, agents register their capabilities in a directory, and other agents discover them dynamically.&lt;/p&gt;

&lt;p&gt;Key A2A concepts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Agent discovery&lt;/strong&gt; — A registry where agents advertise what they can do&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Message routing&lt;/strong&gt; — Standardised envelopes for inter-agent communication&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Capability negotiation&lt;/strong&gt; — Agents declare their skills; others query and invoke them&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Google's pushing A2A hard, and major cloud vendors are lining up support. The &lt;a href="https://www.icentricagency.com/insights/mcp-a2a-the-two-layer-stack-wiring-the-internet-of-agents-2" rel="noopener noreferrer"&gt;two-layer stack&lt;/a&gt; is quickly becoming the de facto architecture for serious multi-agent systems.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where Devs Get It Wrong
&lt;/h2&gt;

&lt;p&gt;The biggest mistake I see? &lt;strong&gt;Using MCP to solve A2A problems, or vice versa.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;❌ Trying to use MCP tool calls to route messages between agents&lt;/li&gt;
&lt;li&gt;❌ Building custom agent discovery when A2A already defines it&lt;/li&gt;
&lt;li&gt;❌ Implementing A2A-style capability negotiation inside MCP servers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Keep it clean:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;MCP = One agent, many tools&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;A2A = Many agents, one conversation&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Real-World Architecture
&lt;/h2&gt;

&lt;p&gt;Here's how I'd structure a production system:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌─────────────────────────────────────┐
│   A2A Layer (Agent Coordination)    │
│  - Discovery registry               │
│  - Message bus                      │
│  - Routing logic                    │
└─────────────────────────────────────┘
           ↓           ↓           ↓
    Agent A       Agent B       Agent C
       ↓              ↓              ↓
┌──────────────────────────────────────┐
│    MCP Layer (Tool Integration)      │
│  - Database connector                │
│  - API wrappers                      │
│  - File system access                │
└──────────────────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each agent has its own MCP stack. The A2A layer orchestrates the whole system.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Standards Risk
&lt;/h2&gt;

&lt;p&gt;One caveat: &lt;strong&gt;neither protocol is governed by a neutral standards body yet.&lt;/strong&gt; MCP is Anthropic's baby; A2A is Google's. That's not necessarily a dealbreaker, but it does mean the specs could shift based on commercial priorities.&lt;/p&gt;

&lt;p&gt;If you're building something enterprise-grade, keep an eye on governance. The worst-case scenario is ending up locked into one vendor's interpretation of the spec.&lt;/p&gt;

&lt;h2&gt;
  
  
  Should You Care Right Now?
&lt;/h2&gt;

&lt;p&gt;If you're building:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Single-agent systems&lt;/strong&gt; → MCP is immediately useful. Start there.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multi-agent orchestration&lt;/strong&gt; → You need both layers. Design for A2A from day one.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enterprise AI at scale&lt;/strong&gt; → The two-layer stack is becoming table stakes. Teams working on &lt;a href="https://www.icentricagency.com" rel="noopener noreferrer"&gt;AI automation and software development&lt;/a&gt; are already adopting this architecture.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The payoff is real: cleaner code, less coupling, easier to extend. And when the next big LLM framework drops, you won't be rewriting everything.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where to Start
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Experiment with MCP&lt;/strong&gt; — Anthropic's docs are solid. Build a simple tool server.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Read the A2A spec&lt;/strong&gt; — Google published it earlier this year. It's clearer than you'd expect.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Design for the split&lt;/strong&gt; — Even if you're not using both today, structure your code as if you will.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The agent internet is coming. These two protocols are the plumbing.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>architecture</category>
      <category>agents</category>
      <category>protocols</category>
    </item>
    <item>
      <title>Why Your Next AI Agent Should Probably Be a Manager</title>
      <dc:creator>Marc Newstead</dc:creator>
      <pubDate>Mon, 06 Jul 2026 09:09:16 +0000</pubDate>
      <link>https://dev.to/icentric/why-your-next-ai-agent-should-probably-be-a-manager-55fb</link>
      <guid>https://dev.to/icentric/why-your-next-ai-agent-should-probably-be-a-manager-55fb</guid>
      <description>&lt;h2&gt;
  
  
  Why Your Next AI Agent Should Probably Be a Manager
&lt;/h2&gt;

&lt;p&gt;If you've built an AI agent that tries to do everything—answer support tickets, query databases, generate reports, and update CRM records—you've probably noticed it's mediocre at all of them. There's a better pattern, and it's one we've used in software architecture for decades: &lt;strong&gt;delegation&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Instead of building one massive agent with an enormous context window and dozens of tools, build a supervisor agent that spawns specialists on demand. Think of it as a tech lead who routes work to the right engineer, not a full-stack developer trying to do everything themselves.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem with Jack-of-All-Trades Agents
&lt;/h2&gt;

&lt;p&gt;A single LLM agent handling a complex workflow hits a wall quickly. You give it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Access to 15+ API endpoints&lt;/li&gt;
&lt;li&gt;A 3,000-word system prompt&lt;/li&gt;
&lt;li&gt;Instructions for edge cases in six different domains&lt;/li&gt;
&lt;li&gt;Tools for everything from data validation to PDF generation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What you get back is an agent that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Picks the wrong tool 20% of the time&lt;/li&gt;
&lt;li&gt;Hallucinates when context exceeds its sweet spot&lt;/li&gt;
&lt;li&gt;Can't specialise deeply enough to handle domain-specific nuance&lt;/li&gt;
&lt;li&gt;Becomes exponentially harder to debug as complexity grows&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Sound familiar? It's the same reason we stopped building monoliths and started building microservices.&lt;/p&gt;

&lt;h2&gt;
  
  
  Enter the Supervisor Pattern
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://www.icentricagency.com/insights/supervisor-and-sub-agents-how-one-agent-learns-to-delegate-2" rel="noopener noreferrer"&gt;supervisor and sub-agents&lt;/a&gt; pattern flips the model. Your supervisor agent doesn't &lt;em&gt;do&lt;/em&gt; the work—it &lt;strong&gt;routes&lt;/strong&gt; it.&lt;/p&gt;

&lt;p&gt;Here's a simplified flow:&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;# Pseudocode: Supervisor agent receives a task
&lt;/span&gt;&lt;span class="n"&gt;task&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Analyse this customer complaint and update their support ticket&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="c1"&gt;# Supervisor decomposes and delegates
&lt;/span&gt;&lt;span class="n"&gt;supervisor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;analyse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# Output: [
#   {"agent": "sentiment_analyser", "input": complaint_text},
#   {"agent": "crm_updater", "input": ticket_id, "sentiment": result}
# ]
&lt;/span&gt;
&lt;span class="c1"&gt;# Each specialist does one thing well
&lt;/span&gt;&lt;span class="n"&gt;sentiment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sentiment_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="n"&gt;complaint_text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;crm_agent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ticket_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sentiment&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The supervisor's job is &lt;strong&gt;orchestration, not execution&lt;/strong&gt;. It:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Breaks down the user's request into subtasks&lt;/li&gt;
&lt;li&gt;Determines which specialist agent handles each subtask&lt;/li&gt;
&lt;li&gt;Passes context between agents&lt;/li&gt;
&lt;li&gt;Aggregates results and responds&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each sub-agent has:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A narrow, well-defined role&lt;/li&gt;
&lt;li&gt;A smaller, focused system prompt&lt;/li&gt;
&lt;li&gt;Only the tools it actually needs&lt;/li&gt;
&lt;li&gt;Higher accuracy within its domain&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why This Works (and Why It's Familiar)
&lt;/h2&gt;

&lt;p&gt;If you've built distributed systems, this should feel natural. It's the same principles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Single Responsibility Principle&lt;/strong&gt;: Each agent does one thing well&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Loose Coupling&lt;/strong&gt;: Agents don't need to know about each other&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bounded Context&lt;/strong&gt;: Clear domain boundaries reduce complexity&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Graceful Degradation&lt;/strong&gt;: One agent failing doesn't tank the whole system&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You wouldn't build a microservice that handles payments, inventory, and email notifications. Don't build agents that way either.&lt;/p&gt;

&lt;h2&gt;
  
  
  Dynamic Spawning: The Next Level
&lt;/h2&gt;

&lt;p&gt;Static sub-agent pools work, but the real power comes when your supervisor can &lt;strong&gt;spawn agents dynamically&lt;/strong&gt;. Frameworks like LangGraph, AutoGen, and CrewAI support this.&lt;/p&gt;

&lt;p&gt;Imagine your supervisor encounters a task it's never seen:&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;# Task: "Translate this legal document to French and summarise it"
&lt;/span&gt;
&lt;span class="c1"&gt;# Supervisor spawns specialists on-the-fly:
&lt;/span&gt;&lt;span class="n"&gt;supervisor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;spawn_agent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;role&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;legal_translator&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="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;translation_api&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;French legal terminology, formal tone&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;supervisor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;spawn_agent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;role&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;document_summariser&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="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;text_analysis&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Legal summary, bullet points, max 200 words&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;No need to pre-define every possible agent. The supervisor adapts to the task.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Gotchas (Because There Always Are)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Routing errors are your biggest risk.&lt;/strong&gt; If the supervisor sends a task to the wrong specialist, you're worse off than with a generalist. Mitigation strategies:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use structured outputs (JSON, Pydantic models) for routing decisions&lt;/li&gt;
&lt;li&gt;Log every delegation decision for debugging&lt;/li&gt;
&lt;li&gt;Implement confidence scores—if the supervisor isn't sure, escalate to a human&lt;/li&gt;
&lt;li&gt;Test routing logic obsessively&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Token costs add up.&lt;/strong&gt; Multiple agents mean multiple LLM calls. Profile your usage and optimise:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use smaller models for specialist tasks&lt;/li&gt;
&lt;li&gt;Cache common decompositions&lt;/li&gt;
&lt;li&gt;Consider local models for low-stakes subtasks&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Observability is critical.&lt;/strong&gt; Distributed agent systems are harder to debug than single agents. Invest in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Tracing (OpenTelemetry, LangSmith)&lt;/li&gt;
&lt;li&gt;Structured logging with request IDs&lt;/li&gt;
&lt;li&gt;Dashboards showing agent performance and routing patterns&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Should You Build This?
&lt;/h2&gt;

&lt;p&gt;If your agent workflow has:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Multiple distinct domains (e.g., data retrieval + analysis + reporting)&lt;/li&gt;
&lt;li&gt;More than 8–10 tools&lt;/li&gt;
&lt;li&gt;Frequent routing mistakes&lt;/li&gt;
&lt;li&gt;Growing system prompts that feel unwieldy&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;...then yes, try the supervisor pattern.&lt;/p&gt;

&lt;p&gt;If you're building a simple chatbot or single-purpose assistant, stick with one agent. Don't over-engineer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where to Start
&lt;/h2&gt;

&lt;p&gt;Pick one complex agent workflow you've already built. Identify two or three distinct subtasks. Refactor into a supervisor + two specialists. Measure accuracy and token usage before and after.&lt;/p&gt;

&lt;p&gt;You'll know quickly if it's the right pattern for your use case.&lt;/p&gt;

&lt;p&gt;For teams working on &lt;a href="https://www.icentricagency.com" rel="noopener noreferrer"&gt;AI automation and software development&lt;/a&gt; at scale, this pattern is increasingly becoming the default. It's not about replacing single agents—it's about knowing when orchestration beats execution.&lt;/p&gt;

&lt;p&gt;Now go build something modular.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>architecture</category>
      <category>automation</category>
      <category>agents</category>
    </item>
    <item>
      <title>MCP + A2A: You're Building Two Integration Layers Whether You Realise It or Not</title>
      <dc:creator>Marc Newstead</dc:creator>
      <pubDate>Mon, 29 Jun 2026 09:05:26 +0000</pubDate>
      <link>https://dev.to/icentric/mcp-a2a-youre-building-two-integration-layers-whether-you-realise-it-or-not-1578</link>
      <guid>https://dev.to/icentric/mcp-a2a-youre-building-two-integration-layers-whether-you-realise-it-or-not-1578</guid>
      <description>&lt;h2&gt;
  
  
  The Problem You Probably Have Already
&lt;/h2&gt;

&lt;p&gt;If you're building agentic systems in 2025, chances are you've already got two integration layers in your stack:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;MCP&lt;/strong&gt; (Model Context Protocol) — wiring your AI models to databases, APIs, filesystems, internal tools&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A2A&lt;/strong&gt; (Agent-to-Agent) protocols — letting your agents discover, negotiate with, and invoke &lt;em&gt;each other&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;They're not competing. They're complementary. But without a clear interoperability story, you're setting yourself up for the kind of integration spaghetti that kept enterprise architects busy (and miserable) in the ESB era.&lt;/p&gt;

&lt;h2&gt;
  
  
  What MCP Actually Does
&lt;/h2&gt;

&lt;p&gt;MCP is Anthropic's answer to a simple problem: how do you give an LLM structured, reliable access to external resources without writing bespoke glue code for every data source?&lt;/p&gt;

&lt;p&gt;Instead of hardcoding database queries or API calls into your prompts, you expose them as &lt;strong&gt;MCP servers&lt;/strong&gt;. Your AI client connects via a standard protocol, discovers available tools, and invokes them with typed parameters.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example use case:&lt;/strong&gt;&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;# MCP server exposes a tool
&lt;/span&gt;&lt;span class="nd"&gt;@mcp_tool&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;query_customer_orders&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;customer_id&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="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Order&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;SELECT * FROM orders WHERE customer_id = ?&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;customer_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your LLM can now call &lt;code&gt;query_customer_orders&lt;/code&gt; as a function — no prompt engineering, no brittle scraping, no hoping the model "figures it out".&lt;/p&gt;

&lt;p&gt;MCP is &lt;strong&gt;vertical integration&lt;/strong&gt;: connecting one agent to the resources it needs to do its job.&lt;/p&gt;

&lt;h2&gt;
  
  
  What A2A Actually Does
&lt;/h2&gt;

&lt;p&gt;A2A is horizontal. It's about agents talking to &lt;em&gt;other agents&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Imagine you've got:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A customer service agent that handles support tickets&lt;/li&gt;
&lt;li&gt;A logistics agent that tracks shipments&lt;/li&gt;
&lt;li&gt;A billing agent that processes refunds&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When a customer asks "Where's my refund?", the support agent needs to talk to billing. That's A2A.&lt;/p&gt;

&lt;p&gt;A2A protocols define:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Discovery&lt;/strong&gt;: how does Agent A find Agent B?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Capability negotiation&lt;/strong&gt;: what can Agent B actually do?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Invocation&lt;/strong&gt;: how does Agent A call Agent B and handle the response?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Unlike MCP, A2A is still fragmented. There's no single standard. You might be using:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;HTTP APIs with custom service meshes&lt;/li&gt;
&lt;li&gt;Pub/sub queues (Kafka, RabbitMQ)&lt;/li&gt;
&lt;li&gt;gRPC with Protobuf schemas&lt;/li&gt;
&lt;li&gt;Proprietary frameworks from LangChain, AutoGen, CrewAI&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each works. None interoperate cleanly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why This Feels Familiar (and Not in a Good Way)
&lt;/h2&gt;

&lt;p&gt;If you worked in enterprise integration in the 2000s, this smells like &lt;strong&gt;ESB déjà vu&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The Enterprise Service Bus promised to solve the n-squared integration problem: instead of every system talking directly to every other system, route everything through a central bus.&lt;/p&gt;

&lt;p&gt;It worked — until it didn't. ESBs became:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Single points of failure&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Performance bottlenecks&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Proprietary lock-in traps&lt;/strong&gt; (looking at you, TIBCO and WebSphere)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;a href="https://www.icentricagency.com/insights/mcp-a2a-the-two-layer-stack-wiring-the-internet-of-agents-1" rel="noopener noreferrer"&gt;two-layer stack&lt;/a&gt; emerging now — MCP below, A2A above — risks the same fate if we're not careful.&lt;/p&gt;

&lt;h2&gt;
  
  
  What You Should Do About It
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Treat MCP as infrastructure, not application logic
&lt;/h3&gt;

&lt;p&gt;MCP is brilliant for standardising resource access. Don't abuse it by cramming business logic into MCP tools. Keep them thin, composable, and stateless.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Pick &lt;em&gt;one&lt;/em&gt; A2A pattern per bounded context
&lt;/h3&gt;

&lt;p&gt;Don't mix pub/sub and RPC in the same workflow unless you have a damn good reason. Consistency beats flexibility when debugging multi-agent failures at 2am.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Design for replaceability
&lt;/h3&gt;

&lt;p&gt;Whatever A2A framework you choose today will probably be legacy in 18 months. Wrap it. Abstract it. Make it swappable.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&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;class&lt;/span&gt; &lt;span class="nc"&gt;AgentInvoker&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Protocol&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;invoke&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;agent_id&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="n"&gt;task&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;dict&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;dict&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="bp"&gt;...&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;KafkaAgentInvoker&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AgentInvoker&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# Implementation today
&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;GrpcAgentInvoker&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AgentInvoker&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# Swap in tomorrow
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. Monitor both layers separately
&lt;/h3&gt;

&lt;p&gt;MCP failures look different to A2A failures:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;MCP: "Tool not found", "Database timeout", "API key expired"&lt;/li&gt;
&lt;li&gt;A2A: "Agent unavailable", "Circular dependency", "Message bus backlog"&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Your observability stack needs to distinguish them.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Boring Truth
&lt;/h2&gt;

&lt;p&gt;There's no silver bullet yet. MCP is maturing fast, but A2A is still the Wild West. If you're building production agentic systems — especially in regulated industries or at scale — treat this as an &lt;strong&gt;architecture risk&lt;/strong&gt;, not just a tooling choice.&lt;/p&gt;

&lt;p&gt;You don't need to freeze development. But you &lt;em&gt;do&lt;/em&gt; need to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Isolate the integration layer&lt;/li&gt;
&lt;li&gt;Version your agent contracts&lt;/li&gt;
&lt;li&gt;Plan for migration&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The teams that get this right won't be the ones with the cleverest agents. They'll be the ones who can rewire them without a full rewrite.&lt;/p&gt;




&lt;p&gt;If you're evaluating MCP, A2A, or any other part of the agentic stack and want a second opinion, teams specialising in &lt;a href="https://www.icentricagency.com" rel="noopener noreferrer"&gt;AI automation and software development&lt;/a&gt; can help you de-risk the architecture before you're too deep to reverse course.&lt;/p&gt;

&lt;p&gt;But honestly? Just don't build another ESB. We've been there. It wasn't fun.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>architecture</category>
      <category>agents</category>
      <category>integration</category>
    </item>
  </channel>
</rss>
