Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.runlayer.com/llms.txt

Use this file to discover all available pages before exploring further.

The Runlayer TypeScript SDK wires custom agent runtimes into Runlayer’s hook enforcement and telemetry pipeline. It is for agents that execute tools directly and need Runlayer to observe, rewrite, or block tool calls.
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.

Capabilities

  • lifecycle telemetry for session, prompt, and stop events
  • pre-tool enforcement with optional argument rewriting
  • post-tool output scanning and blocking
  • failed tool telemetry
  • direct MCP source enforcement
  • preflight session emission for ingestion checks
  • transcript-bearing Stop events for assistant reasoning extraction

Installation

pnpm add @runlayer/sdk@0.1.0 @anthropic-ai/claude-agent-sdk@0.2.80

Configuration

Create a Runlayer user API key, then set:
export RUNLAYER_BASE_URL="https://your-runlayer-instance.com"
export RUNLAYER_API_KEY="rl_..."
The SDK defaults to client: "typescript-sdk" so events are attributed to the first-party TypeScript SDK in Runlayer. Enable Hooks for the TypeScript SDK client in Runlayer workspace settings before testing. Optional environment variables:
VariablePurpose
RUNLAYER_HOOK_CLIENTOverride the client name sent to Runlayer. Only use this when your deployment supports a dedicated SDK client name.
RUNLAYER_HOOK_DEBUG=1Log non-strict hook event failures to stderr.
RUNLAYER_HOOK_TIMEOUT_MSRequest timeout for Runlayer hook calls. Defaults to 10000.
RUNLAYER_HOOK_MAX_TOOL_OUTPUT_BYTESMaximum serialized tool output sent to Runlayer. Defaults to 65536; larger values are truncated with a marker.
RUNLAYER_HOOK_ENFORCEMENT_FAILURE_MODEEnforcement outage behavior. Defaults to closed; set to open only if your agent should continue when Runlayer cannot be reached.
RUNLAYER_ALLOW_INSECURE_TRANSPORT=1Allow a non-HTTPS RUNLAYER_BASE_URL for local development only.
RUNLAYER_DIRECT_MCP_SOURCE_ENFORCEMENT_PATHEndpoint 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 transcript Stop emission. Every hook request uses a timeout, and tool output is capped before upload. 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. baseUrl must use https:// unless allowInsecureTransport 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.
import { RunlayerClient, sendRunlayerPreflight } from "@runlayer/sdk";

const runlayer = RunlayerClient.fromEnv({
  clientVersion: "my-agent/1.0.0",
});

const result = await sendRunlayerPreflight(runlayer, {
  prompt: "Runlayer ingestion preflight",
});

console.log(result.sessionId);
Preflight sends a strict 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’s query options.
import { query } from "@anthropic-ai/claude-agent-sdk";
import {
  claudeAgentSdkAssistantMessageToTranscriptLine,
  createClaudeAgentSdkHooks,
  emitClaudeAgentSdkTranscriptStop,
  RunlayerClient,
} from "@runlayer/sdk/claude-agent-sdk";

const runlayer = RunlayerClient.fromEnv({
  clientVersion: "my-agent/1.0.0",
});

const transcriptLines: string[] = [];
let sessionId: string | undefined;

for await (const message of query({
  prompt: "Inspect this workspace and summarize the active project.",
  options: {
    allowedTools: ["Read", "Glob", "Grep", "Bash"],
    hooks: createClaudeAgentSdkHooks(runlayer, { includeStop: false }),
    maxTurns: 4,
    model: "claude-opus-4-6",
    thinking: { type: "adaptive" },
  },
})) {
  if (message.type === "system" && message.subtype === "init") {
    sessionId = message.session_id;
  }

  if (message.type === "assistant") {
    transcriptLines.push(
      claudeAgentSdkAssistantMessageToTranscriptLine(message.message),
    );
  }
}

if (sessionId) {
  await emitClaudeAgentSdkTranscriptStop(runlayer, {
    model: "claude-opus-4-6",
    sessionId,
    transcriptLines,
  });
}
Use includeStop: 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.

Tool Enforcement

If your runtime executes tools outside Claude Agent SDK hooks, wrap those calls with runTool.
import { RunlayerClient } from "@runlayer/sdk";

const runlayer = RunlayerClient.fromEnv({
  clientVersion: "my-agent/1.0.0",
});

const output = await runlayer.runTool({
  execute: async (toolInput) => {
    return runLocalTool(toolInput);
  },
  sessionId: "session-id",
  toolInput: { command: "cat README.md" },
  toolName: "Bash",
  toolType: "shell",
});
Runlayer can return modified arguments from the pre-tool hook. The SDK passes those modified arguments to execute. If Runlayer denies the tool call or blocks the tool output, the SDK throws RunlayerBlockedError.

Direct MCP Source Enforcement

Use direct MCP source enforcement when a custom agent can call MCP servers without going through the Runlayer proxy.
const runlayer = RunlayerClient.fromEnv({
  directMcpSourceEnforcementPath: "/api/v1/hooks/direct-mcp-source",
});

await runlayer.enforceMcpSource({
  generationId: "generation-id",
  sessionId: "session-id",
  toolName: "mcp__github__list_repos",
  url: "https://tenant.runlayer.com/api/v1/proxy/server-id/mcp",
});
If Runlayer denies the source, enforceMcpSource throws RunlayerBlockedError.

API Reference

RunlayerClient.fromEnv(options?)

Creates a client from RUNLAYER_BASE_URL and RUNLAYER_API_KEY. Options:
OptionDescription
clientClient name sent to Runlayer. Defaults to RUNLAYER_HOOK_CLIENT or typescript-sdk.
clientVersionVersion string for your agent runtime.
directMcpSourceEnforcementPathEndpoint path for direct MCP source enforcement.
timeoutMsPer-request timeout in milliseconds. Defaults to 10000.
maxToolOutputBytesMaximum serialized tool output bytes sent to Runlayer. Defaults to 65536.
enforcementFailureModeclosed blocks on enforcement outages; open allows on outages. Defaults to closed.
allowInsecureTransportAllows non-HTTPS baseUrl; local development only.

createClaudeAgentSdkHooks(client, options?)

Returns a Claude Agent SDK hook map with lifecycle, pre-tool, post-tool, and failed-tool hooks. Options:
OptionDescription
includeStopInclude a stock Stop lifecycle hook. Set this to false when sending a transcript-bearing Stop manually.

sendRunlayerPreflight(client, options?)

Sends a strict synthetic lifecycle sequence to confirm ingestion.

emitClaudeAgentSdkTranscriptStop(client, options)

Sends a strict Stop event with newline-delimited transcript lines.

runTool(options)

Runs a custom tool through Runlayer pre-tool and post-tool enforcement.

enforceMcpSource(options)

Validates a direct MCP source before execution.