Skip to main content

PostgreSQL for Agents

PostgreSQL provides durable storage for your Agents - conversation history survives server restarts, and you can query past interactions. Essential for production Agents that need reliable persistence.

Agent with Persistent Conversations

import { Agent, createNeonPostgres, createPostgresSessionStorage } from 'praisonai';

const db = createNeonPostgres({ connectionString: process.env.DATABASE_URL });
const sessions = createPostgresSessionStorage(db);
await sessions.init();

const agent = new Agent({
  name: 'Support Agent',
  instructions: 'You are a helpful support agent. Use conversation history for context.'
});

// Agent with PostgreSQL-backed memory
async function agentChat(sessionId: string, message: string) {
  // Load full conversation history from PostgreSQL
  const history = await sessions.getMessages(sessionId);
  
  // Build context for Agent
  const context = history.map(m => `${m.role}: ${m.content}`).join('\n');
  const prompt = context ? `${context}\nuser: ${message}` : message;
  
  // Get Agent response
  const response = await agent.chat(prompt);
  
  // Persist to PostgreSQL (survives restarts)
  await sessions.addMessage(sessionId, { id: crypto.randomUUID(), role: 'user', content: message });
  await sessions.addMessage(sessionId, { id: crypto.randomUUID(), role: 'assistant', content: response });
  
  return response;
}

// Conversation persists forever
await agentChat('customer-123', 'I need help with my subscription');
// ... server restarts ...
await agentChat('customer-123', 'What was my issue again?'); // Agent remembers!

Multi-Agent with Shared Database

Multiple Agents can share conversation context:
import { Agent, PraisonAIAgents, createNeonPostgres, createPostgresSessionStorage } from 'praisonai';

const db = createNeonPostgres({ connectionString: process.env.DATABASE_URL });
const sessions = createPostgresSessionStorage(db);

// Agent 1: Handles initial inquiries
const triageAgent = new Agent({
  name: 'Triage',
  instructions: 'Categorize customer issues and gather initial information.'
});

// Agent 2: Handles technical issues
const techAgent = new Agent({
  name: 'Tech Support',
  instructions: 'Resolve technical issues. Review conversation history for context.'
});

// Agent 3: Handles billing
const billingAgent = new Agent({
  name: 'Billing',
  instructions: 'Handle billing inquiries. Check conversation history for customer details.'
});

async function routeToAgent(sessionId: string, message: string) {
  // All agents see the same conversation history
  const history = await sessions.getMessages(sessionId);
  
  // Triage determines which agent handles this
  const category = await triageAgent.chat(`Categorize: ${message}`);
  
  let response: string;
  if (category.includes('technical')) {
    response = await techAgent.chat(`History:\n${formatHistory(history)}\n\nNew message: ${message}`);
  } else if (category.includes('billing')) {
    response = await billingAgent.chat(`History:\n${formatHistory(history)}\n\nNew message: ${message}`);
  } else {
    response = await triageAgent.chat(message);
  }
  
  // Save to shared database
  await sessions.addMessage(sessionId, { id: crypto.randomUUID(), role: 'user', content: message });
  await sessions.addMessage(sessionId, { id: crypto.randomUUID(), role: 'assistant', content: response, metadata: { agent: category } });
  
  return response;
}

Agent with Database Tools

Give your Agent direct database access:
import { Agent, createTool, createNeonPostgres } from 'praisonai';

const db = createNeonPostgres({ connectionString: process.env.DATABASE_URL });
await db.connect();

// Tool to query customer data
const lookupCustomer = createTool({
  name: 'lookup_customer',
  description: 'Look up customer information by ID or email',
  parameters: {
    type: 'object',
    properties: {
      customerId: { type: 'string', description: 'Customer ID' },
      email: { type: 'string', description: 'Customer email' }
    }
  },
  execute: async ({ customerId, email }) => {
    const query = customerId 
      ? 'SELECT * FROM customers WHERE id = $1'
      : 'SELECT * FROM customers WHERE email = $1';
    const result = await db.query(query, [customerId || email]);
    return result.length > 0 ? JSON.stringify(result[0]) : 'Customer not found';
  }
});

// Tool to update customer data
const updateCustomer = createTool({
  name: 'update_customer',
  description: 'Update customer information',
  parameters: {
    type: 'object',
    properties: {
      customerId: { type: 'string', description: 'Customer ID' },
      field: { type: 'string', description: 'Field to update' },
      value: { type: 'string', description: 'New value' }
    },
    required: ['customerId', 'field', 'value']
  },
  execute: async ({ customerId, field, value }) => {
    await db.execute(
      `UPDATE customers SET ${field} = $1, updated_at = NOW() WHERE id = $2`,
      [value, customerId]
    );
    return `Updated ${field} for customer ${customerId}`;
  }
});

const agent = new Agent({
  name: 'Customer Service Agent',
  instructions: 'Help customers by looking up and updating their information.',
  tools: [lookupCustomer, updateCustomer]
});

await agent.chat('Look up customer [email protected] and update their plan to premium');

Agent Analytics & Logging

Track Agent performance in PostgreSQL:
import { Agent, createNeonPostgres } from 'praisonai';

const db = createNeonPostgres({ connectionString: process.env.DATABASE_URL });

// Create analytics table
await db.execute(`
  CREATE TABLE IF NOT EXISTS agent_analytics (
    id SERIAL PRIMARY KEY,
    session_id TEXT,
    agent_name TEXT,
    query TEXT,
    response TEXT,
    tokens_used INT,
    latency_ms INT,
    created_at TIMESTAMP DEFAULT NOW()
  )
`);

const agent = new Agent({
  name: 'Analytics Agent',
  instructions: 'You are a helpful assistant.'
});

async function trackedChat(sessionId: string, query: string) {
  const start = Date.now();
  
  const response = await agent.chat(query);
  
  const latency = Date.now() - start;
  
  // Log to PostgreSQL
  await db.execute(
    `INSERT INTO agent_analytics (session_id, agent_name, query, response, latency_ms) 
     VALUES ($1, $2, $3, $4, $5)`,
    [sessionId, agent.name, query, response, latency]
  );
  
  return response;
}

// Query analytics
async function getAgentStats() {
  const stats = await db.query(`
    SELECT 
      agent_name,
      COUNT(*) as total_queries,
      AVG(latency_ms) as avg_latency,
      DATE(created_at) as date
    FROM agent_analytics
    GROUP BY agent_name, DATE(created_at)
    ORDER BY date DESC
  `);
  return stats;
}

Agent Knowledge Base in PostgreSQL

Store and query Agent knowledge:
import { Agent, createTool, createNeonPostgres } from 'praisonai';

const db = createNeonPostgres({ connectionString: process.env.DATABASE_URL });

// Create knowledge table with full-text search
await db.execute(`
  CREATE TABLE IF NOT EXISTS agent_knowledge (
    id TEXT PRIMARY KEY,
    content TEXT NOT NULL,
    category TEXT,
    search_vector TSVECTOR GENERATED ALWAYS AS (to_tsvector('english', content)) STORED
  );
  CREATE INDEX IF NOT EXISTS knowledge_search_idx ON agent_knowledge USING GIN(search_vector);
`);

const searchKnowledge = createTool({
  name: 'search_knowledge',
  description: 'Search the knowledge base for relevant information',
  parameters: {
    type: 'object',
    properties: {
      query: { type: 'string', description: 'Search query' }
    },
    required: ['query']
  },
  execute: async ({ query }) => {
    const results = await db.query(
      `SELECT content, ts_rank(search_vector, plainto_tsquery($1)) as rank
       FROM agent_knowledge
       WHERE search_vector @@ plainto_tsquery($1)
       ORDER BY rank DESC LIMIT 5`,
      [query]
    );
    return results.map(r => r.content).join('\n\n');
  }
});

const agent = new Agent({
  name: 'Knowledge Agent',
  instructions: 'Answer questions using the knowledge base.',
  tools: [searchKnowledge]
});

Environment Variables

DATABASE_URL=postgres://user:pass@host/database?sslmode=require