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

1import { Recursiv } from '@recursiv/sdk'
2
3const r = new Recursiv()
4const ORG_ID = process.env.RECURSIV_ORG_ID!
5
6async function main() {
7 // 1. Create the agent
8 const { data: agent } = await r.agents.create({
9 name: 'Data Pipeline Agent',
10 username: 'pipeline_agent_' + Date.now(),
11 model: 'anthropic/claude-sonnet-4',
12 system_prompt: `You are an autonomous data pipeline agent. You can:
13- Query and modify your Postgres database
14- Read and write files to your storage bucket
15- Execute code in your sandbox
16Always explain what you're doing before taking action.`,
17 tool_mode: 'autonomous',
18 organization_id: ORG_ID,
19 })
20 console.log('Agent created:', agent.username)
21
22 // 2. Create a project for the agent's infrastructure
23 const { data: project } = await r.projects.create({
24 name: `${agent.username}-infra`,
25 organization_id: ORG_ID,
26 })
27
28 // 3. Provision a database for the agent
29 const { data: db } = await r.databases.ensure({
30 name: 'agent-data',
31 project_id: project.id,
32 })
33 const { data: creds } = await r.databases.getCredentials({
34 project_id: project.id,
35 name: 'agent-data',
36 })
37 console.log('Database ready:', creds.host)
38
39 // 4. Set up file storage
40 const { data: bucket } = await r.storage.ensureBucket({
41 name: 'agent-files',
42 project_id: project.id,
43 })
44 console.log('Storage bucket:', bucket.name)
45
46 // 5. Grant the agent access to the project
47 await r.agents.grantProjectAccess(agent.id, {
48 project_id: project.id,
49 permissions: ['execute_code', 'read_files', 'write_files'],
50 })
51 console.log('Agent granted project access')
52
53 // 6. Start a sandbox for code execution
54 await r.projects.createSandbox(project.id)
55
56 // 7. Run a migration on behalf of the agent
57 await r.projects.executeCode(project.id, {
58 code: `
59 const { Client } = require('pg');
60 const c = new Client({ connectionString: '${creds.connection_string}' });
61 await c.connect();
62 await c.query(\`
63 CREATE TABLE IF NOT EXISTS pipeline_runs (
64 id SERIAL PRIMARY KEY,
65 source TEXT NOT NULL,
66 records_processed INT DEFAULT 0,
67 status TEXT DEFAULT 'pending',
68 started_at TIMESTAMPTZ DEFAULT NOW(),
69 completed_at TIMESTAMPTZ
70 )
71 \`);
72 console.log('Schema ready');
73 await c.end();
74 `,
75 language: 'typescript',
76 })
77
78 // 8. Chat with the agent about its capabilities
79 process.stdout.write('Agent: ')
80 for await (const chunk of r.agents.chatStream(agent.id, {
81 message: 'What infrastructure do you have access to? What can you do?',
82 })) {
83 process.stdout.write(chunk.delta ?? '')
84 }
85 console.log()
86}
87
88main()

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)