When an agent needs a credential for a provider, JoyStream walks these in order and uses the first match:
jstm connection resolve <provider> --workspace <id> prints that walk tier by tier, so you can see exactly which credential an agent will get and why.
Org credential audit
An org owner or admin can see every service credential connected anywhere in their organization, across all workspaces — including workspaces they are not personally a member of. This is a read-and-inspect surface: you see that a credential exists and its metadata, never the secret value. An organization is made of workspaces — the org itself, plus its teams — and each workspace can hold its own credentials. Without the audit there is no single place to answer “what is connected across my whole org, and where?” The audit groups credentials by availability scope:- Org-wide — credentials in the org vault that every workspace can use.
- Selected workspaces — credentials restricted to specific workspaces. A credential restricted to two workspaces appears under each of those workspace groups.
github or discord, type (SERVICE or LLM), status (ACTIVE, NEEDS_REAUTH, or REVOKED), its scope, the owning workspace, and who connected it.
Values are never exposed. No surface in this feature returns token material — not the API, not the CLI, not the UI.Personal vaults are excluded. Credentials a user stored in their personal vault are never visible to org admins.Only an org owner or admin can audit. A non-admin org member sees only credentials for workspaces they belong to.
jstm vault audit from the CLI.
Credential scope
Every credential in the org vault has a scope that decides which workspaces in the org can use it:- Org-wide (
all_workspaces) — available to every workspace in the org. - Selected workspaces (
selected_workspaces) — available only to the workspaces you pick.
all_workspaces and selected_workspaces appear in --json and API payloads.
vault grant and vault revoke commands have been removed. To read a credential’s current scope and its selected workspaces, use jstm vault grant list.
Only an org owner or admin can set a credential’s scope, and only credentials in the org vault are scopeable. Attempting to scope a workspace or personal vault credential is rejected.
How a credential reaches a service
Most tools an agent uses reach their provider through the connector gateway — one destination for every tool call, rather than a separate server per provider. The gateway is the only component that ever holds a provider secret. Three properties of this are worth knowing when you build agents: JoyStream never holds your provider secret. When you connect a service, the OAuth grant is stored by the connection provider. JoyStream records only that the connection exists, which vault owns it, its provider key, and its status. Nothing in a vault row is a token. The connector’s schema is authoritative. Parameter names come from the provider, not from a skill’s own documentation — which routinely disagrees with it,channel_id where Slack actually wants channelId. The action’s schema is captured at build time and frozen into the package, so an agent built today keeps sending exactly the fields it was tested with. At dispatch, parameters are narrowed to the fields that schema declares, and an unexpected field is rejected rather than quietly ignored.
Execution credentials are minted, never stored. A dispatch gets a token scoped to a single service for that one call. Authoring gets a different, weaker token: it can browse the catalog of providers and actions, and it cannot execute anything or enumerate your connections.
Skills backed by a stdio MCP server
A skill backed by an MCP server that runs as a subprocess — rather than through the gateway — is handed its credential in an environment variable, whose name the server itself dictates:DISCORD_TOKEN, GITHUB_PERSONAL_ACCESS_TOKEN, and so on.
JoyStream resolves that name from the server’s manifest first — a well-formed MCP server declares its variables and marks which one is the secret. Failing that, it uses a curated provider overlay, a small map of provider to variable name such as discord → DISCORD_TOKEN. If a server matches neither, JoyStream fails with an error naming the service rather than guessing, and it does the same when a server declares more than one secret variable.
A server’s declared variables are stored in this shape and rendered on its detail page:
type: "secret" marks the variable that receives the credential. A secret variable carries no value or default — it is supplied at run time from your vault, never stored in the catalog. env_vars: null means the manifest declared no variables; it does not mean “no authentication”, only that JoyStream falls through to the overlay.
Whether a skill needs a credential at all is decided by the services it declares it requires, never by whether env_vars is populated. Only an empty required-services set means a skill is genuinely no-auth.
See also
- Audit and scope org credentials — walkthrough.
- Connect a service
jstm vaultandjstm connection