Codumentor logo Codumentor

Database Plugin

The database plugin gives the agent general SQL tools — list connections, list
tables, describe a table, run a read-only query, and run a gated write — against
one or more configured databases. Each connection picks its own backend: a
native pure-Python driver or an external database CLI. Out-of-the-box engines:
Postgres, MySQL/MariaDB, Oracle, SQL Server (plus SQLite).

Switchable backends

A connection's mode decides how it talks to the database:

modeBehaviour
nativeUse the engine's Python DBAPI driver.
cliShell out to the engine's command-line tool.
auto (default)Native if the driver is importable, otherwise the CLI.
EngineNative driver (extra)CLI fallback
Postgrespg8000pip install 'codumentor[postgres]'psql
MySQL / MariaDBPyMySQLpip install 'codumentor[mysql]'mysql
Oracleoracledb (thin mode) — pip install 'codumentor[oracle]'
SQL Serverpython-tdspip install 'codumentor[mssql]'go-sqlcmd
SQLitestdlib sqlite3

pip install 'codumentor[db-all]' installs all four native drivers.

Why both native and CLI

All four native drivers are pure-Python (no system libraries: no libpq, no
Oracle Instant Client, no ODBC/FreeTDS), so they install cleanly and bundle into
the frozen PyInstaller build — the packaged app ships with native support for
every engine. They are imported lazily, so the plugin loads even when a
driver is absent, and mode: auto degrades to the CLI.

The CLI path is the escape hatch: it needs no Python driver at all (you install
or download the CLI separately), and it handles cases the pure-Python drivers
don't — most notably SQL Server with Azure AD / TDS 8.0, where python-tds
is weak and go-sqlcmd (a single static MIT binary) is the better choice.
oracledb thin mode covers Oracle fully, so no Oracle CLI ships.

Native connections support bound params; CLI connections do not (use
mode: native for parameterized queries).

Overview

Five tools, registered via onPromptAssemble (gated by target_agents):

ToolApprovalPurpose
sql_list_connectionsnoneList configured connections (name, engine, host, database, read-only). Touches no database.
sql_list_tablesnoneExplore tables/views. Optional schema and pattern (case-insensitive name substring) filters; see below.
sql_describe_tablenoneColumn metadata (name, type, nullability, default).
sql_querynoneRun a read-only statement; rejects anything that isn't a single SELECT/WITH/EXPLAIN. Row-capped; results are JSON.
sql_executedatabase.executeRun a write/DDL statement. Permission-gated, and refused on read-only connections (no prompt).

When exactly one connection is configured, the connection argument is
optional everywhere and defaults to it.

sql_query results come back as a JSON envelope — {"columns": [...], "rows":
[...], "row_count": N, "truncated": bool}
— rather than an ASCII/markdown
table (which can trip the LLM server's repetition detection). When truncated
is true, narrow the query.

Schema exploration scales down, not up

sql_list_tables adapts its output so a huge catalog can never silently
swallow schemas (a 2,500-table SQL Server catalog is ~127 KB of JSON — the
content store would char-truncate it mid-schema and the agent would report
whatever schemas happened to sort first):

The intended flow on big databases is therefore: counts overview → drill into
one schema, or search by name fragment (pattern: "kivonat").

Configuration

plugins:
  - module: codumentor.plugins.database
    class: DatabasePlugin
    args:
      enabled: true
      target_agents: all          # main | subagent | all
      default_read_only: true     # per-connection default
      max_rows: 1000              # hard cap for sql_query
      statement_timeout: 30       # seconds
      connections:
        - name: analytics         # logical handle the agent uses
          engine: postgres        # postgres | mysql | oracle | sqlserver | sqlite
          mode: auto              # native | cli | auto
          host: db.example.com
          port: 5432
          database: analytics
          user: reporting
          password_secret: pg_analytics_password   # per-user secret name
          read_only: true
        - name: warehouse
          engine: sqlserver
          mode: cli               # go-sqlcmd
          host: mssql.example.com
          port: 1433
          database: warehouse
          user: svc_reader
          password_secret: mssql_warehouse_password
          read_only: true

dependencies: [user_secrets] — passwords resolve through the per-user secrets
registry, so the user_secrets plugin must be loaded.

Credentials

Two models are supported, per connection:

  1. Per-user secret (preferred) — set password_secret: <name>. The config stores only the secret name; each user supplies their own password in Settings → User Secrets, and tools authenticate as the calling user. The plugin declares each password_secret to the User Secrets pane via ui_manifest() so it shows "DB password (<connection>) — needed by Databases". See Secret requirements.
  2. Shared service account — set password: ${secret:<name>} (a shared secret resolved server-side). Useful for a read-only reporting replica with a single account.

If a password_secret is declared but unset, tools return a clear,
non-retryable message naming the secret — no connection attempt is made. A
connection with neither field resolves to "no password" (works for SQLite,
trusted/integrated auth, etc.).

Safety

Notes & limitations