Skip to navigation

Build an Autonomous Agent

Give an agent its own database, storage, and code execution

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

npm install @recursiv/sdk

Set up environment

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

The code

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)