{
  "slug": "retries-and-idempotency-for-ai-agents",
  "title": "How to Make AI Agent Retries Idempotent",
  "description": "A deep-dive on retrying agent tool calls safely: the transient-vs-terminal decision, why an agent side effect can fire before a failure signal reaches the caller, idempotency-key mechanics (run ID + step index), the unknown-outcome edge case, and where idempotency keys do not reach.",
  "kind": "sub",
  "order": 3,
  "target_query": "how to make AI agent retries idempotent",
  "secondary_queries": [
    "idempotency key run ID step index",
    "agent tool call timeout unknown outcome",
    "transient vs terminal error retry",
    "exponential backoff full jitter agents",
    "idempotency key not supported by API"
  ],
  "tags": [
    "agents",
    "reliability",
    "retries",
    "idempotency",
    "rate-limits",
    "production"
  ],
  "published": "2026-08-27",
  "updated": "2026-08-27",
  "words": 1764,
  "estimated_tokens": 2346,
  "premium": false,
  "rights": {
    "access": "free",
    "note": "Editorial guides are always free and never part of the licensed corpus.",
    "license": "https://changegamer.ai/license.xml",
    "pricing": "https://changegamer.ai/api/pricing.json",
    "payment": "https://changegamer.ai/api/payment.json"
  },
  "license": "https://changegamer.ai/license.xml",
  "citation": "ChangeGamer (2026-08-27). How to Make AI Agent Retries Idempotent. ChangeGamer. https://changegamer.ai/articles/retries-and-idempotency-for-ai-agents (updated 2026-08-27).",
  "bibtex": "@misc{changegamer_retries_and_idempotency_for_ai_agents, title = {How to Make AI Agent Retries Idempotent}, publisher = {ChangeGamer}, year = {2026}, url = {https://changegamer.ai/articles/retries-and-idempotency-for-ai-agents}, note = {Updated 2026-08-27}}",
  "canonical": "https://changegamer.ai/articles/retries-and-idempotency-for-ai-agents",
  "markdown": "https://changegamer.ai/articles/retries-and-idempotency-for-ai-agents.md",
  "takeaways": [
    "Exponential backoff with full jitter is the standard retry pattern for agent tool calls — it randomizes the wait between zero and an exponentially growing cap while always treating a provider's Retry-After header as a hard floor, as documented in the handling-rate-limits-and-retries reference as of July 2026.",
    "An agent tool call can trigger a real side effect — a payment, an email, a database write — before a timeout or a dropped connection ever reaches the calling code, which makes \"no response received\" a fundamentally different outcome from \"the call failed cleanly.\"",
    "A safe idempotency key for an agent step combines the workflow run's own identity with that step's position inside the run — never a clock reading or a freshly minted UUID, since either one looks different on every attempt and so cannot tell a downstream service \"this is the same request as before.\"",
    "Retrying the same step after a crash or a dropped connection must reuse that step's original idempotency key so the duplicate attempt collapses into a no-op, while a genuinely new run of the same workflow needs a fresh run identity and therefore a fresh key.",
    "Idempotency-key support is not a guarantee of the HTTP or REST tradition — it is a feature an individual API chooses to implement or not — so an agent cannot assume a downstream service has one and needs an application-level dedupe record ready as a fallback."
  ],
  "outline": [
    {
      "depth": 2,
      "text": "How should an agent retry a failed tool call?",
      "anchor": "how-should-an-agent-retry-a-failed-tool-call",
      "url": "https://changegamer.ai/articles/retries-and-idempotency-for-ai-agents#how-should-an-agent-retry-a-failed-tool-call"
    },
    {
      "depth": 2,
      "text": "Why are agent retries a harder problem than a typical API client's retries?",
      "anchor": "why-are-agent-retries-a-harder-problem-than-a-typical-api-client-s-retries",
      "url": "https://changegamer.ai/articles/retries-and-idempotency-for-ai-agents#why-are-agent-retries-a-harder-problem-than-a-typical-api-client-s-retries"
    },
    {
      "depth": 2,
      "text": "How do you build an idempotency key that actually deduplicates a retry?",
      "anchor": "how-do-you-build-an-idempotency-key-that-actually-deduplicates-a-retry",
      "url": "https://changegamer.ai/articles/retries-and-idempotency-for-ai-agents#how-do-you-build-an-idempotency-key-that-actually-deduplicates-a-retry"
    },
    {
      "depth": 3,
      "text": "Same-step retry vs. a legitimate new run",
      "anchor": "same-step-retry-vs-a-legitimate-new-run",
      "url": "https://changegamer.ai/articles/retries-and-idempotency-for-ai-agents#same-step-retry-vs-a-legitimate-new-run"
    },
    {
      "depth": 2,
      "text": "What do you do when a call's outcome is genuinely unknown?",
      "anchor": "what-do-you-do-when-a-call-s-outcome-is-genuinely-unknown",
      "url": "https://changegamer.ai/articles/retries-and-idempotency-for-ai-agents#what-do-you-do-when-a-call-s-outcome-is-genuinely-unknown"
    },
    {
      "depth": 2,
      "text": "Where idempotency keys don't reach",
      "anchor": "where-idempotency-keys-don-t-reach",
      "url": "https://changegamer.ai/articles/retries-and-idempotency-for-ai-agents#where-idempotency-keys-don-t-reach"
    },
    {
      "depth": 2,
      "text": "Where this leaves you",
      "anchor": "where-this-leaves-you",
      "url": "https://changegamer.ai/articles/retries-and-idempotency-for-ai-agents#where-this-leaves-you"
    }
  ],
  "faq": [
    {
      "question": "What should an idempotency key for an agent tool call be derived from?",
      "answer": "An idempotency key should combine the workflow run's own identity with the specific step's position inside that run. A clock reading or a newly generated UUID cannot serve this purpose, because each one differs on every attempt by construction, and only a value that stays constant across retries lets a downstream service recognize a repeat as the same request rather than a brand-new one."
    },
    {
      "question": "Is it safe to retry a tool call after a timeout with no response?",
      "answer": "A tool call that timed out with no response is not automatically safe to retry as if nothing happened, because the request may have already reached the server and executed before the connection dropped, so any side-effecting call in this state needs to be resent with the same idempotency key it used on the first attempt, not treated as a clean do-over."
    },
    {
      "question": "Do all APIs support idempotency keys for deduplicating retries?",
      "answer": "No — idempotency-key support is not part of the HTTP or REST specification, it is a feature an individual API chooses to implement or not, so an agent cannot assume every downstream service has one. Calling a system that lacks that support means falling back to an application-level dedupe record — checking whether the effect already happened before attempting it again — or accepting the duplication risk for that specific integration."
    },
    {
      "question": "What is the difference between a transient and a terminal failure for retry purposes?",
      "answer": "A transient failure such as a 429 rate limit, a 5xx server error, or a network timeout is one where retrying with backoff has a real chance of succeeding because the underlying condition is temporary, while a terminal failure such as a 400 bad request or a 401 authentication error will fail identically on every retry because the problem is in the request itself, so retrying it only delays the inevitable escalation."
    }
  ],
  "body": "The [agent reliability in production](/articles/agent-reliability-in-production) pillar surveys twelve reliability disciplines at survey depth; this article expands two of them into an operator playbook — how an agent decides what to retry, and how it makes a retry safe once a side effect might already have happened before any failure signal came back.\n\n## How should an agent retry a failed tool call?\n\nAn agent should retry a failed tool call only after classifying the failure as transient, then space out attempts on a jittered exponential schedule that never dips below whatever wait time the provider explicitly mandates. A 429 (rate limited), a 5xx server error, and a plain network timeout are transient — the condition that caused them is temporary, and a second attempt has a real chance of succeeding. A 400 (malformed request) or a 401/403 (bad credentials or missing permission) is terminal — the request itself is wrong, and retrying it produces the identical failure every time while burning a retry budget that should instead escalate immediately to a human or a fallback path. The full backoff formula, the provider-by-provider rate-limit header reference (`x-ratelimit-remaining-tokens`, `anthropic-ratelimit-requests-remaining`, and their peers), and the RPM/TPM/TPD tier structure that governs how much headroom an agent actually has live in [handling rate limits and retries](/resources/handling-rate-limits-and-retries) — this article assumes that mechanism and focuses on what changes once a retried call can duplicate a side effect, which the next three sections cover.\n\nOne detail worth calling out at fleet scale: an agent deployment rarely retries in isolation. Dozens or hundreds of concurrent agent runs can hit the same rate limit within the same window — after a shared model deployment briefly degrades, or after a deploy restarts many workflow replicas at once — and if every one of them backs off on the same fixed schedule, they collide again at the next retry round instead of spreading out. Full jitter, not a fixed delay or a bare exponential schedule with no randomization, is what keeps a fleet of independently retrying agent runs from synchronizing into a self-inflicted retry storm against the same endpoint.\n\n## Why are agent retries a harder problem than a typical API client's retries?\n\nAgent retries are harder than a typical stateless API client's retries because an agent's tool call frequently triggers a real-world side effect, and that side effect can complete on the far side before any failure signal — a timeout, a dropped connection, a crashed process — ever reaches the code deciding whether to retry. A conventional REST client calling a read-only endpoint can safely assume \"I got no response, so nothing happened\" and simply resend the request. An agent issuing a tool call that charges a card, sends an email, or writes a database row cannot make that assumption: the request may have arrived, executed, and only the *response* was lost. Naively resending it does not repeat \"nothing happened\" — it repeats the side effect itself, producing a duplicate charge, a duplicate email, or a corrupted counter.\n\nThis gap is exactly why idempotency has to be designed in deliberately rather than assumed. If a process dies partway through a side-effecting call, the next attempt — whether triggered by your own backoff loop or by a durable-execution engine replaying its checkpoint log after a restart — has no way to know whether that call already landed, and resending it blind risks repeating the exact effect it was trying to complete. The fix is not a smarter retry loop; it is a key that lets the downstream service recognize the second attempt as identical to the first.\n\n## How do you build an idempotency key that actually deduplicates a retry?\n\nBuild an idempotency key from two stable identifiers: the workflow run's own identity, and the index of the specific step being attempted inside that run. A clock reading and a freshly minted UUID are both disqualified by the same property — each is guaranteed to come out different on the next attempt — so a key built from either one shifts every time it is generated, and a key that shifts on retry cannot signal \"same request\" to anything downstream.\n\n```python\ndef step_idempotency_key(run_id: str, step_index: int) -> str:\n    # Stable across every retry of THIS step, in THIS run.\n    # A crash, a 5xx, or a dropped connection can all trigger a retry\n    # that reuses this exact key — that is the point.\n    return f\"{run_id}:step-{step_index}\"\n\ndef charge_customer(run_id, step_index, amount, customer_id):\n    key = step_idempotency_key(run_id, step_index)\n    return payment_api.charge(\n        amount=amount,\n        customer_id=customer_id,\n        idempotency_key=key,   # downstream service treats a repeat key as a no-op\n    )\n```\n\nPass that key to whatever field the downstream service designates for deduplication — a payment processor, a transactional-email sender, or a messaging platform typically has one for exactly this reason — so a duplicate attempt collapses into a no-op response instead of a second real effect. This is the same mechanism durable execution engines rely on internally: resuming a workflow after a crash replays its orchestration logic from the recorded log, and any step still in progress when the crash happened can end up scheduled again, so the engine (or the code layered on top of it) needs a stable key to make that replay land as a no-op, as covered in more depth in [durable execution for long-running agents](/resources/durable-execution-for-agents) — idempotency keys are foundational to how durable execution avoids duplicating side effects on replay, though the mechanics of replay and checkpointing themselves are that resource's and a future sub-article's territory, not this one's.\n\n### Same-step retry vs. a legitimate new run\n\nA retry of the same step must reuse that step's original key; a new run of the same workflow must not. Building the key from both the run's own identifier and the step's position inside it makes this fall out automatically: retrying step 3 of run `abc123` after a timeout produces the identical key `abc123:step-3` every time, so the downstream service correctly treats every attempt as one logical charge. Starting a fresh run of the same workflow — a different customer, a different day, a legitimately new request — gets its own new identifier, and therefore its own new key, so it is never mistaken for a duplicate of unrelated prior work. The failure mode to watch for is the reverse: a key built only from the step's position with no run identity folded in would collide across every run that happens to reach \"step 3,\" silently blocking legitimate charges that have nothing to do with each other.\n\n## What do you do when a call's outcome is genuinely unknown?\n\nWhen a call's outcome is genuinely unknown — a timeout, a dropped connection, a proxy that hung up mid-request — treat it as \"may have executed\" and retry with the same idempotency key, never as a clean failure that is safe to reattempt without one. This is the distinction that actually drives what to do next: a clean error response (a 400, a 401, a well-formed 429) tells you unambiguously what happened on the server side, but a timeout or a connection drop tells you nothing — the request could have failed before it was ever processed, or it could have completed in full with only the acknowledgment lost in transit. Resending with the same key is what makes that ambiguity safe to live with: if the first attempt never landed, the retry executes normally; if it already landed, the downstream service's own deduplication turns the retry into a no-op — either way, the caller does not have to resolve the ambiguity itself before deciding to resend.\n\n| Failure signal | What it tells you | Needs an idempotency key |\n|---|---|---|\n| 400 / validation error | Clean, terminal — rejected before any side effect ran | No — fix the request, don't retry |\n| 401 / 403 | Clean, terminal — credentials or permissions, not payload | No — escalate, don't retry |\n| 429 rate limited | Clean, transient — provider explicitly did not execute it | No for the retry decision, yes if the call is side-effecting regardless |\n| Clean 5xx response | Ambiguous — some 5xx mean \"never ran,\" some mean \"ran, then failed to reply\" | Yes, for any side-effecting call |\n| Timeout / dropped connection | Unknown — request may have reached and executed before the response was lost | Yes, always |\n| Process crash mid-step | Unknown — the step may have been mid-flight when the crash occurred | Yes, always |\n\n## Where idempotency keys don't reach\n\nIdempotency keys are not a universal solve, because nothing in the HTTP or REST tradition requires an API to support one — it is a feature each service chooses to implement or not, and a service that never opted in has no idempotency-key parameter to pass a key to at all. The pattern described above only works where the receiving system was built to support it. Where it isn't supported, the fallback is an application-level dedupe record: before attempting a side-effecting call, check your own store for a record that the same run-and-step key already succeeded, and only proceed if it hasn't. This shifts the deduplication responsibility from the downstream service to your own system, which is strictly more work to build and maintain correctly than passing a header — and for a call where neither an idempotency-key header nor a reliable own-side dedupe record is feasible (a one-off webhook to a system you don't control, for instance), the honest answer is that the duplication risk cannot be fully eliminated, only reduced by minimizing the retry window and alerting on any retry of that specific call so a human can check for a duplicate after the fact.\n\n## Where this leaves you\n\nClassify every tool-call failure as transient or terminal before deciding whether to retry, back off with full jitter so a fleet of agents doesn't resynchronize into its own retry storm, and never let \"no response\" be treated as \"nothing happened\" for a side-effecting call. Build every idempotency key from the run's identity and the step's position within it, reuse that exact key on every retry of that step, and generate a new key only when the run itself is genuinely new. Where a downstream API has no idempotency-key support, fall back to an application-level dedupe record rather than assuming the risk away. For the ten other reliability disciplines this one sits inside, see the [agent reliability in production](/articles/agent-reliability-in-production) pillar; for how this same key pattern underwrites crash-recovery replay in a durable workflow, see [durable execution for long-running agents](/resources/durable-execution-for-agents).",
  "cluster": {
    "id": "agent-reliability",
    "title": "Agent reliability in production",
    "description": "How to make an AI agent reliable — tool-calling contracts, structured outputs, retries and idempotency, timeouts, durable execution, guardrails, evaluation in CI, observability, incident response, and rollout.",
    "status": "complete",
    "pillar": {
      "slug": "agent-reliability-in-production",
      "title": "Agent Guardrails and the AI Agent Reliability Playbook",
      "description": "Agent guardrails plus the eleven other disciplines that make an AI agent reliable in production: tool calling, retries, durable execution and rollout.",
      "kind": "pillar",
      "order": 0,
      "html": "https://changegamer.ai/articles/agent-reliability-in-production",
      "markdown": "https://changegamer.ai/articles/agent-reliability-in-production.md",
      "json": "https://changegamer.ai/api/articles/agent-reliability-in-production.json"
    },
    "articles": [
      {
        "slug": "tool-calling-contracts-for-ai-agents",
        "title": "How to Make AI Agent Tool Calling Reliable",
        "description": "An operator playbook for tool-calling contracts: per-provider strict-mode config (OpenAI, Anthropic, Gemini, self-hosted grammars), the full failure-mode-to-fix table, what BFCL actually measures, and how to stop parallel tool calls from breaking a dependency chain.",
        "kind": "sub",
        "order": 1,
        "html": "https://changegamer.ai/articles/tool-calling-contracts-for-ai-agents",
        "markdown": "https://changegamer.ai/articles/tool-calling-contracts-for-ai-agents.md",
        "json": "https://changegamer.ai/api/articles/tool-calling-contracts-for-ai-agents.json"
      },
      {
        "slug": "structured-outputs-vs-tool-calling",
        "title": "Structured Outputs vs Tool Calling: When to Use Each",
        "description": "A decision framework for structured outputs versus tool calling in AI agents, with runnable JSON Schema examples for OpenAI, Anthropic, Gemini, vLLM/SGLang, and llama.cpp, plus mitigation code for truncation, refusal, and grammar-compilation latency.",
        "kind": "sub",
        "order": 2,
        "html": "https://changegamer.ai/articles/structured-outputs-vs-tool-calling",
        "markdown": "https://changegamer.ai/articles/structured-outputs-vs-tool-calling.md",
        "json": "https://changegamer.ai/api/articles/structured-outputs-vs-tool-calling.json"
      },
      {
        "slug": "retries-and-idempotency-for-ai-agents",
        "title": "How to Make AI Agent Retries Idempotent",
        "description": "A deep-dive on retrying agent tool calls safely: the transient-vs-terminal decision, why an agent side effect can fire before a failure signal reaches the caller, idempotency-key mechanics (run ID + step index), the unknown-outcome edge case, and where idempotency keys do not reach.",
        "kind": "sub",
        "order": 3,
        "html": "https://changegamer.ai/articles/retries-and-idempotency-for-ai-agents",
        "markdown": "https://changegamer.ai/articles/retries-and-idempotency-for-ai-agents.md",
        "json": "https://changegamer.ai/api/articles/retries-and-idempotency-for-ai-agents.json"
      },
      {
        "slug": "durable-execution-for-ai-agents",
        "title": "When Do AI Agents Need Durable Execution?",
        "description": "A deep-dive on durable execution for AI agents: the persisted event log, the replay-determinism constraint, the four architectural shapes mapped across ten engines and frameworks, and a decision framework for when a durable execution engine is worth adding at all.",
        "kind": "sub",
        "order": 4,
        "html": "https://changegamer.ai/articles/durable-execution-for-ai-agents",
        "markdown": "https://changegamer.ai/articles/durable-execution-for-ai-agents.md",
        "json": "https://changegamer.ai/api/articles/durable-execution-for-ai-agents.json"
      },
      {
        "slug": "agent-guardrails-for-reliability",
        "title": "How to Design Guardrails for AI Agent Reliability",
        "description": "An operator playbook for reliability guardrails: the three checkpoints (input, output, action), layering cheap checks under slow ones with a fail-closed default, the two-of-three-properties rule for when a tool call needs human approval, and logging every verdict against the run trace ID.",
        "kind": "sub",
        "order": 5,
        "html": "https://changegamer.ai/articles/agent-guardrails-for-reliability",
        "markdown": "https://changegamer.ai/articles/agent-guardrails-for-reliability.md",
        "json": "https://changegamer.ai/api/articles/agent-guardrails-for-reliability.json"
      },
      {
        "slug": "evaluating-ai-agents-in-ci",
        "title": "How to Evaluate AI Agents in CI",
        "description": "An operator playbook for gating an AI agent release in CI: why agent eval needs trajectory-level scoring across the tasks it actually runs, how public benchmarks diverge as proxies, ground-truth vs LLM-as-judge tool-call scoring, and the three-layer test pyramid that keeps CI fast and non-flaky.",
        "kind": "sub",
        "order": 6,
        "html": "https://changegamer.ai/articles/evaluating-ai-agents-in-ci",
        "markdown": "https://changegamer.ai/articles/evaluating-ai-agents-in-ci.md",
        "json": "https://changegamer.ai/api/articles/evaluating-ai-agents-in-ci.json"
      },
      {
        "slug": "agent-rollout-and-rollback",
        "title": "How to Roll Out a New AI Agent Version Safely",
        "description": "An operator playbook for shipping a new agent version without breaking production: in-repo vs. registry prompt storage, a version-numbering comparison, the six-step promotion flow, A/B-test mechanics, the composite-version trace fields, and a rollback drill.",
        "kind": "sub",
        "order": 7,
        "html": "https://changegamer.ai/articles/agent-rollout-and-rollback",
        "markdown": "https://changegamer.ai/articles/agent-rollout-and-rollback.md",
        "json": "https://changegamer.ai/api/articles/agent-rollout-and-rollback.json"
      },
      {
        "slug": "agent-incident-response-runbooks",
        "title": "How to Build an Incident Response Runbook for AI Agent Failures",
        "description": "An operator playbook for the moment an AI agent fails in production: a triage step to classify the failure fast, trace freezing before rollback destroys the evidence, first-response depth on the four failure classes, and a blameless post-mortem that feeds back into guardrails and eval.",
        "kind": "sub",
        "order": 8,
        "html": "https://changegamer.ai/articles/agent-incident-response-runbooks",
        "markdown": "https://changegamer.ai/articles/agent-incident-response-runbooks.md",
        "json": "https://changegamer.ai/api/articles/agent-incident-response-runbooks.json"
      },
      {
        "slug": "timeouts-and-deadlines-for-ai-agents",
        "title": "How to Set Timeouts for AI Agent Tool Calls",
        "description": "A deep-dive on timeout and deadline design for AI agents: sizing LLM-call, tool-call, and sub-agent-hop timeouts differently, allocating a wall-clock budget across a multi-step chain, and propagating a remaining-deadline value from parent to child calls.",
        "kind": "sub",
        "order": 9,
        "html": "https://changegamer.ai/articles/timeouts-and-deadlines-for-ai-agents",
        "markdown": "https://changegamer.ai/articles/timeouts-and-deadlines-for-ai-agents.md",
        "json": "https://changegamer.ai/api/articles/timeouts-and-deadlines-for-ai-agents.json"
      },
      {
        "slug": "circuit-breakers-and-degraded-mode-for-ai-agents",
        "title": "How to Design a Circuit Breaker for AI Agents",
        "description": "A deep-dive on the circuit breaker pattern for AI agents: the Closed/Open/Half-Open state machine with a worked open-source example, where to place a breaker in an agent's call path, and degraded-mode fallback design as its own discipline per dependency type.",
        "kind": "sub",
        "order": 10,
        "html": "https://changegamer.ai/articles/circuit-breakers-and-degraded-mode-for-ai-agents",
        "markdown": "https://changegamer.ai/articles/circuit-breakers-and-degraded-mode-for-ai-agents.md",
        "json": "https://changegamer.ai/api/articles/circuit-breakers-and-degraded-mode-for-ai-agents.json"
      },
      {
        "slug": "agent-observability-for-reliability",
        "title": "What Should an AI Agent's Observability System Capture?",
        "description": "An operator playbook for instrumenting an AI agent: the trace/span model behind a run, the OpenTelemetry GenAI attributes that name each field, the fields worth capturing per span, and what to redact before any of it gets logged.",
        "kind": "sub",
        "order": 11,
        "html": "https://changegamer.ai/articles/agent-observability-for-reliability",
        "markdown": "https://changegamer.ai/articles/agent-observability-for-reliability.md",
        "json": "https://changegamer.ai/api/articles/agent-observability-for-reliability.json"
      },
      {
        "slug": "agent-reliability-production-checklist",
        "title": "The AI Agent Production Reliability Checklist",
        "description": "A go/no-go checklist that turns the agent reliability pillar's twelve-discipline closing list into checkable gates — the specific artifact, header, or trace field that proves each one holds, with a link to whichever sibling article owns its mechanics.",
        "kind": "sub",
        "order": 12,
        "html": "https://changegamer.ai/articles/agent-reliability-production-checklist",
        "markdown": "https://changegamer.ai/articles/agent-reliability-production-checklist.md",
        "json": "https://changegamer.ai/api/articles/agent-reliability-production-checklist.json"
      }
    ]
  },
  "navigation": {
    "pillar": {
      "slug": "agent-reliability-in-production",
      "title": "Agent Guardrails and the AI Agent Reliability Playbook",
      "description": "Agent guardrails plus the eleven other disciplines that make an AI agent reliable in production: tool calling, retries, durable execution and rollout.",
      "kind": "pillar",
      "order": 0,
      "html": "https://changegamer.ai/articles/agent-reliability-in-production",
      "markdown": "https://changegamer.ai/articles/agent-reliability-in-production.md",
      "json": "https://changegamer.ai/api/articles/agent-reliability-in-production.json"
    },
    "previous": {
      "slug": "structured-outputs-vs-tool-calling",
      "title": "Structured Outputs vs Tool Calling: When to Use Each",
      "description": "A decision framework for structured outputs versus tool calling in AI agents, with runnable JSON Schema examples for OpenAI, Anthropic, Gemini, vLLM/SGLang, and llama.cpp, plus mitigation code for truncation, refusal, and grammar-compilation latency.",
      "kind": "sub",
      "order": 2,
      "html": "https://changegamer.ai/articles/structured-outputs-vs-tool-calling",
      "markdown": "https://changegamer.ai/articles/structured-outputs-vs-tool-calling.md",
      "json": "https://changegamer.ai/api/articles/structured-outputs-vs-tool-calling.json"
    },
    "next": {
      "slug": "durable-execution-for-ai-agents",
      "title": "When Do AI Agents Need Durable Execution?",
      "description": "A deep-dive on durable execution for AI agents: the persisted event log, the replay-determinism constraint, the four architectural shapes mapped across ten engines and frameworks, and a decision framework for when a durable execution engine is worth adding at all.",
      "kind": "sub",
      "order": 4,
      "html": "https://changegamer.ai/articles/durable-execution-for-ai-agents",
      "markdown": "https://changegamer.ai/articles/durable-execution-for-ai-agents.md",
      "json": "https://changegamer.ai/api/articles/durable-execution-for-ai-agents.json"
    }
  },
  "resources": [
    {
      "slug": "handling-rate-limits-and-retries",
      "html": "https://changegamer.ai/resources/handling-rate-limits-and-retries",
      "markdown": "https://changegamer.ai/resources/handling-rate-limits-and-retries.md",
      "json": "https://changegamer.ai/api/resources/handling-rate-limits-and-retries.json"
    },
    {
      "slug": "durable-execution-for-agents",
      "html": "https://changegamer.ai/resources/durable-execution-for-agents",
      "markdown": "https://changegamer.ai/resources/durable-execution-for-agents.md",
      "json": "https://changegamer.ai/api/resources/durable-execution-for-agents.json"
    }
  ]
}