Codumentor logo Codumentor

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 Python driver or an external database CLI. 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 driver.
cliShell out to the engine's command-line tool.
auto (default)Native if the driver is importable, otherwise the CLI.
EngineNative driverCLI fallbackDefault port
Postgres (postgres, also postgresql / pg)pg8000psql5432
MySQL / MariaDB (mysql, also mariadb)PyMySQLmysql3306
Oracle (oracle, also oracledb)oracledb (thin mode)1521
SQL Server (sqlserver, also mssql)python-tdsgo-sqlcmd1433
SQLite (sqlite)stdlib sqlite3

The four native drivers ship with Codumentor (pure Python — no libpq, Oracle Instant Client, or ODBC). They are imported only when a connection uses them, so a missing driver does not prevent the plugin from loading; mode: auto then falls back to the CLI.

Use the CLI path when you prefer not to use the bundled driver, or for cases the pure-Python drivers handle poorly — most notably SQL Server with Azure AD / TDS 8.0, where go-sqlcmd (a single static MIT binary) is the better choice. Oracle 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).

Tools

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.

Who gets which half

Two gates, not one. target_agents (default all) decides whether the tools are offered at all; write_target_agents (default main) then decides who gets sql_execute.

By default a subagent can explore a schema and run read-only queries but cannot change data or DDL — the approval prompt sql_execute raises is meant for a human, and nobody is reading a subagent's tool calls as they happen. Set write_target_agents: all if subagents should also write. A connection's own read_only is the stricter guard and applies to every agent.

sql_query results come back as a JSON envelope — {"columns": [...], "rows": [...], "row_count": N, "truncated": bool} — rather than an ASCII table. When truncated is true, narrow the query.

Schema exploration scales down, not up

sql_list_tables adapts its output so a huge catalog cannot silently swallow schemas:

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 — the whole family
      write_target_agents: main   # same values, sql_execute only
      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

Load user_secrets alongside this plugin so passwords can resolve per user.

Plugin parameters

ParameterTypeDefaultDescription
enabledbooltrueMaster on/off.
target_agentsstringallWho gets the tools: main, subagent, all, or a subagent role name.
write_target_agentsstringmainSame values, applied to sql_execute only. Subagents keep the read half.
default_read_onlybooltrueApplied to any connection that omits read_only.
max_rowsint1000Hard cap for sql_query (and the name cap for filtered sql_list_tables).
statement_timeoutfloat30Per-statement timeout in seconds.
connectionslist[]Named connections (see below). Names must be unique.

Connection parameters

ParameterTypeDefaultDescription
namestring(required)Handle the agent uses in tool calls.
enginestring(required)postgres, mysql, oracle, sqlserver, or sqlite (aliases above).
modestringautonative, cli, or auto.
hoststringlocalhostDatabase host.
portintengine defaultOmit to use the engine default.
databasestringDatabase / service name. For SQLite this is the file path (:memory: if omitted).
userstringLogin user.
password_secretstringPer-user secret name (preferred).
passwordstringShared credential; may contain ${secret:...}.
read_onlybooldefault_read_onlyWhen true, sql_execute is refused.
connect_kwargsmap{}Extra keyword arguments passed to the native driver (for example an Oracle dsn).

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 → Extensions → User Secrets, and tools authenticate as the calling user. The pane shows "DB password (<connection>) — needed by Databases".
  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