Installation
Setup
Set your API key:Usage
Swap your client class and method names. Options come directly fromclaude_agent_sdk:
Method Mapping
| Claude SDK | Raysurfer |
|---|---|
ClaudeSDKClient(options) | RaysurferClient(options) |
await client.query(prompt) | await client.query(prompt) |
client.receive_response() | client.response() |
Options
Options are passed through directly fromclaude_agent_sdk.ClaudeAgentOptions. All standard options work:
RAYSURFER_API_KEY is set.
Agent-Owned Repos
Setagent_id to isolate uploads/searches into an agent-owned repo:
Agent-Accessible Functions
Decorator flow:raysurfer.yaml flow:
Snippet Retrieval Scope
Control which cached snippets are retrieved usingsnips_desired:
| Configuration | Required Tier |
|---|---|
snips_desired="company" | PRO or ENTERPRISE |
snips_desired="client" | PRO or ENTERPRISE (requires workspace_id) |
Public Snippets
Include community public snippets (crawled from GitHub) alongside your private snippets:Full Example
Without Caching
IfRAYSURFER_API_KEY is not set, RaysurferClient behaves exactly like ClaudeSDKClient — no caching, just a pass-through wrapper.
Low-Level API
For custom integrations, use theRaySurfer client directly.
Complete Low-Level Example with Anthropic API
Response Fields
Thesearch() response includes:
| Field | Type | Description |
|---|---|---|
files | list[CodeFile] | Retrieved code files with metadata |
task | str | The task that was searched |
total_found | int | Total matches found |
add_to_llm_prompt | str | Pre-formatted string to append to your LLM system prompt |
CodeFile contains:
| Field | Type | Description |
|---|---|---|
code_block_id | str | Unique identifier of the code block |
filename | str | Generated filename (e.g., "github_fetcher.py") |
source | str | Full source code |
entrypoint | str | Main function to call |
description | str | What the code does |
input_schema | JsonDict | JSON schema for inputs |
output_schema | JsonDict | JSON schema for outputs |
language | str | Programming language |
dependencies | dict[str, str] | Package name to version mapping |
verdict_score | float | Quality rating (thumbs_up / total, 0.3 if unrated) |
thumbs_up | int | Positive votes |
thumbs_down | int | Negative votes |
similarity_score | float | Semantic similarity (0–1) |
combined_score | float | Combined score (similarity * 0.6 + verdict * 0.4) |
Async Version
Search Response
Thesearch() method returns a SearchResponse:
| Field | Type | Description |
|---|---|---|
matches | list[SearchMatch] | Matching code blocks with full scoring |
total_found | int | Total matches found |
cache_hit | bool | Whether results were served from cache |
search_namespaces | list[str] | Namespaces that were searched |
SearchMatch contains:
| Field | Type | Description |
|---|---|---|
code_block | CodeBlock | The code block (has id, name, description, source, entrypoint, language, dependencies, tags) |
combined_score | float | Overall relevance score (0–1) |
vector_score | float | Semantic similarity score |
verdict_score | float | Community quality rating |
error_resilience | float | Error handling robustness score |
thumbs_up | int | Positive votes |
thumbs_down | int | Negative votes |
filename | str | Generated filename for the code |
language | str | Programming language |
entrypoint | str | Main function name |
dependencies | dict[str, str] | Package name to version mapping (e.g., {"pandas": "2.1.0"}) |
agent_id | str | None | Agent identifier when snippet came from an agent-owned repo |
s3_url | str | None | Presigned download URL for agent-stored script content |
functions | list[FunctionReputation] | None | Per-function reputation metadata (when per_function_reputation=True) |
Method Reference
| Method | Description |
|---|---|
search(task, top_k, min_verdict_score, prefer_complete, per_function_reputation) | Search for cached code snippets |
upload(task, file_written, succeeded, ..., per_function_reputation=False) | Store a code file for future reuse |
upload_bulk_code_snips(prompts, files_written, ...) | Bulk upload for grading |
delete(snippet_id) | Delete a snippet by ID or name |
vote_code_snip(task, code_block_id, name, description, succeeded) | Vote on snippet usefulness |
comment_on_code_snip(code_block_id, text) | Add a comment to a snippet |
publish_function_registry(functions) | Publish @agent_accessible functions for agent discovery |
tool(fn) | Register a local function as a tool for execute() |
execute(task, user_code=None, timeout=300, codegen_api_key=None, codegen_prompt=None, codegen_model=...) | Execute user code (primary) or sandbox-generated code (optional) with registered tools |
Programmatic Tool Calling
Also available as an integration guide: Register Python Functions. Register local tools, then either passuser_code (primary mode) or use optional sandbox codegen with your own key + prompt:
@rs.tool decorator can wrap any Python function you want to expose as a tool.
It introspects the function signature to build a JSON schema.
Your function docstring becomes the tool description field in the tool schema payload.
Both sync and async callbacks are supported.
How It Works
- SDK opens a live callback channel for tool call routing
- Your app sends either
user_code(primary mode) orcodegen_*inputs (optional mode) to/api/execute/run - Code runs in a Modal sandbox — tool calls are routed back to your local functions through that callback channel
- Results are returned with full tool call history
user_code: run pre-generated code directly (recommended default)codegen_api_key+codegen_prompt: generate code in sandbox and run it
Execute Options
ExecuteResult Fields
| Field | Type | Description |
|---|---|---|
execution_id | str | Unique execution identifier |
result | str | None | Stdout output from the script |
exit_code | int | Process exit code (0 = success) |
duration_ms | int | Total execution time |
cache_hit | bool | Reserved field (currently always False for execute) |
error | str | None | Error message if exit_code != 0 |
tool_calls | list[ToolCallRecord] | All tool calls made during execution |
