Skip to main content

Secrets and connector credentials

Connector credentials are stored in your Secrets Manager, reach a sandbox only for the duration of one execution, and never appear in a Lambda function's configuration, a table, a log line or a Library. An MCP connector's credential never reaches a sandbox at all: Studio calls the server's tools itself. This page covers where each secret lives, how it reaches code, how MCP tool calls are made, how the AWS connector avoids storing any long-lived secret at all, and exactly what travels when a resource is shared between deployments: a connector's setup, never its credential.

Who this is for​

Security engineers reviewing secret handling, and administrators deciding what may be shared through Libraries.

Before you start​

Connectors are defined by users in Studio: SQL (PostgreSQL, MySQL), Snowflake, REST or OpenAPI, MCP and AWS. The user-facing pages are under Data connectors. Sharing is described for users in Libraries and sharing.

Where credentials live​

StoreHoldsWho reads it
alphaagent-data-connectors (DynamoDB)The connector's non-secret definition: type, name, host, database, auth type, an MCP connector's chosen tools and approval settings, versions, the names or count of secret headers, how it holds its credentialThe data-connector service
alphaagent-data-connector-secrets (Secrets Manager)One JSON body with an entry per connector id: the credential (password, token, key pair, client ID and secret, External ID) and any request headers you marked as secret. This is the binding to this Studio: it is never copied to another deploymentThe data-connector and code-interpreter services, through the Studio task role
alphaagent-connector-creds-<agent id> (Secrets Manager)The credentials of the connectors one agent's live sandbox sessions hold, written when a session starts, refreshes or ends. A connector just removed from the agent stays until the sessions holding it end (they expire after four hours idle)The sandbox, through the scoped session for that agent only
data-connector service memoryAccess tokens an MCP connector fetched with client credentials, and credentials from a role it assumed, each until shortly before it expires; keyed by connector and credential version, so a rotated credential never reuses a tokenThe data-connector service only; never written to a table, a secret or a log
alphaagent-dc-user/<connector id>/<person> (Secrets Manager)One secret for each person and each connector where each person signs in: their OAuth or Microsoft tokens, or their own key values. Nothing personal in its name or tags. Deleted at once when the person presses Disconnect and when the connector is deletedThe data-connector service only; never returned by any route, never copied to another deployment, never sent to the sandbox, never read by Organisations
alphaagent-trusted-ca-bundle (Secrets Manager)Your trusted certificate authorities, as PEM, written by Organisations; public material, not a secret, kept here so every reader gets it the same wayThe data-connector and web-browsing services at start, and the sandbox at its first invocation and every five minutes after

The Studio task role may read secrets named alphaagent-*; the sandbox scoped role may read only alphaagent-connector-creds-*, and each session is narrowed to the one secret for the invoking agent. See Sandbox isolation.

How a credential reaches running code​

At the start of an execution the sandbox handler fetches the agent's connector secret and flattens the connectors of the invoking session, one version of each, into environment variables for the child process only, named CONN_<connector id>_<KEY>. A connector another session of the same agent holds is never injected. A SQL connector surfaces host, database and credentials; an MCP connector surfaces only its type and name (CONN_<connector id>_TYPE, CONN_<connector id>_NAME), never its URL, a header or a credential; a Snowflake connector surfaces the account, user, role, warehouse, database, schema and either the access token or the private key and passphrase. The handler's own process environment is never changed, so nothing is left for the next invocation, and the function's configuration never carries a value.

Shell commands run under bash: connector ids contain hyphens, and /bin/sh would drop those variables before the command runs.

A credential is only issued for a connector the invoking conversation or run holds. The per-agent secret is written from the agent's live sessions, the handler injects only the invoking session's own connectors, and the session policy prevents a sandbox from reading any other agent's secret. A custom environment image built from an earlier download of the handler injects the whole per-agent secret when the delivered handler cannot run; rebuild it from the current download (How agents run code).

MCP connectors: Studio makes the call​

An agent calls an MCP server's tools as its own tools, and every call is made by the data-connector service, not by the agent's code:

  1. agent-runtime offers the agent only the tools enabled on the connector, and sends each call (agent, connector version, tool name and arguments) to data-connector. That route accepts Studio's own services only.
  2. data-connector checks that the agent holds the connector, that the tool is enabled in both the version the agent pins and the latest version (switching a tool off applies at once), and whether it asks before running in either.
  3. A call that asks waits for a person's decision in chat, on the board or in the Inbox. The decision is bound to the agent, the connector, the tool and a SHA-256 hash of the exact arguments; an allow is used once, a deny stands, and no decision within 30 minutes means not run. The model never sees the decision's id.
  4. data-connector signs in: with client credentials it fetches a token from the token endpoint (behind the same network checks as the server) and keeps it in memory; with AWS IAM it signs each request with AWS Signature Version 4, using the Studio task role (which may call bedrock-agentcore:InvokeGateway) or a role it assumes with that connector's External ID; with headers or query parameters it adds your values. Redirects are never followed, on the server or the token endpoint.
  5. A result over 25 MB is refused; a long result is written to the run's workspace as a JSON file, which the agent's code can read like any other workspace file.

Each outcome writes one [MCP-AUDIT] line to the data-connector service's log (ids, the tool name, the outcome, the approval and who decided, a hash of the arguments, the duration and the result size), and each decision an [MCP-APPROVAL] line; neither carries the arguments, the result, a token or a header value. The route that hands connector credentials to the sandbox returns nothing for an MCP connector.

Connectors where each person signs in​

For a connector where each person signs in, data-connector chooses the credential by the person the call is for: the person whose chat, workflow run or schedule it is. A run started with an API key has no person and is refused. Studio signs the person in with OAuth 2.1 and PKCE (or Microsoft Entra ID for the on-behalf-of method), keeps their tokens in their own secret, refreshes them under a lock so a rotated refresh token is never lost, and on Disconnect revokes them where the provider allows and deletes the secret. A connection is bound to the address, scope, client and tenant it was made for: if the connector changes where a token would go, the connection is not used until the person reconnects. When a person has no connection, the call waits for them rather than failing, and the check comes before any approval.

Three controls sit beside the credentials. A Connector policy set in Organisations limits the MCP hosts and sign-in methods (Connector policy, credentials and activity). Each call writes an audit row that Organisations collects: identifiers, the outcome, who approved it and optionally a SHA-256 fingerprint of the arguments, never the arguments, a result, a token or a header value. And a health pass checks each active MCP connector about every 15 minutes and raises the banners on Banners you may see.

The AWS connector: a role you own​

An AWS connector holds no long-lived key. You create an IAM role in your own account whose trust policy allows the deployment's task role to assume it, on the condition that sts:ExternalId equals a value Studio generated for that connector. Studio then:

  1. Reads the role's trust policy when you save or test the connector and refuses a role whose trust does not actually enforce the External ID condition, so a successful test proves the anti-confused-deputy check is in place, not just that a call succeeded.
  2. At run time, calls sts:AssumeRole and hands the sandbox the resulting temporary credentials. They expire on their own, and what the code can do is exactly what your policy on that role allows.

Secret headers on REST connectors​

A REST or OpenAPI connector can carry request headers. Headers you mark as secret (for example an Authorization or API-key header) are stored in the credential secret, not in the table; the table keeps only their names or count. In a Library, the item shows auth_type, header_count and whether an OpenAPI specification is attached, never a header value.

What sharing relays​

Sharing has two halves, and they are deliberately different. Neither moves a credential: a connector's definition is shared, and each deployment supplies its own credential.

Push catalogues. When a user shares a resource, Studio writes a request row in its own account. The Organisations engine, which already polls every registered account, picks it up, re-derives from its own membership rows that the requester is a Contributor on that Library, and catalogues an item: a pointer to the source version plus display fields. Nothing read from the request row is treated as authorisation, and no credential, graph content or table data is ever written to a Library.

Pull relays. When a user downloads an item or updates their copy, the engine opens two sessions, one into the source deployment's account and one into the target's, reads the source live, and writes the target. For a connector it reads and writes the definition only: it never reads the source account's credential secret and never writes the target account's. What travels per type:

TypeCatalogued in the LibraryRelayed on pullSensitive material
AgentAgent id, version, name, type, description, and its dependencies (connectors, environment, knowledge graph, versions)The pinned agent version, re-read live; a new agent row in the target with re-wired pins when pulled as part of a bundleNone on an agent row
WorkflowPer node, the agent's pinned version and that version's pins; a pull-ordered dependency listEach dependency through its own adapter, then the graph with re-mapped agent ids; lands as a draft to activateFollows each dependency
ConnectorId, version, type, name, endpoint host, auth type, how it holds its credential, status, header count, whether a specification is attachedThe definition re-read live with credential fields stripped and secret header values left out (their names travel), including an MCP connector's chosen tools and approval settings. The copy is marked as needing a credential (Needs a credential in Studio) unless its sign-in method needs none. Update my copy writes a new version of the definition, checks only whether the target already holds a credential for it, and never changes that credentialNone: no credential leaves the source account. An MCP connector that signs in with client credentials or AWS IAM is refused, by name and before anything is written, when the receiving Studio release cannot read those sign-in methods
AWS connectorAs aboveThe role ARN and region; never the External ID. The receiving Studio generates its own External ID when the copy is opened, and the copy reads "Open Role setup to get this Studio's External ID, add it to the role's trust policy, then test the connection."Your role's trust policy decides who may assume it, one External ID per Studio
EnvironmentThe row and image referenceA custom image is copied by digest from the source account's repository into the target's; built-in images carry their nameRegistry tokens per account, nothing else
Knowledge graphA pointer to the version plus node and edge countsA one-shot task in the source exports the version to the source staging bucket; the engine copies it to the target staging bucket; a task in the target imports it as a new versionNeo4j credentials come from each deployment's own configuration secret

Every pulled copy records where it came from: Library, item, version, source deployment, who pushed and who pulled, and when, and that no credential was copied. Connectors downloaded before Libraries stopped copying credentials keep the credential they arrived with; Studio labels them Copied credential until their owner stores their own.

Steps: verify secret handling in your account​

  1. In Secrets Manager, filter by alphaagent-. You should see the configuration shells, alphaagent-data-connector-secrets, alphaagent-trusted-ca-bundle, and one alphaagent-connector-creds-<agent id> per agent that has run code with connectors.
  2. Open any alphaagent-env-* Lambda function. No CONN_ variable in its configuration.
  3. For an AWS connector, open the role you created. The trust policy carries Condition: StringEquals sts:ExternalId, and the principal is the deployment's task role.
  4. In the Organisations console, open a Library that holds a connector and read its item. Endpoint host, auth type and Credential are shown; no credential value is.
  5. Download a connector into another deployment, then read CloudTrail in both accounts: the Organisations target role makes no GetSecretValue on alphaagent-data-connector-secrets in the source account and no PutSecretValue in the target.
  6. Run an agent with an MCP connector and an execution that prints its environment: only CONN_<connector id>_TYPE and CONN_<connector id>_NAME appear for it.

What you should see​

  • Secret reads in CloudTrail from the sandbox scoped role name only alphaagent-connector-creds-*.
  • The Library item for a connector changes when the sharer pushes a new version and never carries a value from the credential secret.

Limits​

  • One credential secret per deployment holds every connector's credential; access is by IAM role, not per connector. Per-agent secrets are the narrower unit the sandbox sees.
  • A downloaded AWS connector, or an MCP connector that assumes a role, cannot connect until your role's trust policy names the receiving Studio and its own External ID.
  • Secret headers on a REST connector are classified by you when you create the connector; a header left unclassified is stored as a plain field.

If something goes wrong​

  • A downloaded connector shows Needs a credential: this is by design. Add the credential in the receiving Studio with Add credential; for a role, add that Studio's External ID to the trust policy and test the connection.
  • A test of an AWS connector fails naming the External ID: the trust policy is missing the condition. Add it and test again.
  • A service control policy that denies Secrets Manager stops both the install and every execution; see SCPs and guardrails.