Skip to content
API Reference
Admin
Unified Access Gateway

Autonomous Agent Access

Let agents call API-key-backed MCP servers through a Unified Access Gateway as themselves, with no user in the loop

Some agents do work of their own, with no person in the loop. Those agents can call MCP tools through a Unified Access Gateway by authenticating as themselves: Access Policies decide what an agent can reach, and each call is recorded in the audit log under the agent’s identity. For why an agent should have its own identity, see Give an agent its own identity.

The agent gets an access token from Keycard using its own identity (behind the scenes, the SDK uses the client_credentials grant) and sends it to the gateway’s MCP endpoint.

To keep credentials fully separated, there are two actors in the flow: the agent communicating with the gateway, and the gateway acting on behalf of the agent toward the upstream. On each request, the gateway exchanges the agent’s token with Keycard, which runs a policy check for each actor before the request is allowed through:

CheckPrincipalContext
Subject checkThe agentcontext.on_behalf == false
Delegation checkThe gatewaycontext.on_behalf == true

Access is configured entirely through Access Policies: a Policy permits the agent for the gateway it connects through and for each upstream it may reach.

  1. Author the Policy

    Permit the agent for the gateway and each API-key upstream, scoped to the agent acting as itself (context.on_behalf and context.impersonate both false):

    @id("nightly-report-agent-access")
    @description("Permit the reporting agent the gateway and its API-key upstream")
    permit (
    principal is Keycard::Application,
    action,
    resource
    ) when {
    principal.identifier == "<agent-app-identifier>" &&
    ["<gateway-mcp-url>", "<upstream-mcp-url>"].contains(resource.identifier) &&
    context.on_behalf == false &&
    context.impersonate == false
    };

    An agent permitted for the gateway but not for an upstream connects successfully and is denied that upstream’s tools.

  2. Add it to your policy set

    Add the new Policy to your policy set and activate the set. See Access Policies for authoring and activating policy sets.

Copy the gateway’s MCP Access URL from its Application settings page and your Zone’s Issuer URL from SettingsConnection. The SDK handles authentication for the agent and brokers a token for the gateway. The agent then calls the gateway like any MCP server. This example uses the Keycard LangChain SDK:

import os
import httpx
from mcp import ClientSession
from mcp.client.streamable_http import streamable_http_client
from keycardai.langchain import Access, KeycardGrantMiddleware
GATEWAY_URL = "<gateway-mcp-url>"
keycard = KeycardGrantMiddleware(
zone_url=os.environ["KEYCARD_ISSUER"],
resources=[GATEWAY_URL],
client_id=os.environ["KEYCARD_CLIENT_ID"],
client_secret=os.environ["KEYCARD_CLIENT_SECRET"],
)
async def list_gateway_tools():
with keycard.grant(Access.as_self(), resources=[GATEWAY_URL]) as access:
token = access.access(GATEWAY_URL).access_token
http_client = httpx.AsyncClient(headers={"Authorization": f"Bearer {token}"})
async with http_client, streamable_http_client(GATEWAY_URL, http_client=http_client) as (read, write):
async with ClientSession(read, write) as session:
await session.initialize()
return (await session.list_tools()).tools

There is no sign-in and no authorization prompt: your Policies already authorized the access.

In Keycard Console, open the agent Application’s page and select the Activity tab: each run shows the credential issuance events for the gateway and the upstream, with no user attached. See Read an Activity Feed for how to read the feed.

Remove the agent’s Policy from your policy set, or remove the upstream from that Policy if the agent should keep its other access. The gateway checks policy on every request, so the agent’s very next request is rejected. There is nothing to revoke. The denial shows up in the Audit Log as a denied exchange.

Revoking a user’s access works through grants instead. See Revoke a Grant.

  • The token exchange fails with invalid_target. Either the upstream uses per-user OAuth (which stays on the user path), or the Resource has no vaulted credential yet. For the latter, add one on the Resource with Add credential.
  • The agent gets a token but an upstream’s tools are missing or denied. No Policy permits the agent for that upstream. Being permitted for the gateway is not enough. Add the upstream to the agent’s Policy, then retry. See Diagnosing policy-blocked actions.
  • After activating a custom policy set, an upstream is unreachable through the gateway despite an agent permit. The set is missing the managed default-app-direct-access policy, which the gateway needs for its own access to the upstream. The denial appears in the audit log with the gateway as principal. Add the managed policy back to the set.