Skip to main content
This page is about authenticating to your API and other services when an agent calls a tool. Authenticating to Sidenet is covered under Authentication.

Choosing an auth type

A provider has one auth_type. Pick the row that matches how the upstream expects to be called: Static credentials — bearer, API key, basic, custom — are sent as-is on every call. OAuth 2.0 providers exchange their credentials for an access token, cache it until shortly before it expires, and refresh it for you.

OAuth 2.0 grants

The grant is declared inside auth_config as grant_type. Three are supported: Client credentials — machine-to-machine, and the default when a token URL and client secret are present. Use it for your own API.
Password — for APIs whose only machine access is a username and password presented at the token endpoint. Must be selected explicitly.
Refresh token — a long-lived refresh token obtained from a one-time interactive sign-in, typically for MCP servers fronted by Google or a similar identity provider. Nothing opens a browser at runtime: the platform exchanges the refresh token for access tokens, and when the server rotates the refresh token the new one is written back to the vault.
The Studio’s provider form offers an authorization code option with an authorization URL. The runtime does not perform that redirect flow: a provider saved that way is treated as a static token provider and calls upstream with whatever access_token it holds. Obtain the refresh token once, outside Sidenet, and configure the refresh-token grant instead.
Access tokens are cached per credential set for their expires_in minus a minute, concurrent calls share one token request, and a failed exchange surfaces as the provider’s error rather than a generic transport failure.

Per-user credentials at runtime

Any provider, whatever its auth_type, can also take credentials per end user. Your backend supplies them when it mints the user’s session, keyed by provider id:
Runtime credentials are merged over the provider’s stored configuration, so a partial override works: send only the user’s client_secret and the token URL comes from the provider. A runtime token or access_token short-circuits the OAuth exchange entirely and is sent as a bearer. The optional base_url points that user’s calls at a different host — staging versus production, or a per-tenant instance. GET /v1/tools-auth lists every provider with the credential fields it expects, so you can build the map without reading provider configuration: Credentials persist on the user, not the session: a later mint inherits them, and unattended workflow runs and schedules read the same store. Rotate or remove them with PATCH /v1/users/{userId}. See Authentication.

How this composes with session tokens

Your backend fills tools_auth at mint time. The browser holds a session token that refers to those credentials and cannot read, change or replace them — anything credential-shaped a page sends alongside a session token is ignored. Under the organization API key, a runtimeAuth map in the request body is honoured and wins over the stored credentials, which is how a server-side integration tests a user’s access. See Embedding securely.
Runtime credentials also decide who shares a cached tool result. A walk fetched with organization credentials is shared across the org; one fetched with a user’s credentials is private to that user unless your backend asserts a tenant-wide cache_scope. See Working with large APIs.

Connected apps

Catalogue toolkits — Gmail, Slack, and the rest — authenticate through connected accounts rather than credentials you hold:
  • Org-scoped — one account connected by an admin, used by every user.
  • User-scoped — each end user connects their own account. The agent gets list_connections to see what is connected and connect_toolkit to start the sign-in, which returns a redirect URL for the user.
Which scope a toolkit uses is part of the provider’s configuration. A user-scoped action for a user who has not connected fails with a clear “connect first” result, and scheduled workflows that depend on it are paused with the same reason. See User workflows.

Storage and masking

  • Secrets go to the vault. client_secret, password, refresh_token, tokens and keys are stored encrypted in Supabase Vault; the provider row keeps only a reference. Non-secret settings — grant type, token URL, scope, client id, username, header names — stay on the row.
  • Never returned on read. Every read returns auth_config with secret values replaced by ***ENCRYPTED*** and a has_vault_secret flag. Header names in custom configurations are visible; their values are masked.
  • Preserved on edit. A PATCH merges auth_config rather than replacing it, and any value equal to ***ENCRYPTED*** is skipped, so a read → edit → save round-trip in your own tooling never blanks a secret. Omit auth_secret to keep the current vault entry. A plaintext value sent for a key that lives in the vault is moved into the vault, not left to be shadowed.
  • Masked in logs. Outbound requests log the URL, method, body length, a 200-character body preview and the headers with Authorization and any header whose name contains token, secret, api-key or ends in -key reduced to a length and an eight-character preview. Per-user credentials are never logged, never returned by any endpoint, and never part of a cache key.
The URL is logged in full. If an upstream API takes its key as a query parameter, put it in a custom header configuration instead so it is masked.