Skip to content

Agent Tools

The agent uses a set of tools during its agentic loop to introspect the database, search knowledge, execute SQL, and persist learnings. Each tool is registered with the LLM as a callable function with a JSON Schema describing its parameters.

This page documents every tool, its parameters, the JSON sent to the LLM, and what the tool returns.

Tools are serialized into the format expected by each LLM provider. The package handles this automatically via ToolFormatter.

{
"type": "function",
"function": {
"name": "tool_name",
"description": "What the tool does.",
"parameters": {
"type": "object",
"properties": { ... },
"required": [ ... ]
}
}
}
{
"name": "tool_name",
"description": "What the tool does.",
"input_schema": {
"type": "object",
"properties": { ... },
"required": [ ... ]
}
}

The parameters (OpenAI) and input_schema (Anthropic) objects are identical — only the wrapper differs.


Execute a SQL query against the database. This is the primary tool the agent uses to answer questions.

Description sent to LLM:

Execute a SQL query against the database. Only SELECT and WITH statements are allowed. Returns query results as JSON.

{
"type": "object",
"properties": {
"sql": {
"type": "string",
"description": "The SQL query to execute. Must be a SELECT or WITH statement."
}
},
"required": ["sql"]
}
ParameterTypeRequiredDescription
sqlstringYesThe SQL query to execute. Must start with SELECT or WITH.
{
"rows": [
{"id": 1, "name": "Alice"},
{"id": 2, "name": "Bob"}
],
"row_count": 2,
"total_rows": 2,
"truncated": false
}
FieldTypeDescription
rowsarrayThe query result rows as objects.
row_countintegerNumber of rows returned (after truncation).
total_rowsintegerTotal rows the query produced before truncation.
truncatedbooleanWhether results were truncated to the configured sql.max_rows limit.
  • Only SELECT and WITH statements are allowed (configurable via sql.allowed_statements).
  • Forbidden keywords (DROP, DELETE, UPDATE, INSERT, ALTER, CREATE, TRUNCATE, etc.) are rejected even inside subqueries.
  • Multiple statements separated by ; are blocked.
  • Results are capped at sql.max_rows (default: 1000).
  • On error, a SqlErrorOccurred event is dispatched for auto-learning.
{
"sql": "SELECT COUNT(*) as total FROM orders WHERE status = 'delivered'"
}

Inspect the database schema. The agent uses this to discover tables, columns, types, foreign keys, and sample data before writing SQL.

Description sent to LLM:

Get detailed schema information about database tables. Can inspect a specific table or list all available tables.

{
"type": "object",
"properties": {
"table_name": {
"type": "string",
"description": "Optional: The name of a specific table to inspect. If not provided, lists all tables."
},
"include_sample_data": {
"type": "boolean",
"description": "Whether to include sample data from the table (up to 3 rows). This data is for understanding the schema only - never use it directly in responses to the user.",
"default": false
}
}
}
ParameterTypeRequiredDefaultDescription
table_namestringNoA specific table to inspect. Omit to list all tables.
include_sample_databooleanNofalseInclude up to 3 sample rows for schema understanding.

When listing all tables (no table_name provided):

{
"tables": ["users", "orders", "products"],
"count": 3
}

When inspecting a specific table:

{
"table": "orders",
"description": "Table comment if set in the database",
"columns": [
{
"name": "id",
"type": "bigint",
"nullable": false,
"primary_key": true,
"foreign_key": false,
"references": null,
"default": null,
"description": null
},
{
"name": "customer_id",
"type": "bigint",
"nullable": false,
"primary_key": false,
"foreign_key": true,
"references": "customers.id",
"default": null,
"description": null
}
],
"relationships": [
{
"type": "belongsTo",
"related_table": "customers",
"foreign_key": "customer_id",
"local_key": "id"
}
],
"sample_data": [
{"id": 1, "customer_id": 42, "status": "delivered", "total_amount": 9999}
]
}
FieldTypeDescription
tablestringTable name.
descriptionstring|nullTable comment from the database, if set.
columnsarrayColumn details including type, nullability, keys, and defaults.
relationshipsarrayForeign key relationships detected from the schema.
sample_dataarrayUp to 3 sample rows (only when include_sample_data is true).
{
"table_name": "orders",
"include_sample_data": true
}

Search the knowledge base for relevant query patterns and learnings. The agent calls this before writing SQL to find proven patterns and avoid known pitfalls.

Description sent to LLM:

Search the knowledge base for relevant query patterns and learnings. Use this to find similar queries, understand business logic, or discover past learnings about the database.

{
"type": "object",
"properties": {
"query": {
"type": "string",
"description": "The search query to find relevant knowledge."
},
"type": {
"type": "string",
"description": "Filter results: 'all' (default), 'patterns' (saved query patterns), or 'learnings' (discovered fixes/gotchas).",
"enum": ["all", "patterns", "learnings"]
},
"limit": {
"type": "integer",
"description": "Maximum number of results to return.",
"minimum": 1,
"maximum": 20
}
},
"required": ["query"]
}
ParameterTypeRequiredDefaultDescription
querystringYesThe search query text.
typestringNoallFilter by all, patterns, or learnings.
limitintegerNo5Max results to return (1–20).
{
"query_patterns": [
{
"name": "monthly_revenue",
"question": "Calculate total revenue by month",
"sql": "SELECT DATE_FORMAT(created_at, '%Y-%m') as month, SUM(total_amount) / 100 as revenue FROM orders WHERE status != 'cancelled' GROUP BY month ORDER BY month DESC",
"summary": "Monthly revenue from non-cancelled orders",
"tables_used": ["orders"],
"relevance_score": 8.5
}
],
"learnings": [
{
"title": "orders.total_amount is in cents",
"description": "Always divide total_amount by 100 when displaying dollar amounts.",
"category": "data_quality",
"sql": null,
"relevance_score": 7.2
}
],
"total_found": 2
}
FieldTypeDescription
query_patternsarrayMatching query patterns (from knowledge files and saved validated queries).
learningsarrayMatching learnings (agent-discovered patterns). Only included when learning is enabled.
total_foundintegerTotal number of results across both types.
{
"query": "monthly revenue calculation",
"type": "patterns",
"limit": 5
}

Save a new learning to the knowledge base. The agent uses this when it discovers something important — typically after recovering from a SQL error or when a user provides a correction.

Description sent to LLM:

Save a new learning to the knowledge base. Use this when you discover something important about the database schema, business logic, or query patterns that would be useful for future queries.

{
"type": "object",
"properties": {
"title": {
"type": "string",
"description": "A short, descriptive title for the learning (max 100 characters)."
},
"description": {
"type": "string",
"description": "A detailed description of what was learned and why it matters."
},
"category": {
"type": "string",
"description": "The category of this learning.",
"enum": ["type_error", "schema_fix", "query_pattern", "data_quality", "business_logic"]
},
"sql": {
"type": "string",
"description": "Optional: The SQL query related to this learning."
}
},
"required": ["title", "description", "category"]
}
ParameterTypeRequiredDescription
titlestringYesShort title, max 100 characters.
descriptionstringYesDetailed description of what was learned.
categorystringYesOne of type_error, schema_fix, query_pattern, data_quality, business_logic.
sqlstringNoRelated SQL query.
CategoryDescription
type_errorA correction for a data type mismatch or casting issue.
schema_fixA correction for incorrect schema assumptions.
query_patternA learned pattern for constructing queries.
data_qualityAn observation about data quality or anomalies.
business_logicA learned business rule or domain knowledge.
{
"success": true,
"message": "Learning saved successfully.",
"learning_id": 12,
"title": "users.status is VARCHAR not INT",
"category": "type_error"
}
{
"title": "orders.total_amount is in cents",
"description": "The total_amount column stores values in cents, not dollars. Always divide by 100 when displaying monetary values.",
"category": "data_quality",
"sql": "SELECT total_amount / 100 as amount_dollars FROM orders"
}

Save a validated query pattern after successfully answering a question. This builds the knowledge base organically — future similar questions can reference proven SQL.

Description sent to LLM:

Save a validated query pattern to the knowledge base. Use this when you have successfully executed a SQL query that correctly answers a user question. This helps future queries by providing proven patterns.

{
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "A short, descriptive name for the query pattern (max 100 characters)."
},
"question": {
"type": "string",
"description": "The natural language question this query answers."
},
"sql": {
"type": "string",
"description": "The validated SQL query that correctly answers the question."
},
"summary": {
"type": "string",
"description": "A brief summary of what the query does and what data it returns."
},
"tables_used": {
"type": "array",
"description": "List of table names used in the query.",
"items": {
"type": "string"
}
},
"data_quality_notes": {
"type": "string",
"description": "Optional: Notes about data quality issues, edge cases, or important considerations for this query."
}
},
"required": ["name", "question", "sql", "summary", "tables_used"]
}
ParameterTypeRequiredDescription
namestringYesShort name for the pattern, max 100 characters.
questionstringYesThe natural language question this query answers.
sqlstringYesThe validated SQL (must start with SELECT or WITH).
summarystringYesBrief summary of what the query returns.
tables_usedarray of stringsYesTables referenced in the query.
data_quality_notesstringNoNotes about edge cases or data quality considerations.
{
"success": true,
"message": "Query pattern saved successfully.",
"pattern_id": 7,
"name": "monthly_active_users",
"tables_used": ["users", "logins"]
}

If a query pattern with the same question already exists, the tool returns an error instead of creating a duplicate. This prevents the knowledge base from accumulating redundant patterns.

{
"name": "monthly_active_users",
"question": "How many active users were there last month?",
"sql": "SELECT COUNT(DISTINCT user_id) as active_users FROM logins WHERE created_at >= DATE_SUB(CURDATE(), INTERVAL 1 MONTH)",
"summary": "Count of unique users who logged in during the last calendar month",
"tables_used": ["logins"],
"data_quality_notes": "Only counts users with at least one login event"
}

Not all tools are available in every configuration:

ToolAlways AvailableCondition
run_sqlYes
introspect_schemaYes
search_knowledgeYes
save_learningNoRequires sql-agent.learning.enabled = true
save_validated_queryNoRequires sql-agent.learning.enabled = true

When learning is disabled (SQL_AGENT_LEARNING_ENABLED=false), the save_learning and save_validated_query tools are not registered with the LLM, and the related instructions are removed from the system prompt.

In addition to the built-in tools above, you can register your own tools via the agent.tools config option. See the Custom Tools guide for details.