Author: Christopher Emerson

  • What Is Discovery-by-Introspection for AI Agents?

    Short answer: Discovery-by-introspection is a mechanism that tells an AI agent what it is allowed to do at the moment its credential is checked. When the agent exchanges or validates its token, the response comes back with an operational map: the endpoints its scope permits, and for each one that takes input, the exact fields, types, and which are required. The map is filtered to the agent’s granted scope, so a read-only agent is never even shown a write operation. The agent arrives knowing nothing about the app and is fully operational from that one response, with no documentation and no manual integration.

    The problem it solves

    Connecting an agent to an app normally means someone reads the API documentation and builds an integration: base URLs, endpoint lists, field names, request formats. That work is slow, it breaks when the API changes, and it does nothing for authorization. Worse, discovery and permission are usually separate systems, so an agent can often see far more of an API than it is allowed to use, and what it can use is documented for humans, not for software that has to construct valid requests on its own.

    Without structural information, an agent guesses. It sends a field named “project_title” when the endpoint expects “name,” gets a validation error, and retries. Multiply that across every endpoint and every app, and agent integrations become brittle exactly where they need to be dependable.

    How discovery-by-introspection works

    The mechanism runs at the same moment the agent’s credential is validated, in either of two ways: during the initial token exchange, or later, when an agent with an existing token asks the introspection endpoint to refresh its view. That refresh works only while the user’s grant is still alive. The user sets how long access lasts when they approve the connection, anything from an hour to thirty days to until-I-revoke, depending on what the app offers, and once the grant expires or the user revokes it, there is nothing left to introspect. The agent has no way to renew access on its own; getting back in takes a fresh grant from the user. Either way, the sequence is the same.

    1. The agent presents its credential. No prior knowledge of the app is required.
    2. The system identifies the app and the agent’s granted scopes from the credential.
    3. The full capability map is filtered down to the agent’s scope. Operations that require permissions the agent was not granted are removed, not grayed out. Two agents connected to the same app with different scopes receive different maps.
    4. Field-level schemas are attached. Every authorized operation that accepts input comes with its required fields, optional fields, data types, and descriptions.
    5. One response returns everything: the app’s identity, where to send requests, and the filtered, schema-complete operation map.

    The response is execution-enabling rather than descriptive. It is not documentation for a person to read; it is structure an agent can act on directly, and it stays valid whether the agent calls the operations over HTTP or registers them as tools in a tool-use framework.

    Why filtering by scope matters for security

    Least privilege usually stops at enforcement: the agent is blocked if it tries something out of scope. Discovery-by-introspection moves least privilege up into visibility. An agent granted read-only access receives a map containing only read operations, so the write surface of the API is not merely forbidden, it is invisible. An agent cannot be steered toward operations it has never been told exist, which shrinks what a compromised or manipulated agent can even attempt. And because the map is regenerated from the live grant, revoking or narrowing a scope changes what the agent sees, not just what it is permitted.

    When an agent genuinely needs something outside its grant, there is a path, and it runs through the user. The denied request comes back naming the specific permission that was missing, so the agent can tell the user exactly what it needs and why. Granting it is a step-up: the user approves the additional scope through the same authorization flow they used the first time, or declines. There is no API through which an agent can expand its own permissions, so scope escalation always requires a conscious human decision.

    How this relates to the self-describing credential

    They are two halves of one connection story. The self-describing credential gets the agent to the door: the token itself tells the agent where to exchange it. Discovery-by-introspection is what the agent receives once inside: the scope-filtered, schema-complete map of what it may do. Together they take an agent from “holding a token” to “making correct, in-scope API calls” in a single exchange, with the user’s grant deciding both access and visibility. Both begin with user-mediated authorization: the user approves the scope, and everything the agent sees downstream flows from that choice.

    Frequently asked questions

    Is discovery-by-introspection the same as API documentation or an OpenAPI spec?

    No. Documentation describes the whole API for human developers, regardless of who is asking. Discovery-by-introspection returns a per-agent view at credential-check time: only the operations that agent’s scope allows, with field-level schemas attached, in a format the agent can execute against directly.

    When does the agent receive the discovery response?

    Either during the initial token exchange, so a single request returns both the access token and the full operational map, or later from an introspection endpoint, so an agent with an existing token can refresh its view of what it is allowed to do without repeating authorization. The refresh only works while the user’s grant is still active: if access has expired or been revoked, the agent gets nothing, and only the user can grant access again.

    What does scope filtering actually change?

    It changes what the agent can see, not just what it can do. Operations outside the agent’s grant are absent from the response entirely, so a read-only agent never learns the write endpoints exist. Enforcement still checks every call, but the attack surface an agent can be pointed at is smaller from the start.

    What happens when the agent needs a permission it was not granted?

    The request is denied with a response naming the specific missing permission, so the agent can tell the user exactly what it needs. The user then approves the additional scope through the same authorization flow, or declines. This step-up always goes through the user; there is no API through which an agent can expand its own permissions.

    Does it work with tool-use frameworks like MCP?

    Yes. The discovered operations carry enough structure to be registered as tools in an agent’s tool-use framework, and the map is independent of transport, so it holds whether the agent calls operations over HTTP or through a tool interface.

    Discovery-by-introspection is one of the inventions behind AgentAdmit, and it is patent pending.

    AgentAdmit is the authorization layer for the agent economy: user-mediated, scoped authorization for AI agents, where one exchange returns the token and the scope-filtered map of everything the agent may do. Scoped. Revocable. Auditable. See how AgentAdmit works.

    Related reading: how to let an AI agent access a user’s account safely and MCP security: how to let an AI agent access user data safely.

  • What Is a Self-Describing Credential for AI Agents?

    Short answer: A self-describing credential is a token that carries everything an AI agent needs to connect, so the agent can start working without separate documentation or configuration. The agent reads the exchange location out of the token itself, exchanges it once, and gets back its access token plus the scopes it was granted, the endpoints it can call, and the request schemas for each one. It turns “here is a token” into “the agent is operational” in a single step, with no shared secrets and no manual setup.

    Why connecting an AI agent to an app is usually painful

    The normal way an agent gets access to an app is a scavenger hunt. Someone reads the API docs, finds the base URL, configures endpoints, wires up an auth flow, and pastes in a key. Every new integration repeats the work, and every step is a chance to over-grant access or leak a secret. The agent ends up holding a broad credential and a hand-built map of what to do with it.

    A self-describing credential removes that work by putting the map inside the token.

    How a self-describing credential works

    Two things make the token self-describing.

    • The agent finds the exchange point on its own. The location where the token is redeemed is encoded in the token itself, so the agent determines where to exchange it without external instructions, documentation, or a separate discovery service.
    • One exchange returns everything. When the agent exchanges the token, it receives its scoped access token along with operational instructions in the same response: which app it is talking to, where to send requests, the specific endpoints its scope allows, and the field-level request schema for each of those endpoints.

    The result is that an agent goes from holding a credential to making correct, in-scope calls without a human writing integration code for it.

    What a self-describing credential gives you that an API key does not

    An API key is a bare secret. It says nothing about who granted it, what it is for, or what the agent may do with it, and it usually unlocks far more than the task at hand. A self-describing credential is the opposite on every count:

    • Zero configuration. No docs, no endpoint list to maintain, no shared setup between your app and the agent.
    • Least privilege by construction. The endpoint map the agent receives is filtered to the scope the user approved. A read-only agent is only ever shown read endpoints, so it cannot discover or call anything beyond its grant.
    • No shared secrets to leak. The agent does not need pre-shared configuration or credentials to learn how to operate, because the token carries what it needs.

    Does a self-describing credential work with any AI agent?

    It works directly with any agent that can make HTTP requests, such as Claude Code, Codex, or a custom agent, because those agents can read the token and call the exchange endpoint themselves. Chat interfaces that cannot make arbitrary calls, like Claude Desktop or ChatGPT, connect through an MCP server that acts as the bridge. Either way the agent gets a token it can act on immediately.

    Where this fits with user-mediated authorization

    A self-describing credential is how the agent operates. User-mediated authorization is how the agent got the credential in the first place: the user approved a scope and the token was delivered to the user, not pushed to the agent through an automated channel. Together they mean the user decides what an agent may do, and the agent can then do exactly that, and nothing more, without a manual integration. For the granting side, see what user-mediated authorization for AI agents means.

    Frequently asked questions

    Is a self-describing credential the same as an API key?

    No. An API key is a bare secret with no built-in meaning, usually granting broad access. A self-describing credential tells the agent where to exchange it and, after exchange, returns the scopes, endpoints, and request schemas the agent is allowed to use, so it operates in-scope without extra configuration.

    How does the agent know where to send the token?

    The exchange location is encoded in the token itself. The agent reads it directly from the credential and sends its exchange request there, with no external documentation or separate discovery step.

    What does the agent get back when it exchanges the token?

    A scoped access token plus operational instructions in one response: the app it is connecting to, where to send requests, the endpoints permitted by its scope, and the field-level request schema for each. That is enough for the agent to start making correct calls immediately.

    Does the token expose every endpoint in the app?

    No. The endpoint map is filtered to the scope the user approved. An agent granted read access is only shown read endpoints, so a self-describing credential stays least-privilege rather than handing over the whole surface of the app.

    The self-describing credential is one of the inventions behind AgentAdmit, and it is patent pending.

    AgentAdmit is the authorization layer for the agent economy: user-mediated, scoped authorization for AI agents, with a patent-pending self-describing token that makes an agent operational in one exchange. Scoped. Revocable. Auditable. See how AgentAdmit works.

    Related reading: how to let an AI agent access a user’s account safely and MCP security: how to let an AI agent access user data safely.

  • MCP Security: How to Let an AI Agent Access User Data Safely

    Short answer: MCP standardizes how an AI agent discovers and calls your tools and data, and it added an OAuth-based authorization framework to go with it. What it does not give you on its own is per-agent, scoped, revocable access that the end user controls. To let an agent access user data safely through MCP, add a layer of user-mediated authorization: the user approves specific scopes, the credential is delivered to the user rather than pushed to the agent through an automated channel, and every call is checked against that grant. MCP handles what the agent can see. User-mediated authorization handles whether it is allowed.

    What MCP handles, and what it leaves to you

    The Model Context Protocol solved a real problem: a common way for agents to find tools, read resources, and call them across different systems. Its authorization spec is OAuth-based and is getting stricter. The protocol’s 2026-07-28 revision hardens authorization with six changes, including issuer validation per RFC 9207 and cleaner dynamic client registration.

    But a protocol that standardizes authentication and transport does not, by itself, answer the question a data owner actually cares about: which specific agent is allowed to do which specific thing with this user’s account, and can the user see it and take it back. That is authorization at the level of the individual user and the individual agent, and it is the part builders keep having to solve themselves.

    The authorization gaps builders keep hitting

    Three problems show up again and again when agents get access through MCP.

    Static, over-broad credentials. An audit of more than 5,200 MCP servers found only 8.5% use OAuth. The majority rely on static API keys or personal access tokens, and most pass them through environment variables. A long-lived key in an env var is broad by default and rarely scoped to the one task at hand.

    The confused deputy. The MCP spec itself warns about it: when a server sits in the middle as an OAuth proxy and does not properly validate consent per client, an attacker can get access to a downstream API as the user without the user’s explicit approval. The spec’s own guidance is that proxy servers must implement per-client consent. The trouble is that this is left to each implementation to get right.

    Injected instructions turning access into exfiltration. Agents read untrusted content, and that content can carry commands. Invariant Labs showed a “toxic agent flow” where a malicious public GitHub issue steered an assistant into exposing private repositories through access it already held. EchoLeak (CVE-2025-32711) showed a single crafted email making Microsoft 365 Copilot leak internal data with no click. In each case the credential was valid. What failed was scoping and control over how that credential could be used.

    How to close the gap: user-mediated authorization on top of MCP

    User-mediated authorization is a model where the account holder grants the agent access directly, and the resulting credential is delivered to the user rather than pushed to the agent through an automated channel. The user hands it to their agent. There is no redirect, no callback, and no automated path between your app and the agent for a prompt injection or a misconfiguration to intercept.

    In practice that means:

    1. The user approves specific scopes in your app’s own UI, in plain language, in their authenticated session.
    2. The credential goes to the user, not the agent. The authorization decision happens outside the agent’s execution context, so an injected instruction has nothing to hijack.
    3. Access is scoped, time-limited, and revocable per agent. The user can pull one agent’s connection without breaking the others.
    4. Every call is checked against the grant, and each grant is recorded, so you can answer who authorized this agent and for what.

    This does not replace MCP. It sits on top of it. MCP tells the agent what it can do. User-mediated authorization decides whether it is allowed, on every call, under the user’s control.

    How it fits with the MCP spec

    MCP’s tightening authorization rules and user-mediated authorization are complementary. The spec’s hardening makes the OAuth plumbing safer between clients and servers. User-mediated authorization adds the piece the plumbing does not cover: end-user, per-agent, scoped consent that the user owns and can revoke. For an MCP server, the addition is small. Carry a user-approved token and verify it, per call, against the scopes the user granted. The agent gets a token it can use immediately, and the user keeps a dashboard of exactly which agents can do what.

    Frequently asked questions

    Does MCP handle authorization on its own?

    MCP provides an OAuth-based authorization framework and is hardening it, which covers authentication and the client-to-server flow. It does not, by itself, give end users per-agent, scoped, revocable control over what a specific agent can do with their account. That user-level authorization is the layer you add on top.

    Is an MCP server secure by default?

    No. Security depends on how it is implemented. Audits show most MCP servers rely on static API keys rather than OAuth, and the MCP spec itself warns that proxy servers must implement per-client consent to avoid confused-deputy attacks. A safe deployment scopes access to specific actions, delivers the credential to the user, and checks every call against what the user approved.

    What is a confused deputy attack in MCP?

    It happens when a server in the middle holds a user’s authorization and passes it downstream without properly checking, per client, that this particular agent was approved for it. The attacker never steals the credential directly; they get the intermediary to use its authority on their behalf. Per-client consent and validating authorization on every call are the defenses.

    Does adding user-mediated authorization slow the agent down?

    Approval happens once per grant, when the user allows it. After that the agent operates within its scope without re-prompting, and a self-describing token lets it start working without extra setup. The user gets control and an audit trail without turning every action into a permission dialog.

    User-mediated delivery is one of the inventions behind AgentAdmit, and it is patent pending.

    AgentAdmit is the authorization layer for the agent economy: user-mediated, scoped authorization for AI agents that complements MCP. The credential is delivered to the user, not an automated channel. Scoped. Revocable. Auditable. See how AgentAdmit works.

    Related reading: What is user-mediated authorization for AI agents? and how to let an AI agent access a user’s account safely.

  • What Is User-Mediated Authorization for AI Agents?

    Short answer: User-mediated authorization is a model where the account holder grants an AI agent access directly, and the resulting credential is delivered to the user rather than pushed to the agent through an automated channel. The user gives the credential to their agent, so there is no redirect, callback, or automated path between the app and the agent for an attacker to intercept. Access is scoped to specific actions, time-limited, and revocable. It is how you answer the question every platform now faces as agents multiply: under whose authority is this agent acting?

    Why AI agents need a different authorization model

    Traditional access was built for two things: a person logging in, or one server calling another with a shared key. An AI agent is neither. It acts on a user’s behalf, often continuously, often across several services at once, and it decides in the moment which calls to make. That breaks the old assumptions in two ways:

    • The credential travels an automated channel. Most agent auth today leans on API keys, OAuth redirects, or environment variables. These move a credential with no human at the point of delivery, so they can be intercepted through prompt injection or misconfiguration.
    • The access is broad and hard to undo. Agents are often handed long-lived tokens that grant far more than the task needs, with no clean way to scope a single agent, expire its access, or revoke it on its own.

    The industry has started naming what goes wrong. Security teams call the accountability problem the attribution gap: the distance between what an agent did and your ability to prove who authorized it. When a credential rides an automated channel and grants broad access, an injected instruction can turn the agent into the attacker, and afterward no one can cleanly say who approved what. A model built for AI agents has to close both halves: the interception risk and the attribution gap.

    How user-mediated authorization works

    Four things keep the human in control at the moment access is granted.

    • The user grants access directly. Approval happens with the account holder, in plain language, for specific scopes. The developer does not stand in the middle holding the keys.
    • The credential is delivered to the user. It goes to the human, who gives it to their agent. There is no redirect, no callback, and no automated path between the app and the agent. This is the piece most systems skip, and it is what keeps the user as the authority.
    • The token is self-describing. The agent extracts where to exchange it from the token itself, and after exchange it receives its scopes, endpoints, and request schemas, so it can start operating without extra configuration or shared secrets.
    • Access is scoped, time-limited, and revocable. The user chooses what each agent can do and for how long, and can revoke one agent’s connection at any time without affecting others.

    How is this different from API keys or a normal consent screen?

    An API key or service account is a single broad secret that moves through an automated channel. It cannot express who approved it, it usually grants far more than one task needs, and revoking it tends to break everything else that shares it. A standard consent screen is better, but on its own it still typically returns the credential through an automated redirect or callback and hands the agent broad access.

    User-mediated authorization changes two things. The credential is delivered to the user instead of flowing to the agent automatically, and access is scoped per agent, time-limited, and revocable. The result is least-privilege access that is provable after the fact, not a broad secret you hope never leaks.

    Why deliver the credential to the user instead of the developer?

    Because that is what keeps the user as the authority. If the developer holds the credential, the user is trusting the developer’s infrastructure with their account. Delivering it to the user means a developer never has to custody raw credentials, and a breach of the developer’s systems does not expose user accounts.

    For a step-by-step version aimed at builders, see how to let an AI agent access a user’s account safely.

    Frequently asked questions

    Is user-mediated authorization the same as a standard login or authorization flow?

    No. It complements standards like OAuth rather than replacing them. It changes how the credential reaches the agent, through the user instead of an automated redirect or callback, and adds per-agent scoping, expiry, and revocation, so the human approves and controls access at the moment it is granted.

    Why not just push the credential straight to the agent?

    Because an automated path between your app and the agent is exactly what a prompt injection or a misconfiguration can intercept. Delivering the credential to the user removes that channel. The user gives it to their agent, so there is no automated hop for an attacker to sit on.

    Does this slow the agent down?

    Authorization happens once per grant, when the user approves it. After that the agent operates within the scope it was given without re-prompting, and a self-describing token means it does not need extra setup to start working. The user gets control and an audit trail without turning every action into a permission dialog.

    What is the simplest first step toward this model?

    Stop moving raw, broad credentials to agents through automated channels. Deliver scoped access that the user approves, make each connection time-limited and revocable on its own, and keep a record of every grant.

    User-mediated authorization with credential delivery to the user is the core invention behind AgentAdmit, and it is patent pending. We have also written the model up for the standards community: you can read our Internet-Draft submitted to the IETF OAuth community (a work in progress, not an adopted standard).

    AgentAdmit is the authorization layer for the agent economy: user-mediated, scoped authorization for AI agents. The credential is delivered to the user, not an automated channel. Scoped. Revocable. Auditable. See how AgentAdmit works.

  • How to Let an AI Agent Access a User’s Account Safely

    Short answer: To let an AI agent access a user’s account safely, keep the credential off any automated channel between your app and the agent. Most agent access today runs on API keys, OAuth redirects and callbacks, or environment variables, and those channels can be intercepted through prompt injection or misconfiguration. The safer path is user-mediated delivery: the credential is delivered to the human, and the human gives it to their agent. Pair that with access that is scoped to specific actions, time-limited, and revocable, and the user stays in control of exactly what their agent can do, with a record of who approved what.

    Why an AI agent changes the security picture

    A normal login authenticates a person who is present and reacting to what they see. An AI agent is different. It acts on the user’s behalf, often continuously, often across several services at once, and it decides in the moment which calls to make. It also reads untrusted content along the way, and that content can carry instructions.

    This is not hypothetical. In 2025, researchers showed that a single crafted email could make Microsoft 365 Copilot pull internal data and leak it to an outside server with no click from the user, a zero-click flaw tracked as CVE-2025-32711 and nicknamed EchoLeak. Around the same time, Invariant Labs demonstrated a “toxic agent flow” on the GitHub MCP server: a malicious public issue steered an assistant into exposing private repositories, using the same access the user had already granted it. In both cases the agent had a valid credential. The problem was what that credential could reach and how it was handled.

    Handing that kind of actor a broad, long-lived credential through an automated channel creates three problems:

    • The channel can be intercepted. API keys, redirects, and environment variables move a credential with no human at the point of delivery, so a prompt injection or a misconfiguration can quietly capture it.
    • The access is broader than the task. A single shared key usually grants far more than the one thing the agent was asked to do, so a leak exposes the whole account.
    • No one can prove or undo consent. If access was arranged through automated plumbing, there is no clean record that the user approved it, and no easy way to revoke one agent without breaking the rest.

    The default today leans into all three. An audit of more than 5,200 MCP servers found only 8.5% use OAuth. The majority rely on static API keys or personal access tokens, and most pass them through environment variables. Long-lived, broad, and sitting on an automated channel is exactly the combination these attacks feed on.

    What user-mediated delivery means

    User-mediated delivery puts the human back in the loop at the moment access is granted. Instead of the credential flowing straight from your app to the agent, it is delivered to the user. The user then gives it to their agent. There is no redirect, no callback, and no automated path between your app and the agent. The developer never has to hold the user’s raw credentials, and the user can see and control exactly what they are handing over.

    The reason this matters is where the authorization decision happens. It happens outside the agent’s execution context, in the user’s own authenticated session. So an instruction injected into the agent has nothing to hijack. There is no programmatic path from “injected prompt” to “new grant of access.”

    A safe-access checklist

    1. Keep credentials off automated app-to-agent channels. Don’t push an API key, a redirect, or an environment variable straight to the agent.
    2. Deliver the credential to the user. Route it back through the account holder, who passes it to their agent.
    3. Scope it to specific actions. Grant the minimum the task needs, in plain language the user approves.
    4. Time-limit it and make it revocable. Let the user set how long access lasts and revoke a single agent’s connection at any time, without affecting others.
    5. Use a self-describing token. A good token tells the agent where to exchange it and, after exchange, hands back its scopes, endpoints, and request schemas, so the agent can operate without extra configuration or shared secrets.
    6. Keep an audit trail. Record who approved which scope and when, and show it to the user.

    What this looks like in practice

    When access is delivered this way, it is least-privilege by default. An agent authorized to read one thing cannot quietly reach everything else. A single leaked token is limited to one scope on one account and can be revoked on its own. And because the user granted access directly and it was recorded, both the user and the platform can answer the question that matters as agents multiply: who authorized this, and for what.

    For the model behind this and why the credential goes to the user in the first place, see What is user-mediated authorization for AI agents?

    Frequently asked questions

    Can I just give an AI agent an API key?

    You can, but it is the least safe option. An API key is usually broad, moves through an automated channel that can be intercepted, cannot express who approved it, and is hard to revoke without breaking everything else that uses it. Scoped, user-delivered credentials limit the damage if the agent or its host is compromised.

    Does user-mediated delivery replace OAuth or a normal login?

    No. It complements standards like OAuth. It changes how the resulting credential reaches the agent, through the user rather than an automated redirect or callback, and adds per-agent scoping and revocation, so the human stays in control at the moment of access.

    Does the agent still end up with a credential?

    Yes, and that is fine. The difference is the path. The credential is delivered to the user, and the user gives it to their agent, so there is no automated channel between your app and the agent for an attacker to intercept.

    What is the simplest first step to make agent access safer today?

    Stop pushing raw, broad credentials to agents through automated channels. Move to scoped access that the user approves and delivers, keep a record of each grant, and make each connection revocable on its own.

    User-mediated delivery is one of the inventions behind AgentAdmit, and it is patent pending.

    AgentAdmit is the authorization layer for the agent economy: user-mediated, scoped authorization that lets AI agents access user accounts with the credential delivered to the user, not an automated channel. Scoped. Revocable. Auditable. See how AgentAdmit works.