run_select
run_select runs a read-only SQL query against application data, such as PS_JOB or your custom
tables. It’s the only tool that reads data rather than definitions, so it’s the most tightly
controlled: it can read only the tables on its allow-list, which is empty until an administrator
adds tables, and every query runs with a row cap, a timeout, and masking of sensitive columns.
Use it for
Section titled “Use it for”- “How many training requests are still pending?”
- “Do any ZZ_TRAIN_REQ rows point to a course that no longer exists in ZZ_COURSE_TBL?”
- “Show me five rows from PS_ZZ_TRAIN_REQ so I can see what the data looks like.”
| Argument | Type | Required | Description |
|---|---|---|---|
sql |
string | Yes | One SELECT statement, which can start with WITH. Up to 10,000 characters. |
max_rows |
integer | No | The maximum number of rows to return, from 1 to 1,000. Default: 100. |
{ "type": "object", "properties": { "sql": { "type": "string", "minLength": 8, "maxLength": 10000, "description": "A single read-only SELECT statement" }, "max_rows": { "type": "integer", "minimum": 1, "maximum": 1000, "default": 100 } }, "required": ["sql"], "additionalProperties": false}Output
Section titled “Output”| Field | Description |
|---|---|
columns |
The result’s columns, each with name and type |
rows |
The rows, each an array of values in column order |
rowCount |
The number of rows returned |
truncated |
true when the query had more rows than max_rows |
maskedColumns |
The columns whose values were masked |
elapsedMs |
How long the query took to run, in milliseconds |
For this query:
SELECT ZZ_TRAIN_STATUS, COUNT(*) AS REQUESTS FROM PS_ZZ_TRAIN_REQ GROUP BY ZZ_TRAIN_STATUS ORDER BY ZZ_TRAIN_STATUSthe result is:
{ "columns": [ { "name": "ZZ_TRAIN_STATUS", "type": "Character" }, { "name": "REQUESTS", "type": "Number" } ], "rows": [ ["A", 212], ["C", 1048], ["D", 37], ["P", 64] ], "rowCount": 4, "truncated": false, "maskedColumns": [], "elapsedMs": 41}How it works
Section titled “How it works”Before a query runs, the server parses it and checks four rules:
- One statement. The query is a single
SELECT, which can start withWITH. A semicolon is allowed only at the very end. - Read-only. Statements that change data or definitions, such as
INSERT,UPDATE,DELETE,MERGE,CREATE,ALTER,DROP,TRUNCATE, andGRANT, are rejected, as areSELECT … FOR UPDATE,SELECT … INTO, locking hints such as SQL Server’sWITH (UPDLOCK), and procedure calls. - Allowed tables only. Every table the query reads, including tables in subqueries and
WITHclauses, must be on the allow-list. Database links and references to other databases are rejected. - Sensitive columns used safely. A sensitive column can be selected, including through
SELECT *, and its values come back masked as***. Using one anywhere else, such as in aWHEREclause, an expression, or under an alias, is rejected, because masking couldn’t be guaranteed there.
The query then runs under two limits. The server reads at most max_rows rows and closes the
cursor, so it never has to rewrite your SQL to cap it, and the query is cancelled if it runs
longer than the timeout, 30 seconds by default.
Configuration
Section titled “Configuration”Administrators control run_select in the server’s configuration:
run_select: enabled: true allowed_tables: - PS_ZZ_TRAIN_REQ - PS_ZZ_COURSE_TBL - PS_JOB sensitive_columns: - NATIONAL_ID - BIRTHDATE max_rows: 1000PeopleTools tables can’t be added to the allow-list. The definition tools already cover
PeopleTools metadata, and some PeopleTools tables hold sensitive data: PSOPRDEFN, for example,
stores users’ password hashes.
Limits and errors
Section titled “Limits and errors”- A query that breaks one of the rules returns a tool execution error that says which rule, so the LLM can fix the query. For a table that isn’t allowed, the error lists the allowed tables: “PS_PERSONAL_DATA isn’t on the run_select allow-list. Allowed tables: PS_ZZ_TRAIN_REQ, PS_ZZ_COURSE_TBL, PS_JOB.”
- A query that runs past the timeout is cancelled, and the error reports how long it ran.
- Long text values are cut to 2,000 characters.
- When
run_selectis turned off, or its allow-list is empty, every call returns an error saying so, and the other ten tools keep working.
Related tools
Section titled “Related tools”describe_recordshows a record’s keys, which the LLM needs to write correct queries, especially effective-dated ones.get_translate_valuesdecodes the codes in query results, such as status values.
