Learning Path
Navigate the AXO curriculum
Applications
Principles for Agent-Accessible Services
Six rules that hold regardless of which protocol you end up building on.
In short
An agent-accessible service is one where a program acting for a person can find out what it may do, do it safely, and be held to account for it afterward. Six principles get you there: every action traces to an authorizing human; capabilities are discoverable rather than guessed; permissions are scoped to the task; operations are safe to retry; failures are legible to a machine; and agent traffic is distinguishable in your own logs. They are design constraints, not features — retrofitting any of them after the fact is significantly harder than building with them.
These principles assume the framing from agents as a medium: the caller is a person’s delegate, not an intruder and not a peer. Each principle below is stated, then made concrete.
1. Human accountability
Every action an agent takes against your service must trace back to a specific person who authorized it. Autonomy is about who chooses the steps, not about whether anyone is responsible. If you cannot answer “on whose authority did this happen?” for any write in your system, you do not have an agent problem, you have an audit problem that agents will make acute.
- Carry the authorizing user through every layer — not just the agent’s own service identity. A token that says “this is Acme Assistant” without saying “acting for user 4471” is not enough to reconstruct anything later.
- Record the acting software alongside the acting person, so your audit log can answer both “who authorized this?” and “what performed it?”
- Surface that record to the user, not just to your compliance team. The person who delegated needs to see what was done in their name, and it should be readable as a history of actions, not a stream of API calls.
- Make authority expire. Delegation granted for a task should not persist indefinitely as ambient permission.
2. Capability discovery over documentation-guessing
An agent should be able to learn what your service can do by asking it, at runtime. A human developer reads prose docs once and encodes the result in software. An agent has no such build step: whatever it cannot discover in the moment, it will approximate from prior knowledge of similar APIs. Approximation is where malformed requests come from.
- Publish a machine-readable description of operations, parameters, constraints, and preconditions — a tool list, an OpenAPI document, or both.
- Keep it generated from the implementation. A hand-maintained description drifts, and a confidently wrong description is worse than none.
- Describe capabilities in terms of outcomes a user would recognize (“cancel a subscription at period end”), not internal nouns. The agent is matching against a human’s intent.
- Reflect the caller’s actual permissions where you can, so an agent plans only with operations it can complete.
- Serve documentation in a form a fetcher can read — plain markdown or clean server-rendered HTML. Docs that require JavaScript to reveal their content are, for this purpose, unpublished.
3. Least privilege and scoped permissions
Grant the narrowest authority that lets the task succeed, bounded in scope, resource, and time. This is old security advice with new urgency, because an agent operating under an over-broad grant can exercise all of it in seconds — and because agents process untrusted input (web pages, emails, documents) that may contain instructions designed to make them do exactly that.
- Define scopes around real tasks (“read invoices,” “create a draft order”) rather than around your resource tree. A scope nobody can explain in a consent screen is too coarse.
- Separate read from write, and separate reversible writes from irreversible ones. Spending money, deleting data, and changing security settings deserve their own scopes and their own confirmation path.
- Bound grants by time and by resource. “This assistant, these projects, thirty days” is a far better default than a permanent organization-wide token.
- Give users a place to see and revoke every active delegation, and make revocation take effect immediately rather than at next token expiry.
- Apply limits per grant, not just per account, so one misbehaving agent cannot consume a team’s entire budget.
4. Idempotency and safe retries
Assume every request will be sent more than once. Retry is an agent’s default recovery behavior, and it retries precisely when it cannot tell whether the first attempt worked. If your writes are not idempotent, that ambiguity becomes duplicate charges and duplicate orders — and the customer experiences it as your failure.
- Accept an idempotency key on every state-changing operation and replay the stored result.
- Advertise which operations are safe to retry in your capability description, so an agent does not have to guess.
- Offer a way to check before acting again — a lookup by client reference beats a blind retry.
- Where atomicity is impossible, expose the compensating operation as a real capability rather than a support ticket.
5. Legible failure
A failure response should tell a machine what went wrong, what to change, and whether trying again could ever help. Friendly apology copy is a dead end for a caller that cannot ask a follow-up question. Legibility here is not politeness — it is the difference between an agent that adapts and an agent that hammers a doomed endpoint.
- Use accurate status codes and a consistent structured error body across the whole surface.
- Include a stable machine-readable code, the specific field or resource at fault, and an explicit retryability signal.
- State when to retry rather than leaving it to be inferred — a concrete interval prevents both thundering retries and needless abandonment.
- Treat error codes as public API. Agents branch on them; changing their meaning silently breaks integrations you cannot see.
- Apply the same logic to refusals. If policy blocks the request, say so in a way the agent can relay to its user, so the person knows to take over rather than concluding you are broken. The delegation cycle page has a worked good-versus-bad example.
6. Observability
You should be able to tell agent traffic from human traffic in your own logs, and know which agent. Every strategic decision on this site — what to open, what to gate, what to charge for — depends on measurement you probably do not currently have. Most analytics stacks were built to exclude automation, which means the fastest-growing segment of your traffic is being filtered out before you see it.
- Classify by purpose, not just by name: training ingestion, search indexing, and user-triggered fetches are different relationships even when they come from the same operator.
- Verify identity where you can — signed requests, published IP ranges, reverse DNS — and record the verification outcome, not just the claimed user-agent.
- Log the acting agent alongside the authorizing user on authenticated calls, and keep that association queryable.
- Track outcomes, not just volume. The interesting metric is which agent-initiated attempts succeed, and where the failures cluster — that is your backlog.
- Accept an honest limit: agentic browsers present ordinary browser user-agents, so a share of delegated traffic will never be classifiable. Measure what you can and do not build policy that assumes complete visibility.
Authentication: the honest state of it
Delegated authority is the least settled part of this stack, and it is worth being direct about that rather than presenting a clean picture.
The failure mode to design out
A user handing their password to an agent. It is unscoped, unattributable, unrevocable without a reset, and it defeats multi-factor authentication. Worse, it is what users do when nothing better exists — so the absence of a delegation path is not neutral, it actively pushes people toward the worst option. The same reasoning applies to long-lived personal access tokens pasted into agent configuration: convenient, over-scoped, and effectively permanent.
What works today. OAuth 2.1 remains the practical foundation: the user authenticates with you directly, consents to a specific scope, and the agent receives a token that is narrow, expiring, and revocable. Make the consent screen state what the agent will be able to do in plain terms, keep scopes task-shaped, prefer short-lived access tokens with refresh, and give users a visible list of connected agents. Dynamic client registration matters more here than in conventional integrations, because agents connect to services nobody pre-registered them with.
What is still missing. OAuth expresses that an application may act for a user. It does not natively express a chain — this person authorized this assistant, which called this sub-agent, which reached your service — nor per-action constraints like “up to $200, once, today.” Work on delegated-authority and agent-identity standards was active through 2026 across the IETF and identity industry bodies, but nothing has emerged as the settled answer, and implementations vary. Treat vendor-specific agent-identity features as useful today and unlikely to be the final shape.
What to do in the meantime. Encode the constraints you need in your own authorization layer rather than waiting for a standard to carry them: bound scopes, spending and rate limits attached to the grant, step-up confirmation for consequential actions, and an audit trail that records both the person and the software. Verification of the calling agent’s identity — Web Bot Auth and published IP ranges — is covered on the implementation page.
One last framing. Almost everything above is ordinary good service design applied with less tolerance for slack. Humans route around vague errors, undocumented behavior, and missing idempotency; agents do not. Building for agents mostly means being unable to get away with things you were already getting away with.
Stay Updated
Analysis of AI search, crawler policy and agent standards — sent when there is something worth reading, roughly twice a month. Unsubscribe anytime.