Contents

  1. Error messages are 2026's hidden API UI
  2. KanseiLink data — where agents actually get stuck
  3. The six anti-patterns
  4. The fix: an LLM-friendly error envelope
  5. Implementation example — Before/After
  6. Provider-side checklist
  7. FAQ

Error messages are 2026's hidden API UI

Until 2025, API error messages were "for human developers." Stuck? Ask in Slack, open the docs, search Stack Overflow — there were always escape hatches.

2026 inverted this. The primary consumer of an API is no longer a human; it's an AI agent, and an agent can't Google the problem or ping a coworker. The error response is its only signal for how to recover.

One widely cited industry write-up describes a team whose agent perpetually retried a 422 response that arrived with no body. Adding the explicit message "missing required field 'first_name'" let the agent self-correct on the next try. Error messages are the hidden UI of an agent-era API — and they deserve UX investment.

The agent-era rule

"A vague error is, to an agent, an absent error." An API that returns nothing more than 400 Bad Request looks to the agent like an opaque wall. Zero-information errors are functionally identical to a downed service.

KanseiLink data — where agents actually get stuck

The KanseiLink MCP collects live agent-behaviour reports. Slicing the error-related fields shows a clear pattern.

freee MCP — measured (April 2026, 212 reports)

15
api_error
(top error)
4
auth_expired
(2nd)
90%
overall success rate
216ms
avg latency

What stands out is that 'api_error' has no breakdown. An implementation that lumps 429, 422, 404, and 500 into one bucket leaves the agent unable to tell whose problem it is or whether retrying is worthwhile. Meanwhile, auth_expired has a verified, reproducible workaround on file ("Refresh the OAuth token; lifetime is 24h"), so agents can self-recover next time.

That contrast is the core message of this piece: error granularity and an explicit fix determine success rates.

The six anti-patterns

From KanseiLink data and industry reporting, six error-message patterns reliably make agents give up.

❌ #1: 4xx with no body

"422 Unprocessable Entity" with an empty body — or worse, {"error": "validation failed"}. The agent can't tell which field failed or why, so it retries the same request indefinitely, burning tokens. The widely cited fix — adding "missing required field 'first_name'" — shows that simply naming the field is the minimum bar.

❌ #2: Error codes too coarse to act on

Generic codes like {"error": "api_error"} or {"code": "ERR_001"} that can't be machine-routed. KanseiLink's 15 freee api_error events are exactly this: the breakdown isn't visible, so neither agents nor operators know where to start. An error code should uniquely determine what the agent does next; stable, verb-noun strings like amount_must_be_positive or quota_exceeded_for_period work; opaque IDs do not.

❌ #3: No retryable hint

Agents perpetually retrying a 422 disappear with one new field: retryable: false. Conversely, 429 / 503 should ship retryable: true with retry_after_seconds. That single boolean cuts wasted token spend dramatically, by industry accounts. The cost-to-benefit ratio is one of the best available — make this change first.

❌ #4: Stack traces and internals leaking

Returning NullPointerException at com.example.UserService.findById:142 verbatim. Beyond the security risk, agents get distracted by irrelevant internal state and miss the actual issue. There are documented cases of implementation-side JavaScript errors like "Cannot read property 'id' of undefined" surfacing all the way to end users via agent transcripts.

❌ #5: Mixed languages and inconsistent style

Field names in English ("validation_error") but messages in mixed Japanese — and tone shifts between polite and imperative across endpoints. Agents understand the languages, but if "machine-readable" and "human/LLM-readable" parts aren't separated, switch-case logic breaks. The hybrid pattern: error.code and error.field in stable English; error.message and error.user_message localised.

❌ #6: Inconsistent envelope across endpoints

Auth errors as {"err": "..."}, validation errors as {"errors": [{"msg": "..."}]}, server errors as raw HTML — all in the same API. Agents can't ship one shared error parser across all tools; they need a per-endpoint adapter. For MCP servers wrapping legacy upstream APIs, the 2026 best practice is to normalise to a single envelope at the MCP boundary — that's a signature MCP win.

The fix: an LLM-friendly error envelope

An envelope shape that absorbs all six anti-patterns. Field names follow industry convention (Stripe, GitHub, Anthropic SDK), extended for the agent use case.

{
  "error": {
    "code": "amount_must_be_positive",          // stable, machine-readable
    "message": "The 'amount' field must be a positive integer. Received: -100.",
    "field": "amount",                          // which input failed
    "retryable": false,                         // can a retry succeed?
    "suggested_fix": "Pass an integer >= 1 (in JPY).",
    "doc_url": "https://api.example.com/docs/errors#amount_must_be_positive",
    "request_id": "req_01HQ8K3...",
    "user_message": "Please enter a positive integer for the amount."  // optional
  }
}

Specific categories benefit from extra fields.

Category Add these fields Why
auth_expired refresh_url, token_lifetime_seconds Lets the agent jump straight into a refresh flow
rate_limited retry_after_seconds, scope (global/tool) Drives backoff and tells the agent the blast radius
not_found resource_type, searched_id Stops the agent re-searching for an ID that won't exist
conflict conflicting_resource_id, resolution_hint Lets the agent handle duplicates without round-tripping the user

Implementation example — Before/After

Before (the agent gets stuck)

HTTP/1.1 422 Unprocessable Entity
Content-Type: application/json

{
  "error": "validation failed"
}

Agent behaviour: "Something failed but I don't know what." → resends the same request → same error → after a few round trips, gives up and tells the user "it failed." Ten or twenty wasted retries before the user even hears back.

After (the agent recovers)

HTTP/1.1 422 Unprocessable Entity
Content-Type: application/json

{
  "error": {
    "code": "missing_required_field",
    "message": "Required field 'client_email' is missing in the request body.",
    "field": "client_email",
    "retryable": false,
    "suggested_fix": "Add 'client_email' as a string (RFC 5322 email format) to the request body.",
    "doc_url": "https://api.example.com/docs/invoices#create",
    "request_id": "req_01HQ8K3..."
  }
}

Agent behaviour: parses "client_email is missing" instantly → extracts (or asks for) the email → succeeds on the first retry. Latency and token spend drop by an order of magnitude.

✅ The design principle

An error is incomplete unless it answers both "what went wrong" and "what should I do next." The four-field minimum is code (machine-routable), field (target), retryable (can a retry help), and suggested_fix (one short remediation hint).

Provider-side checklist

Ten checks for whether your API or MCP server is "agent-friendly."

See your API's errors through an agent's eyes

KanseiLink aggregates real agent behaviour across 225+ services — error patterns, success rates, and known fixes. Get a measurement of whether your SaaS clears the agent-era error-design bar.

Audit your API's error quality

FAQ

Q1. Why do error messages matter so much for agent-era APIs?

The primary consumer is now an agent, not a human. Agents can't Google or ask a coworker — the error response is the only recovery signal. Vague errors trigger pointless retry loops, burn tokens, and erode UX.

Q2. What's the most common error in KanseiLink data?

For freee MCP (212 reports): 15 'api_error' (no breakdown — agents can't act), 4 'auth_expired' (with a verified workaround — agents self-recover). The contrast is the textbook lesson.

Q3. Why does adding 'retryable' save tokens?

Agents default to retrying on failure and burn tokens forever on 422-class errors. retryable: false lets them switch immediately to higher-level recovery. Industry reports describe a visible drop in token spend within a week of introduction.

Q4. Do localised error messages work for agents?

Comprehension is fine; machine routing isn't. Recommended hybrid: error.code and error.field in stable English; error.message and error.user_message localised. Separate switch-cased fields from spoken-aloud fields.

Q5. What's the minimum bar for an MCP server's error responses?

Five fields: error.code (stable string), error.message (LLM-readable, 1–2 sentences), error.field, error.retryable (boolean), error.suggested_fix. Small implementation cost, high success-rate impact.

Q6. Does this apply to MCP servers wrapping legacy upstream APIs?

Yes — and it's a signature MCP win. Even if the upstream returns inconsistent shapes, normalise everything to a single envelope at the MCP boundary so agents see one clean error vocabulary across tools.

Disclosures and notes

The freee MCP figures ("212 reports, 15 api_error, 4 auth_expired") come from KanseiLink MCP's get_insights tool as of 2026-04-13; confidence_score is 0.61 (medium), and the distribution may shift as samples grow. The "perpetual 422 retry" and "missing first_name fix" examples come from publicly available industry write-ups including DEV.to ("Your API Wasn't Designed for AI Agents. Here Are 5 Fixes.") and Medium ("Handling HTTP Errors in AI Agents: Lessons from the Field"). The recommended envelope structure is a synthesis of Stripe, GitHub, and Anthropic SDK conventions extended for agent use cases — it is not a formal standard. Pricing and specifications may change without notice; please check the latest official documentation before relying on these figures in production.