Announcing CIMD support for MCP Client registration
Learn more

Claude Managed Agents and OpenClaw: The Auth Gap & The Fix

TL;DR

  • Claude Managed Agents and OpenClaw are both production-ready agent runtimes, but neither ships with a complete authentication layer. Vaults, the built-in credential store in Claude Managed Agents, only store tokens. OpenClaw ships with no credential management at all.
  • There are five specific gaps that surface the moment you move beyond a single-user demo: OAuth ownership, reactive-only refresh, missing connectors, no re-auth recovery path, and rigid credential scoping.
  • Scalekit AgentKit closes every one of those gaps for both runtimes. You call ensure_instance(), receive a pre-authenticated MCP URL, and pass it to your agent.
  • Scalekit manages OAuth consent, token vault, proactive refresh, re-auth recovery links, and audit logging, whether you are running Claude Managed Agents or OpenClaw.
  • This blog includes complete working code for an enterprise incident response agent built on Claude Managed Agents and Scalekit. The Scalekit setup steps are identical for OpenClaw.

Most agent demos break in production for the same reason: the runtime is ready, but the auth layer is not. Claude Managed Agents and OpenClaw both handle tool execution well. Neither handles whose token runs at 2 am, how it stays fresh across a long session, or what happens when a Slack admin revokes access mid-incident.

This blog walks through exactly where both runtimes fall short in authentication, how Scalekit fills each gap, and includes a complete, working incident response agent for Datadog, Linear, and Slack that you can run today.

How Claude Managed Agents and OpenClaw Actually Work

Claude Managed Agents compresses months of agent infrastructure work into a few API calls. You define an agent once with a model, a system prompt, a set of tools, and one or more MCP servers. Anthropic takes it from there. The platform runs the entire agent loop for you, handling tool discovery, execution, retries, streaming, and session state management. You do not build any of that infrastructure yourself.

OpenClaw works differently. Instead of a managed cloud runtime, it runs on your own infrastructure, a VPS, a Docker container, or an AWS Lightsail instance, and the agent loop lives inside OpenClaw itself rather than on Anthropic's servers. You connect it to messaging platforms like Telegram, Discord, Slack, and WhatsApp so your users can interact with the agent through those channels.

Both runtimes face the same authentication gap. Neither ships with multi-user OAuth management, proactive token refresh, pre-built connectors, or a re-auth experience when tokens are revoked. The execution layer is solved, but the identity layer is not.

Dimension
Claude Managed Agents
OpenClaw
What it is
Anthropic's fully managed cloud runtime for agent execution
Open-source conversational agent designed for messaging platforms
Hosting
Runs on Anthropic's cloud infrastructure
Self-hosted on your own infrastructure
Setup complexity
Python SDK, define agent via API calls
clawhub install plus four environment variables
Agent loop
Anthropic manages tool discovery, execution, retries, and session state
OpenClaw manages conversation flow, dispatch, and message history
Scalekit integration
Pass the MCP URL to the agent.create() as an MCP server
Install the skill and configure environment variables
Best for
Production APIs, long-running multi-tool pipelines, and complex orchestration
Telegram, Slack, and Discord bots, rapid prototyping, conversational interfaces

For authenticating with third-party services like Datadog, Slack, and Linear, Claude Managed Agents ships with Vaults, a per-user credential store hosted by Anthropic. The Vault workflow operates as follows:

  • You create a vault for each user in your system.
  • You add credentials to each vault, each bound to a specific MCP server URL. These can be OAuth access tokens, refresh tokens, or static bearer tokens.
  • When you start a session, you pass vault_ids so the agent knows which credentials to use.
  • At runtime, Anthropic automatically injects the correct credentials when the agent connects to that MCP server.

Token refresh is the one additional mechanism Vaults provide, and it only fires after something breaks. The agent hits a 401 mid-session, the vault attempts a refresh using the stored refresh token, and if that cycle does not complete cleanly, the entire session fails. There is no proactive check, no pre-flight validation, and no way to catch an expired token before it kills a running task.

OpenClaw has no equivalent mechanism. There is no built-in credential store, no token injection, and no refresh logic. If your OpenClaw agent needs to call Datadog or Slack on behalf of a user, you are building that infrastructure entirely from scratch.

This covers the fundamentals, but the problems start to appear when you move from a single-user prototype to a multi-user production system.

The following diagram shows how the Vault approach works and where you are responsible for building infrastructure yourself:

Where the Authentication Layer Falls Short at Scale

Vaults give Claude Managed Agents a starting point for credential storage, but everything beyond storage is left for you to build. OpenClaw ships with no credential management at all. Neither runtime handles OAuth flows, token refresh lifecycle, connector integrations, or re-authorization out of the box. Here is a closer look at the five specific gaps that emerge as you move toward production, and how each affects both runtimes.

You Own Every OAuth Flow from Scratch

Vaults store tokens, but they do not initiate OAuth flows. They do not handle redirect URIs, exchange authorization codes, run PKCE verification, or manage consent screens. For every external service your agent connects to, you need to architect and host a complete OAuth implementation yourself.

At a small scale, this is manageable. At the production scale, the numbers compound quickly. If your agent connects to four services and you have 100 users, that is 400 separate OAuth flows that you need to design, build, and maintain. Each service has its own scope, token format, and expiry window.

For OpenClaw, the problem is the same, but it starts one step earlier. There is no credential store to even receive the tokens once you have obtained them. You are building OAuth and storage from scratch for every service.

Token Refresh Only Fires After a Failure

The vault only triggers a token refresh when the agent actually hits a 401 error during an active session. Claude Managed Agents is designed for long-running tasks that can persist across minutes or hours. If a token expires mid-session and the 401-to-refresh cycle does not complete cleanly, the entire session fails. You end up debugging a runtime failure instead of catching a configuration error before it ever reaches the user.

OpenClaw has no refresh mechanism at all. A token that expires mid-conversation fails silently, with no recovery path or retry logic.

Scalekit takes a fundamentally different approach. It proactively refreshes tokens before every tool call, so the agent session never encounters an expired credential, regardless of which runtime you are using.

No Pre-Built Connectors for Third-Party Services

Neither Claude Managed Agents nor OpenClaw ships pre-built MCP servers for external services. Vaults accept credentials for any MCP server URL, but Anthropic does not build or maintain those servers. Datadog, Slack, Linear, Salesforce, Notion, GitHub: for each one, you need to build or source the MCP server yourself.

This goes well beyond writing OAuth code. You also need to host the MCP server, define tool schemas, map API endpoints, handle errors, and manage versioning for each service you want to connect.

No Recovery Path When a Token Is Revoked

When a token is revoked or expires in a way that the vault cannot refresh, the session fails silently with a session.error event. There is no built-in mechanism to detect this scenario, generate a re-authorization link, surface it to the user through your application, and resume the session once the user completes the flow.

OpenClaw has no session error event or detection mechanism either. A revoked token silently breaks the conversation with no way to surface a re-auth link to the user.

In both cases, you need to build that entire detection, notification, and recovery loop yourself.

Rigid Credential Scoping Limits Multi-Role Architectures

This gap is specific to Claude Managed Agents. The vault enforces a hard constraint: only one active credential per mcp_server_url per vault. If you need a read-only Datadog token for one agent role and a full-access token for another, you need separate vaults or separate MCP server URLs. At scale, this per-role credential scoping adds significant architectural complexity to your system.

For OpenClaw, there is no credential scoping layer, so multi-role architectures require building the scoping logic from scratch.

The following diagram summarizes everything the Vault provides against everything you still need to build on your own:

Managed Agents is built for long-running, multi-step tasks that span multiple services. Its vault system is designed for simple, single-service credential injection. The more services your agent connects to and the more users it serves, the more OAuth infrastructure you need to layer on top.

How Scalekit AgentKit Fills the Authentication Layer

Scalekit AgentKit is not a replacement for Claude Managed Agents or OpenClaw. It is the identity and authentication layer that both runtimes intentionally leave out. The integration pattern works the same way for both: you call ensure_instance() with a user identifier, you receive a pre-authenticated MCP URL, and you pass that URL to the agent as its MCP server. Scalekit handles everything underneath that URL.

The Building Blocks

Before looking at code, it helps to understand the three objects that Scalekit uses to manage the authentication lifecycle:

Object
What It Does
When You Create It
Connection
Represents a configured OAuth application for one service, such as Datadog, Slack, or Linear. It defines the client ID, scopes, and redirect URI for that service.
Once, in the Scalekit Dashboard. You reuse the same connection across all users.
MCP Config
A reusable template that declares which connections and which specific tools are exposed through the MCP server. Think of it as the capability surface for a particular agent role.
Once per agent role. You can create multiple configs to give different roles access to different tools.
MCP Instance
A per-user instantiation of a config. Each instance has its own unique, pre-authenticated URL that encodes which user it belongs to and which connections they have authorized.
Once per user per config. The ensure_instance() call is idempotent, so it is safe to call on every session start.

The Three-Phase Integration Model

The integration follows three distinct phases, each with a clear boundary of responsibility.

Phase 1: One-time setup

You call create_config() once to declare which connections and tools your MCP server exposes. This defines your agent's capability surface and does not change from user to user.

Phase 2: Per-user authorization

You call ensure_instance() for each user. If the user has not yet authorized a connection, Scalekit generates an authentication link. Once the user completes the OAuth flow through that link, you receive a unique, pre-authenticated MCP URL for that specific user.

Phase 3: Runtime execution

You pass the MCP URL to the agent as its MCP server. When the agent calls a tool, Scalekit routes the request using that user's stored credentials, which are proactively refreshed before the call. Your application code does not manage any part of this loop.

How Each Gap Gets Resolved

Here is how each vault limitation maps to a specific Scalekit capability:

Vault Limitation
How Scalekit Resolves It
You build and host every OAuth flow
ensure_instance() handles OAuth initiation, redirect, code exchange, PKCE verification, and token storage automatically
Token refresh only fires reactively on 401
Scalekit refreshes tokens proactively before every tool call, so sessions never encounter an expired credential
No pre-built connector catalog
Scalekit provides 75+ pre-built connectors with correct scopes, typed tool schemas, and complete API mappings
No recovery path for revoked tokens
A magic link is auto-generated whenever a token is revoked and can be surfaced to the user immediately
One credential per URL per vault
Credentials are scoped per user, per connector, and per config, so multiple roles use separate configs without vault proliferation

Seeing the Difference in Code

The clearest way to understand what Scalekit removes from your codebase is to compare the two approaches side by side.

Without Scalekit: Building on Vaults Alone

# 1. Run your own OAuth flow for EACH service (redirects, PKCE, code exchange) dd_token = your_oauth_handler.get_token(user_id, service="datadog") lr_token = your_oauth_handler.get_token(user_id, service="linear") slk_token = your_oauth_handler.get_token(user_id, service="slack") # 2. Store each token in an Anthropic vault (one vault per user) vault = client.beta.vaults.create() for service_url, token in [ ("https://your-datadog-mcp.com/mcp", dd_token), ("https://your-linear-mcp.com/mcp", lr_token), ("https://your-slack-mcp.com/mcp", slk_token), ]: client.beta.vaults.credentials.create( vault_id=vault.id, mcp_server_url=service_url, # you build and host each one credential={"type": "mcp_oauth", "access_token": token, ...}, ) # 3. Create a session with vault_ids to inject credentials session = client.beta.sessions.create( agent=agent.id, environment_id=environment.id, vault_ids=[vault.id], )

What you now own and maintain:

  • 3 separate OAuth servers (Datadog, Linear, Slack)
  • 3 separate MCP servers (hosting, tool schemas, API mapping for each)
  • Reactive token refresh (fires only when the agent hits a 401)
  • Re-auth flow for each service (no built-in mechanism)
  • At 100 users and 3 services, that is 300 vault entries to manage

With Scalekit: One Call Replaces Everything Above

Three separate OAuth servers, three MCP servers, and the entire token refresh and re-auth infrastructure disappear from your codebase. Scalekit manages all of it behind a single MCP URL.

import scalekit.client sk = scalekit.client.ScalekitClient( client_id=os.getenv("SCALEKIT_CLIENT_ID"), client_secret=os.getenv("SCALEKIT_CLIENT_SECRET"), env_url=os.getenv("SCALEKIT_ENV_URL"), ) # One call. Scalekit handles: OAuth flows for all 3 services, token storage, # proactive refresh, re-auth magic links, MCP server hosting, audit logging. inst = sk.actions.mcp.ensure_instance( config_name="incident-responder", # MCP config you created once user_identifier="user_123", # your app's internal user ID ) mcp_url = inst.instance.url # pre-authenticated, per-user, all 3 services # This call is identical for Claude Managed Agents and OpenClaw. # --- Claude Managed Agents: pass as MCP server on agent.create() --- session = client.beta.sessions.create( agent=agent.id, environment_id=env_id, # no vault_ids — Scalekit handles auth through the MCP URL ) # --- OpenClaw: set TOOL_ENV_URL in your .env to the mcp_url value above --- # The scalekit-agent-auth skill picks it up automatically. No API calls needed.

Now that the authentication layer is clear, here is what it looks like in practice. The following walkthrough builds a Claude Managed Agent that triages Datadog alerts, creates Linear tickets, and notifies the team via Slack, all authenticated through Scalekit. Every concept from the sections above maps directly to a step in this code.

Building an Enterprise Incident Response Agent

The following is a complete walkthrough for building a Claude Managed Agent that triages Datadog alerts, creates Linear tickets, and notifies the team via Slack, all authenticated through Scalekit. This is the kind of multi-service agent that enterprise SRE and DevOps teams actually need in production.

The code is organized around the natural lifecycle of the integration: one-time setup, per-user authorization, and per-session execution. Steps 1 and 2 are identical if you are building with OpenClaw only. Steps 3 through 5 are specific to Managed Agents.

How the Pieces Fit Together

What You Need Before Starting

  • Python 3.10 or later is installed on your machine.
  • An Anthropic API key with Managed Agents beta access from platform.anthropic.com/settings/keys.
  • A free Scalekit account at app.scalekit.com.
  • Datadog, Linear, and Slack connectors are configured in your Scalekit Dashboard under Agent Auth. Navigate to Connections, add each service, and complete their respective OAuth app setup.

Step 1: Define the Agent's Permission Boundary (run once)

The MCP config declares which connections and tools your agent can access. You create it once, and it is reused across every user and every session. For an incident response agent, the config exposes monitoring tools from Datadog, issue management tools from Linear, and communication tools from Slack.

# 01_create_mcp_config.py import os import scalekit.client from scalekit.actions.models.mcp_config import McpConfigConnectionToolMapping from dotenv import load_dotenv load_dotenv() scalekit_client = scalekit.client.ScalekitClient( client_id=os.getenv("SCALEKIT_CLIENT_ID"), client_secret=os.getenv("SCALEKIT_CLIENT_SECRET"), env_url=os.getenv("SCALEKIT_ENV_URL"), ) cfg = scalekit_client.actions.mcp.create_config( name="incident-responder", description="Triages Datadog alerts, creates Linear tickets, and notifies via Slack", connection_tool_mappings=[ McpConfigConnectionToolMapping( connection_name="datadog", tools=["datadog_monitors_list", "datadog_monitor_get", "datadog_incidents_list"], ), McpConfigConnectionToolMapping( connection_name="linear", tools=["linear_issue_create", "linear_issue_update", "linear_comment_create"], ), McpConfigConnectionToolMapping( connection_name="slack", tools=["slack_post_message", "slack_reply_to_thread", "slack_list_channels"], ), ], ) print(f"Config created: {cfg.config.name}")

This tells Scalekit to create an MCP server configuration named "incident-responder" that exposes 9 tools across 3 services. Each connection is whitelisted to only the tools this agent needs. The Datadog connection provides read access to monitors and incidents. The Linear connection allows creating and updating issues. The Slack connection enables posting messages and listing channels.

By whitelisting specific tools per connection, you enforce the principle of least privilege at the infrastructure level. The agent cannot send emails, delete Slack channels, or modify Datadog dashboards because those tools are simply not exposed through this config.

You can also create separate configs for different agent roles. An on-call config might expose all three services, while a read-only reporting config might only expose Datadog monitoring tools without Linear or Slack write access.

Step 2: Authorize the User via OAuth (run once per user)

Before the agent can call Datadog, Linear, and Slack on a user's behalf, that user must authorize each connection. The ensure_instance() method is idempotent, which means it is safe to call on every session start. If the user is already authorized for all three services, it returns the MCP URL immediately without repeating any OAuth flow.

# 02_authorize_user.py import os import scalekit.client from dotenv import load_dotenv load_dotenv() scalekit_client = scalekit.client.ScalekitClient( client_id=os.getenv("SCALEKIT_CLIENT_ID"), client_secret=os.getenv("SCALEKIT_CLIENT_SECRET"), env_url=os.getenv("SCALEKIT_ENV_URL"), ) inst_response = scalekit_client.actions.mcp.ensure_instance( config_name="incident-responder", user_identifier="user_123", # your app's stable internal user ID ) # Check authorization status for all connections in the config auth = scalekit_client.actions.mcp.get_instance_auth_state( instance_id=inst_response.instance.id, include_auth_links=True, ) for conn in auth.connections: if conn.connected_account_status == "ACTIVE": print(f"{conn.connection_name}: authorized") else: print(f"{conn.connection_name}: needs authorization") print(f"Auth link: {conn.authentication_link}") # In production: send this link via email, Slack DM, or in-app prompt mcp_url = inst_response.instance.url print(f"\nMCP URL: {mcp_url}") # Store this URL per user in your database. # It is stable and does not need to be regenerated per session.

When a user has not yet authorized a connection, Scalekit generates a magic link for that specific service. The user opens each link in their browser, completes the OAuth consent screens for Datadog, Linear, and Slack, and Scalekit stores all resulting tokens in an AES-256-encrypted vault. From that point forward, every call to ensure_instance() for that user returns the pre-authenticated MCP URL instantly, covering all three services through a single URL.

In a production application, store the MCP URL in your database alongside the user record and call ensure_instance() at the start of every session to verify that all authorizations are still active.

If you are using OpenClaw, set the returned mcp_url as the value of TOOL_ENV_URL in your .env file. The scalekit-agent-auth skill picks it up automatically at runtime.

Step 3: Create the Claude Managed Agent (run once)

The agent definition is created once and reused across all sessions via agent.id. The MCP URL you pass here is a per-user value returned by ensure_instance() in Step 2.

For this demo we read it from an environment variable, but in production, you should fetch it from your database per user and call ensure_instance() at the start of every session to verify the auth state before passing the URL. Notice there are no vault_ids anywhere in this code. The Scalekit MCP URL already carries the user's identity and authorized connections for all three services.

# 03_create_agent.py import os from anthropic import Anthropic from dotenv import load_dotenv load_dotenv() client = Anthropic() mcp_url = os.getenv("SCALEKIT_MCP_URL") # in production: fetch per user from your database agent = client.beta.agents.create( name="Incident Response Agent", model="claude-sonnet-4-6", system=( "You are an enterprise SRE assistant for incident response. " "You triage Datadog alerts, create Linear bug tickets with severity " "and context, and notify the team via Slack. " "Be concise and prioritize by severity (critical > warning > info). " "Always confirm before posting to Slack or creating Linear tickets. " "Include monitor name, status, tags, and relevant metrics in tickets." ), mcp_servers=[ {"type": "url", "name": "scalekit", "url": mcp_url}, ], tools=[ { "type": "mcp_toolset", "mcp_server_name": "scalekit", "default_config": {"permission_policy": {"type": "always_allow"}}, }, ], ) print(f"Agent ID: {agent.id}") # Save agent.id and reference it in every session.

The Anthropic Console confirms the agent is live with the Scalekit MCP server attached. The MCP URL you passed in the code appears here as the connected tool source.

The always_allow permission policy means the agent executes every tool call without pausing for human confirmation. This works well for a demo, but requires thought in production. Because the policy applies at the toolset level and covers all tools exposed through that MCP server, you cannot mix always_allow and always_ask within a single toolset.

If you want human approval on write operations like Linear ticket creation and Slack messages, create two separate Scalekit MCP configs: one scoped to read-only Datadog tools with always_allow, and one scoped to Linear and Slack write tools with always_ask. Each config gets its own toolset in the agent definition.

One important security consideration: the MCP URL is pre-authenticated and encodes the user's identity and authorized connections for all three services. Never expose this URL in client-side code, API responses, or logs. It should only be passed server-side.

Step 4: Set Up the Execution Environment (run once)

An environment is the cloud container where the agent runs. You create it once and reuse the environment.id across all sessions.

# 04_create_environment.py from anthropic import Anthropic from dotenv import load_dotenv load_dotenv() client = Anthropic() environment = client.beta.environments.create( name="incident-response-env", config={ "type": "cloud", "networking": {"type": "unrestricted"}, }, ) print(f"Environment ID: {environment.id}") # Save environment.id and reuse across all sessions.

Step 5: Run a Live Incident Response Session (run per task)

This is the script you run every time you want the agent to perform a task. It creates a session, sends the incident response task as a user message, and streams the agent's response in real time. The agent will pull data from Datadog, create tickets in Linear, and post summaries to Slack, all through the single Scalekit MCP URL.

# 05_run_session.py import os from anthropic import Anthropic from dotenv import load_dotenv load_dotenv() client = Anthropic() agent_id = os.getenv("AGENT_ID") env_id = os.getenv("ENVIRONMENT_ID") # No vault_ids needed: Scalekit handles auth through the MCP URL set on the agent session = client.beta.sessions.create( agent=agent_id, environment_id=env_id, title="Incident response session", ) print(f"Session started: {session.id}") with client.beta.sessions.events.stream(session.id) as stream: client.beta.sessions.events.send( session.id, events=[{ "type": "user.message", "content": [{ "type": "text", "text": ( "Check Datadog for any critical or warning monitors that " "triggered in the last hour. For each one, create a Linear " "issue with the monitor name, status, and tags. Then post " "a summary to the #incidents Slack channel." ), }], }], ) for event in stream: match event.type: case "agent.message": for block in event.content: print(block.text, end="", flush=True) case "agent.mcp_tool_use": print(f"\n → [{event.name}]", flush=True) case "session.status_idle": print("\n" + "-" * 50) print("[Session complete]") break case "session.error": print(f"\n[Error] {event.error}") # If this is an auth error, re-run 02_authorize_user.py break

Real Output from a Live Test Run

We ran this agent against a production Datadog environment, a Linear workspace, and a Slack channel. Here is the actual output from the session:

Session started: sesn_01UgZUYAXMZFQj4ncBM7i9nE -------------------------------------------------- Datadog Monitor Status -- All 8 Monitors > [datadog_monitors_list] | Monitor Name | Status | Tags | | ----------------------------------------- | --------- | ---------------------------------- | | CPU usage is high for host | OK | integration:host, monitor_pack:host| | Network traffic (sent) is high on host | OK | integration:host, monitor_pack:host| | Network traffic (received) is high | OK | integration:host, monitor_pack:host| | Watchdog Anomaly (APM) | OK | monitor_pack:apm, product:apm | | Disk latency is high for host/device | No Data | monitor_pack:host | | Disk usage is high for host/device | No Data | monitor_pack:host | | System load is high for host | No Data | monitor_pack:host | | Memory space is low for host | No Data | monitor_pack:host | 4 monitors reporting "No Data" -- hosts not sending metrics. > [linear_issue_create] Linear Ticket Created: INF-29 -- "Infra Review: Datadog monitors reporting No Data" Team: Infrasity | Priority: High https://linear.app/infrasity/issue/INF-29 > [slack_post_message] Posted incident summary to #incidents: "Datadog scan complete: 4 OK, 4 No Data. Created Linear ticket INF-29 to track monitors with missing host metrics. No critical alerts active." -------------------------------------------------- [Session complete]

Both sessions show as Idle, the Anthropic platform term for a cleanly completed session. The timestamps match the live test run.

The agent pulled all eight monitors from Datadog, identified four with missing data, created a high-priority Linear ticket (INF-29) with the full breakdown, and posted a summary to the team's Slack incident channel.

Three services, three sets of credentials, all managed through a single Scalekit MCP URL, with no custom authentication code.

Every tool call the agent makes is logged in the Scalekit dashboard with the connector, exact tool name, user identity, timestamp, and duration. The Datadog call completed in 287ms at 20:01:46.

The Linear call followed 3 seconds later, at 20:01:49, and completed in 145ms.

Both logged under the same user identifier, one audit trail across two services, zero custom logging code.

What Scalekit Managed Behind the Scenes

To make a multi-service incident response session work, Scalekit handled the following responsibilities entirely on its own, without any custom code on our part:

  • OAuth consent flows for three services with different auth models (Datadog API key, Linear OAuth with PKCE, Slack OAuth with workspace scopes), all abstracted behind a single ensure_instance() call.
  • Token storage in an AES-256 encrypted vault, scoped per user and per service. At 100 on-call engineers, that is 300 credential sets managed automatically with full isolation between them.
  • Proactive token refresh before every tool call. The agent made four calls across three services during the session and never hit a 401 or triggered a retry.
  • Pre-built MCP servers for Datadog, Linear, and Slack with correct tool schemas, API mappings, and error handling. We did not deploy, host, or configure any of them.
  • Re-auth recovery via a single status check. When a Slack admin removes access or a Datadog API key is rotated, the connected account status moves to REVOKED or EXPIRED. Your application calls get_authorization_link(), the same call regardless of connector type, and Scalekit generates a hosted re-auth page tailored to that service. OAuth connectors get a consent screen. API key connectors get a credential form. No per-service recovery code to maintain.
  • Audit logging of every tool execution with user identity, service, tool name, timestamp, and outcome.

We wrote five Python scripts totaling roughly 100 lines of actual logic, configured four environment variables, and got a production-grade incident response agent that authenticates across three enterprise services.

Everything else, the OAuth servers, the MCP servers, the token vault, the refresh logic, the re-auth flows, and the audit trail, is infrastructure that Scalekit manages on our behalf.

Using OpenClaw with Scalekit for Conversational Agents

Steps 1 and 2 from the walkthrough above are identical for OpenClaw. The only difference is how you pass the MCP URL to the runtime. Instead of calling agent.create() and sessions.create() through the Anthropic API, you install the Scalekit skill and configure four environment variables. OpenClaw handles the agent loop itself, and the skill manages all credential operations transparently.

clawhub install scalekit-agent-auth

Add these to your .env in the OpenClaw project root. Set TOOL_ENV_URL to the MCP URL returned by ensure_instance() in Step 2:

TOOL_CLIENT_ID=skc_your_client_id TOOL_CLIENT_SECRET=your_client_secret TOOL_ENV_URL=https://your-env.scalekit.cloud TOOL_IDENTIFIER=your_default_user_id

From that point, when a user asks the agent to interact with a connected service, the skill looks up the active connection in Scalekit, verifies it is authorized or generates a magic link if not, retrieves the available tool schemas, and executes the tool call transparently. The same token refresh, re-auth, and audit logging that Scalekit provides for Managed Agents applies here too.

Connectors Available Out of the Box

Any connector configured in Scalekit works with both Claude Managed Agents and OpenClaw. Here are the most commonly used ones:

Connector
Auth Type
Example Tools
Datadog
API Key
datadog_monitors_list, datadog_monitor_get, datadog_incidents_list
Slack
OAuth
slack_post_message, slack_reply_to_thread, slack_list_channels
Linear
OAuth
linear_issue_create, linear_issue_update, linear_comment_create
100+ more
OAuth or API Key

For services not in the catalog, you can use Bring Your Own Provider to configure your own OAuth application and expose it through the same MCP URL pattern.

Conclusion

The runtime problem is solved. Claude Managed Agents handles complex multi-tool pipelines on Anthropic infrastructure, and OpenClaw brings conversational agents to Telegram, Slack, and Discord. Both are production-ready and do their jobs well.

The part that catches teams off guard is the auth. Everything works fine in the demo with one user and a hardcoded token. The problems show up when real users hit Datadog, Linear, and Slack through the same agent at odd hours. Expired tokens, silent session failures, revoked access with no recovery path. Building that infrastructure yourself is weeks of work that has nothing to do with what your agent actually does.

Scalekit is the layer that handles it all. One ensure_instance() call per user returns a pre-authenticated MCP URL that covers all connected services. Tokens refresh before they expire, revoked access triggers a magic link, and every tool call is logged. Your agent code stays simple, and the OAuth flows you were about to build never need to get written.

FAQ

What are Claude Managed Agents?

Anthropic's fully managed runtime for AI agents. You define the model, system prompt, tools, and MCP servers once — Anthropic handles tool discovery, execution, retries, and session state. It entered public beta in April 2026.

What is OpenClaw?

An open-source personal AI assistant framework that runs on your own infrastructure and connects to messaging platforms like Telegram, Discord, Slack, and WhatsApp. It manages its own agent loop and supports multiple LLM providers. The Scalekit integration is a single skill install via Clawhub with four environment variables — no custom code required.

What authentication gap do both runtimes share?

Neither ships with multi-user OAuth management, proactive token refresh, pre-built connectors, or a re-auth experience when tokens are revoked. Claude Managed Agents has Vaults for basic token storage. OpenClaw has nothing. In both cases, you build the rest yourself unless you use Scalekit.

What does Scalekit AgentKit actually do?

It handles everything Vaults don't: OAuth consent flows, token storage, proactive refresh before every tool call, 75+ pre-built connectors, and automatic re-auth magic links when tokens are revoked. Your agent gets a single pre-authenticated MCP URL per user — no custom auth code required.

How does the Scalekit integration work in practice?

One call: ensure_instance(config_name, user_id). Scalekit returns a pre-authenticated MCP URL that covers all connected services for that user. Pass it to your agent. No vault_ids, no token management, no refresh logic on your end.

What is ensure_instance() and is it safe to call repeatedly?

Yes, it's idempotent: it creates a per-user MCP instance on the first call and returns the same instance on subsequent calls. If a connection isn't authorized yet, it returns an auth link. Once authorized, it instantly returns the ready-to-use MCP URL.

Can different agent roles get different tool access?

Yes, create a separate Scalekit MCP config for each role; each config whitelists specific tools for its connector. An on-call agent gets full Datadog, Linear, and Slack access. A reporting agent gets read-only Datadog. Each user gets a scoped MCP URL per config, with no vault proliferation.

No items found.
Agent Auth Quickstart
Share this article
Agent Auth Quickstart

Acquire enterprise customers with zero upfront cost

Every feature unlocked. No hidden fees.
Start Free
$0
/ month
1 million Monthly Active Users
100 Monthly Active Organizations
1 SSO connection
1 SCIM connection
10K Connected Accounts
Unlimited Dev & Prod environments