API strategy
Agent infrastructure
HATEOAS AI agents finally have a caller who reads responses at runtime. Why hypermedia for agents fixes tool selection failures — and where it stops short.

HATEOAS was a good idea trapped in the wrong decade. The web spent twenty years arguing about whether REST APIs should embed links and affordances alongside their data, and the answer was almost always no. Human developers didn't want them. SDK generators didn't need them. Documentation covered the gap. So the idea sat there, quietly correct, waiting for a caller who actually benefited from being told at runtime what it could do next.
That caller has arrived. AI agents are the first API consumers who would rather read the response than the docs. And that changes the argument.
HATEOAS stands for Hypermedia as the Engine of Application State. Roy Fielding put it in his 2000 dissertation as the constraint that separates real REST from RPC-over-HTTP. The idea is that a response shouldn't just carry data. It should carry the set of actions the caller can take next, expressed as links and affordances the caller discovers at runtime.
A plain JSON invoice response tells you the invoice's amount and status. A hypermedia response tells you the same thing, plus: here is the URL to pay it, here is the URL to void it, here is the URL to send a reminder — and the void link isn't in the payload because this invoice is already paid.
The API tells the caller what it can do, from this specific state, right now.
For twenty years, human developers responded to this with a shrug. They read the docs once, hardcoded the URLs, and shipped. The affordances the server was trying to teach them were things they'd already learned. Hypermedia was overhead for a caller who didn't need it.
Agents are not that caller.
A human developer integrating Stripe reads the docs, decides which endpoints they need, and writes code that calls them in a fixed order. The developer holds the state machine in their head. They know that you can only refund a charge that's succeeded, only capture an authorisation that hasn't expired, only cancel a subscription that's active. That knowledge lives in the code they wrote.
An agent doesn't get to do any of that. It reads a schema, gets called with a user request, and has to decide — at runtime, from whatever context it has — which tool to invoke and with what arguments. The state machine is not in its head. If the response doesn't tell it what's now possible, it has to guess. And guessing is where agent projects go to die.
We wrote about agent tool selection earlier this year — the failure mode where models call the wrong tool with plausible-looking arguments. A lot of that is a hypermedia problem in disguise. The model called refund_charge because the tool was in scope, not because the charge was refundable. Nothing in the response the model was working from told it that a refund wasn't allowed. So it tried, got a 400, and either looped or gave up.
Hypermedia responses collapse a class of these failures. If the previous response embedded {"refund": null, "reason": "already_refunded"} alongside the other affordances, the model has a signal it can actually use. It doesn't have to memorise Stripe's state machine. The state machine is in the response.
Most of the noise around hypermedia is about format wars — HAL, JSON:API, Siren, Collection+JSON. The format matters less than the payload carrying three things.
Available affordances. Not "here are all the operations on this resource type" — that's the OpenAPI spec, and the agent already has it. Available affordances means: given this specific resource in this specific state, which of those operations are valid right now? An invoice in draft allows send, edit, delete. The same invoice in paid allows none of them. The response should say so.
Structured parameters, not URL templates. Many hypermedia formats leaned hard on URL templates — /invoices/{id}/refund. Agents don't want templates. They want the same thing tool schemas already give them: named parameters with types and constraints. Embed the parameter shape alongside the affordance so the model can fill it in one step.
Semantic labels the model can actually read. "rel": "next" is fine for a browser. "description": "Advance this invoice to the next state in its lifecycle. Only valid when status is draft." is what a model needs. The link relations registry (RFC 8288) was written to give browsers and generic clients a shared vocabulary for navigating between resources, not to give language models semantic instructions they can act on. Agent-era hypermedia has to include natural-language semantics for every affordance, because the caller is a probabilistic thing that reads English.
When we talk to teams building agents on their own APIs, this is where the conversation lands. Not "should we return HAL or JSON:API," but "can we describe, per response, what the caller can do next, with what parameters, and in language the model can act on." That's the useful shape of the idea.
Hypermedia responses fix a class of tool selection failures. They don't fix the harder ones, and it's worth being honest about that before anyone treats HATEOAS as the answer.
Hypermedia doesn't help if the affordance the agent needs doesn't exist in the API at all. This is the 2% problem — the SaaS product's UI can do a hundred things and the API exposes two of them. A perfectly self-describing response of the two things you exposed doesn't help the agent do the other 98. Hypermedia is a shape for the surface that exists. It doesn't extend the surface.
Hypermedia doesn't help with authorisation boundaries either. A response can list ten affordances, and the caller only has scopes for three of them. The other seven will 403 the moment the agent tries. Some hypermedia implementations filter affordances by the caller's permissions, and that helps — but only if the API actually knows the caller's scopes at response time. Delegated auth, which we covered in zero trust for AI agents, is the boundary that makes filtered affordances actually meaningful.
And hypermedia doesn't help with tool granularity. If your API exposes updateInvoice as one giant endpoint that can do fifteen things depending on which fields are set, no amount of link embedding rescues the agent from that shape. It'll still pick the wrong field and hit the wrong branch. Some problems are surface problems, not response problems.
So where does that leave a team who thinks the idea is right and wants to use it?
Start with the responses your agents are already calling most often. Add three things: the list of valid next actions in the resource's current state, structured parameters for each of those actions, and a short description a model can read. Don't rewrite your API. Don't argue about the format. Do it in whatever JSON shape your existing responses already use — a _actions block is fine.
Then check whether your agents' tool selection accuracy improves. It should, on the specific failure mode where the model was calling operations that weren't valid for the current state. If it does, keep going. If it doesn't, the failure was somewhere else — schema quality, tool granularity, or missing capability — and hypermedia wasn't going to fix it.
The old REST purists were right about one thing: an API that tells the caller what it can do next is a better API. They were wrong about who the caller was going to be. It was never going to be a developer. It was going to be the thing the developer built.
Pontil sits in the tools layer — between the model that reasons and the product that gets acted on. When we generate tools from an existing codebase, one of the things we can carry through is exactly the kind of state-aware affordance data hypermedia responses were reaching for. The tool definition the agent sees at call time reflects what the API can do; the runtime response can reflect what this specific resource, for this specific authenticated user, can do next.
That matters because it collapses two of the failure modes we see most often: models calling operations that aren't valid for the current state, and models calling operations the authenticated user isn't allowed to perform. Both stop being guesses when the response tells the truth.
Hypermedia was always the right idea for a caller that reads at runtime. Agents are that caller.
If you're building agents on your own APIs, the useful move isn't to relitigate the HATEOAS wars. It's to pick the three or four responses your agents call most, and add state-aware affordances to them. Measure whether the tool selection failures on those endpoints go down. If they do, you've validated the pattern on your own surface, and you can scale it.
And if they don't — if your agents are still picking the wrong tool, still hitting 400s, still looping — then the problem isn't the response shape. It's the surface underneath. That's a harder conversation, and it's the one most agent projects end up needing to have.
Stay up to date on the ever changing agentic landscape.