Connect Metabase to AI Agents: Control SQL & Data Permissions
Give your AI agent Metabase tools.
A step-by-step engineering guide to connecting Metabase to AI Agents. Learn how to fetch AI-ready tools, handle Metabase's complex MBQL constraints, manage rate limits, and build autonomous data workflows.
In this guide
- 01Fetch AI-ready tools from Truto
- 02Bind schemas to your LLM framework
- 03Prompt the agent for data operations
- 04Handle execution and rate limits
- 05Return context to the agent
The guide
Learn how to connect Metabase to AI Agents using Truto's /tools API to autonomously execute SQL, build dashboards, and audit collection permissions.
You want to connect Metabase to an AI agent so your system can autonomously execute SQL queries, generate dashboards, audit collection permissions, and manage data access. Here is exactly how to do it using Truto's /tools endpoint and SDK, bypassing the need to build and maintain a custom Metabase API integration from scratch.
Giving a Large Language Model (LLM) read and write access to your primary business intelligence tool is a high-stakes engineering task. You cannot afford for the model to hallucinate SQL joins, accidentally archive core dashboards, or misconfigure row-level permissions. If your team uses ChatGPT, check out our guide on connecting Metabase to ChatGPT - or if you are building on Anthropic's models, read our guide on connecting Metabase to Claude. For developers building custom autonomous workflows, you need a programmatic, heavily validated way to fetch these tools and bind them to your agent framework.
This guide breaks down exactly how to fetch AI-ready tools for Metabase, bind them natively to an LLM using frameworks like LangChain, LangGraph, CrewAI, or the Vercel AI SDK, and execute complex data operations. For a broader look at this design pattern across multiple SaaS platforms, refer to our research on architecting AI agents and the SaaS integration bottleneck.
Why a Unified Tool Layer Matters for Agent Safety
Before writing a line of integration code, you must decide what layer your agent interacts with. This choice determines the reliability and safety of your production system.
Direct API tools - mapping one tool per raw Metabase endpoint - look convenient on paper, but they push provider-specific quirks directly into the LLM's context window. The model has to remember that Metabase relies heavily on its proprietary JSON-based query language (MBQL), that dashboard parameters require specific UUID mappings, and that permissions are represented as deeply nested graph objects. Every one of those quirks is a hallucination waiting to happen.
A unified tool layer collapses these complexities behind a stable schema. Your agent sees normalized operations like create_a_metabase_agent_execute_sql and update_a_metabase_collection_by_id rather than raw, under-documented REST paths. This provides three concrete engineering wins:
- Smaller attack surface for hallucination. The LLM only chooses from explicitly defined function names with strict JSON schemas. Invalid arguments are caught before they ever hit your database.
- Normalized pagination and authentication. The agent does not need to waste tokens reasoning about continuation tokens, offset limits, or session key lifecycles.
- Framework agnosticism. Because the tools are served via a standard API, they plug directly into any orchestrator - you are not locked into a specific agent framework.
The Engineering Reality of the Metabase API
Giving an LLM access to external SaaS sounds simple in a quick prototype. You write a Node.js function that makes a fetch request and wrap it in a tool decorator. In production, against complex business intelligence systems, this approach collapses.
Metabase's API introduces several specific integration challenges that break standard REST assumptions. If you hardcode these interactions into your agent, you will spend your sprints writing defensive integration code instead of improving your model's reasoning.
The MBQL vs Native SQL Divide
Metabase operates on two parallel tracks for queries: Native SQL and MBQL (Metabase Query Language). MBQL is a highly nested, portable JSON representation of a query that powers the visual query builder. Standard LLMs are excellent at writing raw SQL, but they will fail catastrophically if asked to construct valid MBQL from scratch.
If you expose the raw Metabase query endpoints to an agent, it will likely attempt to send SQL strings to endpoints expecting MBQL objects, resulting in immediate 400 Bad Request errors. A proper tool layer must abstract this divide, providing specific tools for raw SQL execution (create_a_metabase_agent_execute_sql) that handle the necessary base64 encoding and database ID targeting behind the scenes.
Collection Graph Permissions
Metabase does not use simple role-based access control (RBAC) strings for folders and dashboards. Permissions are managed via "Collection Graphs" - a complex, nested map of group IDs to collection IDs to permission levels (e.g., read, write, none).
Updating permissions requires fetching the entire graph, mutating the specific nodes, and pushing the entire graph back with the correct revision ID. If an AI agent attempts to patch a permission by sending a flat JSON object like {"group_id": 5, "access": "write"}, the API will reject it. The tool layer must translate the LLM's intent into a valid graph mutation, ensuring that other group permissions are not accidentally wiped out during the update.
Implicit Soft Deletes
Many core Metabase entities - such as dashboards, cards (questions), and metrics - do not have standard DELETE endpoints. Attempting to issue an HTTP DELETE to /api/dashboard/:id will fail. Instead, Metabase relies on soft deletes via an archived boolean flag. To "delete" a dashboard, the agent must issue a PUT request with {"archived": true}. If you do not map this correctly in your tool descriptions, the LLM will repeatedly try to call non-existent delete tools and get stuck in an error loop.
Essential Metabase Tools for AI Agents
Truto provides a comprehensive suite of AI-ready tools for Metabase. By using Truto's /tools endpoint, you can dynamically load these capabilities into your agent's context. Here are the highest-leverage tools for building autonomous data workflows.
Execute Raw SQL Queries
Tool: create_a_metabase_agent_execute_sql
This tool allows the agent to bypass the visual query builder and execute raw SQL directly against a connected Metabase database. It returns the query result, including column metadata, result rows, row count, and execution time. This is the primary engine for agents acting as autonomous data analysts.
"Run a SQL query against database ID 3 to find the top 10 customers by lifetime value, grouped by their acquisition channel. Return the raw data for analysis."
Construct Dashboards Dynamically
Tool: create_a_metabase_agent_dashboard
Agents can use this tool to create new dashboards on the fly, optionally populated with existing saved questions passed as an array of IDs. The tool automatically handles the complex grid positioning of dashcards based on their display types, saving the LLM from having to calculate X/Y coordinates.
"Create a new dashboard named 'Q3 Marketing Performance' and add the saved questions with IDs 45, 46, and 48 to it. Place it in the root collection."
Save Queries as Questions
Tool: create_a_metabase_agent_question
Once an agent has constructed and validated a useful query, it can persist it as a named "Question" (Card) in Metabase. This makes the LLM's work permanently accessible to human users in the Metabase UI. It returns the new card's ID and collection path.
"Take the user retention SQL query I just wrote and save it as a new question called '30-Day Cohort Retention'. Save it to collection ID 12."
Audit User Permission Warnings
Tool: create_a_metabase_app_user_permission_warning
This tool is critical for security and compliance agents. It checks which users cannot access specific tables used by a data app or dashboard. It returns a structured list of user IDs and the exact missing tables, allowing the agent to audit data governance policies automatically.
"Audit the user permissions for the 'Financial Exec' group. Check if there are any missing table permissions preventing them from viewing the Revenue run-rate app."
Update Collection Permission Graphs
Tool: metabase_collection_graphs_bulk_update
This tool allows an agent to submit a modified permission graph to batch update collection access rights. It abstracts the complex revision history requirements, ensuring the agent only overwrites the parts of the graph explicitly mentioned in the request body.
"Update the collection graph so that the 'Engineering' group (ID 4) has read-only access to the 'Production Metrics' collection (ID 8)."
Manage API Key Lifecycle
Tool: update_a_metabase_api_key_by_id
For agents handling infrastructure and DevOps tasks, this tool allows for the programmatic rotation or updating of Metabase API keys. It can change the key's associated permission group or name, ensuring strict access control for downstream services.
"Update the API key with ID 94, renaming it to 'Service_Account_Rotated' and moving it to permission group ID 2."
To view the complete schema details, query parameters, and full inventory of available operations, visit the Metabase integration page.
Workflows in Action
By chaining these tools together, you can build highly specialized agents that execute complex business intelligence operations. Here are two concrete examples of how these tools work in production.
1. The Autonomous BI Analyst
Data teams spend hours fielding ad-hoc requests for reports. You can build an agent that takes plain text requests, explores the database schema, writes the SQL, and generates a permanent dashboard for the stakeholder.
"I need a report showing our monthly recurring revenue (MRR) churn rate over the last 12 months, split by enterprise vs mid-market tiers. Put it on a new dashboard for the sales team."
Execution Steps:
- The agent calls
list_all_metabase_databasesand subsequent schema tools to understand the exact table structures for billing and accounts. - The agent formulates the SQL and calls
create_a_metabase_agent_execute_sqlto test the query and ensure it returns valid data without syntax errors. - Satisfied with the result, the agent calls
create_a_metabase_agent_questionto save the validated SQL as a permanent Card. - Finally, the agent calls
create_a_metabase_agent_dashboard, passing the new Card ID, to generate the final deliverable for the sales team.
Outcome: The stakeholder receives a link to a fully functional, auto-laid-out Metabase dashboard, built from a single natural language prompt.
2. The Data Governance Enforcer
Managing who has access to sensitive financial or PII data in Metabase is a constant compliance headache. An agent can act as an active governance monitor, responding to security alerts or regular audit schedules.
"Audit the 'Contractors' group in Metabase. Ensure they do not have any access to the 'Customer PII' collection. If they do, revoke it immediately."
Execution Steps:
- The agent calls
list_all_metabase_collection_graphsto fetch the current, active permission graph for the entire instance. - The LLM analyzes the graph structure, identifying the node mapping the 'Contractors' group ID to the 'Customer PII' collection ID.
- The agent detects unauthorized read access and calls
metabase_collection_graphs_bulk_update, submitting a mutated graph that explicitly removes that specific group-to-collection mapping.
Outcome: The system's compliance posture is automatically enforced. The agent parses the complex graph, identifies the violation, and executes a surgical permission rollback without human intervention.
Building Multi-Step Workflows
To build these workflows, your agent framework needs to fetch the tools from Truto, bind them to the LLM, and handle the execution loop.
When orchestrating multiple API calls across SaaS integrations, rate limiting is a critical engineering constraint. Truto does not automatically retry, throttle, or apply backoff on rate limit errors. When the upstream Metabase API returns an HTTP 429 (Too Many Requests), Truto passes that error directly back to your agent. Truto normalizes the upstream rate limit information into standardized IETF headers (ratelimit-limit, ratelimit-remaining, ratelimit-reset), but your agent code is strictly responsible for inspecting these headers, pausing execution, and retrying. Do not build an agent that ignores 429s - it will crash in production.
Here is an architectural example of how to fetch tools, bind them using LangChain, and implement a robust execution loop with proper rate limit handling.
import { ChatOpenAI } from "@langchain/openai";
import { HumanMessage, AIMessage, SystemMessage } from "@langchain/core/messages";
// 1. Fetch Metabase tools from Truto's Unified API
async function getMetabaseTools(integratedAccountId: string, trutoApiKey: string) {
const response = await fetch(
`https://api.truto.one/integrated-account/${integratedAccountId}/tools?methods[0]=custom&methods[1]=read&methods[2]=write`,
{
headers: {
"Authorization": `Bearer ${trutoApiKey}`,
"Content-Type": "application/json"
}
}
);
if (!response.ok) {
throw new Error(`Failed to fetch tools: ${response.statusText}`);
}
const toolsData = await response.json();
// Map the Truto JSON schema into LangChain structured tools
return toolsData.map(toolDef => ({
name: toolDef.name,
description: toolDef.description,
schema: toolDef.query_schema,
// The execution function handles the actual API call back to Truto
func: async (args) => executeTrutoTool(integratedAccountId, toolDef.name, args, trutoApiKey)
}));
}
// 2. Execute the tool with explicit Rate Limit (429) handling
async function executeTrutoTool(accountId: string, toolName: string, args: any, apiKey: string) {
const maxRetries = 3;
for (let attempt = 0; attempt < maxRetries; attempt++) {
const response = await fetch(`https://api.truto.one/integrated-account/${accountId}/tools/${toolName}/execute`, {
method: "POST",
headers: {
"Authorization": `Bearer ${apiKey}`,
"Content-Type": "application/json"
},
body: JSON.stringify(args)
});
if (response.status === 429) {
// Truto passes the 429 through. We must parse the IETF ratelimit headers.
const resetTime = response.headers.get('ratelimit-reset');
const waitSeconds = resetTime ? Math.max(1, parseInt(resetTime, 10)) : Math.pow(2, attempt);
console.warn(`Rate limited by Metabase. Backing off for ${waitSeconds} seconds...`);
await new Promise(resolve => setTimeout(resolve, waitSeconds * 1000));
continue; // Retry the loop
}
if (!response.ok) {
return JSON.stringify({ error: `API Call Failed: ${response.status} ${response.statusText}` });
}
return await response.text();
}
return JSON.stringify({ error: "Max rate limit retries exceeded." });
}
// 3. Bind tools to the Agent and execute the workflow
async function runMetabaseAgent(prompt: string) {
const llm = new ChatOpenAI({ modelName: "gpt-4-turbo", temperature: 0 });
const metabaseTools = await getMetabaseTools("acc_metabase_123", "truto_api_key_...");
// Bind the strict schemas to the LLM
const modelWithTools = llm.bindTools(metabaseTools);
const messages = [
new SystemMessage("You are a Metabase database administrator. Use the provided tools to execute SQL, manage dashboards, and audit permissions."),
new HumanMessage(prompt)
];
// Initial reasoning step
const response = await modelWithTools.invoke(messages);
messages.push(response);
// Handle Tool Calling Loop
if (response.tool_calls && response.tool_calls.length > 0) {
for (const toolCall of response.tool_calls) {
const tool = metabaseTools.find(t => t.name === toolCall.name);
if (tool) {
console.log(`Executing tool: ${tool.name}`);
const toolResult = await tool.func(toolCall.args);
// Append the tool result back into the agent's context
messages.push({
role: "tool",
tool_call_id: toolCall.id,
content: toolResult
});
}
}
// Final generation based on the tool results
const finalResponse = await modelWithTools.invoke(messages);
console.log("Agent Response:", finalResponse.content);
}
}The sequence of this multi-step orchestration looks like this:
sequenceDiagram
participant Agent as AI Agent
participant LLM as LLM Provider
participant Truto as Truto API Layer
participant Upstream as Metabase API
Agent->>LLM: "Run SQL and save as dashboard"
LLM-->>Agent: Call create_a_metabase_agent_execute_sql
Agent->>Truto: Execute tool via /execute
Truto->>Upstream: Forward normalized request
Upstream-->>Truto: Return 429 Too Many Requests
Truto-->>Agent: Pass 429 with ratelimit-reset headers
Agent->>Agent: Wait for backoff duration (e.g., 5s)
Agent->>Truto: Retry tool execution
Truto->>Upstream: Forward request
Upstream-->>Truto: Return SQL data payload
Truto-->>Agent: Normalized JSON response
Agent->>LLM: Provide SQL results in context
LLM-->>Agent: Call create_a_metabase_agent_dashboardMoving from Prototyping to Production
Building an AI agent that talks to a database is an excellent weekend project. Building an agent that can safely navigate Metabase's MBQL constraints, manage its nested permission graphs, and handle dynamic pagination in production is a massive engineering undertaking.
By routing your agent frameworks through Truto's /tools endpoint, you completely sidestep the integration boilerplate. You stop writing custom JSON schemas, you stop handling OAuth flows, and you stop wrestling with implicit soft deletes. You get highly constrained, deterministic function calls that prevent your LLMs from hallucinating destructive API payloads.
FAQ
- How does Truto handle Metabase API rate limits for AI agents?
- Truto does not automatically retry, throttle, or apply backoff logic when an upstream API rate limits. Instead, Truto passes the HTTP 429 error directly to the caller, normalizing the rate limit information into standard IETF headers (ratelimit-limit, ratelimit-remaining, ratelimit-reset). The caller's agent loop must parse these headers and implement its own retry and backoff logic.
- Do I need to teach the LLM how to write MBQL?
- No. Metabase uses a complex, proprietary JSON format called MBQL, which is highly prone to LLM hallucination. Truto abstracts this by providing normalized tools like `create_a_metabase_agent_execute_sql`, allowing the LLM to write standard SQL while the tool handles the underlying protocol translation.
- Can I use Truto's tools with any AI agent framework?
- Yes. Because Truto exposes tools via a standard REST endpoint (/tools) that returns strict JSON schemas, they are framework-agnostic. You can bind them natively to LangChain, LangGraph, CrewAI, Vercel AI SDK, or any custom orchestrator.
- How does Truto handle Metabase dashboard and card deletions?
- Metabase often uses implicit soft deletes instead of HTTP DELETE endpoints. For example, to delete a card, the system requires a PUT request updating the `archived` boolean flag to true. Truto's tool layer standardizes these operations so your agent doesn't get stuck calling non-existent DELETE endpoints.