Build1 distinct publisher3 min readUpdated
A developer's LLM issued the same refund three times after a timeout. The defect was in the wiring, not the model, and the fixes are schema validation and scoped toolsets.
The Engineer · Build desk

Compiled by The EngineerSomething wrong?How this is made
A developer writing on dev.to handed a language model access to a real API, demoed it to a nodding room, and two weeks later watched the same setup try to issue the same refund three times in a row because a timeout made it think the first attempt had failed [1][2]. That is the case for treating tool calling as a systems problem: the moment you pass a function schema, the model stops being a text generator and becomes an actor inside your system [4].
The author is blunt that the model was not the defect. Nothing was wrong with the model; everything was wrong with how he had wired it up [3]. The triple refund is a retry story. Most agent frameworks and most hand-rolled loops have retry logic somewhere, and a thrown exception looks like transient infrastructure failure, so something retries it: the framework, the queue, or your own catch block [17]. He says the incident cost him real money [18].
Worth being clear about the limits of the source: the published text stops mid-sentence as it starts walking through a payment API timing out, so it never states the remedy [20]. What survives is the shape of the problem. Any deduplication has to sit on the same side of the boundary as the payment call, because the retry can originate from three different layers, none of which knows the first request landed [17].
The parts the piece does finish are about narrowing what the model can reach. A function call is text that looks like JSON, parsed by your SDK into an object, and that object has the epistemic status of user input from a public form [5]. The failure mode is arguments that are almost right: a string where a number belongs, an ISO date in the wrong timezone, an enum synonym such as "cancelled" when your API says "canceled", a negative quantity, an ID copied from the wrong part of the conversation [6]. His rule is schema-first, validated at runtime, with one schema deriving both the tool definition sent to the model and the validator that guards execution [7]. Business limits go in the schema, not the prompt: his example caps amountCents at 50,000, which makes a single refund structurally incapable of exceeding 500 dollars [8][9][19]. Prompts are suggestions; validators are laws [9].
The second half is capability scoping, which is the cheaper control. Read and write tools are different risk classes, and a conversation that only answers questions gets only read tools, because a model cannot misuse a tool it was never given [12]. Account identifiers are injected server-side; if the model can pass a customerId, it can pass the wrong one [13]. The refund tool enters the toolset only after an order has been located and verified, which shrinks the blast radius of every earlier turn [14]. He argues this also improves accuracy, since tool selection is a decision the model can get wrong and every irrelevant tool is another chance to get it wrong [15].
Watch whether your agent framework retries tool executions by default, and at which layer. Then check whether your write endpoints can tell a repeat call from a new one.
Follow any of these and your For You feed starts watching them — no settings page required.
Ranked by verification strength, evidence, and original report placement.
The author of the dev.to article "Letting an LLM call your APIs without losing sleep" says the first time he gave a language model access to a real API it worked perfectly in a demo: it looked up an order, summarized the status, and everyone in the meeting nodded.
Two weeks later, in production, the same setup tried to issue the same refund three times in a row because a timeout made it think the first attempt had failed.
When a model "calls a function" it emits text that looks like JSON; the SDK parses it and hands you an object, and that object has the epistemic status of user input from a public form.
Models constantly produce arguments that are almost right: a string where a number was expected, an ISO date with the wrong timezone, an enum value that is a plausible synonym of a real one ("cancelled" when the API says "canceled"), a negative quantity, or an ID copied from the wrong part of the conversation.
The supplied text of the article ends mid-sentence while beginning to walk through what happens when a payment API times out, and so does not state the remedy for the duplicate-refund failure.
The author argues business rules belong in the schema: the model should be structurally incapable of requesting a $40,000 refund rather than merely discouraged by the prompt, because "Prompts are suggestions; validators are laws."
Evidence-backed comparisons of source perspectives and observed adoption signals. Read the methodology
Which Builder, Operator, and Investor concerns the observed source mix emphasized—not a truth score.
Evidence, demonstrated adoption, hype gap, incentives, and confidence are assessed independently, each on its own current evidence. How these are measured.
Single-source practitioner account with concrete code but no verification
The mechanisms are stated precisely and are inspectable as code (zod schema plus derived JSON Schema, ToolResult union with retryable:false, idempotency keys), which raises the floor above pure opinion. But everything rests on one dev.to post by one author: the production incident is undated and unquantified, no model, SDK, provider, or framework is named, the 'most agent frameworks retry' generalization is unsupported, and the accuracy benefit of smaller toolsets is asserted without any measurement. There is no second publisher, no benchmark, and no third-party confirmation anywhere in the cluster.
No adoption signal beyond one undated self-report
The only observation in the cluster is the author's own disclosure that he ran such an integration in production and was bitten by it. There are no release notes, version numbers, download or usage figures, deployment counts, third-party case studies, or framework defaults documented in the supplied source, so no adoption level for these patterns or for LLM tool calling against write APIs can be measured without inventing facts.
Mostly restrained, with one unmeasured accuracy claim
The piece deliberately deflates model-centric framing by locating the defect in the wiring, and its remedies are conventional API engineering: validate input, least privilege, idempotency keys. That is close to aligned. The modest positive reading comes from rhetoric outrunning measurement in two places: 'fewer tools also make the model smarter' is called 'one of the few free lunches in this field' with no evidence, and the retry problem is generalized to 'most agent frameworks' without naming one. The headline framing of tool calls as a systems problem is supported by the source's own reasoning rather than overstated.
Low commercial pressure; practitioner reputation on a developer platform
Within the supplied text there is no product, service, pricing, funding, sponsorship, or vendor being promoted; the named dependencies (zod, zod-to-json-schema, node:crypto) are third-party or standard-library and are not positioned for sale. The observable incentive is the ordinary one for a self-published developer post: demonstrating competence to an audience via a war story, which favors a memorable anecdote and confident maxims like 'Prompts are suggestions; validators are laws' over caveats and measurement. The author's employer or affiliation is not disclosed, so any stronger commercial interest cannot be assessed.
Moderate: claims are clearly stated but singly sourced and partly truncated
Confidence in what the article says is high because the text is explicit and the code is unambiguous. Confidence in the world-claims is only moderate: one publisher, one author, an unverifiable production incident, unnamed stacks, no adoption or benchmark data, and a body that ends mid-signature inside the idempotencyKey helper. The engineering substance is well-established enough elsewhere that the prescriptions are plausible, but this cluster alone cannot establish prevalence or effect size.
build
The only gate that ran was a hand-typed enum, and it had never heard of the new value1 distinct publisher
build
Thirty MCP tools become three: the reliability bug is in your schema, not the model1 distinct publisher
build
Allow-list the closed set, block-list the open one: 193 thin geo pages, one gate1 distinct publisher
build
A GAN beauty filter is a device budget allocation, not a feature toggle1 distinct publisher
Distinct publishers with included, body-backed reporting in this cluster.
dev.to
1 article · August 16, 2026