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_eventbefore_toolafter_toolrun_toolshould_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, setRUNLAYER_USER_EMAIL(or theuser_emailclient 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_toolwith_runlayer_vercel_ai_toolswith_runlayer_openai_agents_toolwith_runlayer_google_adk_toolrun_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_hooksemit_claude_agent_sdk_transcript_stopclaude_agent_sdk_assistant_message_to_transcript_linetool_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)
| File | Size | Uploaded | |
|---|---|---|---|
| runlayer_hooks_sdk-0.2.3.tar.gz | 61.1 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| 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}
|