This SDK is different from an MCP client SDK. To connect an agent framework to
Runlayer-hosted MCP servers, use the framework integration docs for
Vercel AI SDK,
OpenAI Agents SDK, or
Google ADK. For Claude Agent SDK MCP
server setup, see Claude Agent SDK.
Capabilities
- lifecycle telemetry for prompt, stop, and synthetic preflight session events
- pre-tool enforcement with optional argument rewriting
- post-tool output scanning and blocking
- failed tool telemetry
- direct MCP source enforcement
- tool enforcement filters for Runlayer-owned MCP tools and proxy URLs
- duck-typed tool adapters for Vercel-style and custom tool dictionaries
- preflight session emission for ingestion checks
- transcript-bearing
Stopevents for assistant reasoning extraction
Installation
Configuration
Create a Runlayer user API key, then set:client_credentials, then caches and refreshes that token internally. Do not
configure or pass a pre-minted bearer token.
For OBO agent tokens, also set:
client="python-sdk" so events are attributed to the
first-party Python SDK in Runlayer. Ensure your workspace hook-client allowlist
includes python-sdk before testing. If your deployment’s settings UI does not
expose that client yet, ask Runlayer support to enable it for your workspace.
Optional environment variables:
| Variable | Purpose |
|---|---|
RUNLAYER_AGENT_CLIENT_ID | Agent account Client ID for client_credentials token exchange. |
RUNLAYER_AGENT_CLIENT_SECRET | Agent account Client Secret for client_credentials token exchange. |
RUNLAYER_AGENT_SUBJECT_TOKEN | Optional user identity for OBO agent token exchange. |
RUNLAYER_AGENT_SUBJECT_TOKEN_TYPE | Token type for RUNLAYER_AGENT_SUBJECT_TOKEN; use urn:runlayer:token-type:user-id, urn:runlayer:token-type:user-email, or urn:ietf:params:oauth:token-type:access_token. |
RUNLAYER_HOOK_CLIENT | Override the client name sent to Runlayer. Only use this when your deployment supports a dedicated SDK client name. |
RUNLAYER_HOOK_DEBUG=1 | Log non-strict hook event failures to stderr. |
RUNLAYER_HOOK_TIMEOUT_MS | Optional timeout override, in milliseconds, for Runlayer hook calls. |
RUNLAYER_HOOK_MAX_TOOL_OUTPUT_BYTES | Maximum serialized tool output sent to Runlayer. Defaults to 65536; larger values are truncated with a marker. |
RUNLAYER_HOOK_ENFORCEMENT_FAILURE_MODE | Enforcement outage behavior. Defaults to closed; set to open only if your agent should continue when Runlayer cannot be reached. |
RUNLAYER_ALLOW_INSECURE_TRANSPORT=1 | Allow a non-HTTPS RUNLAYER_BASE_URL for local development only. |
RUNLAYER_DIRECT_MCP_SOURCE_ENFORCEMENT_PATH | Endpoint path for direct MCP source validation, when enabled by your deployment. |
Runtime Safety
Runlayer enforcement is fail-closed by default. If pre-tool, post-tool, or direct MCP source enforcement cannot reach Runlayer, the SDK treats the call as blocked. Lifecycle telemetry is best-effort unless a helper documents strict behavior, such as preflight and transcriptStop emission.
Every hook request uses a timeout, and tool output is capped before upload.
When no timeout override is set, enforcement and tool lifecycle hooks use 30
seconds, lifecycle event hooks use 5 seconds, and direct endpoint calls use 10
seconds.
Failed tool outputs include bounded stdout, stderr, and output fields with
truncation metadata when available, so Runlayer can scan failure context without
the SDK uploading unbounded logs.
The SDK skips pre-tool and post-tool enforcement for Runlayer’s own MCP server
names (runlayer, runlayer-plugin, and onelayer) and for MCP calls whose
tool_url points at a Runlayer proxy URL. Third-party MCP tools remain enforced
by default. For custom runtimes, use the exported should_enforce_tool(...)
helper or the client’s tool_enforcement option so new adapters make the same
decision consistently. Additional ignored_mcp_server_names are added to the
default Runlayer self-MCP skip list; set skip_runlayer_self_mcp=False only if
you need to enforce those self-MCP names. If you call should_enforce_tool(...)
directly with absolute self-hosted Runlayer MCP proxy URLs, pass
runlayer_base_url; RunlayerClient does this automatically.
base_url must use https:// unless allow_insecure_transport or
RUNLAYER_ALLOW_INSECURE_TRANSPORT=1 is set. Only enable insecure transport for
a trusted local development endpoint.
Preflight
Use preflight to verify that Runlayer receives hook events before invoking a real model.SessionStart, UserPromptSubmit, and Stop sequence
for a synthetic session. If any request fails, the helper throws.
Claude Agent SDK Hooks
Pass Runlayer hooks into Claude Agent SDK’squery options.
include_stop=False when you emit a transcript-bearing Stop manually.
That lets Runlayer extract assistant thinking or reasoning blocks from the
completed transcript instead of receiving a bare lifecycle stop.
The generated hook map covers UserPromptSubmit, PreToolUse, PostToolUse,
PostToolUseFailure, and Stop by default. It does not register Claude
SessionStart or SessionEnd hooks; use preflight when you need a strict
synthetic session sequence.
Tool Enforcement
If your runtime executes tools outside Claude Agent SDK hooks, wrap those calls withrun_tool.
execute. If Runlayer denies the tool call or blocks
the tool output, the SDK throws RunlayerBlockedError.
To avoid recursively enforcing Runlayer-owned tools, configure
tool_enforcement when constructing the client:
runlayer,
runlayer-plugin, onelayer) and Runlayer MCP proxy URLs.
Framework Tool Adapters
The Python SDK includes dependency-free wrappers for common tool dictionary shapes. These adapters callrun_tool around the original execute function
and preserve extra context arguments for custom runtimes that use OpenAI,
Google ADK, or Vercel-style option dictionaries.
These helpers do not wrap native Python FunctionTool or callable objects from
the OpenAI Agents SDK or Google ADK. Use RunlayerClient.run_tool(...) directly
inside those callables until native callable adapters are available.
| Helper | Purpose |
|---|---|
with_runlayer_vercel_ai_tool / with_runlayer_vercel_ai_tools | Wraps Vercel AI-style tool dictionaries by tool name or tool-set key. |
with_runlayer_openai_agents_tool | Wraps custom OpenAI Agents-style tool dictionaries. |
with_runlayer_google_adk_tool | Wraps custom Google ADK-style tool dictionaries. |
run_runlayer_adapter_tool | Low-level adapter helper for custom framework wrappers. |
Direct MCP Source Enforcement
Use direct MCP source enforcement when a custom agent can call MCP servers without going through the Runlayer proxy. Direct MCP source enforcement posts to the Cursor hook route and currently requires user API-key auth. ConfigureRUNLAYER_API_KEY for this client; agent
account bearer auth is supported for lifecycle and tool hooks, but not this
direct MCP source route.
enforce_mcp_source throws
RunlayerBlockedError.
API Reference
RunlayerClient.from_env(**options)
Creates a client from RUNLAYER_BASE_URL plus one auth source:
RUNLAYER_API_KEY or RUNLAYER_AGENT_CLIENT_ID /
RUNLAYER_AGENT_CLIENT_SECRET.
When agent credentials are configured, the SDK exchanges them at
/api/v1/oauth/token, caches the bearer token, and refreshes before expiry.
The SDK does not accept pre-minted bearer tokens.
Options:
| Option | Description |
|---|---|
client | Client name sent to Runlayer. Defaults to RUNLAYER_HOOK_CLIENT or python-sdk. |
client_version | Version string for your agent runtime. |
direct_mcp_source_enforcement_path | Endpoint path for direct MCP source enforcement. |
timeout_ms | Optional per-request timeout override in milliseconds. If unset, enforcement and tool lifecycle hooks use 30000 ms, lifecycle event hooks use 5000 ms, and direct endpoint calls use 10000 ms. |
max_tool_output_bytes | Maximum serialized tool output bytes sent to Runlayer. Defaults to 65536. |
enforcement_failure_mode | closed blocks on enforcement outages; open allows on outages. Defaults to closed. |
tool_enforcement | Optional filter config for ignored tools, ignored MCP server names, Runlayer proxy URLs, and custom predicates. |
allow_insecure_transport | Allows non-HTTPS base_url; local development only. |
create_claude_agent_sdk_hooks(client, options=None, *, include_stop=None)
Returns a Claude Agent SDK hook map with prompt telemetry, pre-tool, post-tool,
failed-tool, and optional stop hooks.
Set include_stop=False as a keyword argument, or pass
{"include_stop": False} / {"includeStop": False} as options, when you emit
the transcript-bearing Stop event yourself.
send_runlayer_preflight(client, **options)
Sends a strict synthetic lifecycle sequence to confirm ingestion.
emit_claude_agent_sdk_transcript_stop(client, **options)
Sends a strict Stop event with newline-delimited transcript lines.