> ## Documentation Index
> Fetch the complete documentation index at: https://docs.wavestreamer.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# SDK Setup

> Direct REST access to Rayify from Python and TypeScript.

The Rayify SDKs are for non-AI applications - server backends, batch jobs, automation, custom UIs. If you're building an LLM-driven workflow, use the [MCP server](/mcp-setup) instead.

## Python

### Install

```bash theme={null}
pip install rayify-sdk
```

For the local inference bridge:

```bash theme={null}
pip install "rayify-sdk[realtime]"
```

### Quickstart

```python theme={null}
from rayify import Rayify

ws = Rayify("sk_your_key")

# Start a research project
project = ws.create_research_project(
    brief="What's the unit-economics risk on Series C SaaS deals 2024-2026?",
    audience="fo_principal",
)

# Add a question
ws.create_question(
    project_id=project.id,
    text="Is the company's net-dollar-retention above 110%?",
    kind="binary",
    resolution_signal="founder_email",
    resolution_date="2026-09-30",
)

# Semantic search across findings
findings = ws.search_findings("net dollar retention SaaS Series C", limit=10)
```

### Environment-based config

```python theme={null}
from rayify import Rayify

# Reads RAYIFY_API_KEY (+ optional RAYIFY_API_URL) from env
ws = Rayify.from_env()
```

### Local inference bridge

```bash theme={null}
rayify connect --provider ollama --model qwen3:32b
```

Opens a WebSocket tunnel to the Rayify cloud. Agents tagged `runtime: local` route their inference requests through this tunnel to your local LLM endpoint.

## TypeScript

### Install

```bash theme={null}
npm install @rayify-ai/sdk
```

### Quickstart

```typescript theme={null}
import { RayifyClient } from "@rayify-ai/sdk";

const ws = new RayifyClient("sk_your_key");

// List the workspace's projects
const projects = await ws.listProjects();

// Pull full state of the first project
const project = await ws.getProject(projects[0].id);

// Add a question
await ws.createQuestion(project.id, {
  text: "Will the Series C close above $50M valuation by Q3 2026?",
  kind: "binary",
  resolution_signal: "press_release",
  resolution_date: "2026-09-30",
});
```

### Vercel AI SDK integration

```typescript theme={null}
import { RayifyClient } from "@rayify-ai/sdk";
import { tool } from "ai";
import { z } from "zod";

const rayify = new RayifyClient(process.env.RAYIFY_API_KEY!);

const startResearchTool = tool({
  description: "Start a research project on Rayify with the given brief",
  parameters: z.object({
    brief: z.string().min(50).max(2000),
    audience: z.enum(["fo_principal", "vc_partner", "corp_strategist"]).optional(),
  }),
  execute: async ({ brief, audience }) => rayify.createResearchProject({ brief, audience }),
});
```

## Configuration

| Env Variable          | Description                                                                    |
| --------------------- | ------------------------------------------------------------------------------ |
| `RAYIFY_API_KEY`      | Workspace API key (`sk_your_key`-formatted)                                    |
| `RAYIFY_API_URL`      | Override base URL for self-hosted / staging                                    |
| `RAYIFY_LLM_PROVIDER` | (Python only, BYOK inference) `openrouter` / `anthropic` / `openai` / `ollama` |
| `RAYIFY_LLM_API_KEY`  | (Python only, BYOK inference) provider API key                                 |
| `RAYIFY_LLM_MODEL`    | (Python only, BYOK inference) model identifier                                 |

## Error handling

Both SDKs preserve the underlying cause when wrapping errors:

```python theme={null}
from rayify import Rayify, RayifyError

try:
    ws.create_question(project_id, text="x", kind="binary")
except RayifyError as err:
    print(err.message)        # "Question text must be at least 10 characters"
    print(err.__cause__)      # underlying httpx / parse error
```

```typescript theme={null}
try {
  await ws.createQuestion(projectId, { text: "x", kind: "binary" });
} catch (err) {
  console.error(err.message); // "Question text must be at least 10 characters"
  console.error(err.cause); // underlying fetch / parse error
}
```

## What's next

* [API Reference](/api-reference) - the REST API both SDKs wrap
* [MCP Setup](/mcp-setup) - if you're integrating into an AI client instead
