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.3

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.3
File Size Uploaded
runlayer_hooks_sdk-0.2.3.tar.gz 61.1 kB Details

Built distribution (wheel)

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

Total release size: 95.3 kB

Release files / runlayer_hooks_sdk-0.2.3.tar.gz

Download URL runlayer_hooks_sdk-0.2.3.tar.gz
Size 61.1 kB
Tags Source
SHA-256 checksum
How to use checksums
0bbb25f9214294ca96a3844f6c7d0f3cf45ff26835897ec418875abfdf9df7ec
BLAKE2b-256 checksum
How to use checksums
7f1f5f73b99ff96951c711205fb5864692d7c955de2e090ba83623969ca30233
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.12 {"installer":{"name":"uv","version":"0.12.12","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.3-py3-none-any.whl

Download URL runlayer_hooks_sdk-0.2.3-py3-none-any.whl
Size 34.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
baf8ff74823d190f0494717294a9ef80724a8c40ed7963893f2e2f4e538c0fd9
BLAKE2b-256 checksum
How to use checksums
1d1c84e6325fc4f565931f77f08b463fe0307a0bd497fa3832f8dcd2903b61c9
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.12 {"installer":{"name":"uv","version":"0.12.12","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

This release

0.2.3 This release

2 release files

0.2.2

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