Metadata-Version: 2.4
Name: runlayer-hooks-sdk
Version: 0.1.0
Summary: Runlayer Hooks SDK for Python agent runtimes
Project-URL: Homepage, https://runlayer.com
Project-URL: Documentation, https://docs.runlayer.com/
Author-email: Runlayer <engineering@runlayer.com>
License: Apache-2.0
Keywords: agent,llm,mcp,runlayer,security
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.10
Requires-Dist: httpx==0.28.1
Description-Content-Type: text/markdown

# Runlayer Hooks Python SDK

Python SDK companion to `@runlayer/hooks-sdk`.

## Configure

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

Agent account auth is also supported:

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

Optional OBO subject fields:

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

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

```python
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:

```python
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`.

## 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:

```python
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.
