<?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: IRC-A</title>
    <description>The latest articles on DEV Community by IRC-A (irc-a).</description>
    <link>https://dev.to/irc-a</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%2Forganization%2Fprofile_image%2F14316%2Fa003bd19-dc4b-485d-9cfc-59323931be87.png</url>
      <title>DEV Community: IRC-A</title>
      <link>https://dev.to/irc-a</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/irc-a"/>
    <language>en</language>
    <item>
      <title>From n8n to IRC-A: a week migrating a real project — and a 679-token bill that's hard to believe</title>
      <dc:creator>Sandro Garcia</dc:creator>
      <pubDate>Thu, 06 Aug 2026 11:30:00 +0000</pubDate>
      <link>https://dev.to/irc-a/from-n8n-to-irc-a-a-week-migrating-a-real-project-and-a-679-token-bill-thats-hard-to-believe-3h3b</link>
      <guid>https://dev.to/irc-a/from-n8n-to-irc-a-a-week-migrating-a-real-project-and-a-679-token-bill-thats-hard-to-believe-3h3b</guid>
      <description>&lt;p&gt;I went a bit quiet last week. The reason: I was heads-down working on the framework to complement the SDK. And what better way to build a framework that's genuinely useful and simple to use than starting from a real project — and seeing what functionality can be "packaged" into it?&lt;/p&gt;

&lt;p&gt;So I spent the week migrating an old customer-service project from my wife's business, from n8n to IRC-A. And every time I use this approach, I fall in love with it a little more.&lt;/p&gt;




&lt;h2&gt;
  
  
  The magic (not black magic): extending the system with a single &lt;code&gt;curl&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;It's amazing to watch: you build an agent or an MCP tool, connect it to the server, and two seconds later your multi-agent system's capabilities have grown. No extra code. No component knowing about any other. No drawing graphs and edges. Just this:&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;"http://[irc-server]/register/agent?url=http://[agent-url]&amp;amp;channels=%23content"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the magic &lt;strong&gt;Alan Kay&lt;/strong&gt; envisioned with &lt;strong&gt;Smalltalk&lt;/strong&gt; — objects sending messages to each other without knowing one another — brought to the agentic era.&lt;/p&gt;




&lt;h2&gt;
  
  
  A real log, unedited
&lt;/h2&gt;

&lt;p&gt;So this doesn't sound like marketing, here's a real log from the running system. The user asks the chatbot: &lt;em&gt;"How many customers did we have in August?"&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;main-agent       | [Chatbot] Message received in crm session: How many customers did we have in August
customers-agent  | [Customers Agent] Processing query: 'How many customers did we have in August'
customers-agent  | [Customers Agent] Technical intent refined by LLM: 'count_customers_by_date CRM'
customers-agent  | [Customers Agent] /discover Raw Response: {"status":"success","det":"v4.public.eyJ...","url":"http://host.docker.internal:8003","target_node_id":"count_contacts","type":"tool"}
&lt;/span&gt;&lt;span class="gp"&gt;customers-agent  | [Customers Agent] BFA Gateway indicated calling -&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Type: &lt;span class="s1"&gt;'tool'&lt;/span&gt;, Destination: &lt;span class="s1"&gt;'http://host.docker.internal:8003'&lt;/span&gt;
&lt;span class="go"&gt;customers-agent  | [Customers Agent] Schema for Tool 'count_contacts' per BFA/Fallback: {'type': 'object', 'properties': {'from': {'type': 'string'}, 'to': {'type': 'string'}}}
customers-agent  | [Customers Agent] Extraction LLM response: '{"from":"2026-08-01","to":"2026-08-31"}'
&lt;/span&gt;&lt;span class="gp"&gt;customers-agent  | [Customers Agent] ---&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;FINAL PARAMETERS TO SEND TO &lt;span class="s1"&gt;'count_contacts'&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;'from'&lt;/span&gt;: &lt;span class="s1"&gt;'2026-08-01'&lt;/span&gt;, &lt;span class="s1"&gt;'to'&lt;/span&gt;: &lt;span class="s1"&gt;'2026-08-31'&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="go"&gt;customers-agent  | [Customers Agent] Invoking P2P Tool 'count_contacts' at http://host.docker.internal:8003/tools...
customers-agent  | [Customers Agent] P2P Tool 'count_contacts' Response: "{\"count\":21}"
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Read that log again and notice the important part: &lt;strong&gt;nobody knows anybody&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;main-agent&lt;/code&gt; doesn't know the &lt;code&gt;customers-agent&lt;/code&gt; exists, and it doesn't know the &lt;code&gt;count_contacts&lt;/code&gt; tool either. It only knows its own job: talk to the user and fulfill their request, asking the Gateway for assistance.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;customers-agent&lt;/code&gt; doesn't know the &lt;code&gt;main-agent&lt;/code&gt;, nor the &lt;code&gt;count_contacts&lt;/code&gt; tool. It only knows its responsibilities, defined in its agent-card:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;agent_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;customers_agent&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Customers Agent&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Agent in charge of handling any kind of task on the customers and contacts database. It connects to the EspoCRM CRM through its MCP and exposes tools to query, add, update and delete contacts.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="n"&gt;tags&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;customers&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;contacts&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;leads&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;crm&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="n"&gt;examples&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;I want the list of customers from last month&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;how many new customers did we have this month&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;how many contacts do we have&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;how many contacts are registered&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;Add the customer &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;John Doe&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt; with phone 123456789&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;Update &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;John Doe&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;s phone to 987654321&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And its prompt is as simple as 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;system_prompt&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;You are the specialist agent for CRM customers/contacts. &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Convert the user&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;s request into a single short MCP tool-search phrase (e.g. &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;count_contacts CRM&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;, &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;search_contacts CRM&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;) &lt;/span&gt;&lt;span class="sh"&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;to look up the right tool on the BFA network for: &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_message&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;'"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here &lt;code&gt;user_message&lt;/code&gt; has already been refined: an earlier LLM pass distills the exact intent, shortens the message, and cuts unnecessary token spend.&lt;/p&gt;

&lt;p&gt;The full flow:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The agent refines the intent: &lt;code&gt;"count_customers_by_date CRM"&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The BFA Gateway tells it &lt;strong&gt;who to call&lt;/strong&gt;, hands over the authorization token (DET) and the parameter schema.&lt;/li&gt;
&lt;li&gt;The agent extracts the parameters and invokes the tool P2P.&lt;/li&gt;
&lt;li&gt;Result: &lt;code&gt;{"count": 21}&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Without anyone knowing anyone — or any tool — we got the answer. It's that simple.&lt;/p&gt;




&lt;h2&gt;
  
  
  The other number hiding in that flow: 679 tokens
&lt;/h2&gt;

&lt;p&gt;Here's the part that made me stare at the LangSmith dashboard for a while.&lt;/p&gt;

&lt;p&gt;During testing, a user had a complete two-turn interaction with the system: they asked whether a contact existed in the CRM (she didn't), then asked to add her with name and phone number (done). That flow involved &lt;strong&gt;2 agents coordinating, 4 LLM calls, and an MCP tool execution&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The total cost: &lt;strong&gt;679 tokens. Less than a tenth of a cent.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The per-call breakdown (gpt-4.1-mini, temperature 0, straight from the traces):&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Step&lt;/th&gt;
&lt;th&gt;LLM call&lt;/th&gt;
&lt;th&gt;Tokens&lt;/th&gt;
&lt;th&gt;Cost&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Lookup&lt;/td&gt;
&lt;td&gt;Intent refinement → &lt;code&gt;search_contacts CRM &amp;lt;name&amp;gt;&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;103&lt;/td&gt;
&lt;td&gt;&amp;lt;$0.0001&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Lookup&lt;/td&gt;
&lt;td&gt;Parameter extraction for &lt;code&gt;search_contacts&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;192&lt;/td&gt;
&lt;td&gt;&amp;lt;$0.0001&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Insert&lt;/td&gt;
&lt;td&gt;Intent refinement → &lt;code&gt;add_contact CRM &amp;lt;name&amp;gt; &amp;lt;phone&amp;gt;&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;135&lt;/td&gt;
&lt;td&gt;&amp;lt;$0.0001&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Insert&lt;/td&gt;
&lt;td&gt;Parameter extraction → &lt;code&gt;{"firstName": ..., "lastName": ..., "phone": ...}&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;249&lt;/td&gt;
&lt;td&gt;$0.0002&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Total&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;679&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;&amp;lt; $0.001&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

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

&lt;p&gt;For context: a typical agentic loop dragging its full conversation history and tool state through every step easily burns &lt;strong&gt;5k–10k tokens per task&lt;/strong&gt;. This is two orders of magnitude less. Why?&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;LLM calls are surgical.&lt;/strong&gt; The model is used exactly twice per agent turn: once to distill intent into a short search phrase, once to extract parameters against a JSON schema. No endless chit-chat, no history re-feeding.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Discovery and routing cost zero tokens.&lt;/strong&gt; Finding &lt;em&gt;who to call&lt;/em&gt; is FAISS vector search over capability metadata — deterministic, fast, and free of LLM involvement.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Execution is P2P.&lt;/strong&gt; Once the agent knows the destination and holds its authorization token (DET), it talks directly to the tool. There's no central orchestrator inflating every step with system-wide context.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Efficiency in agent systems isn't achieved with shorter prompts. It's achieved with &lt;strong&gt;architecture&lt;/strong&gt; — using the LLM where it adds value (understanding, extracting) and not where it doesn't (searching, routing, authorizing).&lt;/p&gt;




&lt;h2&gt;
  
  
  The week's real value: what a real project taught the framework
&lt;/h2&gt;

&lt;p&gt;As I said, the goal was to improve the SDK and isolate what matters most for the framework. And this mini-project worked exactly as hoped: migrating something real exposed friction I would never have found writing toy tests. Here are the 6 improvements that came out of the week:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Semantic routing and circular interception in FAISS
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;The problem:&lt;/strong&gt; when asking &lt;em&gt;"how many new customers were added from July 27th to 30th?"&lt;/em&gt;, the Gateway returned the &lt;code&gt;main_agent&lt;/code&gt; itself as the destination instead of delegating to the &lt;code&gt;customers_agent&lt;/code&gt; or the MCP tool. This created circular invocation loops &lt;code&gt;customers_agent -&amp;gt; main_agent -&amp;gt; customers_agent&lt;/code&gt;, which were rejected with an error.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The cause:&lt;/strong&gt; the &lt;code&gt;main_agent&lt;/code&gt;'s descriptions and examples contained broad domain keywords ("customers", "contacts", "tasks"), making its embedding vector overlap with the specialists' vectors in the Gateway's FAISS index. On top of that, the &lt;code&gt;customers_agent&lt;/code&gt; was sending generic search phrases that didn't indicate it was looking for MCP tools.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The fix:&lt;/strong&gt; I narrowed the &lt;code&gt;main-agent&lt;/code&gt;'s description down to purely conversational welcome tasks, and instructed the &lt;code&gt;customers-agent&lt;/code&gt;'s LLM to generate short search phrases explicitly oriented toward MCP tools (&lt;code&gt;"count_contacts CRM"&lt;/code&gt;). Architectural lesson: &lt;strong&gt;in semantic routing, agent descriptions are the routing contract&lt;/strong&gt; — if they overlap, the system gets confused; if they're precise, the system routes itself.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Empty &lt;code&gt;{}&lt;/code&gt; parameters caused by the Gateway omitting &lt;code&gt;input_schema&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;The problem:&lt;/strong&gt; the &lt;code&gt;count_contacts&lt;/code&gt; tool was receiving empty arguments &lt;code&gt;{}&lt;/code&gt; and returning the unfiltered total count; &lt;code&gt;save_contact&lt;/code&gt; failed with &lt;code&gt;ValueError: at least one field is required to create the contact&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The cause:&lt;/strong&gt; the Gateway's &lt;code&gt;/discover&lt;/code&gt; endpoint sometimes returned &lt;code&gt;"input_schema": {}&lt;/code&gt; instead of the registered JSON Schema. The agent's parameter-extraction LLM, upon receiving an empty schema, &lt;em&gt;correctly&lt;/em&gt; concluded the tool took no parameters.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The fix:&lt;/strong&gt; a fallback table &lt;code&gt;KNOWN_MCP_SCHEMAS&lt;/code&gt; in the agent. If the Gateway returns an empty schema for known tools, the agent dynamically injects the fallback JSON Schema, ensuring the LLM extracts &lt;code&gt;from&lt;/code&gt;, &lt;code&gt;to&lt;/code&gt;, &lt;code&gt;firstName&lt;/code&gt;, &lt;code&gt;phone&lt;/code&gt;, etc., in ISO format. The agent becomes resilient to an imperfect Gateway — &lt;em&gt;defense in depth&lt;/em&gt; applied to multi-agent systems.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. The Gateway's Pinger was deregistering live agents
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;The problem:&lt;/strong&gt; the logs periodically showed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[DISCOVERY] http://customers-agent:8311: Endpoint is dead/unreachable. Automatically unindexed from FAISS.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The agent was alive, but the Gateway kept delisting it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The root cause (my favorite of the week):&lt;/strong&gt; during synchronous LLM calls, Python blocked Uvicorn's event loop on the main thread. When the Gateway's Pinger sent &lt;code&gt;GET /tools&lt;/code&gt; every 3 seconds, the agent couldn't respond in time, and the Gateway assumed the container had died.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The fix:&lt;/strong&gt; make LLM invocations asynchronous:&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;await&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_thread&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;llm_router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;generate&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 event loop stays 100% free to answer health checks at 0ms in the background. A classic concurrency bug disguised as a network bug.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Hardcoded ports and URLs
&lt;/h3&gt;

&lt;p&gt;Agents were trying to register using stale fallbacks (&lt;code&gt;127.0.0.1:8003&lt;/code&gt;, port &lt;code&gt;8005&lt;/code&gt;) that conflicted with the Docker setup. The obvious but necessary fix: &lt;strong&gt;everything comes from the environment&lt;/strong&gt;. &lt;code&gt;CUSTOMERS_AGENT_PORT&lt;/code&gt;, &lt;code&gt;MAIN_AGENT_URL&lt;/code&gt;, &lt;code&gt;BFA_GATEWAY_URL&lt;/code&gt; — zero magic values in the code.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. &lt;code&gt;No module named 'llm_router'&lt;/code&gt; inside the containers
&lt;/h3&gt;

&lt;p&gt;When running the agent from its subdirectory, the project root wasn't on Python's &lt;code&gt;sys.path&lt;/code&gt;. A two-move fix: insert the root directory at the top of the script, and declare &lt;code&gt;PYTHONPATH=/app&lt;/code&gt; in &lt;code&gt;docker-compose.yml&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. MCP registration failing due to an incomplete path
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# ❌ This failed with "Failed to discover MCP tools":&lt;/span&gt;
curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="s2"&gt;"http://localhost:8000/register/mcp?url=http://host.docker.internal:8003/mcp"&lt;/span&gt;

&lt;span class="c"&gt;# ✅ This registered all 10 CRM tools in one shot:&lt;/span&gt;
curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="s2"&gt;"http://localhost:8000/register/mcp?url=http://host.docker.internal:8003&amp;amp;channels=%23deotroangulo"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Gateway expects the &lt;strong&gt;root base URL&lt;/strong&gt;, from which it dynamically discovers the endpoints. A small framework UX detail that's now documented and polished.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why I insist this is architecturally clean
&lt;/h2&gt;

&lt;p&gt;After this week, I can say it with more confidence than ever:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Total decoupling:&lt;/strong&gt; the &lt;code&gt;main-agent&lt;/code&gt; and the &lt;code&gt;customers-agent&lt;/code&gt; don't know each other. Tomorrow I could delete the &lt;code&gt;customers-agent&lt;/code&gt; and register a new one written in another language, and the system wouldn't even notice. That's real maintainability, not theoretical.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Discovery, not configuration:&lt;/strong&gt; capabilities register themselves and are discovered semantically via FAISS. No graphs to redraw, no edges to rewire when you add a node.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Security in the protocol:&lt;/strong&gt; the Gateway issues a token (DET) carrying the permitted action, the issuer, and the audience. Authorization travels with discovery.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Contained failures:&lt;/strong&gt; every bug from this week was fixed in &lt;em&gt;a single component&lt;/em&gt;. Not one fix required touching the other agents. That's the acid test of a clean architecture: changes stay local.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Efficiency by design:&lt;/strong&gt; 679 tokens for a full lookup + insert flow isn't an optimization trick — it's what falls out naturally when the LLM only does what only the LLM can do.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Migrating away from n8n wasn't just a tooling change: it was moving from a hand-drawn workflow to a network of agents that organize themselves. And best of all, the framework came out of the week stronger — because every difficulty found in a real project became a permanent SDK improvement.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Are you using n8n, LangGraph, or another orchestrator? How do you handle capability discovery between agents — and have you ever measured tokens per task? I'd love to hear about it in the comments.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>architecture</category>
      <category>agents</category>
    </item>
    <item>
      <title>IRC-A: Agents on the Wire — The Series Kicks Off 🚀</title>
      <dc:creator>Sandro Garcia</dc:creator>
      <pubDate>Tue, 04 Aug 2026 17:50:40 +0000</pubDate>
      <link>https://dev.to/irc-a/irc-a-agents-on-the-wire-the-series-kicks-off-8l3</link>
      <guid>https://dev.to/irc-a/irc-a-agents-on-the-wire-the-series-kicks-off-8l3</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt; I'm starting a series where I'll document, out in the open and unfiltered, everything I've been testing and researching around &lt;strong&gt;IRC-A (Internet Relay Chat for Agents)&lt;/strong&gt;: the protocol, the SDK, the framework, the experiments that work, and the ones that blow up along the way.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Why this series?
&lt;/h2&gt;

&lt;p&gt;For a while now, I've been hooked on an idea: &lt;strong&gt;what if AI agents had their own "IRC"?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Not a chat for humans, but a network where specialized agents register, announce their capabilities, discover each other, and collaborate to get tasks done — just like we used to do in the IRC channels of the 90s/2000s, but at machine scale.&lt;/p&gt;

&lt;p&gt;That idea became &lt;strong&gt;IRC-A (Internet Relay Chat for Agents)&lt;/strong&gt;, a protocol for decentralized agent networks with semantic capability routing and secure-by-design architecture. And alongside the protocol, the &lt;strong&gt;BFA SDK&lt;/strong&gt;, an open-source Python framework to actually implement it — not just on paper.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The problem&lt;/strong&gt;: all of that work is scattered across the repo, the whitepaper, my notes, and dozens of tests that never left the lab. &lt;strong&gt;This series is here to organize that chaos and share it.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  What will you find in this series?
&lt;/h2&gt;

&lt;p&gt;Everything related to IRC-A will live here, grouped into four content lines:&lt;/p&gt;

&lt;h3&gt;
  
  
  🧪 1. Tests &amp;amp; experiments
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Semantic routing benchmarks with FAISS (how well does it route without exact keywords?).&lt;/li&gt;
&lt;li&gt;Hot dynamic registration tests: agents joining and leaving the network on the fly.&lt;/li&gt;
&lt;li&gt;Embedding provider comparisons: local (&lt;code&gt;sentence-transformers&lt;/code&gt;) vs. cloud (OpenAI) vs. offline mock.&lt;/li&gt;
&lt;li&gt;Cold-starts on AWS Lambda with the Mangum adapter: is a serverless gateway actually viable?&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  🔬 2. Research
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;The IRC-A whitepaper, broken down: decentralized agent networks, &lt;em&gt;semantic capability routing&lt;/em&gt;, and &lt;em&gt;secure-by-design&lt;/em&gt; architecture.&lt;/li&gt;
&lt;li&gt;Cryptographic registration handshakes (asymmetric challenge-response).&lt;/li&gt;
&lt;li&gt;Logical channels and &lt;em&gt;channel masking&lt;/em&gt;: segregating vector search spaces per channel (&lt;code&gt;#public&lt;/code&gt;, &lt;code&gt;#banking&lt;/code&gt;, etc.).&lt;/li&gt;
&lt;li&gt;DET (Delegated Execution Tokens): direct P2P invocation with no gateway bottleneck.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  🛠️ 3. The SDK (BFA SDK)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;BFAAgent&lt;/code&gt;: building A2A agents with declarative semantic metadata.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;BFAMCP&lt;/code&gt;: exposing discoverable MCP tools with tags and examples.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;BFAInteractiveAgent&lt;/code&gt;: coordinator agents with execution memory and subtask delegation.&lt;/li&gt;
&lt;li&gt;Deployment with Docker, docker-compose, and the ready-to-use image on Docker Hub.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  🏗️ 4. The Framework &amp;amp; architecture
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;strong&gt;BFA (Backend for Agents)&lt;/strong&gt; pattern: the gateway as a semantic middleware between consumers and agents.&lt;/li&gt;
&lt;li&gt;The admin dashboard (React) to monitor the network in real time.&lt;/li&gt;
&lt;li&gt;Design decisions, mistakes made, and refactorings along the way.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Who is this series for?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;If you're into &lt;strong&gt;agent orchestration&lt;/strong&gt; beyond "one LLM with tools."&lt;/li&gt;
&lt;li&gt;If you work with &lt;strong&gt;A2A (Agent-to-Agent)&lt;/strong&gt;, &lt;strong&gt;MCP (Model Context Protocol)&lt;/strong&gt;, or multi-agent architectures.&lt;/li&gt;
&lt;li&gt;If you like seeing real, open-source code — with its wins and its failures documented.&lt;/li&gt;
&lt;li&gt;And if you ever missed the IRC philosophy — simple, open, federated — and wondered what it would look like applied to the agent era.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  The starting point
&lt;/h2&gt;

&lt;p&gt;Everything I'll be showing is published and open source:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;📦 &lt;strong&gt;SDK repo:&lt;/strong&gt; &lt;a href="https://github.com/SandroG1977/bfa-sdk" rel="noopener noreferrer"&gt;github.com/SandroG1977/bfa-sdk&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;📄 &lt;strong&gt;IRC-A Whitepaper v1.0.0:&lt;/strong&gt; &lt;em&gt;Decentralized Agent Networks, Semantic Capability Routing, and Secure-by-Design Software Architecture&lt;/em&gt; (link in the repo)&lt;/li&gt;
&lt;li&gt;🐳 &lt;strong&gt;Docker image:&lt;/strong&gt; &lt;code&gt;sandro77/irc-a-gateway:latest&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you want to start playing around before the next post:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;git+https://github.com/SandroG1977/bfa-sdk.git
irc-a-gateway
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  What's coming next
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;next article&lt;/strong&gt; is already in the pipeline: &lt;em&gt;"From n8n to IRC-A: a week building the framework while migrating a real project"&lt;/em&gt; — the story of migrating a real customer-service project off n8n, the 6 bugs it exposed (including circular routing loops and a Pinger deregistering live agents), and how each one made the SDK stronger. Real logs included.&lt;/p&gt;

&lt;p&gt;After that, the tentative roadmap (subject to whatever I discover along the way):&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;#&lt;/th&gt;
&lt;th&gt;Article (tentative)&lt;/th&gt;
&lt;th&gt;Track&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;02&lt;/td&gt;
&lt;td&gt;From n8n to IRC-A: a week building the framework while migrating a real project&lt;/td&gt;
&lt;td&gt;🏗️ Framework&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;03&lt;/td&gt;
&lt;td&gt;Your first IRC-A network in 5 minutes: Gateway + A2A Agent + MCP Server&lt;/td&gt;
&lt;td&gt;🛠️ SDK&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;04&lt;/td&gt;
&lt;td&gt;Semantic routing with FAISS: how the gateway "understands" queries&lt;/td&gt;
&lt;td&gt;🔬 Research&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;05&lt;/td&gt;
&lt;td&gt;The handshake: secure agent registration on the network&lt;/td&gt;
&lt;td&gt;🏗️ Framework&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;06&lt;/td&gt;
&lt;td&gt;Benchmarks: local vs. cloud vs. mock embeddings&lt;/td&gt;
&lt;td&gt;🧪 Tests&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;07&lt;/td&gt;
&lt;td&gt;DET tokens and decentralized P2P invocation&lt;/td&gt;
&lt;td&gt;🔬 Research&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Join the network 📡
&lt;/h2&gt;

&lt;p&gt;This is just getting started, and feedback is gold: if you're building something with agents, if you see flaws in the approach, or if you just want to debate multi-agent architecture, the comments are open.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Follow the series&lt;/strong&gt; so you don't miss the next posts, and if you're into the project, a ⭐ on the repo always helps.&lt;/p&gt;

&lt;p&gt;See you on the channel. o/&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Credits: the &lt;a href="https://medium.com/@mdbaraujo/o-padr%C3%A3o-back-end-para-agentes-bfa-a53c1c6d87fb" rel="noopener noreferrer"&gt;BFA pattern&lt;/a&gt; was originally designed and documented by Michael Douglas Barbosa Araujo. The BFA SDK is a community implementation and expansion of that concept.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
      <category>opensource</category>
      <category>irca</category>
    </item>
  </channel>
</rss>
