Claude Managed Agents
Run Claude Managed Agents with Scalekit-authenticated tools using Virtual MCP Servers and Anthropic vaults.
Run a background agent that reads Gmail and creates Google Calendar events — without managing any agent loop. Anthropic handles tool discovery, execution, retries, and session state. You provide the task.
Scalekit connects the agent to user-authorized tools via a Virtual MCP Server. Before each run, you mint a short-lived session token and store it in an Anthropic vault. The agent accesses the MCP server using the vault credential.
Prerequisites
Section titled “Prerequisites”- A Scalekit account with Gmail and Google Calendar connections configured. See Configure a connection.
- An Anthropic API key with access to the Managed Agents beta.
- An Anthropic environment ID set as
ANTHROPIC_ENVIRONMENT_ID.
How it works
Section titled “How it works”The flow has three phases:
- Build (one-time) — Create a Virtual MCP Server and a Claude Managed Agent. Save
mcp_idandagent_id. - Authorize user for external connections (once per user) — Authorize the user’s Gmail and Google Calendar accounts.
- Run a session (per agent run) — Check connections, mint a session token, store it in an Anthropic vault, and start a session.
Install
Section titled “Install”pip install anthropic scalekit-sdk-python python-dotenvRun this once to create your Virtual MCP Server and Claude Managed Agent. Save the returned mcp_id and agent_id — you reuse them for every user and every session.
import osimport anthropicfrom scalekit import ScalekitClientfrom scalekit.actions.models.mcp_config import McpConfigConnectionToolMappingfrom dotenv import load_dotenv
load_dotenv()
anthropic_client = anthropic.Anthropic()scalekit_client = ScalekitClient( env_url=os.environ["SCALEKIT_ENV_URL"], client_id=os.environ["SCALEKIT_CLIENT_ID"], client_secret=os.environ["SCALEKIT_CLIENT_SECRET"],)
GMAIL_TOOLS = ["gmail_fetch_mails"]GCAL_TOOLS = [ "googlecalendar_list_calendars", "googlecalendar_list_events", "googlecalendar_get_event_by_id", "googlecalendar_create_event", "googlecalendar_update_event",]
vmcp_response = scalekit_client.actions.mcp.create_config( name="email-calendar-demo", connection_tool_mappings=[ McpConfigConnectionToolMapping( connection_name="gmail", tools=GMAIL_TOOLS, ), McpConfigConnectionToolMapping( connection_name="googlecalendar", tools=GCAL_TOOLS, ), ],)
mcp_id = vmcp_response.config.idmcp_server_url = vmcp_response.config.mcp_server_url
agent = anthropic_client.beta.agents.create( name="Email Meeting Manager", model="claude-haiku-4-5-20251001", system=( "You are an email and calendar assistant. When invoked, you will:\n" "1. Fetch the single most recent unread email from Gmail.\n" "2. Summarize it in 2-3 sentences.\n" "3. Create a Google Calendar event titled 'Action Required: <email subject>' " "with your summary as the description." ), mcp_servers=[ { "type": "url", "name": "email-calendar-mcp", "url": mcp_server_url, } ], tools=[ {"type": "agent_toolset_20260401", "default_config": {"enabled": True}}, { "type": "mcp_toolset", "mcp_server_name": "email-calendar-mcp", "default_config": { "enabled": True, "permission_policy": {"type": "always_allow"}, }, }, ],)
print("Virtual MCP ID:", mcp_id)print("Agent ID: ", agent.id)The agent definition references the mcp_server_url but carries no auth credentials. Authentication is injected at runtime via the Anthropic vault.
Authorize user for external connections
Section titled “Authorize user for external connections”Each user authorizes their Gmail and Google Calendar accounts once. All future agent sessions for that user reuse those connections.
import osfrom scalekit import ScalekitClientfrom dotenv import load_dotenv
load_dotenv()
scalekit_client = ScalekitClient( env_url=os.environ["SCALEKIT_ENV_URL"], client_id=os.environ["SCALEKIT_CLIENT_ID"], client_secret=os.environ["SCALEKIT_CLIENT_SECRET"],)
# Retrieve mcp_id by listing Virtual MCP Servers filtered by name to use belowaccounts_response = scalekit_client.actions.mcp.list_mcp_connected_accounts( config_id=mcp_id, identifier=identifier, # your app's unique user ID)
for account in accounts_response.connected_accounts: if account.connected_account_status != "ACTIVE": auth_response = scalekit_client.actions.get_authorization_link( identifier=identifier, connection_name=account.connection_name, ) print(f"{account.connection_name} needs auth: {auth_response.link}") else: print(f"✓ {account.connection_name} — {account.connected_account_status}")Surface the auth link in your app UI or send it via email. Users only need to do this once.
Run a session
Section titled “Run a session”Run the following for each agent execution.
-
Check that connections are active
Section titled “Check that connections are active”Before minting a token, confirm all connections are still
"ACTIVE". OAuth tokens for connected accounts can expire or be revoked.executor.py accounts_response = scalekit_client.actions.mcp.list_mcp_connected_accounts(config_id=mcp_id,identifier=identifier,)inactive = [a.connection_namefor a in accounts_response.connected_accountsif a.connected_account_status != "ACTIVE"]if inactive:print("Inactive connections:", inactive)# Prompt the user to re-authorize before proceeding -
Mint a session token and store in vault
Section titled “Mint a session token and store in vault”Mint a short-lived session token and store it in an Anthropic vault. Claude Managed Agents access the MCP server using the vault credential — not a direct bearer header.
executor.py from datetime import timedeltaconfigs_response = scalekit_client.actions.mcp.list_configs(filter_id=mcp_id)mcp_server_url = configs_response.configs[0].mcp_server_urltoken_response = scalekit_client.actions.mcp.create_session_token(mcp_config_id=mcp_id,identifier=identifier,expiry=timedelta(hours=1),)token = token_response.token# Create vault and credential on first run; update the token on subsequent runsif vault_id and credential_id:anthropic_client.beta.vaults.credentials.update(credential_id,vault_id=vault_id,auth={"type": "static_bearer", "token": token},)else:vault = anthropic_client.beta.vaults.create(display_name="email-calendar-vault")vault_id = vault.idcredential = anthropic_client.beta.vaults.credentials.create(vault_id,display_name="email-calendar-credential",auth={"type": "static_bearer","mcp_server_url": mcp_server_url,"token": token,},)credential_id = credential.id -
Start the session
Section titled “Start the session”Pass
vault_idsto the session so the agent can authenticate against the MCP server.executor.py session = anthropic_client.beta.sessions.create(agent=agent_id,environment_id=os.environ["ANTHROPIC_ENVIRONMENT_ID"],vault_ids=[vault_id],)with anthropic_client.beta.sessions.events.stream(session_id=session.id) as stream:anthropic_client.beta.sessions.events.send(session_id=session.id,events=[{"type": "user.message", "content": [{"type": "text", "text": prompt}]}],)for event in stream:if event.type == "agent.message":for block in event.content:if block.type == "text":print(block.text, end="", flush=True)elif event.type == "agent.mcp_tool_use":print(f"\n→ {event.name}", flush=True)elif event.type in ("session.status_idle", "session.status_terminated"):break