{"slug": "http-has-a-new-method-now-after-16-years-and-it-lands-where-ai-agents-were", "title": "HTTP Has a New Method Now (After 16 Years!), and it lands where AI agents were bleeding", "summary": "The HTTP specification has added a new QUERY method (RFC 10008) after 16 years, designed to allow safe and idempotent read operations with a request body, solving long-standing issues for AI agents that rely on retries and caching. The method provides the same body affordance as POST but with GET-like guarantees, enabling proxies and caches to treat queries as safe reads and eliminating the need for idempotency keys in agent loops.", "body_md": "Every search endpoint forces the same compromise. The operation reads data, so it should be a GET. But the filter payload (nested conditions, date ranges, a vector query, a GraphQL selection) won’t fit in a URL. So you POST it, and inherit costs you never signed off on: POST is not safe, not idempotent, and not cacheable for future reads. Proxies can’t retry it. Caches skip it. Anything that reads “POST” as “state change” treats your read like a write.\n\nFor a human-driven app, tolerable. For an agent that loops, retries, and re-issues near-identical retrievals dozens of times per task, that ambiguity becomes real breakage. RFC 10008 fixes the cause.\n\nQUERY asks the target resource to process the request body as a query and return the result, in a safe and idempotent manner (RFC 10008, Section 1). Same body affordance as POST, same guarantees as GET. The three ways to ask for one feed:\n\n```\nGET /feed?q=foo&limit=10&sort=-published        # correct, until the query outgrows the URLPOST /feed   (body: q=foo&limit=10&sort=-published)   # fits, but lies about intentQUERY /feed  (body: q=foo&limit=10&sort=-published)   # fits and tells the truth\n```\n\nThree design points carry the weight.\n\n**Safety is declared, not inferred.** The standard marks QUERY as safe and idempotent, so any generic client, proxy, or cache treats it that way without knowing your API. The guarantee moves from “documented, hopefully read” to “encoded in the protocol.” Remember that line; it’s the whole agent story.\n\n**Format-agnostic.** The spec defines a transport, not a query language. The body’s Content-Type sets the semantics; its examples span application/x-www-form-urlencoded, application/sql, application/jsonpath, and application/xslt+xml. A new Accept-Query response header advertises which formats a resource takes, discoverable via OPTIONS or HEAD.\n\n**A query can get a URI.** A server can return Location (GET this to re-run the query without resending the body) or Content-Location (this exact result snapshot). They answer different questions and aren't interchangeable. This turns an expensive QUERY into a cheap conditional GET next time.\n\nThe query, then the cheap follow-up, end to end:\n\n```\nQUERY /products HTTP/1.1Host: api.example.comContent-Type: application/jsonAccept: application/json\n{\"category\": \"laptops\", \"price\": {\"max\": 1500}, \"sort\": \"price_asc\"}\nHTTP/1.1 200 OKContent-Type: application/jsonAccept-Query: application/jsonLocation: /products?sq=9f2cContent-Location: /products/results/8b71ETag: \"8b71\"Cache-Control: max-age=60\n[ {\"id\": 41, \"name\": \"...\"}, {\"id\": 77, \"name\": \"...\"} ]\n```\n\nThe server ran the read once and handed back two URIs. Next time the same list is needed, skip the body entirely:\n\n```\nGET /products?sq=9f2c HTTP/1.1Host: api.example.comIf-None-Match: \"8b71\"\nHTTP/1.1 304 Not Modified\n```\n\nOne expensive structured read collapses into a conditional GET a shared cache can serve. Under POST, none of this exists.\n\n**Retries stop being a gamble.** Agents are retry machines: loops, timeouts, partial responses, often retried by the HTTP client or orchestrator beneath the model. With POST, a retry after a lost response is a coin flip on whether the server already ran it, so you hand-build idempotency keys or accept double execution. QUERY makes the read repeatable by definition, and a whole class of “did my retry double-fire?” code disappears.\n\nHere’s a retrieval tool an agent calls, with safe-retry and fallback baked in:\n\n``` php\nimport json, httpxdef retrieve(filters: dict) -> list:    \"\"\"Read-only retrieval tool. QUERY is safe + idempotent,    so retrying a lost request is always correct: no idempotency key needed.\"\"\"    body = json.dumps(filters)    headers = {\"Content-Type\": \"application/json\", \"Accept\": \"application/json\"}    for _ in range(3):        try:            r = httpx.request(\"QUERY\", \"https://api.example.com/docs\",                              content=body, headers=headers, timeout=10)            if r.status_code == 405:              # server doesn't speak QUERY yet                r = httpx.post(\"https://api.example.com/docs/search\",                               content=body, headers=headers, timeout=10)            r.raise_for_status()            return r.json()        except httpx.TransportError:            continue                              # safe to loop: a repeated read changes nothing    raise RuntimeError(\"retrieval failed after 3 attempts\")\n```\n\n**A read/write boundary the gateway can enforce.** The proven way to run agents safely is behind a gateway that limits what they can do. Until now you couldn’t cleanly say “this agent may read, but needs approval to write,” because read-only searches were POSTs, indistinguishable from writes. Now a gateway allows QUERY freely and routes state changes through approval or audit:\n\n```\nallow  QUERY                     # reads: cache, log, rate-limit on the GET budgetgate   POST PUT PATCH DELETE      # writes: require approval / audit\n```\n\nThe read/write split moves from convention to enforcement. For an agent harness or MCP gateway, QUERY is the first HTTP primitive that draws that line mechanically.\n\n**Caching cuts redundant work.** Agentic retrieval repeats itself: RAG steps, self-correction, multi-hop plans re-issue overlapping queries. POST caches none of it. QUERY responses cache, with one hard rule from the spec: the cache key must include the request body, since a different body is a different query. Pair that with the Location trick above and repeat passes become 304s. Retrieval cost sits upstream of token cost, so fewer backend hits means fewer tokens spent re-reading the same context.\n\n**Fat filters fit.** Hybrid vector-plus-keyword search, RAG metadata constraints, JSONPath over a corpus, GraphQL selections: all read-only, all too big for a URL, all POST today. QUERY is the right verb, and it lets a tool schema (OpenAPI, MCP) state “I only read” as a fact instead of a hopeful sentence in a description field.\n\n**“Safe” is not “free.”** Safe means no state change, not zero cost. QUERY still hits databases, replicas, and your bill. An agent looping on “it’s only a read” can flatten a backend. Rate-limit QUERY as its own class.\n\n**A mis-normalized cache can poison a plan.** The spec warns that a cache normalizing the body differently from the server can return a false-positive hit. A human spots a wrong search result; an agent folds it silently into its reasoning. Cache QUERY in front of an agent only if body normalization is exact.\n\n**Adoption is a road, not a switch.** Full support means updates across clients (curl, fetch, axios), frameworks (Express, FastAPI, Django, Spring), and CDN cache engines. Cloudflare’s Snell and Akamai’s Bishop co-authoring the spec signals edge support lands early. Browsers lag: QUERY isn’t CORS-safelisted, so cross-origin calls trigger an OPTIONS preflight. The 405 → POST fallback above buys client-side time.\n\nThe break for agent teams: most agent traffic runs inside infrastructure you own, the agent, the gateway, and the tool servers. That’s exactly where QUERY is safe to adopt first, ahead of the open web.\n\nOwn a search, analytics, or retrieval surface? Audit read-only POST endpoints now; those are your migration candidates. Advertise Accept-Query before cutting over. Risk is low, because the method is a string your framework already routes.\n\nBuilding agents? Treat QUERY as an authorization primitive, not a performance tweak. “Reads flow, writes gate” at the protocol layer is easier to defend to a security team than “the model was told not to.” Adopt inside your perimeter first, key caches on the full normalized body, and rate-limit it separately.\n\nDon’t rebuild your public API around it this quarter. QUERY walks the same curve PATCH did after 2010: frameworks first, infrastructure after. Model the semantics correctly now, let support catch up underneath.\n\nThanks for reading! If you have any questions or feedback, please let me know on [Medium](https://medium.com/@kushalbanda) or [LinkedIn](https://www.linkedin.com/in/kushalbanda/)\n\n[HTTP Has a New Method Now (After 16 Years!), and it lands where AI agents were bleeding](https://pub.towardsai.net/http-has-a-new-method-now-after-16-years-and-it-lands-where-ai-agents-were-bleeding-5c380543c814) was originally published in [Towards AI](https://pub.towardsai.net) on Medium, where people are continuing the conversation by highlighting and responding to this story.", "url": "https://wpnews.pro/news/http-has-a-new-method-now-after-16-years-and-it-lands-where-ai-agents-were", "canonical_source": "https://pub.towardsai.net/http-has-a-new-method-now-after-16-years-and-it-lands-where-ai-agents-were-bleeding-5c380543c814?source=rss----98111c9905da---4", "published_at": "2026-07-12 14:53:53+00:00", "updated_at": "2026-07-12 15:09:52.395712+00:00", "lang": "en", "topics": ["artificial-intelligence", "ai-agents", "developer-tools"], "entities": ["RFC 10008", "HTTP"], "alternates": {"html": "https://wpnews.pro/news/http-has-a-new-method-now-after-16-years-and-it-lands-where-ai-agents-were", "markdown": "https://wpnews.pro/news/http-has-a-new-method-now-after-16-years-and-it-lands-where-ai-agents-were.md", "text": "https://wpnews.pro/news/http-has-a-new-method-now-after-16-years-and-it-lands-where-ai-agents-were.txt", "jsonld": "https://wpnews.pro/news/http-has-a-new-method-now-after-16-years-and-it-lands-where-ai-agents-were.jsonld"}}