QueryShield

How do I use QueryShield with LangChain SQL agents?

LangChain's SQLDatabaseChain and create_sql_agent are popular text-to-SQL primitives but ship with weak guardrails — the top_k row limit and a string-match denylist (QUERY_CHECKER) are bypassable. QueryShield slots in as a custom SQLDatabase wrapper or as a tool-level callback.

Pattern A — wrap the SQLDatabase:

from langchain_community.utilities import SQLDatabase
from queryshield.langchain import QueryShieldSQLDatabase

db = QueryShieldSQLDatabase.from_uri( DB_URI, policy="analytics-agent", api_key=os.getenv("QUERYSHIELD_API_KEY"), ) agent_executor = create_sql_agent(llm, db=db, agent_type="openai-tools") ```

Every db.run(query) call is validated; rejections raise an exception the agent's reasoning loop can recover from ("try a different query with a tenant_id filter").

Pattern B — callback-based:

from queryshield.langchain import QueryShieldCallback
agent_executor.invoke(
    {"input": user_query},
    config={"callbacks": [QueryShieldCallback(policy="analytics-agent", context=ctx)]},
)

The callback intercepts tool calls, validates SQL, and either approves, rewrites (injects required predicates), or rejects with an LLM-recoverable error message. Evidence log captures the original NL prompt, the LangChain trace, and the validation decision — auditable end-to-end.