Skip to main content
Publish a registry of your functions so agents can discover and call them across sessions. Raysurfer auto-infers the function name, description, and input schema from the function signature, type hints, and docstring — so you don’t need to write schemas by hand. Once registered, functions can be:
  • Published to Raysurfer for agent discovery via publish_function_registry / publishFunctionRegistry
  • Converted to Anthropic tool definitions via to_anthropic_tool / toAnthropicTool for direct use with Claude’s tool calling
  • Tracked automatically — every call records execution duration, inputs, outputs, and success/failure

Which Path Passes Functions Back To The Running Agent?

These three paths are related, but they are not the same runtime:
PathPurposeHow functions are wired at runtime
publish_function_registry / publishFunctionRegistryPersist reusable functions for discovery across sessionsFunctions are uploaded as registry snippets and made available to Raysurfer sandbox runs for that scope
to_anthropic_tool / toAnthropicToolGenerate Anthropic-compatible tool schemasYou pass the returned schema to your Claude tool-calling loop and handle tool execution in your app
@rs.tool / tool(...) + execute(...)Live tool calling in Raysurfer sandboxRaysurfer opens a callback channel and routes each tool call back to your local callback during execution
If your question is “how does the function call get passed back into my agent process during execution?”, use @rs.tool / tool(...) with execute(...). See Register Python Functions or Register TypeScript Functions.

Python

Auto-inferred (no explicit params)

from raysurfer import AsyncRaySurfer, agent_accessible

rs = AsyncRaySurfer()

@agent_accessible()
def generate_board_report(company: str, quarter: str) -> str:
    """Generate a quarterly board report.

    Args:
        company: The company name to generate the report for.
        quarter: The fiscal quarter (e.g. "Q1 2026").
    """
    return build_report(company=company, quarter=quarter)
Name, description, and input schema are all inferred from the function name, docstring, and type hints.

With explicit description

@agent_accessible("Generate a quarterly board report")
def generate_board_report(company: str, quarter: str) -> str:
    return build_report(company=company, quarter=quarter)

Org/workspace scoping

@agent_accessible(org_id="acme-corp", workspace_id="finance-team")
def generate_board_report(company: str, quarter: str) -> str:
    """Generate a quarterly board report."""
    return build_report(company=company, quarter=quarter)

Converting to Anthropic tool format

from raysurfer import agent_accessible, to_anthropic_tool

@agent_accessible()
def generate_board_report(company: str, quarter: str) -> str:
    """Generate a quarterly board report."""
    return build_report(company=company, quarter=quarter)

tool = to_anthropic_tool(generate_board_report)
# Returns: {"name": "generate_board_report", "description": "...", "input_schema": {...}}

Publishing to Raysurfer

rs = AsyncRaySurfer()
await rs.publish_function_registry([generate_board_report])

TypeScript

Auto-inferred (no explicit options)

import { RaySurfer, agentAccessible } from "raysurfer";

const rs = new RaySurfer();

const generateBoardReport = agentAccessible(
  (company: string, quarter: string) => buildReport(company, quarter),
);
Name and parameters are inferred from the function.

With explicit options

const generateBoardReport = agentAccessible(
  (company: string, quarter: string) => buildReport(company, quarter),
  {
    name: "generateBoardReport",
    description: "Generate a quarterly board report",
  },
);

Org/workspace scoping

const generateBoardReport = agentAccessible(
  (company: string, quarter: string) => buildReport(company, quarter),
  { orgId: "acme-corp", workspaceId: "finance-team" },
);

Converting to Anthropic tool format

import { agentAccessible, toAnthropicTool } from "raysurfer";

const generateBoardReport = agentAccessible(
  (company: string, quarter: string) => buildReport(company, quarter),
  { description: "Generate a quarterly board report" },
);

const tool = toAnthropicTool(generateBoardReport);
// Returns: { name: "generateBoardReport", description: "...", input_schema: {...} }

Publishing to Raysurfer

const rs = new RaySurfer();
await rs.publishFunctionRegistry([generateBoardReport]);

Persistent Sandbox

Previously published functions are available in the sandbox execution environment, scoped by org and workspace. When an agent runs code through Raysurfer’s sandbox, functions published via publish_function_registry / publishFunctionRegistry for that scope are available without re-uploading each session. For live callback routing during a run, use @rs.tool / tool(...) with execute(...).

Running In Raysurfer Sandbox

To run a coding agent in Raysurfer’s remote sandbox with tool callbacks:
  1. Register callbacks with @rs.tool (Python) or tool(...) (TypeScript).
  2. Call execute(...) with either user_code / userCode or optional sandbox codegen inputs.
  3. Handle results from ExecuteResult (result, error, and tool_calls / toolCalls).
Use the end-to-end guides: