Interview prep
RefactoringSafety and reliability

Validate Before Execute

Validar Antes de Executar

Validate Before Execute is an AI refactoring for LLM systems, in the Safety and reliability group. Check generated code, SQL, or commands and run them in an isolated environment.

Element
27/35
Level
Intermediate
Read
4 min
Updated
On this page 9
  1. 01Problem
  2. 02Solution
  3. 03Before and after
  4. 04Why it works
  5. 05Safe mechanics
  6. 06Risks
  7. 07Challenge
  8. 08Related
  9. 09Check your understanding
  10. ··Quick answers

Problem

The analyst asks “which customers missed their Pix this month?”. The model generates DELETE FROM customers; SELECT .... Code sends the text to the production database. The first statement runs. Code, SQL, or commands generated by the model run directly, with no checks, in the real environment. This is the Unvalidated Executed Output smell.

Solution

Before executing, check what was generated with rules in code (parser, allowlist, static analysis). Then execute in an isolated, disposable environment, with no network, no secrets, and limits on time and resources. If the check fails, send the error back to the model to fix.

Before and after

-sql = llm(SQL_PROMPT, question)
-rows = prod_db.execute(sql)
+sql = llm(SQL_PROMPT, question)
+
+problems = validate_sql(sql,
+    allowed_statements={"SELECT"},
+    allowed_tables=ANALYTICS_VIEWS,
+    require_limit=True)                          # a parser, not a regex
+if problems:
+    sql = llm(SQL_PROMPT, question, feedback=problems)   # one repair attempt
+    problems = validate_sql(sql, ...)
+if problems:
+    return refuse(problems)
+
+if explain_cost(replica, sql) > MAX_COST:
+    return refuse(["query too expensive; add a date filter"])
+rows = replica_ro.execute(sql, timeout_s=10)     # read-only user, replica

Before: whatever the model writes, runs.

flowchart LR
  M(["1. Model generates SQL"]):::llm --> X["2. Runs in production"]:::tool
  X --> DB[("3. Real database")]:::store

After: validate, repair if needed, and execute in isolation.

flowchart LR
  M(["1. Model generates SQL"]):::llm --> V{"2. Parser and allowlist"}
  V -->|failed| R(["3. Repair with the error"]):::llm
  R --> V
  V -->|ok| C{"4. Estimated cost"}
  C -->|ok| X["5. Runs on the read-only replica with a timeout"]:::tool
  C -->|too expensive| N(["Refusal with a reason"]):::io
  1. The model generates the query.
  2. A parser checks the command type, the tables, and that a limit is present.
  3. On failure, the error goes back to the model once, with the exact message.
  4. Before running, the execution plan estimates the cost.
  5. Execution happens in an environment that cannot do damage, under limits.

Why it works

Two layers cover two kinds of error. Validation catches what you can know without executing: a forbidden command, a table off the list, a missing filter. Isolation covers what only shows up on execution: the unexpected effect, the loop, the memory blowup. Either one alone leaves holes.

Validation in code also improves quality. A precise error (“table customers is not allowed; use analytics.customers_v”) is exactly the information the model needs to fix things. That is output validation and repair, with execution in a sandbox.

A regex over the text is not a parser. r"^SELECT" accepts SELECT * FROM t; DELETE FROM t as the second statement, accepts comments in the middle, accepts SeLeCt. A SQL parser (sqlglot, pglast) returns the tree: statement type, table names, presence of LIMIT. The allowlist lives on that tree. For generated Python, the equivalent tree is the AST (ast.parse): imports, calls, names. A substring os in the source does not replace that.

Worked example: two statements, a happy regex

Input: “delete the tests and show me the late ones”. The model generates:

DELETE FROM analytics.pix_tests; -- done
SELECT * FROM analytics.pix_overdue

The regex ^SELECT|no delete in the prompt does not see the DELETE. The parser sees two statements, refuses, and returns “SELECT only, one at a time, tables on the list”. The model rewrites a single SELECT with LIMIT 100. The read-only replica would still reject the DELETE as a permission error if the parser failed. Three nets: parser, credential, isolation.

Combine this with Narrow Tool Permissions. Validating the text does not replace a user that cannot write.

Check +20 XP on first tryYour SQL validation is if 'delete' in sql.lower(): refuse. The model generates DELETE FROM t with a /* delete */ comment on a SELECT, or it uses DROP. What is wrong with the check?

Safe mechanics

  1. Measure. Build an eval with normal requests and dangerous ones (delete, read a forbidden table, unfiltered query). Record how many dangerous ones execute today.
  2. List what is allowed: command types, tables, modules, binaries, paths.
  3. Implement validation with a parser, not with regular expressions over the text.
  4. Set up the isolated environment: read-only user and replica for SQL; a container with no network, a temporary file system, and limits for code and shell.
  5. Return explanatory errors to the model, with one repair attempt and then a refusal.
  6. Record on the trace what was generated, the validation result, and the execution result.
  7. Measure again. Dangerous requests executed should drop to zero; normal requests should keep working.

Trap: a sandbox with the network open

An “isolated” container with DNS and outbound internet still downloads a payload or talks to the real database. No network, no credential environment variables, a temporary filesystem, CPU and memory limits, a short timeout. The user’s CSV is mounted read-only. Secrets stay out.

Another trap: repair in a loop. One correction attempt helps. Five become Blind Retry, paying tokens and maybe hitting a bypass on the sixth. One chance, then refuse.

Check +20 XP on first tryThe Python sandbox allows import os because ‘sometimes the code needs paths’. The user's CSV is at /data/input.csv. What happens with an os.system?

Risks

  • Bypassable validation. A regex over SQL is easy to fool (comments, capitals, multiple statements). Use a parser.
  • Incomplete isolation. A container with network access, or with the repository mounted writable, can still do damage. Review what is mounted.
  • Too many refusals. Strict rules block legitimate requests. Track the refusal rate and adjust the list. Sometimes the right move is a new view, not a looser parser.
  • Wrong result, safe environment. The sandbox protects the infrastructure, not the answer. Validate the result too (types, ranges, totals) before showing it.

Challenge

A spreadsheet assistant generates Python code to answer questions about a CSV the user uploaded. What would you validate before executing, and what would the environment look like?

Show solution

Static validation: imports only from a list (pandas, numpy, math, statistics), no os, subprocess, socket, no open beyond the input file, no eval or exec. Environment: a disposable container per session, no network, the CSV mounted read-only, a temporary output directory, and limits on CPU, memory, and a 30-second runtime. After execution, check that the result has the expected type (a number, a table with the requested columns) before showing it.

Check your understanding

Check +20 XP on first tryValidation passed a SELECT. EXPLAIN estimates a seq scan over 40 million rows. No date filter. What does the code do before executing?

Check +20 XP on first tryYou have a strict parser and you run on the production database, ‘because the replica lags by 30 seconds’. Which layer is missing?

Check +20 XP on first tryRepair already ran once and the SQL is still invalid. The agent calls the tool again, in the same turn, with the same question. What do you do in code?

Quick answers

What is Validate Before Execute?

Validate Before Execute is an AI refactoring for LLM systems, in the Safety and reliability group. Check generated code, SQL, or commands and run them in an isolated environment.

What problem does Validate Before Execute solve?

It treats Unvalidated Executed Output.

Which pattern does Validate Before Execute lead to?

The Output Validation and Repair and Code Execution Sandbox design pattern.

Go further

Relations

Search