APIs Weren’t Built for AI, Now What?
- Nuwan Dias
- VP and Deputy CTO, WSO2
APIs are built for experiences, not generic pipes. They encode assumptions about who's calling, how often, in what order, and with what intent. Most APIs we build today are experience-driven in exactly this way.
Those assumptions hold beautifully for deterministic apps. They start to crack when the consumer becomes an agent.
A human-centric experience versus an agentic one
Take a look at a human-centric retail experience for buying a pair of shoes.
- You search for “running shoes under $150”
- You filter by size and brand
- You view a product
- You add it to cart
- You check out
This experience is linear, intentional, rate-limited by human behavior, and holds its context in the UI rather than the API. An API built for this experience looks like:
GET /products?query=running+shoes&max_price=150
GET /products/{id}
POST /cart/items
POST /checkout
Now imagine an AI shopping agent acting on your behalf.
“Find me the best running shoes under $150, in my size,
available to deliver within 2 days, with the best reviews.”
To satisfy this request, the agent may:
- Query hundreds of products
- Repeatedly re-rank results
- Compare prices across vendors
- Re-check inventory and delivery windows
- Simulate multiple carts
- Retry aggressively when responses are unclear
- Chain calls across multiple APIs
This experience is exploratory, non-linear, probabilistic, machine-driven, and cost-blind unless constrained.
In comparison,
- A human app does: Search → click → decide → buy
- An AI Agent does: Search → fan-out → evaluate → simulate → validate → loop → decide → buy
Can the Model Context Protocol (MCP) help?
APIs were designed for human developers writing deterministic code. They assume stable call patterns, explicit inputs, and predictable control flow. Large language models and agents break these assumptions. They reason probabilistically, explore options, retry dynamically, and decide what to do at runtime. Asking agents to directly call arbitrary APIs exposes them to fragile contracts, unclear semantics, and unsafe side effects.
Model Context Protocol (MCPs) was built to bridge this gap. It is an experience layer built for agentic clients.
MCP introduces a tool-based interaction model, where capabilities are described, discovered, and invoked in a way that aligns with how agents think and reason. Instead of binding agents to low-level API shapes, MCP presents intent-oriented tools with clear inputs, bounded outputs, and controlled execution. This allows agents to safely explore, plan, and act, while giving system owners a place to enforce constraints, security, and cost controls.
With MCP, the “API surface” exposed to the agent becomes the tool interface, which might look like this.
search_products(...)
get_product_details(...)
check_inventory(...)
estimate_shipping(...)
In short: APIs expose implementation. MCPs expose capability.
MCP is an integration layer, not a cure
MCP servers may run locally, alongside the Agent, or remotely, accessed over HTTP by the Agent. However, most MCPs just use existing APIs to implement their functionality. For example, the search_products tool still calls GET /products?query=running+shoes underneath. So the problem of agents using APIs in unprecedented ways doesn't go away. It just moves one layer up.
If agents use MCP tools, does API AI-readiness still matter?
Yes. It’s a common misconception that agents use MCP tools built by humans and therefore AI-readiness of the actual APIs doesn’t really matter. That’s far from true. MCP tools amplify the weaknesses of the APIs behind them.
MCP tools are thin orchestration layers. They translate agent intent into concrete operations, fan out to existing APIs, and aggregate and normalize results. So when an agent makes one tool call, it can result in 10 search API calls, 30 product detail calls, 20 inventory checks, and so on. From the API's point of view, nothing about the traffic pattern has changed for the better: it's bursty, non-human, error-amplifying, and prone to cascading retries. As you can see, unless APIs are AI-ready, MCP tools just amplify their weaknesses.
If an API has ambiguous error semantics, inconsistent schemas, hidden side effects, expensive operations with no cost signal or weak idempotency, tool builders are forced to resort to workarounds such as adding heuristics, guessing intent, hard-coding retries and inventing caching strategies.
Let’s look at an example. Your retail API for product information returns a response that looks like the following.
{
"error": "Product unavailable"
}
Now, what exactly does this error message mean? Does it mean the product is out of stock? Does it mean discontinued? Is it available in that particular region? Or is the particular variable of the product unavailable? Since agents need to know what the next step is, it needs to understand what exactly this error is about. To support that, tool authors now have to do something like the following.
if error contains "unavailable":
try variants endpoint
try inventory endpoint
try different fulfillment method
As you can see, the tool is guessing meaning from string, creating undocumented branching logic. And this code becomes vulnerable to future wording changes on the API. If the API had machine readable error codes such as OUT_OF_STOCK, DISCONTINUED, REGION_BLOCKED, none of this guessing would be necessary.
Let’s take another example of an agent wanting to find the best shoe under $150 that can be delivered in under 2 days. The operations provided by the API are as follows.
/products
/inventory
/shipping/options
/pricing
The API does not offer an /evaluate operation. The tool author would therefore have to write a logic like the following to achieve their goal.
candidates = search()
for product in candidates:
if has_size(product):
if in_stock(product):
if shipping_date <= x days:
compute total_price
When MCPs are used in front of existing APIs, tools are supposed to serve the experience layer required by the agent. But as you can see from above, the business logic of evaluating a product has now moved to that experience layer. This is all because the API itself is not built for AI. Resulting in anti-patterns in the architecture.
When APIs don’t encode semantics, tools are forced to invent them.
Getting API designs right for AI
Let’s look at a couple of ways we can improve API design to make APIs AI-ready.
Make intent explicit, not implicit
Tools reconstruct business meaning from low-level endpoints. Improve this by adding intent oriented operations even if they call internal API endpoints.
For example, POST /products-recommend would make the API be able to perform recommendations on products. It would take in as input things like budget, size, delivery SLA, preferences, etc and provide a recommendation. This would prevent multi-call fanouts and make behaviour predictable.
Use machine readable errors and semantics
Tools parse strings like “unavailable” and makes guesses. Having proper error codes prevents heuristics and makes retry behaviour safe.
For example, Error codes like OUT_OF_STOCK, INVALID_VARIANT, PRICE_CHANGED leaves no room for guesses, making agents more efficient and accurate.
First-class idempotency and safe retries
Agents retry constantly, and not every retry is safe. Picture a checkout that's slow to confirm. The agent, unaware of the delay, retries the operation. Without protection, that's a duplicate charge.
An idempotency key solves this: the agent generates a unique key per write operation. The server stores that key alongside the request hash and response. If the same key comes in again, the server returns the cached response instead of processing the request twice.
Support dry-runs
Tools must bolt on safety checks to protect against errors on irreversible actions. Think of a check-out process where users are given notices on the final price, delivery date, and so on. An actual check-out will process the transaction without opportunity for validation, without reverse. To protect against these, APIs must provide dry-run operations.
POST /checkout-dry-run
Another possible approach is to allow two phase commits.
POST /checkout → creates confirmation_id
POST /confirm-checkout/{confirmation_id}
Offer bulk endpoints to prevent fan-outs
Agents iterate over items looking for “best-possible” options. They end up calling endpoints N times for N items. These endpoints were meant to be called infrequently and therefore can explode due to the patterns in them being used by agents. This can be prevented by offering bulk endpoints for agents to use.
POST /products-batch-get
{
“ids”: [1, 4, 7, 13, 21]
}
This is probably one of the highest ROIs for agentic patterns.
Runtime enforcement for agent traffic
Enforcing runtime policies are critical to make APIs AI-ready. Let’s look at a few examples of what runtime enforcements can be done to make APIs AI-ready.
Identifying and classifying the caller as an AI consumer
This is critical to any API that is consumed by an AI agent. Human apps and agents should not be treated the same. Human apps are deterministic, agents are not. It is therefore critically important to distinguish between them to apply guardrails on APIs.
API gateways can add context into requests, such as
- Agent identity (workload identity, client credentials, etc.)
- Tool identity (which MCP tool is making this call)
- User on behalf of context (end user ID, consent scope)
This context can be used by APIs to enforce limits and rules on API calls based on who is accessing the API.
Safe write protections for autonomous clients
Unlike humans, agents retry a lot. Humans understand when something is taking longer than expected, they don’t retry beyond a certain limit. For example, if a payment processing request is taking longer than expected, humans won’t retry/refresh due to the complications involved in it. But to an agent, a “payment” is just another step in a series of steps required to accomplish a particular task. If it is taking longer than expected, an agent would happily retry without considering its consequences. Preventing such behaviour becomes critical in production systems. Following are some mechanisms we can use to do so.
Enforcing idempotency on writes
One mechanism to avoid duplicate writes is to require an Idempotency-Key on every write operation. Here’s how this would work:
- Check if Idempotency-Key exists on request.
- Reject the request if it doesn’t.
- If an Idempotency-Key exists, check if the same key has been used before.
- If not, process the request, cache the key and the response.
- If the key has been used before, respond with the previously cached response without processing the request again.
Two-phase commit for sensitive operations
Humans may grant permissions for agents to perform actions on their behalf. But this shouldn’t mean that agents can perform all such actions. Taking the payment example again, an agent may be given permission to make payments on behalf of a user. A traditional API gateway would check for the permission (scope) associated with the token of the caller (agent). However, special consent checks may be required to process payments larger than $100. This requires the API gateway to make additional checks to verify a signed consent header from the user before processing the transaction.
Dry-run requirement
When humans perform actions themselves, they get to review everything until the very last step. But when agents perform actions, the final step review may not be considered as important. Making a purchase for example may include unexpected charges due to taxes, shipment, or other reasons. These may not have been visible at the point of selecting the product and only visible just before payment. Preventing these kinds of situations require performing dry-run checks to simulate the final price.
API gateways can enforce dry-run operations n minutes before performing the actual operation. This can be implemented by introducing an API resource for the dry-run operation (POST /checkout-dry-run) and another resource for the actual operation (POST /checkout-confirm)
AI ready API discovery
Traditionally, APIs are made available on developer portals for discovery. These developer portals are made for human developers. Human developers browse these portals with a use case for an application in mind, search for APIs, read through their documentation, figure out the required orchestrations, and build applications.
AI agents require machine readable content, preferably in text format. Fancy portals with images, styles, and HTML content are not very useful for these agents.
Expose capability endpoints
APIs, by design, expose implementation details of operations. Agents require capability endpoints, not implementation detail. Think of a flight booking example. An API system would typically expose the following endpoints.
GET /flights?origin=LHR&destination=JFK&date=2026-07-15&return=false
GET /flights/{id}/seats
POST /passengers
POST /bookings
POST /bookings/{id}/payment
The caller of these APIs need to understand the data model, figure out the sequence of endpoints to call and execute them in order. This works fine with human developers and deterministic applications. Because, once you get it right, it always works the same way. But think of an AI agent. There is no guarantee an AI agent will get the flow right every time, it is probabilistic. Even if it does manage to get the sequence right, having to figure out the sequence every time a flight has to be booked is a massive waste. Ideally you would build an MCP tool for flight bookings and expose the tool to the AI agent. However, MCP tools aren’t a necessity for AI agents. They can work well with direct API endpoints too.
Modern portals should expose capability endpoints so that they better serve AI agents. The Arazzo specification is a good way to document capability endpoints. An Arazzo workflow will represent a capability while workflow steps will represent API endpoints and orchestrations within them.
Make APIs self describing for AI
A large amount of “API context” that makes sense for human beings is not so for agents. For example, when an agent decides to execute a certain sequence of actions to achieve a goal, it will try and retry each action until it gets the task done. Assume one of these actions involves a financial transaction. Retrying such a transaction could have serious consequences. Given a reasonable description of such an operation, a human developer would easily understand its significance and program against it accordingly.
OpenAPI, AsyncAPI, RAML, and other standards that are used to document APIs are good at documenting the technical specifications of the APIs, however the other inherent capabilities of APIs have not been considered. Developers have to take into account the following factors for documenting their APIs.
- Explicit operation intent descriptions
- Clear side-effect classification
- Retry semantics
- Idempotency requirement flags
- Cost hints
- Rate classification
- Sensitivity classification
Here is an example of how some of this information can be given to AI agents.
x-ai-metadata:
side_effect: irreversible
retryable: false
requires_confirmation: true
sensitivity: financial
estimated_cost_unit: 5
Expose a machine readable capability registry
Traditional portals designed for humans would list a collection of APIs with a little bit of metadata. An AI agent browsing such a portal looking for APIs would have to first get the list of APIs and iterate through, fetching for more data on each one of them. This makes it quite hard for the agent to find relevant information of each API and inefficient as well. To solve this problem modern portals should expose a machine readable capability endpoint, such as
GET /.well-known/ai-capabilities
{
"capabilities": [
{
"name": "recommend_products",
"description": "Find best products within constraints",
"safe_for_agents": true,
"side_effect": "none",
"max_results": 50
},
{
"name": "place_order",
"safe_for_agents": false,
"requires_confirmation": true
}
]
}
This way, AI agents get to discover capabilities offered through the developer portal without heavy iterations and scraping.
Making APIs AI-ready isn't about replacing REST, OpenAPI, or even adopting MCP. It's about recognizing that the consumer has fundamentally changed. As software evolves from deterministic applications to autonomous agents, APIs must evolve from exposing implementation to expressing intent, capabilities, and safe execution. AI readiness is therefore not another integration feature; it is the next chapter in API design.
Summary
The API economy connected applications. The AI economy will connect autonomous decision-makers. That transition demands more than wrapping existing APIs with MCP servers or LLM tools. It requires APIs that communicate intent, expose capabilities, support safe autonomy, and provide the governance needed for machine-driven consumption. AI readiness isn't another feature to bolt onto an API platform it is the next evolution of API design itself. The organizations that recognize this shift early will be the ones whose digital capabilities become first-class building blocks for the agentic enterprise.