> ## Documentation Index
> Fetch the complete documentation index at: https://agents.nanonets.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# PostgreSQL Query

> Runs a **SELECT** against a connected PostgreSQL database.

Runs a **SELECT** against a connected PostgreSQL database. Display name **"PostgreSQL Query"**. Off by default.

## Authentication and enablement

Requires a workspace Postgres integration. Host, port, database, user, password, SSL, and optional schema are injected from that integration (`x-exclude-from-llm`). Enable the tool on the agent and bind the integration.

## Inputs

* `query` (required): SELECT only. Example: `SELECT * FROM users WHERE status = 'active' LIMIT 10`.
* `query_params` (object, pinned queries only): values for the query's named placeholders. Supplied by the agent per call — it is **not** a configurable field and does not appear in the tool's configuration dialog. It is offered to the agent only when `query` is pinned to a statement containing placeholders — see below.

## Pinned queries with named parameters

Instead of letting the agent write the SQL on every run, set the tool's **Query** field in its configuration dialog to a fixed
statement that addresses its values by name:

```sql theme={null}
SELECT id, payment_terms
FROM vendors
WHERE name = :vendor_name
  AND organisation_id = :org_id::uuid
LIMIT 50
```

The tool then offers the agent a `query_params` object whose keys are exactly the
placeholders that query declares, and the agent only supplies values:

```json theme={null}
{ "query_params": { "vendor_name": "O'Brien Supply Co.", "org_id": "3f2a…" } }
```

Values travel to the server as bound parameters, so a value containing a quote or an
apostrophe needs no escaping and cannot change the statement. A query is only ever
inspected for placeholders on a call that carries `query_params`, and `query_params` is
offered only when a pinned query declares some — so a query the agent writes itself is
passed to the database exactly as written. Prefer this over a
model-authored query for any lookup that runs in production: the SQL is reviewed once,
at configuration time, instead of being regenerated on every task.

Notes:

* Placeholder names use `:name`. A `::type` cast is a cast, not a placeholder, so
  `:org_id::uuid` binds one value and casts it.
* Repeat a name to reuse the same value: `WHERE name = :n OR alias = :n` binds once.
* Declare types in the SQL (`:amount::numeric`) rather than in the value — values are
  sent as text and cast server-side.
* Placeholders substitute **values**, never table or column names, and cannot supply a
  list to `IN (...)`. Use `= ANY(:ids::uuid[])` for a list — and because every value is
  scalar text, pass the Postgres array **literal** as a string
  (`"{id1,id2}"`), not a JSON array. A JSON array is rejected.
* A placeholder cannot appear inside an array subscript. A colon between brackets is
  read as a slice separator, so `arr[lo:hi]` stays a slice rather than becoming a
  parameter named `hi`.
* Named and ordinal (`$1`) placeholders cannot be mixed in one query.
* Maximum 64 distinct placeholders.

## Output

Structured rows plus:

* `query` — the SQL as authored, with its `:name` labels intact. This is what the task
  feed renders, so a lookup that returned nothing can still be read against the values
  it was meant to filter on.
* `query_bound` — the statement actually sent, with placeholders replaced by `$1`, `$2`…
* `query_param_keys` — the placeholder names that were bound. The **values** are never
  reported: they are customer document data and do not belong in a rendered feed item.
* `param_count`, `row_count`, `truncated`, `columns`, `rows`.

Suitable as `content` for `generate_file`.

## Limits and side effects

* Non-SELECT statements are rejected.
* Read-only by design; use `postgres_upsert` (separate tool) to write.
* Returns at most `max_rows` rows (default and maximum 3000); `truncated` reports when
  the limit was hit.

## Expected errors

* Missing/invalid integration credentials.
* Non-SELECT `query`.
* A placeholder in the pinned query with no value in `query_params`, or a
  `query_params` key that is not a placeholder in the query (both name the offending
  key and list the placeholders the query expects, so the agent can retry).
* A `query_params` value that is an object or an array (numbers and booleans are
  accepted and sent as text).
* A pinned query mixing `:named` and `$1` placeholders, or declaring more than 64
  placeholders. Both are rejected when the tool is saved, and again at run time.
* A query declaring placeholders on a call that supplied no `query_params` at all —
  reported with the placeholder names, rather than reaching the database with `:name`
  markers intact.
* SQL error from the database (surfaced as a tool error, not a panic).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.