Skip to main content
The Secrets API lets room participants (or agents/tools acting on their behalf) store and retrieve per-user credentials during a live session. This is most often used for OAuth flows, but works for any credential you need to keep tied to an individual user rather than a project-wide service.

What it provides

  • Interactive OAuth flows: Request a token, trigger a sign-in prompt for the user, and get back access + refresh tokens.
  • Automatic refresh: Tokens are refreshed automatically before expiry if a refresh token is available.
  • Offline access: Services can reuse stored credentials without bothering the user again.
  • Inventory and cleanup: List what secrets you have stored, or delete ones you no longer need.

When to use the Secrets API

Use the Secrets API when you need per-user credentials inside a room session, such as:
  • An OAuth token to access a user’s Google Drive files.
  • A delegated credential allowing one agent to act on behalf of another.
For project-wide / shared credentials, use Project Secrets instead.

Core API Methods

  • request_oauth_token: Request or refresh a user token. Emits an event if the user needs to approve.
  • provide_oauth_authorization: Client responds to that event, either approving or denying access.
  • get_offline_oauth_token: Retrieve the latest valid credential for background use.
  • list_secrets: View stored secrets (metadata only, never raw values).
  • delete_secret: Remove a stored secret.

How it works (simplified flow)

  1. Your agent/service calls request_oauth_token.
  2. Server checks if a valid credential already exists:
    • If yes → refresh if needed and return it.
    • If no → request the token from the target participant.
  3. Client app shows the sign-in flow, the user signs in, then the client app calls provide_oauth_authorization with the proper code.
  4. Server exchanges the code with the provider, stores the new credential, and returns an access token.
  5. Later, offline calls can fetch or refresh the token without bothering the user.

Permissions

When a service or participant joins a room, it does so with a participant token that declares which APIs it may call. One part of that scope is the SecretsGrant, an allow-list of OAuth endpoints and client IDs that the participant is trusted to use when it talks to room.secrets. request_oauth_token and get_offline_oauth_token first check the caller’s SecretsGrant. That grant sits inside the participant token’s API scope and lists which authorization endpoints and client IDs are allowed.
  • Default allow: Service endpoints generated by ServiceHost fall back to ApiScope.agent_default(), which carries an empty SecretsGrant. “Empty” means “allow all OAuth endpoints,” so everything works until you opt in to tighter rules.
  • Restrict providers: When minting a participant token, add explicit OAuthEndpoint entries. Wildcards (*) match URL prefixes.
from meshagent.api.participant_token import ApiScope, OAuthEndpoint, SecretsGrant

token.add_api_grant(
    ApiScope(
        secrets=SecretsGrant(
            request_oauth_token=[
                OAuthEndpoint(
                    endpoint="https://www.linkedin.com/oauth/v2/*",
                    client_id="YOUR_APP_ID",
                ),
                OAuthEndpoint(
                    endpoint="https://accounts.google.com/*",
                    client_id="ANOTHER_APP_ID",
                ),
            ]
        )
    )
)
In your ServiceTemplate or Service manifest you can add the secrets grant to a specific endpoint. Setting secrets: {} allows all permissions.
yaml
ports:
  - num: *
    type: meshagent.callable
    endpoints:
      - path: /my-agent
        identity: my-agent
        api:
          secrets:
            request_oauth_token:
              - endpoint: https://www.linkedin.com/oauth/v2/*
                client_id: YOUR_APP_ID
              - endpoint: https://accounts.google.com/*
                client_id: ANOTHER_APP_ID

If the grant exists but no entry matches a request, MeshAgent raises a permission error and the OAuth flow stops. Other runtime-secret calls (provide_oauth_authorization, list_secrets, delete_secret) do not read the grant. Instead, they’re automatically scoped to the participant identity (and optional delegated_to value) attached to the room connection, so each participant still sees only their own stored credentials. See the API scopes reference for full details on SecretsGrant and related fields.