Semantic code caching for LLM agents
Project description
RaySurfer Python SDK
Drop-in replacement for Claude Agent SDK with automatic code caching.
Installation
pip install raysurfer
Setup
Set your API key:
export RAYSURFER_API_KEY=your_api_key_here
Get your key from the dashboard.
Usage
Swap your client class and method names. Options come directly from claude_agent_sdk:
# Before
from claude_agent_sdk import ClaudeSDKClient, ClaudeAgentOptions
# After
from raysurfer import RaysurferClient
from claude_agent_sdk import ClaudeAgentOptions
options = ClaudeAgentOptions(
allowed_tools=["Read", "Write", "Bash"],
system_prompt="You are a helpful assistant.",
)
async with RaysurferClient(options) as client:
await client.query("Generate quarterly report")
async for msg in client.response():
print(msg)
Method Mapping
| Claude SDK | Raysurfer |
|---|---|
ClaudeSDKClient(options) |
RaysurferClient(options) |
await client.query(prompt) |
await client.query(prompt) |
client.receive_response() |
client.response() |
How It Works
- On
query(): Retrieves cached code blocks matching your task - Downloads to sandbox: Files ready for the agent to execute
- Injects into prompt: Agent sees proven code snippets
- After success: New code is cached for next time
Caching is enabled automatically when RAYSURFER_API_KEY is set.
Snippet Retrieval Scope
Control which cached snippets are retrieved using snips_desired:
from raysurfer import RaysurferClient
from claude_agent_sdk import ClaudeAgentOptions
options = ClaudeAgentOptions(
allowed_tools=["Read", "Write", "Bash"],
)
# Include company-level snippets
client = RaysurferClient(
options,
snips_desired="company", # Company-level snippets (Team/Enterprise)
)
# Enterprise: Retrieve client-specific snippets only
client = RaysurferClient(
options,
snips_desired="client", # Client workspace snippets (Enterprise only)
)
| Configuration | Required Tier |
|---|---|
snips_desired="company" |
TEAM or ENTERPRISE |
snips_desired="client" |
ENTERPRISE only |
Full Example
import asyncio
import os
from raysurfer import RaysurferClient
from claude_agent_sdk import ClaudeAgentOptions
os.environ["RAYSURFER_API_KEY"] = "your_api_key"
async def main():
options = ClaudeAgentOptions(
allowed_tools=["Read", "Write", "Bash"],
system_prompt="You are a helpful assistant.",
)
async with RaysurferClient(options) as client:
# First run: generates and caches code
await client.query("Fetch GitHub trending repos")
async for msg in client.response():
print(msg)
# Second run: retrieves from cache (instant)
await client.query("Fetch GitHub trending repos")
async for msg in client.response():
print(msg)
asyncio.run(main())
Without Caching
If RAYSURFER_API_KEY is not set, RaysurferClient behaves exactly like ClaudeSDKClient — no caching, just a pass-through wrapper.
Low-Level API
For custom integrations, use the RaySurfer client directly with three core methods:
from raysurfer import RaySurfer
from raysurfer.types import FileWritten, LogFile
client = RaySurfer(api_key="your_api_key")
# 1. Get cached code snippets for a task
snips = client.get_code_snips(task="Fetch GitHub trending repos")
for match in snips.code_blocks:
print(f"{match.code_block.name}: {match.score}")
# Or use the unified search endpoint
search_result = client.search(task="Fetch GitHub trending repos")
for match in search_result.matches:
print(f"{match.code_block.name}: {match.combined_score}")
# 2. Upload a new code file after execution
file = FileWritten(path="fetch_repos.py", content="def fetch(): ...")
client.upload_new_code_snip(
task="Fetch GitHub trending repos",
file_written=file,
succeeded=True,
)
# 2b. Bulk upload prompts/logs/code for sandboxed grading
logs = [LogFile(path="logs/run.log", content="Task completed", encoding="utf-8")]
client.upload_bulk_code_snips(
prompts=["Build a CLI tool", "Add CSV support"],
files_written=[FileWritten(path="cli.py", content="def main(): ...")],
log_files=logs,
auto_vote=True,
)
# 3. Vote on whether a cached snippet was useful
client.vote_code_snip(
task="Fetch GitHub trending repos",
code_block_id="abc123",
code_block_name="github_fetcher",
code_block_description="Fetches trending repos from GitHub",
succeeded=True,
)
Async Version
from raysurfer import AsyncRaySurfer
from raysurfer.types import FileWritten
async with AsyncRaySurfer(api_key="your_api_key") as client:
snips = await client.get_code_snips(task="Fetch GitHub trending repos")
file = FileWritten(path="fetch_repos.py", content="def fetch(): ...")
await client.upload_new_code_snip(
task="Fetch GitHub trending repos",
file_written=file,
succeeded=True,
)
await client.vote_code_snip(
task="Fetch GitHub trending repos",
code_block_id=snips.code_blocks[0].code_block.id,
code_block_name=snips.code_blocks[0].code_block.name,
code_block_description=snips.code_blocks[0].code_block.description,
succeeded=True,
)
Method Reference
| Method | Description |
|---|---|
search(task, top_k, min_verdict_score, prefer_complete) |
Unified search for cached code (recommended) |
get_code_snips(task, top_k, min_verdict_score) |
Retrieve cached code snippets by semantic search |
upload_new_code_snip(task, file_written, succeeded) |
Store a single code file for future reuse |
upload_bulk_code_snips(prompts, files_written, log_files, auto_vote) |
Bulk upload prompts/logs/code for sandboxed grading |
vote_code_snip(task, code_block_id, name, description, succeeded) |
Vote on snippet usefulness |
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file raysurfer-0.6.10.tar.gz.
File metadata
- Download URL: raysurfer-0.6.10.tar.gz
- Upload date:
- Size: 4.7 MB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bc9e9bcd57bf7be1bc64b991bf7a55f9bdf6ccd289a5defbaa4c754229b3ddbb
|
|
| MD5 |
2920ba8a71cecb1fda20ff186fe8bd2b
|
|
| BLAKE2b-256 |
6fd158060c86b6321c9f41a9b91d95f58ced5d71dba19ee9a7af69906cd37d5e
|
File details
Details for the file raysurfer-0.6.10-py3-none-any.whl.
File metadata
- Download URL: raysurfer-0.6.10-py3-none-any.whl
- Upload date:
- Size: 20.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d42703f958a3972bc856a64441fcbccf9b7cf69de190abd9af8fe754fa621827
|
|
| MD5 |
755346fcee9b2d2d16d237be25794b3e
|
|
| BLAKE2b-256 |
fd0e1373942a9e05dac193821121e330a46bea35976a8ce490ac245f3e6af026
|