> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.recursiv.io/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.recursiv.io/_mcp/server.

# Agent Recipes

Short, self-contained recipes for working with agents. Every agent is model agnostic: set `model` to any OpenRouter-compatible identifier and the rest of the code is identical. Each snippet assumes `const r = new Recursiv()`, which reads `RECURSIV_API_KEY` from the environment.

### Create an agent

Spin up a named agent backed by any LLM with a system prompt that defines its behavior.

```typescript
import { Recursiv } from '@recursiv/sdk';

const r = new Recursiv();

const { data: agent } = await r.agents.create({
  name: 'Research Bot',
  username: 'researcher',
  model: 'anthropic/claude-sonnet-4.6',
  system_prompt: 'You are a thorough research assistant. Always cite sources.',
});

console.log(agent.id, agent.username);
```

### Chat and get a full reply

Send one message and read the whole response back. Pass `conversation_id` on the next call to keep context.

```typescript
const { data: reply } = await r.agents.chat(agent.id, {
  message: 'Summarize the latest trends in vector databases.',
});

console.log(reply.content);
console.log(reply.conversation_id); // reuse this to continue the thread
```

### Stream a reply token by token

Render output as it generates instead of waiting for the full response. The stream yields typed chunks.

```typescript
for await (const chunk of r.agents.chatStream(agent.id, {
  message: 'Explain how transformers work.',
})) {
  if (chunk.type === 'text_delta') process.stdout.write(chunk.delta ?? '');
}
```

### Give an agent tools

Flip an agent into tool-using mode. `autonomous` runs tools without asking; `permission` pauses for human approval before each call.

```typescript
const { data: agent } = await r.agents.create({
  name: 'Ops Agent',
  username: 'ops_agent',
  model: 'anthropic/claude-sonnet-4.6',
  tool_mode: 'autonomous', // or 'permission' to gate each tool call
});
```

### Connect hundreds of integrations

Recursiv ships hundreds of data integrations through one connection layer. Enable a connected integration (Gmail, Slack, Linear and more) for an agent and scope exactly which tools it may call.

```typescript
const orgId = 'org_123';

// What is connected for this org
const { data: connections } = await r.integrations.listConnections(orgId);
const gmail = connections.find((c) => c.provider === 'gmail');

// Enable it for the agent, allowing only specific tools
await r.integrations.updateAgentIntegration(agent.id, {
  user_integration_id: gmail!.id,
  enabled: true,
  allowed_tools: ['GMAIL_FETCH_EMAILS', 'GMAIL_SEND_EMAIL'],
});
```

### Persist memory across runs

Store facts and decisions so an agent remembers context between sessions. Memory is searchable and scoped per project.

```typescript
const PROJECT_ID = 'proj_123';

// Write what the agent learned
await r.memory.facts.add({
  fact: 'Customer prefers async email over Slack for approvals.',
  project_id: PROJECT_ID,
  agent_id: agent.id,
  tags: ['preferences'],
});

// Load relevant context before the next run
const { data: { context } } = await r.memory.context({
  message: 'Draft an approval request for the customer.',
  project_id: PROJECT_ID,
  agent_id: agent.id,
});

await r.agents.chat(agent.id, {
  message: `Context from memory:\n${context}\n\nDraft the approval request.`,
});
```

### Run the same agent on a different model

Model choice is one field. Swap providers without touching any other logic.

```typescript
await r.agents.update(agent.id, { model: 'openai/gpt-5.4' });
// next chat call runs on the new model, same prompt and tools
await r.agents.update(agent.id, { model: 'google/gemini-3.1-pro-preview' });
```

### List and inspect conversations

Pull an agent's conversation history to audit what it has been doing.

```typescript
const { data: conversations } = await r.agents.conversations(agent.id);

for (const conv of conversations) {
  console.log(conv.id, conv.last_message?.content ?? '(empty)');
}
```

### Hand work from one agent to another

Agents can message each other directly to delegate tasks and return results.

```typescript
await r.agents.sendMessage('target_agent_id', {
  from_agent_id: agent.id,
  type: 'delegation',
  content: 'Analyze the deployment logs for proj_123 and report failures.',
  project_id: 'proj_123',
});

// The receiving agent reads its inbox
const { data: messages } = await r.agents.inbox('target_agent_id', {
  unread_only: true,
});
```