Skip to main content

Lightweight multi-agent runtime for Postgres teams with planning and resilience

Project description

PG Agent

License: MIT CI PyPI Python 3.10+

PG Agent is a multi-agent runtime for PostgreSQL that turns natural language into secure, executable query plans. It supports multi-turn conversations, schema-aware RAG, self-correcting execution, and result critique — all with zero infrastructure required beyond a Postgres database.


Architecture

User Question
     │
     ▼
 Supervisor (coordinator.py)
     │
     ├── RAG Pipeline ──► LongTermMemory (pgvector)
     │       └── Retrieves relevant schema context
     │
     ├── PlanningAgent ──► Gemini 2.5 Flash
     │       └── Decomposes question into typed steps (SQL / ANALYZE / SEARCH / VERIFY)
     │
     ├── ExecutionAgent
     │       ├── SecureSQLTool   — validates + runs SELECT queries
     │       ├── AnalyticsTool   — pandas/numexpr for math & aggregation
     │       └── SearchTool      — web search for external context
     │
     └── CriticAgent ──► Gemini 2.5 Flash
             └── Post-execution result validation

Key properties:

  • Multi-turn chat — conversation history is passed to the planner on every turn
  • Schema-aware RAG — your table/column schema is embedded in pgvector and retrieved per query
  • Self-correcting — failed SQL steps are re-planned up to 2 times automatically
  • Read-only enforcement — all queries are parsed with sqlglot; DROP, DELETE, UPDATE, etc. are blocked at the tool level
  • No LIMIT required — the SQL validator automatically adds LIMIT 1000 to unconstrained queries

Quick Start

1. Install

pip install pgagent-llm

Or from source:

git clone https://github.com/siddharth7786/pg-agent
cd pg-agent
pip install -e .

2. Configure Environment

Create a .env file or export these variables:

# Required
GEMINI_API_KEY=your_gemini_api_key
DATABASE_URL=postgresql://user:password@localhost:5432/your_db

# Optional — in-memory state is used if not set
REDIS_URL=redis://localhost:6379

3. First-Time Setup

Run once to create the long_term_memory table and enable the required PostgreSQL extensions (pgvector, pg_trgm):

pg-agent setup

4. Index Your Schema

Scan your database schema and store it in pgvector so the planner can write accurate SQL:

pg-agent --index ask "What tables do I have?"

Re-run with --index any time your schema changes.


CLI Reference

Commands

Command Description
pg-agent setup One-time setup: enables pgvector/pg_trgm and creates memory tables
pg-agent ask "<question>" Ask a single question and get a result
pg-agent chat Start an interactive multi-turn session

Global Flags

Flag Description
--index Re-index the database schema before running
--verbose, -v Show full internal logs (planning, execution, critique)

ask Flags

Flag Default Description
--pattern SEQUENTIAL Orchestration pattern: SEQUENTIAL or PARALLEL
--retries 1 Max planning retries on execution failure
--redis $REDIS_URL Override Redis URL

chat Flags

Flag Default Description
--pattern SEQUENTIAL Orchestration pattern: SEQUENTIAL or PARALLEL
--redis $REDIS_URL Override Redis URL

Examples

# Single question
pg-agent ask "Who are the top 5 customers by total payments?"

# Index schema and ask in one shot
pg-agent --index ask "What tables exist and how are they related?"

# With verbose logging
pg-agent -v ask "What is the total revenue per store?"

# Interactive chat
pg-agent chat

# Chat with verbose output
pg-agent -v chat

# Override Redis for this session
pg-agent chat --redis redis://localhost:6379

Chat Session Commands

Inside pg-agent chat:

Input Action
Any question Plan and execute against your database
index Re-index the database schema
exit or quit End the session
Ctrl+C End the session

Python Library Usage

Embed PG Agent directly in your application:

import asyncio
from pg_agent.orchestration.coordinator import Supervisor, CoordinationPattern

async def main():
    agent = Supervisor(
        api_key="your-gemini-key",
        db_url="postgresql://user:pass@localhost:5432/db",
        redis_url="redis://localhost:6379",  # optional
    )

    # Index schema once (or after migrations)
    await agent.index_database_schema()

    # Single question
    state = await agent.orchestrate(
        session_id="session-123",
        pattern=CoordinationPattern.SEQUENTIAL,
        question="What is the total revenue per store?"
    )

    print(state.plan.reasoning)
    for step in state.plan.steps:
        print(f"[{step.id}] {step.description}: {state.results.get(step.id)}")

asyncio.run(main())

For multi-turn conversations, reuse the same session_id across calls — the supervisor persists and passes conversation history automatically.


How It Works

Planning

The PlanningAgent sends your question (plus schema context from RAG) to Gemini and receives a structured JSON plan with typed steps:

Step Type Tool When used
SQL SecureSQLTool Any database query
ANALYZE AnalyticsTool Math, aggregation, combining results
SEARCH SearchTool External web context
VERIFY Internal Checking prior step results

Execution

The ExecutionAgent runs steps with dependency resolution — steps with depends_on wait for their dependencies before starting. A circuit breaker halts execution after 5 failures in 60 seconds.

Self-Correction

If a SQL step fails, the planner receives the error message and the failed query, and generates a corrected plan. This happens up to 2 times per question.

Critique

After execution, the CriticAgent asks Gemini whether the results actually answer the original question. If not, a warning is logged (results are still returned).

Schema RAG

When you run --index, fetch_schema() reads information_schema for all public tables, columns, and foreign key relationships. Each table and relationship is embedded with gemini-embedding-001 (768 dimensions) and stored in pgvector. On each question, the top-10 most relevant schema chunks are retrieved and injected into the planner's system prompt.

State Persistence

Session state (plan, results, conversation history) is stored as JSON, either in Redis (if REDIS_URL is set) or in-memory. The same session_id is reused across turns in chat mode, enabling multi-turn context while resetting the plan and results for each new question.


Database Requirements

Requirement Notes
PostgreSQL 14+ Required
pgvector extension Installed by pg-agent setup; requires superuser on managed DBs
pg_trgm extension Installed by pg-agent setup; used for hybrid keyword search

Manual Extension Install (if setup lacks permissions)

CREATE EXTENSION IF NOT EXISTS vector;
CREATE EXTENSION IF NOT EXISTS pg_trgm;

Development

# Install with dev dependencies
pip install -e ".[dev]"

# Run tests
pytest

# Lint
ruff check src/

# Type check
mypy src/

# Security scan
bandit -r src/

License

MIT — see LICENSE for full text.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pgagent_llm-0.1.0.tar.gz (37.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pgagent_llm-0.1.0-py3-none-any.whl (35.2 kB view details)

Uploaded Python 3

File details

Details for the file pgagent_llm-0.1.0.tar.gz.

File metadata

  • Download URL: pgagent_llm-0.1.0.tar.gz
  • Upload date:
  • Size: 37.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.3

File hashes

Hashes for pgagent_llm-0.1.0.tar.gz
Algorithm Hash digest
SHA256 da687b508b654c170ba8be9ec5b434962591ba24186e13b9d0a7f65ff759d143
MD5 ddf38a8aa06c11869cab20abecdb9d49
BLAKE2b-256 1378cfc10ad067cb94f7fff049a42bd97e33ca0ff4144c9a8102359ba8335be9

See more details on using hashes here.

File details

Details for the file pgagent_llm-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: pgagent_llm-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 35.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.3

File hashes

Hashes for pgagent_llm-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 4295ad1744ecbfe3b060a6baaea85d852f3fc936d320704af9fc28a670f06c7d
MD5 110652fdcea8a2a77770abcc8a7e9578
BLAKE2b-256 fd843a86bb0364fa818b52080867ea7743b74055da71796b0a99073e83d8b8a7

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page