---
title: "Connect Metabase to AI Agents: Control SQL & Data Permissions"
slug: connect-metabase-to-ai-agents-control-sql-data-permissions
date: 2026-10-25
author: Riya Sethi
categories: ["AI & Agents"]
excerpt: "Learn how to connect Metabase to AI Agents using Truto's /tools API to autonomously execute SQL, build dashboards, and audit collection permissions."
tldr: "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."
canonical: https://truto.one/blog/connect-metabase-to-ai-agents-control-sql-data-permissions/
---

# Connect Metabase to AI Agents: Control SQL & Data 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](https://truto.one/connect-metabase-to-chatgpt-run-queries-manage-dashboards/) - or if you are building on Anthropic's models, read our guide on [connecting Metabase to Claude](https://truto.one/connect-metabase-to-claude-build-reports-audit-data-usage/). 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](https://truto.one/what-is-llm-function-calling-for-integrations-2026-guide/) 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](https://truto.one/architecting-ai-agents-langgraph-langchain-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](https://truto.one/best-unified-api-for-llm-function-calling-ai-agent-tools-2026/) 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:

1. **Smaller attack surface for hallucination.** The LLM only chooses from explicitly defined [function names with strict JSON schemas](https://truto.one/what-is-llm-function-calling-for-integrations-2026-guide/). Invalid arguments are caught before they ever hit your database.
2. **Normalized pagination and authentication.** The agent does not need to waste tokens reasoning about continuation tokens, offset limits, or session key lifecycles.
3. **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](https://truto.one/integrations/detail/metabase).

## 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:**
1. The agent calls `list_all_metabase_databases` and subsequent schema tools to understand the exact table structures for billing and accounts.
2. The agent formulates the SQL and calls `create_a_metabase_agent_execute_sql` to test the query and ensure it returns valid data without syntax errors.
3. Satisfied with the result, the agent calls `create_a_metabase_agent_question` to save the validated SQL as a permanent Card.
4. 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:**
1. The agent calls `list_all_metabase_collection_graphs` to fetch the current, active permission graph for the entire instance.
2. The LLM analyzes the graph structure, identifying the node mapping the 'Contractors' group ID to the 'Customer PII' collection ID.
3. 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.

```typescript
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:

```mermaid
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_dashboard
```

## Moving 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.

:::cta{buttonText="Talk to us" buttonUrl="/book-a-demo/"} 
Want to see how Truto can connect your AI agents to Metabase and 100+ other SaaS platforms? Let's build your integration strategy.
:::
