{"slug": "irc-a-in-production-part-2-a-46-minute-agent-an-ai-assistant-that-broke-the-and", "title": "IRC-A in production, part 2: a 46-minute agent, an AI assistant that broke the rules — and a $0.04 bill", "summary": "A developer's decentralized multi-agent protocol, IRC-A, successfully handled a live production query about July sales, returning real data from a real database within 46 minutes of adding a new sales-reports agent. The experiment also revealed that an AI coding assistant's unauthorized modifications to an agent were cryptographically rejected, serving as an involuntary penetration test that validated the system's security invariants.", "body_md": "**It's 1:53 AM and I'm asking my CRM's chatbot: \"what's the total amount we have parked in the Proposal stage?\" Three seconds later it answers: $3,134.90. I follow up with just \"and in prospecting?\" — no context — and it breaks down the 10 open opportunities with amounts, close probability and estimated dates. A week earlier, this system was an n8n flow that only knew how to count contacts.**\n\nThis is the second part of the series about running [IRC-A](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) — my decentralized multi-agent protocol — in production. In part 1 I covered the week-long migration from n8n and the absurd 679-token bill. This time: a stopwatch experiment, the night the protocol defended itself from AI-written code, and a confession about one of the fixes I proudly showed you last time.\n\nThe trigger was a failure. I asked the system \"how much did we sell in July?\" — and the Gateway routed it to the *customers* agent, because semantically it was the closest thing registered. There was simply no sales domain in the network. (That false positive is why we're adding a configurable similarity threshold to `/discover`\n\n.)\n\nBut instead of patching it, I saw the perfect experiment: **create a sales-reports specialist agent and plug it into the live system — with a stopwatch running.**\n\nThe results:\n\n`curl`\n\nfrom part 1.`.env`\n\nfile, an MCP refactoring that had silently broken the FastMCP instance-to-handler binding, and a regression of the classic \"synchronous LLM call blocking Uvicorn's event loop\" bug from part 1 (yes, the Pinger started deregistering the main agent again — same bug, twice; that's why the fix is moving into the SDK's base class, where it belongs).The moment of truth came at 11:19 PM: *\"how much did we sell in July?\"* → **\"$3,259.70\"**. Real data, from the real database, semantically routed through a network that didn't know that domain existed an hour earlier.\n\nThe hidden value of the experiment wasn't the 46 minutes — it's that adding a node is such a clean operation that **every weakness in the surrounding components becomes visible**. Extending the system is now the best integration test I have.\n\nHere's the part I didn't expect to write. At some point, an AI coding assistant (Antigravity) modified one of the agents. Its change did two things the design explicitly forbids:\n\n**1. The agent tried to build the call with its own parameters** instead of the ones the Gateway had signed into the DET. Result: rejected. The parameter lockdown isn't a convention — it's cryptographically enforced. If the authorized data doesn't match, the call doesn't execute.\n\n**2. When that failed, the agent improvised an alternative endpoint** instead of using the URL the Gateway had returned. Here's the real, unedited log:\n\n```\n=== [INVOCACIÓN P2P AL MCP TOOL SERVER: guardar_contacto] ===\n🔹 Endpoint: http://host.docker.internal:8003/tools\n🔹 Payload: {\"tool\": \"guardar_contacto\", \"arguments\": {}, \"delegated_token\": \"v4.public.eyJ...\"}\n🔹 HTTP Status: 500 → \"Se requiere al menos un campo para crear el contacto\"\n=== fallback call ===\n🔹 Endpoint: http://host.docker.internal:8003/mcp\n🔹 Payload: {\"jsonrpc\":\"2.0\",\"method\":\"tools/call\",\"params\":{\"name\":\"guardar_contacto\",\"arguments\":{}},\"id\":1}\n🔹 HTTP Status: 404 → {\"error\":{\"code\":-32600,\"message\":\"Session not found\"}}\n```\n\nRead it closely: one external change violated **three invariants at once** — the route is the Gateway's authority, the DET is bound to its destination, and execution is stateless (the improvised `/mcp`\n\nendpoint demanded an SSE session, which P2P calls don't have). And still, **the system degraded safely**: two informative rejections, zero unauthorized executions, zero data corruption.\n\nAnd here's the scientific bonus: these incidents worked as an **involuntary penetration test**. The whitepaper *claimed* the DET makes it impossible to alter authorized data; the badly-written code *proved* it empirically. I reverted the change, the retest passed — and the invariant is now backed by evidence, not faith.\n\nMy takeaway: as more and more code is written by AI assistants that don't know your architecture, the controls can't live in documentation. They have to live in the inheritance of your SDK's base classes. *Secure by default* stops being a best practice and becomes a survival requirement.\n\nRemember problem #2 from the previous article? The Gateway intermittently returned an empty `input_schema`\n\n, and I \"fixed\" it with a `KNOWN_MCP_SCHEMAS`\n\nfallback table hardcoded in the agent. I called it *defense in depth*.\n\nIt worked. And I've since torn it out, because it was **coupling in disguise**. An agent that needs to know tool schemas in advance isn't *discovering* capabilities — it has the network hardcoded, and every new tool would require touching every agent. The marginal cost of extending the system would stop being marginal.\n\nThe correct solution wasn't patching the agent — it was *returning to the pattern*. IRC-A already defines it: **the BFA returns the URL with the complete parameters plus the signed DET, so authorized data can't be changed.** The calling agent doesn't care about parameters at all; it transports intent and token. The extraction living in the agent was an implementation drift, not a protocol gap. Once again, the fix didn't require touching the protocol — it required going back to it.\n\nConsolidated lesson: **the agent must not know anything the Gateway already knows.** Every redundancy of knowledge is coupling disguised as robustness.\n\nWith LangSmith wired in, that 2 AM validation session left hard figures (cumulative across *all* project testing, not just that night):\n\n| Metric | Value |\n|---|---|\n| Executions | 333 runs, 0% errors |\n| Latency per LLM call |\n1.04s avg (p99 ≈ 2.9s) |\n| Total tokens | 79,263 |\n| Total cost | $0.04 |\n| Most expensive single call | 5,462 tokens / 3.93s / $0.0025 (a full pipeline status report) |\n\nIn part 1 I bragged about a 679-token flow. This time, **the entire testing history of the project costs four cents.** A multi-agent network with vector-based semantic discovery and cryptographic signing per delegation costs between $0.0001 and $0.0025 per user query. The routing and security overhead is negligible next to the LLM cost. The paradigm's economic viability is no longer an assumption.\n\nAnd the system that night wasn't just cheap — it was *conversational*: multi-turn context (\"and in prospecting?\" resolved from the previous turn), two specialists coexisting in one session, and a 101-opportunity pipeline summarized by stage on request. All in Spanish, against a CRM whose enums are in English (we found out \"prospección\" doesn't match `Prospecting`\n\n— a few-shot prompt problem, not an architecture one; it's on the list).\n\nThe case-study logbook now holds **12 documented incidents. Zero attributable to the protocol.** In the two most severe ones, the protocol defended itself. The system went — in one migration week plus one afternoon of experimentation — from \"an agent that counts contacts\" to answering conversational business statistics at 2 AM, with a third specialist added in 46 minutes and zero changes to what was already running.\n\nStill on the list: the configurable similarity threshold in `/discover`\n\n, native framework telemetry (so I don't depend on an external platform), few-shots for CRM vocabulary, async-by-default enforced in the base classes, and fixing the root `input_schema`\n\nserialization bug in the Gateway. Every item traces back to a documented incident — which is exactly how a framework should grow.\n\n*How are you handling authorization between agents in your multi-agent setups — and has AI-generated code ever violated your architecture's invariants? Did your system notice? I'd love to hear about it in the comments.*", "url": "https://wpnews.pro/news/irc-a-in-production-part-2-a-46-minute-agent-an-ai-assistant-that-broke-the-and", "canonical_source": "https://dev.to/irc-a/irc-a-in-production-part-2-a-46-minute-agent-an-ai-assistant-that-broke-the-rules-and-a-004-2nm", "published_at": "2026-08-14 20:40:15+00:00", "updated_at": "2026-08-14 21:05:14.830150+00:00", "lang": "en", "topics": ["ai-agents", "ai-infrastructure", "ai-safety", "ai-research", "developer-tools"], "entities": ["IRC-A", "Antigravity", "n8n", "FastMCP", "Uvicorn"], "alternates": {"html": "https://wpnews.pro/news/irc-a-in-production-part-2-a-46-minute-agent-an-ai-assistant-that-broke-the-and", "markdown": "https://wpnews.pro/news/irc-a-in-production-part-2-a-46-minute-agent-an-ai-assistant-that-broke-the-and.md", "text": "https://wpnews.pro/news/irc-a-in-production-part-2-a-46-minute-agent-an-ai-assistant-that-broke-the-and.txt", "jsonld": "https://wpnews.pro/news/irc-a-in-production-part-2-a-46-minute-agent-an-ai-assistant-that-broke-the-and.jsonld"}}