Skip to main content
Register your existing Python functions so agents can call them. Raysurfer wraps your functions with @rs.tool, auto-infers the schema from the signature and docstring, and routes tool calls back to your app during sandbox execution.

Setup

Install the SDK and set RAYSURFER_API_KEY in your environment.
uv add raysurfer

Register Tools

@rs.tool can wrap any Python function. The function signature is converted to schema fields, and the function docstring is used as the tool description in the tool payload.
from raysurfer import AsyncRaySurfer

rs = AsyncRaySurfer(api_key="your_api_key")

@rs.tool
def add(a: int, b: int) -> int:
    """Add two numbers."""
    return a + b

How Functions Get Passed Back To The Agent

@rs.tool registers two things locally in your app process:
  • A tool schema (name, description, parameters) that Raysurfer sends to the sandbox run
  • A callback function that stays local and is invoked when the sandbox requests that tool
Execution flow:
  1. execute() opens a callback session and sends tool schemas plus your task to Raysurfer.
  2. Sandbox code calls a tool (for example add(5, 3)).
  3. Raysurfer sends a tool_call message back to your app.
  4. Your local callback runs, and the SDK sends tool_result back to the sandbox.
  5. The sandbox continues running with that result.
This is the mechanism that passes tool execution back into your running agent app.

Execute Modes

Use exactly one mode per execute() call:

Primary Mode: Pass user_code

result = await rs.execute(
    "Compute 5 + 3",
    user_code="print(add(5, 3))",
)

End-To-End Sandbox Example

import asyncio
from raysurfer import AsyncRaySurfer


async def main() -> None:
    rs = AsyncRaySurfer(api_key="your_api_key")

    @rs.tool
    def add(a: int, b: int) -> int:
        """Add two numbers."""
        return a + b

    result = await rs.execute(
        "Compute 5 + 3",
        user_code="result = add(5, 3)\nprint(result)",
    )
    print(result.result)      # "8"
    print(result.tool_calls)  # tool call history


asyncio.run(main())

Optional Mode: Sandbox Codegen

In this mode, code is generated inside Raysurfer’s remote sandbox from your prompt.
result = await rs.execute(
    "Compute 5 + 3",
    codegen_api_key="YOUR_ANTHROPIC_API_KEY",
    codegen_prompt="Write Python code that calls add(a, b) for 5 and 3, then prints the result.",
    codegen_model="claude-opus-4-6",
)

Full SDK Reference

See Python SDK for full method signatures and response fields.