Agent-First PSQL v0.6: SSH Transport and Explicit Write Permissions

by Agent-First Kit Contributors

v0.6 adds an SSH transport that keeps the agent local while reaching server-only PostgreSQL, and splits write permission into separate direct and SSH families so an agent cannot silently turn a read across a boundary into a remote write.

Agent-First PSQL v0.6 lands the two features that were missing for agents working with remote PostgreSQL: a local SSH transport, and a permission model that does not blur “write” and “remote write”.

SSH transport: the agent stays local

Most production PostgreSQL only listens on the server’s loopback. The usual workaround — SSH into the server and run human psql — mixes the database task with shell state, server files, and prose output the agent cannot reliably parse.

v0.6 keeps the agent on the local machine and tunnels only the PostgreSQL transport:

afpsql --ssh user@server --host 127.0.0.1 --port 5432 \
  --user app --dbname appdb \
  --password-secret-env PGPASSWORD \
  --sql "select now()"

The server does not need afpsql installed. The agent still reads structured Agent-First Data events locally. TLS behavior is aligned with libpq’s sslmode semantics, so server certificates verify the same way across both transports.

For PostgreSQL that listens only on a Unix socket, afpsql forwards the socket. For the harder sudo -u postgres psql case, an explicit non-interactive sudo bridge uses sudo -n and requires the socket path to be passed explicitly — no ambient-path surprises.

Permissions: read by default, write across the right boundary

afpsql native CLI and pipe mode now default to PostgreSQL read-only transactions. Writes are explicit and split by transport:

--permission read       direct read   (default)
--permission write      direct write
--permission ssh-read   SSH read      (default with --ssh)
--permission ssh-write  SSH write

The split is the point. A request that uses afpsql’s SSH transport with --permission write is rejected before execution with a hint to use ssh-write. A direct session with --permission ssh-write is rejected the same way. The agent cannot accidentally generalize “I have write permission” into “I can write to whatever side of the SSH tunnel I am on.”

--mode psql keeps psql’s writable default for non-interactive script compatibility and intentionally does not expose afpsql permission flags or SSH transport extensions. The agent-safety contract lives in native afpsql.

Pipe-mode hardening

Several pipe-mode failure modes were tightened so an agent can rely on the protocol shape:

CLI input limits, result limits, and startup logging were also tightened so argv and connection secrets no longer reach log output. Redaction now goes through the same Agent-First Data policy other kit tools use, so secret handling looks the same across afhttp, afpsql, afpay, and afmail.

Agent Skill

v0.6 ships skills/agent-first-psql.md so coding agents that load skill files automatically pick up afpsql’s operating guidance: read-by-default, structured rows, SQLSTATE-based error handling, named sessions for state, and when to use SSH transport vs. a local connection.

psql wrapper, documented

afpsql psql install and afpsql psql status were documented as a first-class workflow: non-interactive psql calls in existing scripts can be routed through afpsql while interactive sessions and meta-commands are explicitly rejected with structured errors pointing back at the real psql binary.

Adoption

brew install agentfirstkit/tap/afpsql   # macOS / Linux
cargo install agent-first-psql          # any platform

For the agent-side framing behind these choices, see the v0.5 design post.