Skip to main content

Runlayer Hooks Python SDK

Python SDK companion to @runlayer/hooks-sdk.

Configure

export RUNLAYER_BASE_URL="https://your-runlayer-instance.com"
export RUNLAYER_API_KEY="rl_..."

For cloud installations that authenticate with a shared organization API key (rl_org_...), also name the Runlayer user the deployment runs as so sessions and enforcement are attributed to it:

export RUNLAYER_API_KEY="rl_org_..."
export RUNLAYER_USER_EMAIL="svc-my-agent@your-company.com"

The identity can be a service user provisioned just for the deployment; events sent before that user exists in the workspace are buffered and replayed once it does. The organization key must carry the AI Watch scan role. user_email is also available as a RunlayerClient constructor option; it applies only to API key auth (agent accounts express the acting user via subject_token).

Agent account auth is also supported:

export RUNLAYER_BASE_URL="https://your-runlayer-instance.com"
export RUNLAYER_AGENT_CLIENT_ID="client_..."
export RUNLAYER_AGENT_CLIENT_SECRET="..."

Optional OBO subject fields:

export RUNLAYER_AGENT_SUBJECT_TOKEN="user@example.com"
export RUNLAYER_AGENT_SUBJECT_TOKEN_TYPE="urn:runlayer:token-type:user-email"

The SDK mints an agent token with client_credentials and, when an OBO subject is configured, exchanges it via RFC 8693 token exchange (urn:ietf:params:oauth:grant-type:token-exchange); both tokens are cached and refreshed internally.

Optional runtime controls:

Variable Purpose
RUNLAYER_HOOK_TIMEOUT_MS Hook request timeout. Defaults to 10000.
RUNLAYER_HOOK_MAX_TOOL_OUTPUT_BYTES Maximum serialized tool output sent to Runlayer. Defaults to 65536.
RUNLAYER_HOOK_ENFORCEMENT_FAILURE_MODE Defaults to closed; set to open only if tool calls should continue when Runlayer is unreachable.
RUNLAYER_ALLOW_INSECURE_TRANSPORT=1 Allow non-HTTPS RUNLAYER_BASE_URL for local development.

Usage

from runlayer_sdk import RunlayerClient

runlayer = RunlayerClient.from_env(client_version="my-agent/1.0.0")


def run_local_tool(tool_input: dict[str, object]) -> str:
    return "tool output"


output = runlayer.run_tool(
    execute=run_local_tool,
    session_id="session-id",
    tool_input={"command": "cat README.md"},
    tool_name="Bash",
    tool_type="shell",
)

Use tool_enforcement to skip Runlayer-owned MCP tools or proxy URLs:

runlayer = RunlayerClient.from_env(
    tool_enforcement={
        "ignored_mcp_server_names": ["github-preview"],
        "skip_runlayer_mcp_proxy_urls": True,
    }
)

RunlayerClient exposes:

  • emit_event
  • before_tool
  • after_tool
  • run_tool
  • should_enforce_tool

The package also exports send_runlayer_preflight.

Troubleshooting: sessions not appearing

Lifecycle hooks send events best-effort and do not raise on their own. If the server accepts an event but does not record it, it responds with status: "ignored" and a reason. The client logs a one-time warning to stderr for the actionable reasons so a misconfiguration is not silent:

  • client_not_enabled — the SDK session-monitoring client is off for this workspace. Enable the client (and any required SDK toggle) in Runlayer settings. This is a separate switch from tool enforcement, so both must be on to get full session + tool telemetry.
  • sessions_disabled — the applicable MDM configuration disables session reporting. Ask a Runlayer administrator to enable Sessions in that MDM configuration.
  • actor_unresolved — the request authenticated but Runlayer could not map it to a user/agent. With an organization API key, set RUNLAYER_USER_EMAIL (or the user_email client option) to the Runlayer user the deployment runs as; events are buffered until that user exists in the workspace. Otherwise use a personal API key (RUNLAYER_API_KEY) or agent-account credentials (RUNLAYER_AGENT_CLIENT_ID / RUNLAYER_AGENT_CLIENT_SECRET).

Set RUNLAYER_HOOK_DEBUG=1 to also log transient ignore reasons and network failures. Run send_runlayer_preflight() for an explicit check.

Framework tool adapters

Dependency-free adapters wrap common tool dictionary shapes:

  • with_runlayer_vercel_ai_tool
  • with_runlayer_vercel_ai_tools
  • with_runlayer_openai_agents_tool
  • with_runlayer_google_adk_tool
  • run_runlayer_adapter_tool

Claude Agent SDK hooks

Use the adapter helpers when a Python agent runtime wants the same Claude Agent SDK hook output shapes as the Hooks TypeScript SDK:

from runlayer_sdk import RunlayerClient, create_claude_agent_sdk_hooks

runlayer = RunlayerClient.from_env()
hooks = create_claude_agent_sdk_hooks(runlayer, include_stop=False)

The adapter exports:

  • create_claude_agent_sdk_hooks
  • emit_claude_agent_sdk_transcript_stop
  • claude_agent_sdk_assistant_message_to_transcript_line
  • tool_type_from_name

TypeScript-style camelCase aliases are also available for SDK parity.

Each query() call starts a new Claude Agent SDK session with a fresh session_id, and Runlayer records each session id as a separate session. To keep a multi-prompt conversation in a single Runlayer session, resume the previous session on follow-up calls (leave fork_session unset so the session id is preserved), then emit the transcript Stop per run as usual:

options = ClaudeAgentOptions(
    hooks=create_claude_agent_sdk_hooks(runlayer, include_stop=False),
    resume=session_id,  # session_id captured from the previous run's init message
)

Metadata

Release files for runlayer-hooks-sdk 0.2.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for runlayer-hooks-sdk 0.2.2
File Size Uploaded
runlayer_hooks_sdk-0.2.2.tar.gz 51.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for runlayer-hooks-sdk 0.2.2
File Interpreter ABI Platform
runlayer_hooks_sdk-0.2.2-py3-none-any.whl Python 3 none any Details

Total release size: 84.7 kB

Release files / runlayer_hooks_sdk-0.2.2.tar.gz

Download URL runlayer_hooks_sdk-0.2.2.tar.gz
Size 51.7 kB
Tags Source
SHA-256 checksum
How to use checksums
754102db0a1a41d4a563206c08561ee261797253d9f57778d57cb931def0b7fb
BLAKE2b-256 checksum
How to use checksums
4fefa36db723940a3be6e21f1a35058715143b7a8cbd4bd66259435937605ad8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.5 {"installer":{"name":"uv","version":"0.12.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / runlayer_hooks_sdk-0.2.2-py3-none-any.whl

Download URL runlayer_hooks_sdk-0.2.2-py3-none-any.whl
Size 33.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
d9b851a2278e397d8c0ef98af6abf30e8e8449981ebf51cbef28be63b78a67e6
BLAKE2b-256 checksum
How to use checksums
ab4a1d08adf2f935d756b07dab1345c1a002f894976ae8f2410db0750e2615a6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.5 {"installer":{"name":"uv","version":"0.12.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release history Release notifications | RSS feed

0.2.3

2 release files

This release

0.2.2 This release

2 release files

0.2.1

2 release files

0.2.0

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page