> 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.

# Build an Autonomous Agent

Create an AI agent with its own database, file storage, and code execution capabilities.

This is Recursiv's most differentiated pattern: an agent that isn't just an LLM wrapper, but has real infrastructure it can provision and manage.

## Prerequisites

* Node.js >= 18
* A Recursiv API key with scopes: `agents:read`, `agents:write`, `projects:read`, `projects:write`
* Your Organization ID

## Install

```bash
npm install @recursiv/sdk
```

## Set up environment

```bash
export RECURSIV_API_KEY=sk_live_xxx
export RECURSIV_ORG_ID=your-org-id
```

## The code

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

const r = new Recursiv()
const ORG_ID = process.env.RECURSIV_ORG_ID!

async function main() {
  // 1. Create the agent
  const { data: agent } = await r.agents.create({
    name: 'Data Pipeline Agent',
    username: 'pipeline_agent_' + Date.now(),
    model: 'anthropic/claude-sonnet-4.6',
    system_prompt: `You are an autonomous data pipeline agent. You can:
- Query and modify your Postgres database
- Read and write files to your storage bucket
- Execute code in your sandbox
Always explain what you're doing before taking action.`,
    tool_mode: 'autonomous',
    organization_id: ORG_ID,
  })
  console.log('Agent created:', agent.username)

  // 2. Create a project for the agent's infrastructure
  const { data: project } = await r.projects.create({
    name: `${agent.username}-infra`,
    organization_id: ORG_ID,
  })

  // 3. Provision a database for the agent
  const { data: db } = await r.databases.ensure({
    name: 'agent-data',
    project_id: project.id,
  })
  const { data: creds } = await r.databases.getCredentials({
    project_id: project.id,
    name: 'agent-data',
  })
  console.log('Database ready:', creds.host)

  // 4. Set up file storage
  const { data: bucket } = await r.storage.ensureBucket({
    name: 'agent-files',
    project_id: project.id,
  })
  console.log('Storage bucket:', bucket.name)

  // 5. Grant the agent access to the project
  await r.agents.grantProjectAccess(agent.id, {
    project_id: project.id,
    permissions: ['execute_code', 'read_files', 'write_files'],
  })
  console.log('Agent granted project access')

  // 6. Start a sandbox for code execution
  await r.projects.createSandbox(project.id)

  // 7. Run a migration on behalf of the agent
  await r.projects.executeCode(project.id, {
    code: `
      const { Client } = require('pg');
      const c = new Client({ connectionString: '${creds.connection_string}' });
      await c.connect();
      await c.query(\`
        CREATE TABLE IF NOT EXISTS pipeline_runs (
          id SERIAL PRIMARY KEY,
          source TEXT NOT NULL,
          records_processed INT DEFAULT 0,
          status TEXT DEFAULT 'pending',
          started_at TIMESTAMPTZ DEFAULT NOW(),
          completed_at TIMESTAMPTZ
        )
      \`);
      console.log('Schema ready');
      await c.end();
    `,
    language: 'typescript',
  })

  // 8. Chat with the agent about its capabilities
  process.stdout.write('Agent: ')
  for await (const chunk of r.agents.chatStream(agent.id, {
    message: 'What infrastructure do you have access to? What can you do?',
  })) {
    process.stdout.write(chunk.delta ?? '')
  }
  console.log()
}

main()
```

## What just happened

You created an autonomous agent with:

* Its own Postgres database with a custom schema
* A file storage bucket for reading/writing data
* A sandbox for executing arbitrary code
* Project access permissions connecting it all

The agent is no longer just an LLM wrapper — it has real infrastructure it can use to accomplish tasks independently.

## Next steps

* Monitor the agent's work with `r.projectBrain.tasks(projectId)`
* Track usage and costs with `r.projectBrain.usage(projectId)`
* View agent conversations with `r.agents.conversations(agentId)`
* Revoke access when done with `r.agents.revokeProjectAccess(agentId, projectId)`