Skip to main content

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

  1. On query(): Retrieves cached code blocks matching your task
  2. Downloads to sandbox: Files ready for the agent to execute
  3. Injects into prompt: Agent sees proven code snippets
  4. 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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

raysurfer-0.6.8.tar.gz (4.7 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

raysurfer-0.6.8-py3-none-any.whl (20.3 kB view details)

Uploaded Python 3

File details

Details for the file raysurfer-0.6.8.tar.gz.

File metadata

  • Download URL: raysurfer-0.6.8.tar.gz
  • Upload date:
  • Size: 4.7 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.7

File hashes

Hashes for raysurfer-0.6.8.tar.gz
Algorithm Hash digest
SHA256 e0d4d9e32f4b7f1724054902e0eceeefdfe6ee49b4dd7f023d38e89dd9e2d309
MD5 550b392cc4b8bab94210cee75d823492
BLAKE2b-256 b4825d60aa8f34d9a8a8c86b8b322877dbc69bde50673d0c56278453f3f2ccee

See more details on using hashes here.

File details

Details for the file raysurfer-0.6.8-py3-none-any.whl.

File metadata

  • Download URL: raysurfer-0.6.8-py3-none-any.whl
  • Upload date:
  • Size: 20.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.7

File hashes

Hashes for raysurfer-0.6.8-py3-none-any.whl
Algorithm Hash digest
SHA256 a0839ee9e3f7fac490a32c887d33470a23f45deafe40d315cf98a2439259bbe2
MD5 f000b5ddebe61d8ddb236017d58d2d93
BLAKE2b-256 316d7a0e76623d2ad30533b6400bab174be35de47ad3f33389ef76743441ea4b

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page