connections.get(...) in an authored tool or MCP server definition to resolve it at runtime.
Connections let you:
- Keep credentials out of your project:
mda deploycollects.envvalues as deployment secrets on every deploy. A connection value stays in the workspace instead. - Give each caller their own identity: A user-owned connection resolves the credential of the person who made the request, so the agent reads that person’s documents and acts under their name. An environment variable holds one value for everyone.
- Skip the OAuth plumbing: Managed Deep Agents runs the authorization round-trip, so a project needs no callback route, token store, or consent screen. These flows are handled automatically by your Managed Deep Agent.
- Reuse one slug across agents: Connections belong to the workspace, so several deployments can resolve the same slug. Each deployment holds its own credential under that slug: run
mda connections create <slug>once from each project root. Rotating a deployment’s value takes effect on its next run, with no redeploy.
Managed Deep Agents is in public beta and available on LangSmith Cloud in the US region only.
Choose a credential owner
Everyconnections.get(...) call names who owns the credential it resolves:
connections.get(...) resolves to the credential value as a string.
A connection is a container, and it belongs to the workspace rather than to an owner. The credentials inside it have owners. There is no --owner flag: the create mode you use sets the owner.
connections.get(...) selects an owner. It does not create one. Asking for an owner with no credential of its own fails the run for agent, and raises a credential_authorization_required interrupt for user. A credential stored under the same slug for a different owner does not satisfy the lookup.
Agent-owned credentials belong to the project’s deployment, so create them after at least one successful mda deploy. A deployment reads only the credential it owns. To resolve the same slug from a second deployment, run mda connections create <slug> again from that project root: on an existing slug the command attaches a new agent-owned credential instead of failing.
Identify the caller
A user-owned connection resolves against the caller identity that Managed Deep Agents attaches to the run. Where that identity comes from depends on how the agent is called:
The default identity declaration verifies a LangSmith API key. That key authenticates the calling client, not an individual person, so every caller who presents it resolves to the same identity. To give each signed-in person their own credentials, declare Supabase identity.
Code never passes a user ID to
connections.get(...). The runtime resolves the caller and returns that person’s credential.
Slack and Studio complete the authorization round-trip for the caller. First-class support for custom channels is in development. To build a custom frontend against caller identity today, see Handle the authorization interrupt and contact the LangChain team.
Choose a create mode
Ownership decides what the agent does with a credential. The create mode decides how that credential reaches the workspace, and depends on how the external service authenticates:
For example:
--mcp cannot combine with --oauth, custom endpoints, --client-id, or a secret value.
Name a connection
The first argument tomda connections create is a slug: your name for the connection, and the name your code passes to connections.get(...). It is not the provider name, which goes to --oauth:
organization-tavily or engineering-notion.
Create an opaque secret
Store a fixed secret for the agent. Read the value from an environment variable, a file, stdin, or a prompt. This mode fits API keys for custom tools, such as a Tavily search key. Opaque secrets created with the CLI are agent-owned. Put the source value in the shell environment or project.env file, then create the connection from that variable. Run the command from the project root. The CLI requires a LangSmith API key and workspace ID.
TAVILY_API_KEY as an agent-owned secret. Runtime code resolves it with connections.get(...).
Other ways to supply the value:
--secret-from-file PATH: Read one value from a file that contains only the secret.- stdin: Pipe or redirect the value, for example
printf '%s' "$ACME_API_KEY" | mda connections create acme-api. - Interactive prompt: Omit a value flag on a TTY. The CLI hides the input so the secret does not appear on screen or in shell history.
Use an opaque secret in a custom tool
The following tool resolves theorganization-tavily connection for the agent, then sends it to the Tavily API:
tools/search-web.ts
Create a general OAuth connection
Register a bring-your-own-app (BYOT) OAuth client so callers can grant the agent access to a provider API. Use this mode for REST or GraphQL APIs where you own the OAuth app registration. For MCP servers that discover and register clients automatically, use MCP OAuth instead.Use the OAuth catalog
Every OAuth provider needs the same five settings: an authorization URL, a token URL, a token endpoint authentication method, authorization parameters, and default scopes. A catalog entry supplies all five, so--oauth <service> plus your own client ID and secret is the whole configuration.
The catalog is not a gate on which providers you can use. For a service it does not cover, pass the endpoints yourself.
List the catalog with:
--oauth.
A service with no default scopes requires
--scope.
Some services run separate OAuth apps for their API and their MCP server
Some services run separate OAuth apps for their API and their MCP server
Notion is one of them.
--oauth notion-api registers an app against Notion’s REST API, and that app does not authorize Notion’s MCP server. To use the MCP server, create an MCP OAuth connection instead. Check the provider’s documentation when a service offers both.GITHUB_CLIENT_SECRET, then create the connection. Replace ******** with the client ID:
https://api.smith.langchain.com/v1/agent-auth/oauth/callback on production.
Optional flags:
--scope SCOPE: Replace the catalog defaults. Repeat for each scope.--allowed-scope SCOPE: Ceiling any later authorization may request. Defaults to the--scopevalues and must cover every--scope.--authorization-param KEY=VALUE: Extra authorization query parameter. Repeat for each parameter.--auth-method METHOD: How the client authenticates to the token endpoint:client_secret_basic,client_secret_post, ornonefor a public client. Defaults to the catalog service’s method.
Register a provider with custom endpoints
For a service the catalog does not cover, pass both endpoints plus a client ID and scopes:scope parameter. Pass --scope for manual registrations, or use --oauth <service> when the catalog covers the provider.
Authorize an agent-owned OAuth account
When a provider issues its own application credential, such as a Slack bot token, a GitHub App installation token, or a Notion internal integration token, prefer that credential stored as an agent-owned secret. An application credential is scoped to the application, is revocable on its own, and does not depend on any person’s account. Use--authorize when the provider offers no application identity and its API authenticates only as a person.
By default, an OAuth connection collects a grant from each caller at runtime. Pass --authorize to sign in once yourself and store the grant for the deployment. Every caller then acts as that one account, and no caller sees an authorization prompt:
--authorize applies to OAuth connections only. Combine it with --oauth, custom endpoints, or --mcp. Run it from the project directory, because the grant belongs to that project’s deployment.
Use an agent-owned OAuth account when every caller should act as one shared account rather than as themselves. A company Notion account that grants read access to a question-answering agent is one example.
Access an OAuth token in a custom tool
This tool resolves the authenticated caller’s GitHub connection and calls the GitHub REST API:tools/get-github-user.ts
Create an MCP OAuth connection
For remote MCP servers that support OAuth client registration, Managed Deep Agents discovers the server’s OAuth metadata and registers a client automatically. You do not supply a client ID or client secret.Declare the MCP server first
Add the server intools/mcp.ts and reference the connection slug.
tools/mcp.ts
Create from the project declaration
When the slug matches exactly one user-owned MCP connection in the project, create with the slug alone. The CLI reads the server URL from the MCP declaration:Create from an explicit MCP URL
Pass--mcp when you want to name the server URL explicitly, or when the slug is not yet declared in the project:
mcp.notion.com/mcp is stored as https://mcp.notion.com/mcp.
If the server cannot register a client automatically, the CLI says so and points you at general OAuth (--oauth or manual endpoints) instead.
mda deploy applies the same inference to missing user-owned MCP connections. It leaves existing connections unchanged, creates each unique missing MCP connection through OAuth discovery, and fails before deployment when discovery or registration is unavailable.
Handle the authorization interrupt
Managed Deep Agents runs the OAuth round-trip for you. A project needs no callback route, no token store, no refresh logic, and no consent screen. The run pauses, the caller grants access, and the run resumes with that person’s credential. Before the first model turn, Managed Deep Agents checks every user-owned connection the run needs. If the caller is missing one or more grants, the credential gate raises a single LangGraph interrupt. Slack and LangSmith Studio handle that interrupt for the caller. A custom frontend reads the same payload from the LangChain frontend SDK and resumes after the caller connects. User-owned connections require an authenticated caller. Anonymous or agent-only runs cannot complete the credential gate. See Identify the caller for where that identity comes from.Interrupt payload
WithuseStream (@langchain/react, @langchain/vue, @langchain/svelte) or injectStream (@langchain/angular), the pending interrupt is on stream.interrupt. The credential gate payload is stream.interrupt.value.
For a missing OAuth grant, each entry in credentials carries the URL where the caller completes consent:
"kind": "secret" represents a user-owned API key rather than an OAuth grant. Slack and Studio do not collect those. For more information, see Review current limitations.
Read the interrupt in your UI
The frontend that renders this interrupt is a web application, so these examples are TypeScript whether the agent is written in Python or TypeScript. Detect the credential gate payload onstream.interrupt, render a connect card, then resume with stream.respond after every grant is stored:
stream.interrupt, resume, checkpoints), see Human-in-the-loop.
Handle OAuth grants (kind: "oauth2")
For each OAuth entry:
- Show the
slugand a Connect control that opensconnect_url(HTTPS only; reject URLs with embedded credentials). - Long-poll Agent Auth until the session completes:
status is pending, completed, failed, or expired. Keep polling while the status is pending. On completed, mark that slug connected. On failed or expired, ask the caller to start a new run for a fresh connect link.
Do not put the access token in your UI. Agent Auth stores the grant for the caller; the agent reads it on resume through connections.get(...).
Resume the run
After every entry incredentials is connected, resume with:
stream.respond(resume, { interruptId: stream.interrupt?.id }) as shown above. If you resume while a grant is still missing, the gate interrupts again with a fresh payload.
Built-in Slack handling
When the agent runs through the Slack channel, Slack renders OAuth entries that include an HTTPSconnect_url. The caller opens the link, completes consent, and Slack resumes the run, so nobody has to open LangSmith to connect a service.
Screenshot placeholder: Add the Slack OAuth authorization prompt screenshot here.
Slack OAuth authorization prompt
Inspect and delete connections
Uselist or get to inspect connection metadata. list shows every connection in the workspace, not only the ones this project uses:
--json to list or get for machine-readable output. Pass --yes to delete to skip the confirmation prompt.
Develop locally
Formda dev, an agent-owned opaque connection reads MDA_DEV_<SLUG>. The CLI converts the slug to uppercase and replaces hyphens with underscores. For example, organization-tavily reads MDA_DEV_ORGANIZATION_TAVILY.
User-owned connections require an authenticated caller and Agent Auth. Deploy the agent to exercise the authorization interrupt end to end.
Review current limitations
Connections are part of the Managed Deep Agents public beta. The following gaps apply to the current release:- User-owned API keys: A user-owned connection holds an OAuth grant. Slack and Studio do not collect a per-caller API key, and the CLI does not create an empty slot for one. Use an agent-owned secret instead, or collect the key in a custom frontend as described in the following section.
- Custom channels: Slack and Studio resolve caller identity and complete authorization for the caller. A custom frontend handles the authorization interrupt itself.
- Workspace UI: LangSmith does not list connections in the UI. Use
mda connections listandmda connections getfor connection metadata. - Grant visibility:
mda connections listis workspace-scoped and does not report which deployments hold a credential under a slug. A run that fails withno agent connection is set for slug '<slug>'means this deployment owns no credential for it, even whenlistshows the slug. Runmda connections create <slug>from the project root to mint one.
Store a user-owned API key through Agent Auth
Store a user-owned API key through Agent Auth
An interrupt entry with Agent Auth reuses the existing connection for that slug and attaches the caller’s secret. Secret material is write-only. After a successful create, mark that slug connected and resume the run. For more information, see Set up Agent Auth.
"kind": "secret" has no connect_url. To collect one in a custom frontend, prompt for the value with a hidden input, then create the credential against the existing connection slug:See also
- Managed Deep Agents CLI reference
- Connect to MCP servers
- Add custom tools
- Add identity to Managed Deep Agents
- Deploy an agent
- Human-in-the-loop
- Set up Agent Auth
Connect these docs to Claude, VSCode, and more via MCP for real-time answers.

