Skip to content
Patrick Desjardins Blog
Patrick Desjardins picture from a conference

HATEOAS as the Natural Interface for Autonomous Agents

Posted on: 2026-07-17

The web was built for humans using a browser. APIs were built for developers who read documentation. Both scenarios never anticipate autonomous agents that must reason about what to do next. As LLM agents increasingly interact with services, a question emerges that few people are addressing directly: what kind of API architecture best serves a caller that cannot memorize logic of which endpoints is legit to call, yet must act reliably in a world of shifting state?

My position is that HATEOAS (Hypermedia As The Engine Of Application State) is the most natural interface for autonomous agents because it encodes the same information a competent human operator would need at each decision point. What can I do right now, and how exactly do I do it? The answer to that question changes with every request, and only HATEOAS makes that dynamism explicit.

The Gap Between Static Documentation and Runtime Reality

Traditional REST APIs operate on a clean separation between documentation and runtime. An OpenAPI specification tells you what endpoints exist and what shapes they accept. Think of it as a static map of every road in the network. But it cannot tell you which roads are open right now, for this particular resource, in its current state, for this specific caller. That knowledge lives somewhere else entirely buried in prose documentation, encoded in conditional logic scattered across client code, or discovered only when the server returns a 400.

For a human developer, this is manageable. You read the docs, you learn the rules, you build the client containing those rules. For an autonomous agent, this separation is an issue, and the reasons compound on each other. The agent suffers from what I call business logic blindness. For example, nothing in a static specification communicates that an account is frozen, that an order has already shipped, or that archiving an item requires it to be completed first. The agent must memorize these invariants and hope they haven't changed since its training data was assembled. When those rules do change, the agent doesn't know until it crashes into a 400 or a 409 at runtime. This blindness leads directly to business logic duplication. Every state rule the server knows but doesn't express becomes a rule the agent must independently implement. The server knows that you can only archive a completed task. The server knows that sharing and unsharing are mutually exclusive. The server knows that every write must carry the current optimistic-locking version. But if none of that is communicated in the response, it all becomes the agent's problem to track and enforce. You end up with business logic duplicated in every client, maintained by every team, drifting independently from the source of truth.

And then there is context overhead. Loading an entire API specification into a context window is expensive and noisy. Large specifications consume thousands of tokens, elevate the risk of the model losing track of critical instructions buried in the middle of the document, and invite hallucinations about endpoints that don't behave the way the model thinks they do based on a partial reading. The agent is forced to carry an entire atlas when it only needs turn-by-turn directions.

The Thesis

HATEOAS resolves these problems by collapsing the gap between documentation and runtime into a single artifact: the response itself. Each response carries only the actions valid in the present moment, with their required fields, types, constraints, and current values embedded directly. An action that is illegal simply does not appear. The agent reasons from what it sees rather than from what it remembers. Consider a task-tracking system where items pass through states: open, in progress, completed, archived. Under a traditional API, an agent must know the rule that archiving is only legal after completion. It must carry that rule in its context or its training. If the rule changes, for example a new "approved" state is inserted between completed and archived, the agent breaks silently until someone notices and updates the documentation and retrains or re-prompts. Under HATEOAS, the archive action is simply absent from the response until the item reaches the completed state. The illegal operation becomes unrepresentable rather than a runtime error. When the business adds a new state, the server's logic updates, and the actions in the response reflect the new reality immediately. No documentation to update. No agents to retrain. The server owns the state machine, the agent merely follows it. This is not a minor ergonomic improvement, it is a design change where response contains intelligence navigations and actions knowledge along the data. With traditional APIs, every consumer must be smart enough to know the rules. With HATEOAS, the server is smart, and consumers only need to be smart enough to read what they are given. For agents that cannot reliably memorize complex invariants across thousands of possible state combinations, this is the difference between fragile and robust.

Objections

No honest argument can survive without confronting its weaknesses, and there are genuine objections to this position that deserve serious treatment. The most compelling objection is that LLMs are not naturally good at parsing hypermedia and chaining links across turns. They are good at calling well-described functions. Models perform most reliably when given a typed tool definition with clear parameters and not when asked to interpret a document, follow a rel, and reason about what the next hop should be. If adopting HATEOAS means asking the model to become a hypermedia client, you are require informing the client that consume the API how to interpret the basic format that contains that enhanced payload.

Another objection concerns weight and complexity. Every response now carries actions, fields, links, and embedded schemas. For read-heavy workloads where the caller simply wants data, this is overhead without benefit. Payloads grow. Caching becomes harder because responses vary by state and by caller. You may be solving a problem on the write path while making the read path worse.

There is the pragmatist's objection of simplicity that we can achieve most of this benefit with less complexity. Rather than adopting a full hypermedia format with its specification, its envelope, its parsing libraries, you could simply attach a computed custom field, for example, valid_actions field to your standard JSON responses. A small array listing what is legal right now, with the current version pre-filled. This captures the benefit without the format debates, the caching complications, or the ecosystem overhead.

Defense

Each of these objections is valid in isolation. None of them survives contact with how the system actually works in practice. The function-calling objection dissolves once you understand that HATEOAS need not be a format the model reads directly. It serves best as the authoritative source of truth from which a function-calling interface is generated per-response. The server computes which actions are valid. A thin translation layer presents those actions as typed tool definitions the model consumes natively. The model sees ergonomic functions, exactly the interface it performs best with. But those functions reflect reality rather than a stale specification, because underneath them the hypermedia engine is computing what is actually valid right now. The distinction matters: the model never parses raw hypermedia, but the hypermedia governs what the model is offered. You get the reliability of function-calling with the correctness of state-aware benefits. The two are not in tension because they compose naturally.

The weight objection is real but misplaced when stated as a universal criticism. The weight and complexity pay off specifically on state-changing, action-oriented paths but maybe not on reads. The correct architecture applies hypermedia where business rules govern transitions and uses conventional query mechanisms for read-heavy data retrieval. This matches what we observe in production at scale. PayPal, whose API drives stateful payment workflows, employs full HATEOAS with contextual link arrays filtered by resource state. Spotify, whose API is overwhelmingly read-only, uses only lightweight navigation links and paging cursors. GitHub sits somewhere in between, using link headers for pagination and embedding resource URLs for traversal but not advertising possible actions. The gradient is not accidental. It reflects where the benefit concentrates. You would not wrap every GET endpoint in a hypermedia envelope any more than you would serve a static image through a state machine. The claim is not that HATEOAS is universally superior. The claim is that for stateful workflows with conditional transitions, it is the honest architecture.

The pragmatist's objection deserves the most respect because it is closest to being correct. A lightweight field called valid_actions does capture the core insight. And for a single service maintained by a single team with a single consumer, it might genuinely be enough. But bespoke conventions grow. What begins as a small array increase field schemas because the agent needs to know what to send. It adds type information because the agent needs to know the shape. It adds version tokens because writes need optimistic locking. It accrues conditional presence logic because some actions only appear in certain states. Over six months you find yourself maintaining a half-specified hypermedia format without the benefit of standardization, shared tooling, parsers, or a versioned contract that multiple services can bind to independently. A documented format like Siren is not heavier by nature, it is the same information with a stable specification. The marginal cost of standardization is repaid the moment a second service adopts the same surface, and in any organization with more than one API team, that moment arrives quickly.

What This Looks Like in Practice

To make this concrete rather than abstract, consider what happens when an agent encounters a task in the "in progress" state. Under HATEOAS, the response includes the task's properties alongside only the actions that are valid: mark as complete, flag for discussion, update the title. Each action carries its HTTP method, its target URL, and the exact fields required, including the current optimistic-locking version pre-filled so the agent doesn't have to fetch it separately. Notice what is absent. There is no archive action because the task is not yet completed. There is no unshare action because the task is not currently shared. The illegal operations don't exist as options. The agent cannot hallucinate them into existence because they are not in the response. Once the agent follows the complete action, the next response includes the newly valid archive action with version incremented to reflect the state change. The agent never had to know the rule. It simply followed what was offered, and the workflow progressed correctly.

Now contrast this with the traditional approach. The agent holds the full API specification in context. It sees that archive exists as an endpoint. It must reason-based on training data, or a system prompt, or a previous error, that archive requires the completed state. If it gets this wrong, it wastes a round-trip, burns tokens on error handling, and risks confusing the user. Multiply this across a complex domain with dozens of state-dependent rules, and the reliability gap between the two approaches compounds rapidly.

The Broader Shift

There is something philosophically significant about this architecture that goes beyond the engineering details. HATEOAS inverts the burden of knowledge. In a traditional API, intelligence must be distributed to every consumer. Every client, every agent, every integration must independently acquire and maintain an understanding of the business rules. Under HATEOAS, intelligence is centralized at the server. The server knows the rules and communicates only what is valid. Consumers need only the ability to read and follow. This is a more honest distribution of responsibility. The entity that owns the business logic, the server, is also the entity that communicates it. There is no gap between knowledge and expression, no unsynchronization between what the rules are and what clients believe the rules to be.

For human developers maintaining a handful of integrations, this centralization is a nice-to-have. For autonomous agents operating at scale across many services, each with evolving state machines, it is the difference between systems that work and systems that fail in subtle, hard-to-debug ways. The agent that follows what it is given is robust against changes it was never told about. The agent that memorizes specifications is brittle against every change that outpaces its documentation.

Conclusion

The claim is scoped rather than universal. For read-heavy data retrieval, conventional REST with well-designed query mechanisms remains appropriate. For stateless operations with no conditional logic, HATEOAS adds weight without benefit. But wherever an API governs a workflow with conditional transitions, where what you may do depends on where you stand and who you are, HATEOAS transforms the interaction from memorization to observation. The agent reads the response and acts on what it sees, rather than consulting a manual and hoping it is current. As we build systems that autonomous agents will navigate daily, we should ask ourselves a simple question: do we want every agent to independently learn our business rules, or do we want our APIs to communicate those rules at the moment they matter?

Discussion

Replies are loaded from the public Mastodon thread for this article.

Loading replies from Mastodon...