Delegated User access
Use this pattern when an agent acts for a signed-in User. TypeScript uses AxecAuthClient; Python uses AuthClient. Both start OAuth Authorization Code with S256 PKCE, create a User GrantBundle through consent, and reload live Grants before governed work.
Begin authorization
Section titled “Begin authorization”import { AxecAuthClient, MemoryStorage } from "@axec/sdk";
const resource = "https://axec.example/g/support-agent/mcp";const auth = new AxecAuthClient({ baseUrl: "https://axec.example", clientId: "public-client-id", redirectUri: "http://127.0.0.1:3000/callback", storage: new MemoryStorage(),});
auth.startAuthorization(resource, { allowedConnectors: ["tickets"], scopes: ["mcp:invoke", "connector:proxy"],});from axec_sdk import AuthClient, MemoryStorage
resource = "https://axec.example/g/support-agent/mcp"auth = AuthClient( base_url="https://axec.example", client_id="public-client-id", redirect_uri="http://127.0.0.1:8765/callback", storage=MemoryStorage(),)
authorization_url = auth.authorization_url( resource, allowed_connectors=["tickets"], scopes=["mcp:invoke", "connector:proxy"],)Redirect the User to the authorization URL, then complete the registered callback. TypeScript calls await auth.completeCallback(callbackUrl); Python calls await auth.complete_callback(callback_url). The returned gateway token is bound to one exact Resource and the requested operation scopes. Reload current authority with grantBundle() in TypeScript or fetch_grant_bundle() in Python; a cached bearer does not preserve a revoked Grant, Connection, or attachment.
Public clients use secretless PKCE and cannot exchange a credential. Store pending PKCE state, tokens, and refresh tokens in caller-owned storage, never in logs, analytics, or serialized agent state. For public MCP clients without a client ID, TypeScript also provides resolvePublicClient() to follow protected-resource and authorization-server metadata and register an eligible public client.
Call one governed capability
Section titled “Call one governed capability”Use the mediated proxy when Axec must enforce current authority, policy, approval, credential custody, result masking, and evidence for each action.
const result = await auth.proxyRequest(resource, { connectorKey: "tickets", capabilityKey: "tickets.list", arguments: { state: "open" },});
if (result.kind === "pending") { const state = await auth.actionRequest(resource, result.actionRequestId); if (state.status === "approved") { await auth.retryProxyRequest(resource, result); }}result = await auth.proxy_request( resource, connector_key="tickets", capability_key="tickets.list", arguments={"state": "open"},)
if result.kind == "pending": state = await auth.action_request(resource, result.action_request_id) if state.status == "approved": await auth.retry_proxy_request(resource, result)An immediate result contains the governed response. A pending result is an approval workflow state, not completed work. Polling reads status only; retry only the approved frozen request. Do not automatically replay denied or outcome_unknown work.
Credential exchange is a confidential-server exception for an eligible delegated OAuth Connector. It requires credential:exchange, a matching Grant, and fresh Application proof. A released provider token is secret material, and Axec cannot govern later direct provider calls. Prefer the mediated proxy or MCP path whenever per-action governance matters.
See Act on behalf of a User for the browser and consent flow.
Continue
Section titled “Continue”- Connect an MCP client to invoke admitted tools with the gateway bearer.
- Inspect tool-call evidence after the first governed operation.
- Configure Governance when a delegated action needs policy, approval, or result protection.