Skip to Content
ConceptsIn-band access requests

In-band access requests

When an agent is missing a permission, the old answer was: the agent fails, a human notices later, and someone opens the dashboard to fix it. In-band access requests close that loop. The agent can ask for exactly the access it needs, right when it needs it, and you decide from your notifications.

What the agent sees

When a governed use_platform call is blocked, the proxy returns a 403 and adds a hint telling the agent it can call request_platform_access({ platform, scope, reason }) to ask an admin to grant it.

If the agent calls that tool, AgentValet:

  1. Records the request and works out why the call was blocked (the reason code, see below).
  2. Notifies your organisation’s admins.
  3. Lets the agent poll for a decision for about 50 seconds.

If you decide inside that window, the agent is told the outcome immediately. If not, the agent is told the request is pending and to retry later. Either way the request itself stays open for 30 minutes.

One deliberate difference from the human-in-the-loop approval flow: approving an access request does not re-run the agent’s original call for it. The agent is told to retry use_platform itself once access is granted.

The reasons a call is blocked

At the moment the agent asks, AgentValet classifies the block into one reason code, in this priority order:

  1. not_connected: no account for that platform is connected at all.
  2. grant_expired: the agent held the scope, but the grant has lapsed.
  3. not_granted: the platform is connected, but this agent was never granted the scope.
  4. needs_consent: the agent is granted on a remote MCP OAuth server, but nobody has completed that server’s consent screen yet, so there is no token to call it with.
  5. scope_denied: the agent has the grant, but a policy is blocking the scope.

The reason code determines what “Approve” is even able to do, which is why some requests are one-click and some are not.

For every reason a human can fix from a page (not_connected, not_granted, needs_consent) the agent’s result carries a connect_url of the form https://app.agentvalet.ai/connect?token=.... Whoever is reading the conversation can open it, sign in, and finish the request: connect the account, grant the scope, or authorize the MCP server. The token is a reference, not authority: every action on that page re-checks your session, your organisation and, for grants and consent, your admin role.

An MCP server consent is raised by the proxy itself, not only by request_platform_access. A governed call to a granted but unauthorized OAuth MCP server is refused with 409 needs_consent before anything is queued, the request is created at that moment, and the same connect_url and poll_url come back in the refusal. On the stdio server the call is held open: if your client supports MCP elicitation, the link is presented in place and the call resumes on its own once an admin has authorized the server. On the in-proxy remote server (claude.ai connectors) the tool fails with the MCP UrlElicitationRequired error carrying the link, and the model re-invokes it after you are done.

What approving does

  • not_granted: approving grants the scope. AgentValet merges the requested scope into the agent’s platform-wide permissions so the retry succeeds.
  • scope_denied: approving adds an allow rule to the requesting member’s assigned policy for that platform and scope. This requires two things: the request has to carry a specific scope, and the member has to already have a policy assigned. If they have no policy, you are asked to assign one first.
  • not_connected: approving before an account exists returns “connect first”. The /connect page does the connection for you and then falls through to the grant.
  • grant_expired: approving cannot revive a lapsed grant and says so. Re-grant on the agent’s page, where you choose the duration.
  • needs_consent: the Approve button is not the remedy. The /connect page shows Authorize, which runs the MCP server’s own consent screen; when the token lands the request closes itself. Approving while the token is still missing returns consent_pending.

Denying works for every reason and simply records the denial.

Guardrails on the request

  • Admins only decide, and only for requests inside their own organisation.
  • One pending request per agent, platform, and scope. If a matching request is already waiting, the agent is pointed at the existing one instead of piling up duplicates.
  • Requests expire after 30 minutes.
  • Every approve or deny is written to the audit log (agent.access_granted or agent.access_denied), and the requesting member gets a notification of the outcome.

Next

Last updated on