{"slug": "your-ai-agent-has-no-colleagues", "title": "Your AI Agent Has No Colleagues", "summary": "A developer argues that AI agents fail at tool-call retries because error messages like \"422 validation_error\" carry no signal about whether a retry is worthwhile, leaving models to guess based on the retry-heavy code they were trained on. The post proposes a three-part failure trace — a normalized stable identity for each failure, a recorded outcome rather than an intention, and a denominator of total calls — so agents can learn which failures are transient and which require a schema fix. It also warns that intermittent retry success acts as a variable-ratio reinforcement schedule, making the behavior hard to extinguish.", "body_md": "\"The coordination of the builders is not direct. It is the work already done\n\nthat directs and triggers the work that follows.\"\n\n— Pierre-Paul Grassé, describing termites, 1959\n\nYou have seen this. Every agent framework does it :)\n\n```\n> create_issue\n  x 422 validation_error\n\n> create_issue        (retry)\n  x 422 validation_error\n\n> create_issue        (retry, arguments tweaked slightly)\n  x 422 validation_error\n```\n\nThree attempts. Three identical failures. Then it apologises to you, which\n\nsomehow makes it worse.\n\nThe instinct is to blame the model. But look at what it had to work with:\n\n```\n422 validation_error\n```\n\nTell me, from that string, whether retrying is worth it.\n\nIs it a field renamed in last week's release, or a service having a bad ten\n\nminutes? Same six characters either way. In one case retrying is exactly right\n\nand works in thirty seconds. In the other you can retry until your budget is\n\ngone, and the real answer was \"the field is called `content` now, refresh your\n\ntool schema.\"\n\nThe model has to guess. It guesses retry, because that is what nearly all the\n\ncode it ever read does.\n\nThe first instinct, once you notice this, is to write a rule.\n\n```\nWhen a tool call fails, do not retry immediately.\nConsider whether the failure is transient before trying again.\n```\n\nIt sounds reasonable. It does approximately nothing, for a boring reason:\n\n**the instruction does not contain the missing information either.**\n\nYou have told the agent to consider whether the failure is transient. It still\n\nhas no way to find out. You have asked it to make the same guess, more\n\nthoughtfully. On a hard task, under context pressure, it will guess retry\n\nagain — and it will be right often enough that the behaviour never extinguishes.\n\nThat last part is the trap. A retry that works occasionally, at unpredictable\n\nintervals, is a **variable-ratio reinforcement schedule** — the same mechanism\n\nthat makes slot machines difficult to walk away from. It is the schedule\n\npsychologists reach for when they want a behaviour to be maximally resistant to\n\nextinction. Your agent is on it. So are you, at 1am, hammering the same test.\n\nThe temptation is to log the error and call it a trail. That does not work,\n\nbecause an error message is not a signal about what to *do*.\n\nA useful trace needs three parts:\n\n```\n┌──────────────────────────────────────────────────────────────────┐\n│  THE ANATOMY OF A USEFUL FAILURE TRACE                           │\n├──────────────────────────────────────────────────────────────────┤\n│  1. AN IDENTITY                                                  │\n│     A stable id for \"this exact failure\", so two agents can      │\n│     tell they hit the same thing. Not the raw string: that one   │\n│     contains a request id and a timestamp and will never match   │\n│     anything again.                                              │\n├──────────────────────────────────────────────────────────────────┤\n│  2. AN OUTCOME, NOT AN INTENTION                                 │\n│     What the next agent tried, and whether it worked. \"I         │\n│     refreshed the schema\" is worthless. \"I refreshed the schema  │\n│     and the call then succeeded\" is the whole point.             │\n├──────────────────────────────────────────────────────────────────┤\n│  3. A DENOMINATOR                                                │\n│     Successes too, or the failure rate is meaningless. 100       │\n│     failures out of 200 calls is an outage. 100 out of a         │\n│     million is a Tuesday.                                        │\n└──────────────────────────────────────────────────────────────────┘\n```\n\nPart 1 is fiddly and worth spelling out. These two are the same bug:\n\n```\nRepository 8823 rejected field body at 2026-09-11T14:02:11Z\nRepository 41902 rejected field body at 2026-09-12T09:41:55Z\n```\n\nCompare them raw and you have two unrelated incidents forever. So you normalise\n\nfirst — replace the parts that vary, keep the parts that mean something — and\n\nhash what is left together with the service and operation:\n\n```\ntext = URL_RE.sub(\"<URL>\", text)\ntext = UUID_RE.sub(\"<UUID>\", text)\ntext = TIMESTAMP_RE.sub(\"<TS>\", text)\ntext = LONG_NUMBER_RE.sub(\"<N>\", text)\n```\n\nBoth lines collapse to one shape. Now they are one thing you can count. It is\n\nalso a good place to strip anything credential-shaped, since you are already\n\nwalking the string with regexes and you very much do not want tokens in a\n\nshared log.\n\nAnd once you are counting, resist the urge to have a model score the result.\n\nCount it. If an action was tried 5 times and worked 5 times, that is 5/5 — but\n\nso is 117/124, and those are not equally trustworthy. A Wilson score lower\n\nbound folds sample size in for you: 5/5 scores about **0.57**, 117/124 scores\n\nabout **0.89**. Ten floating point operations, no dependencies, and you can\n\nrecompute it by hand when somebody asks where the number came from.\n\nWhen there is not enough evidence, return that. Not a guess with a low\n\nconfidence bolted on — an actual \"I don't know\". Agents handle it fine.\n\nHere is the thing I keep coming back to, and cannot settle by thinking harder:\n\n**Do different people's agent failures actually overlap? 🤔**\n\nThe theory says they should. We are all calling the same twenty MCP servers and\n\nthe same dozen public APIs, and when GitHub renames a field it renames it for\n\neveryone at once. Your 422 on Tuesday and my 422 on Thursday are plausibly the\n\nsame 422.\n\nBut \"obviously true\" is where most wrong ideas live. It is equally plausible\n\nthat the interesting failures are all local — your auth setup, my rate limit,\n\ntheir internal service — and that the shared surface is too thin for any of\n\nthis to matter. A pheromone trail nobody else walks is just a smell.\n\nI do not know which world we are in. It is decidedly testable, and I do not\n\nthink anyone has tested it.\n\nI am collecting answers to the middle one in particular. If enough people\n\ndescribe failures that turn out to be the same failure, that settles it.", "url": "https://wpnews.pro/news/your-ai-agent-has-no-colleagues", "canonical_source": "https://dev.to/fuyuki0/your-ai-agent-has-no-colleagues-514b", "published_at": "2026-09-13 20:51:42+00:00", "updated_at": "2026-09-13 21:21:47.417108+00:00", "lang": "en", "topics": ["ai-agents", "ai-tools", "developer-tools", "large-language-models"], "entities": ["Pierre-Paul Grassé"], "alternates": {"html": "https://wpnews.pro/news/your-ai-agent-has-no-colleagues", "markdown": "https://wpnews.pro/news/your-ai-agent-has-no-colleagues.md", "text": "https://wpnews.pro/news/your-ai-agent-has-no-colleagues.txt", "jsonld": "https://wpnews.pro/news/your-ai-agent-has-no-colleagues.jsonld"}}