AX
noun
short for Agent Experience.
The overall experience of an AI Agent interacting with a product such as a website or app, especially in terms of how easy or token-efficient it is to use.
Some History
The term “user experience” (abbr. UX) was coined by Don Norman in 1993 while he was working at Apple. The phrase has since become ubiquitous in product development, used to encompass all concepts relating to how users interact with systems, from usability to graphics. If you’re building an app, optimising for UX is sure to be a top priority.
In the early 2010s Software as a Service (SaaS) became the hot new thing, companies were selling software to other companies (B2B). More often than note, a key audience of such software were developers. So in 2011, Jeremiah Lee Cohick coined the term “developer experience” (abbr. DX) to describe how developers feel while using third-party platform offerings.
A fact shared between both UX and DX is the target audience will always prefer a software that has the better experience. For example, Linear became popular due to having a better DX than Jira.
Now, with the rise of AI Agents and more “Claws” in the wild, a new audience of software has emerged. Agents. With this new audience comes a unique set of requirements that traditional software is not fine-tuned for.
Why should you care
As of writing, Codex has over 2 million weekly active users, adding Claude Code, OpenCode, OpenClaw, [insert your agent here] to that number, we’re talking a non-trivial number of agents. These agents search the web, they call CLIs, APIs, write code, and install packages. Let’s say you are a driver of these agents and need your agent to access some data. There are two providers to choose from. One provides the data via a set of API endpoints, while the other has a dedicated CLI to get the data. Chances are, you will pick the provider with the CLI. Why? because it’s much easier for your agent to reason about using a CLI than it is with a set of API endpoints. Even from a purely token-efficiency view, the output of
my-awesome-cli --help
likely has a much smaller set of tokens for the LLM to digest compared to an entire OpenAPI spec (if there even is one).
Let’s look at an admittedly contrived example. Let’s say you ask your agent to book you movie tickets. What cinema are you going to book the tickets at and ultimately attend? The one that only has a website, where your agent has to spin up a browser and click buttons. Or the one that exposes an MCP server to book tickets?
As you can see, if agents are to become our everyday assistants, we (and by extension the agents) will prefer services that make it easy for agents to interact with them. That is, we will prefer products that have good AX.
Sidenote
I know the “Book X for me” example is overused and mostly useless, because people like to be in control of their big purchases like flights (at least for now), but since I go to movies relatively a lot more than I book flights this felt like something I would actually use if it was reliable.
Optimising AX
We’re still figuring out how to build good agent experiences, there are no unanimously agreed upon “best practices”. We still don’t know if CLIs with Skills is a better alternative to MCPs. However, there are emerging patterns that are likely here to stay (in my opinion), and consequently metrics that should be optimised. Let’s go through them.
Revenge of the CLI
Agents are extremely good at writing bash. It’s also good that bash is extremely dense as a “language”. The same thing you could achieve in 10-15 lines of python can be achieved in a single bash command. So it’s a no-brainer for agents to prefer CLIs. Thus, CLI tools that run in bash are also at an advantage over other methods of calling systems. Since the agent already knows bash, it can run all the CLI commands in bash too. If you’re writing a new CLI tool though, how is the agent going to know how to use it (aside from doing --help)?
Skills
There’s a saying “They try to muddy the waters to make it seem deep” and it applies perfectly to how everyone hypes Skills. They are effectively packaged prompts, that optionally tell the model to execute a specific pre-written function that comes package with the skill. This is a useful pattern for familiarising your agent with a CLI it hasn’t seen before, or isn’t well-represented in its weights. Very quickly, the way developers use skills converged to “agent-friendly documentation for new libraries and tools”, and it’s great for that. When it comes to security and governance though, Skills can’t do much. If your CLI needs a secret or API key, your agent needs that token it it’s context to call it. This is obviously a no-go for enterprise and anyone interested in security. Sure, you could write something that handles this securely, but you’d just be reinventing the wheel as we will see in a moment.
MCP
The Model Context Protocol is still finding its footing in this space. It has gone through many iterations. At it’s core, it exposes a set of tools, prompts, and additional context to the agent at runtime. Rather than you having to implement a bunch of tools to call a service, that service simply gives you an MCP endpoint to connect to, loading the necessary tools into the agent. There are some nice advantages of using a protocol like this. Mainly, authentication is covered via OAuth. So you don’t have to create short-lived tokens and pass them to your agent insecurely. The agent can just sign in on your behalf. However, since it’s early days there was one concept that was quite powerful (and underrated) for agentic interactions.
Elicitation
MCP allows servers to request additional information from a client mid-interaction. This is pretty cool. Going back to the cinema booking example, let’s say your agent calls a tool from the cinema’s MCP server that books a specific movie and time. Typically the next step is to select your seats. The user didn’t say what seats they wanted (they couldn’t possibly know in advance). So, the server sends an elicitation request with a list of available seats, asking which seat they would like. The agent can then surface this request to the user and even display a nice UI for them to choose their seat. Had our agent been using a raw API or CLI, this workflow would be much less reliable. You can use Elicitation as a way to ask the user for permission too. When we’re about to book the cinema tickets, before the server performs a payment, it sends a request back to let the user confirm all the details.
Why aren’t more people using MCP?
When MCP initially came out, a lot of people started writing server implementations. Most of them were sloppy API wrapper that mapped every single endpoint to an API endpoint and returned JSON. Thus, they were context-hungry monsters. The other problem of course was that not many people were writing client implementations. Without a client that supports MCP, the server is useless. Popular agent harnesses like Claude Code didn’t support the cooler features like elicitation. As more poor server implementations went around, people got the impression that MCP just sucked. When in reality, the implementations sucked.
Writing useful MCP servers
I’ve written an MCP server at work that is currently running in production. In this section I’m going to share my learnings.
Do not map API endpoints to tools
This is probably the biggest issue in the wild. Developers map a single API endpoint to a single tool. REST APIs are stateless, usually each endpoint typically does one atomic thing. This is not good for agents. The more choices the agent has to make, the less reliable it becomes. You get better results by building workflows around multiple API endpoints. For example, you can have a single global_search tool that calls multiple GET requests from your API, using a predicate parameter to filter results by entities your agent is interested in. As opposed to having an individual search tool for each entity. This is not a hard rule, there are times when it just makes sense for a single endpoint to become a tool.
Your tools don’t need to return JSON
This was something I had to get used to. Of course, MCP communicates via JSON-RPC, but I’m referring specifically to the payload property here that gets sent to the LLM. Truth is, your agent prefers plaintext to JSON. There’s no reason to have the tool return a JSON object that eats up tokens. If you have a POST endpoint that creates an object and then returns the object, the tool for that endpoint doesn’t need to return that JSON. Moreover, you can post-process the output to be friendlier, like converting ISO timestamps. See below.
JSON
{
"id": "0000-0000-0000",
"payload": {
"title": "blah",
"price": 23.20
},
"timestamp": "2026-03-20T04:39:39.189Z"
}
Tokens: 60
Plaintext
Created blah with price 23.20 successfully on 20 Mar 2026, 15:09:39
Tokens: 23
Sidenote Token counts were calculated using Tiktoken.
Use Progressive Disclosure and namespace tool names
This one is really simple but probably the most important. Rather than loading all the tools upon connecting with the client (and obliterating the agent’s context window in the process) simply return something like a tool_search_tool that let’s the client write regex to search for tools they need based on names, parameters and descriptions. The client can also implement this out of the box, so the server doesn’t have to worry about it. Nevertheless, as a server it’s good practice to prefix (i.e. namespace) your tool names with the service they belong to. For example, a GitHub tool may be prefixed with github_ to make searching for it easier.
Codemode
Codemode is a new concept made popular by Cloudflare where the tools are converted to actual coded functions in some language that agent is good at (i.e. Python or JS). For example, the following tool definition
{
"name": "get_weather",
"title": "Weather Information Provider",
"description": "Get current weather information for a location",
"inputSchema": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "City name or zip code"
}
},
"required": ["location"]
}
"outputSchema": {
"type": "object":
"properties": {
"temperature": {
"type": "number",
"description": "The temperature in Celcius"
}
}
}
}
…becomes
function get_weather({ location }: { location: string }): Promise<{ temperature: number }>
Not only is this way less tokens for the agent to digest. It also let’s the agent chain tool calls together in code, interweaving custom logic between tool calls to reach its goal. This is very powerful. The only challenge is making sure the code execution happens in a secure sandbox.
WebMCP
I’m very excited about this. A specification proposed by Google in its early stages that outlines how existing websites can enable agents to interface with them easily. Notably, it lets website owners to define tools on form elements that agents can pick up and use immediately, just as you would define an aria-label for screen readers. This makes the whole “booking a cinema ticket” scenario way easier to do and without the agent having to interpret DOM elements. It just knows what to click and what to input and where. The main advantage of this API is that it makes it extremely easy for website owners to integrate with agents. They don’t need to do deploy a whole new remote MCP server, or write a CLI tool, or rewrite their API, they just update their HTML and it works.
WebMCP is currently available in Chrome behind a feature flag. It’s currently an early stage W3C proposal. So far MS Edge is also onboard, my main concern is if Firefox and Safari will implement it, as that will largely inform the adoption of this protocol on websites.
The future of the web looks pretty crazy. It might be mostly occupied by agents, which is not a bad thing honestly if that means humans spend more time touching grass. One thing is for certain, agents will need better AX when interacting with your software, as that will inform a non-trivial percentage of your product’s adoption.