Skip to main content
Wildo.ai Coming soon

Machine and agent access

Let agents act with a person’s permission

A person can authorize a connected tool to act through a particular agent endpoint without sharing a full application session. Wildo binds the token to that destination and retains both the person’s identity and the requesting client’s attribution.

Alex delegates to an agent, which uses a time-limited token to reach MCP or A2A endpoints.

Let agents act with a person’s permission

A person can authorize a connected tool to act through a particular agent endpoint without sharing a full application session. Wildo binds the token to that destination and retains both the person’s identity and the requesting client’s attribution.

The person’s current roles still determine which operations are available.

Example — Approve a tool for one assistant

A tool receives permission to call the selected MCP endpoint. That token does not become permission to call the ordinary application API or a different agent instance.

For engineers

The authorization request names the intended resource. The code exchange reads that stored audience and rejects a different resource echoed by the token request. It then verifies the audience against the registered delegatable endpoints:

This implementation excerpt from oauth-provider-token.backend.service.ts shows the decision in context; explanatory source comments are omitted.

const requestedAudience = grant.resource;
    if (!requestedAudience) {
      throw this._oauthError(ErrorType.AUTHORIZATION, ErrorCustomMessageReference.AUTHORIZATIONS_ACCESS_DENIED, 'invalid_target',
        'the `resource` parameter (RFC 8707) is required for the authorization_code grant');
    }
    if (request.resource && request.resource !== requestedAudience) {
      throw this._oauthError(ErrorType.AUTHORIZATION, ErrorCustomMessageReference.AUTHORIZATIONS_ACCESS_DENIED, 'invalid_target',
        'the token-request `resource` does not match the resource authorized at the authorization endpoint');
    }
    const allowedDelegatedAudiences = this.container
      .get<ResourceServerInstancesRegistryBackendService>(SAAS_SERVICE_TYPES.ResourceServerInstancesRegistry)
      .listResourceServerAudiences(DELEGATED_TOKEN_RESOURCE_SERVERS);
    if (!allowedDelegatedAudiences.includes(requestedAudience)) {
      throw this._oauthError(ErrorType.AUTHORIZATION, ErrorCustomMessageReference.AUTHORIZATIONS_ACCESS_DENIED, 'invalid_target',
        `resource '${requestedAudience}' is not a delegatable agent endpoint (A2A / MCP)`);
    }

Keep identity and business permissions separate

The delegated access claim includes the user, their authorization version and azp, which identifies the authorizing client. Business roles are resolved at request time; granting an identity scope does not grant the ability to edit a record.

Before issuance the provider checks that the user remains active and has a usable authorization version. The delegated token lifetime is capped and no refresh token is returned. The connected tool must return through authorization when it needs a new delegation.

Call through the agent contract

Present the returned Bearer token to the audience it names and use that endpoint’s MCP or A2A contract. The resource server verifies the audience before dispatching the operation. This preserves a different boundary from a machine principal, whose roles belong to the registered service rather than a consenting user.

Carry the delegation into an MCP request

Use the complete discovery and PKCE recipe to obtain accessToken, expiresIn and the original resource. For an MCP delegation, that resource is the exact chosen MCP endpoint, including a named instance when applicable. It is not the application’s general API origin.

After the MCP handshake has negotiated the locally supported 2025-06-18 revision and sent the initialized notification, this illustrative request lists the tools available to the consenting person:

const response = await fetch(resource, {
  method: 'POST',
  headers: {
    authorization: `Bearer ${accessToken}`,
    'content-type': 'application/json',
    accept: 'application/json',
    'MCP-Protocol-Version': '2025-06-18',
  },
  body: JSON.stringify({ jsonrpc: '2.0', id: 2, method: 'tools/list', params: {} }),
});
if (!response.ok) throw new Error(`MCP HTTP ${response.status}`);
const envelope = await response.json();
if (envelope.error) throw new Error('MCP discovery was refused');
const tools = envelope.result.tools;

Select a tool and its argument schema from that authenticated result before calling it. Tool exposure and the person’s current business permissions still determine what can execute. An empty catalogue is not permission to invent a tool name. Other negotiated revisions require their own metadata, so let the client’s transport handle version changes.

OutcomeClient response
Callback state or redirect mismatchReject the callback before attempting exchange
Different resource echoed at exchangeCorrect the client request; the server cannot retarget the consented code
Token sent to another endpointUse the originally authorized resource; do not treat an audience refusal as a role problem
Expired delegationBegin a new authorization; this grant does not return a refresh token
Authenticated operation refusalRespect the user’s current scope/roles and the exposed operation contract

For A2A, apply the same audience-bound Bearer to the selected A2A endpoint using its request and response contract. An agent token does not become a first-party API session merely because both endpoints belong to the same application.

Building a B2B product or an internal tool?

Wildo is not self-service yet. Tell us what you have in mind and we will say plainly whether it fits, and what happens next.