Verified SOP & TutorialAudited Score 98/100

The Complete Production SOP: How to Deploy and Run Metabase BI Data Modeling & Interactive Questions in Autonomous AI Agents

Deploy Metabase BI Data Modeling & Interactive Questions in Codex, Claude Code, and Cursor. Configure field filters, data models, and JWT embedding safely.

Target Runtimes:codexclaude-codecursorwindsurf
5 min read • Updated for 2026

Technical Overview & Architectural Context

Autonomous coding agents frequently stumble when engineering Metabase BI pipelines. A common failure mode involves writing raw SQL parameter syntax (such as WHERE date >= {{start_date}}) instead of Metabase's specialized Field Filter variable syntax (WHERE {{created_at}}), which requires variable mapping directly to table column metadata rather than explicit comparison operators. Furthermore, agents often miss critical Data Model administrative configurations—such as explicitly tagging Foreign Keys and semantic column types (Entity Key, Category, Avatar Image URL)—causing Metabase's visual question builder and drill-down links to break. The 'metabase-bi-data-model-questions' skill enforces deterministic boundaries across Codex, Claude Code, Cursor, and Windsurf. It establishes strict procedural guardrails that guide the agent through entity-relationship metadata declarations, field filter parameterization, dashboard variable linkage, and cryptographically secure signed JWT payload generation for application embedding.

Prerequisites & Environment Requirements

Codex Desktop, Claude Code CLI, Cursor, or Windsurf installed with agent tools enabled
Access to a running Metabase v0.46+ instance (Admin or Data Model permissions)
Node.js 20+ or Python 3.10+ in workspace for JWT embedding and API validation scripts
Git 2.40+ initialized within your project workspace repository

Verified Search Intents & Long-Tail Queries Solved

SEO Audit Score: 98/100

This operational tutorial is engineered to provide deterministic solutions for these developer search queries:

#install metabase-bi-data-model-questions in cursor ide#claude code metabase field filter query rules#codex desktop metabase data modeling tutorial#how to fix metabase field filter syntax error agent#deterministic metabase bi agent SOP#metabase-bi-data-model-questions sandbox permissions and security score#metabase jwt signed embedding backend route prompt examples

Step-by-Step Execution Playbook

1

Local Environment Setup & SKILL.md Mounting

Create the local skill manifest directory and inject verified procedural rules into your agent's execution path.

Autonomous agent frameworks look for skill definitions inside the global or project-scoped skills directory (~/.agents/skills or .cursor/skills). Installing the Metabase BI skill file allows the agent runtime to parse trigger keywords such as 'create metabase field filter' and inject schema modeling rules before executing code generation or API interaction.

Terminal Command
mkdir -p .agents/skills/metabase-bi-data-model-questions && curl -fsSL https://askills.dev/api/skills/metabase-bi-data-model-questions/raw -o .agents/skills/metabase-bi-data-model-questions/SKILL.md
.agents/skills/metabase-bi-data-model-questions/SKILL.md
---
name: "metabase-bi-data-model-questions"
description: "Model data schemas, foreign keys, and self-service visual questions in Metabase."
metadata:
  author: "Metabase"
  version: "1.0.0"
  runtime_compatibility:
    - "codex"
    - "claude-code"
    - "cursor"
    - "windsurf"
triggers:
  - "create metabase field filter"
  - "model data relationships metabase"
  - "embed metabase dashboard"
permissions:
  fs_read: true
  fs_write: "workspace"
  shell_exec: false
  net_access: false
---

# Metabase BI Data Modeling & Interactive Questions

Configures Metabase data models: defining metadata types, configuring entity relationships and foreign keys, authoring visual query questions, writing native SQL with Field Filters ({{field_filter}}), and embedding dashboards.

## When to Invoke
Invoke this skill whenever you need to:
- create metabase field filter
- model data relationships metabase
- embed metabase dashboard

## Execution SOP & Rules
1. In Admin -> Data Model, set column types (Entity Key, Category, Description) and map Foreign Keys.
2. Write native SQL queries with Field Filters: WHERE {{created_at}} linked directly to table timestamp column.
3. Combine questions into a Dashboard and add interactive dropdown filters mapped to query parameters.
4. Configure Embedding settings with secret key and sign JWT payloads in application backend routes.

## Verification Checklist
- Run local linting, syntax validation, and type-checks before reporting completion.
- Ensure all created or modified files adhere to workspace boundaries and avoid uncommitted secrets.
- Verify tests or build commands exit cleanly with return code 0.
Production Pro-Tip

Keep the SKILL.md file inside the workspace root (e.g., .agents/skills/) to allow Cursor and Claude Code to load it on-demand without consuming global token overhead on unprompted queries.

Sandbox Gotcha

The skill specifies net_access: false and shell_exec: false. Agents should author native SQL templates and backend route files locally rather than attempting live unauthenticated REST calls against your remote Metabase database.

2

Environment Secrets & Dependency Validation

Inject Metabase embedding secrets and API session variables securely into isolated workspace environments.

Interactive Metabase embedding requires a cryptographically secure 256-bit secret key to sign JSON Web Tokens (JWT). Rather than hardcoding these in analytics routes or prompt context, set up an isolated .env.local file and establish dependency requirements (jsonwebtoken in Node or pyjwt in Python).

Terminal Command
test -f .env.local || touch .env.local && echo 'METABASE_SITE_URL="https://analytics.example.com"' >> .env.local && echo 'METABASE_SECRET_KEY="0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"' >> .env.local && echo '.env.local' >> .gitignore
server/api/metabase-token.ts
import jwt from 'jsonwebtoken';

interface EmbedParams {
  dashboardId: number;
  userOrgId: string;
}

export function generateMetabaseDashboardUrl({ dashboardId, userOrgId }: EmbedParams): string {
  const secretKey = process.env.METABASE_SECRET_KEY;
  const siteUrl = process.env.METABASE_SITE_URL;

  if (!secretKey || !siteUrl) {
    throw new Error('Missing METABASE_SECRET_KEY or METABASE_SITE_URL configuration.');
  }

  const payload = {
    resource: { dashboard: dashboardId },
    params: {
      org_id: userOrgId
    },
    exp: Math.round(Date.now() / 1000) + (10 * 60) // 10 minute expiration
  };

  const token = jwt.sign(payload, secretKey);
  return `${siteUrl}/embed/dashboard/${token}#bordered=true&titled=true`;
}
Production Pro-Tip

Never inject Metabase admin credentials (username/password) directly into agent conversation prompts; use read-only session tokens or local mock responses when testing token signing.

Sandbox Gotcha

Ensure .env.local is added to .gitignore before prompting Claude Code or Codex, avoiding accidental secret leaks in pull requests.

3

Intent Matching & Trigger Invocation

Invoke deterministic Metabase generation workflows using frontmatter trigger phrases.

When prompted with trigger terms like 'create metabase field filter' or 'model data relationships metabase', the agent loads the SOP rules from SKILL.md. This forces the agent to use Metabase double-bracket variable interpolation without column comparison operators in SQL.

queries/monthly_active_tenants.sql
-- Correct: Field filter handles column name and operators implicitly
SELECT
  org.id AS organization_id,
  org.name AS organization_name,
  COUNT(e.id) AS event_count
FROM organizations org
LEFT JOIN app_events e ON e.org_id = org.id
WHERE {{event_date}}
  [[AND {{organization_category}}]]
GROUP BY org.id, org.name
ORDER BY event_count DESC;
Production Pro-Tip

Use optional syntax brackets [[AND {{filter_name}}]] in Metabase native queries so that if the user does not apply the dashboard filter, the query executes valid SQL without empty WHERE clauses.

Sandbox Gotcha

Do not write WHERE e.created_at = {{event_date}}. When using Field Filters in Metabase, the column comparison is injected automatically; writing e.created_at = will produce a SQL syntax error.

4

Verification, Linting & Output Quality Gate

Run linting and test suites to confirm embedding token generation and SQL syntax consistency.

Before accepting changes from the agent, run the project's test suite to verify that the signed JWT claims match Metabase's embedding protocol and that all SQL queries follow the database-specific dialect (PostgreSQL, MySQL, Snowflake).

Terminal Command
npm test -- tests/metabase-token.test.ts
tests/metabase-token.test.ts
import { describe, it, expect } from 'vitest';
import jwt from 'jsonwebtoken';
import { generateMetabaseDashboardUrl } from '../server/api/metabase-token';

describe('generateMetabaseDashboardUrl', () => {
  process.env.METABASE_SECRET_KEY = 'test_secret_key_1234567890123456';
  process.env.METABASE_SITE_URL = 'https://analytics.test.internal';

  it('generates a valid signed JWT containing dashboard id and params', () => {
    const url = generateMetabaseDashboardUrl({ dashboardId: 42, userOrgId: 'org_abc123' });
    expect(url).toContain('https://analytics.test.internal/embed/dashboard/');
    
    const token = url.split('/embed/dashboard/')[1].split('#')[0];
    const decoded = jwt.verify(token, process.env.METABASE_SECRET_KEY!) as any;
    expect(decoded.resource.dashboard).toBe(42);
    expect(decoded.params.org_id).toBe('org_abc123');
    expect(decoded.exp).toBeGreaterThan(Math.floor(Date.now() / 1000));
  });
});
Production Pro-Tip

Review `git diff` to ensure the agent did not introduce extraneous table aliases in native queries that break Metabase schema mapping.

Sandbox Gotcha

Metabase Field Filters do not work with SQL table aliases inside the filter variable definition. Reference the raw table directly in the FROM clause or map the Field Filter to the physical table column in Metabase Admin.

Real-World Scenario: Implement Embedded Multi-Tenant Analytics Dashboard with Date Range & Category Field Filters

Tested Trigger Prompt (Feed directly into Codex, Claude, or Cursor):

“We need to embed Metabase dashboard ID 12 for our SaaS customers. Please create metabase field filter SQL for a 'revenue_by_tier' question that supports optional date range and customer tier filters, and provide a secure Express/Next.js API route that generates the signed JWT embedding URL locked to the authenticated user's organization.”

Deterministic Agent Verification Pipeline:
Consults SKILL.md and identifies the triggers 'create metabase field filter' and 'embed metabase dashboard'.
Generates an idempotent SQL file using Metabase Field Filter variables `{{date_range}}` and optional clauses `[[AND {{customer_tier}}]]` without explicit SQL comparison operators.
Generates a server-side embedding handler in TypeScript using `jsonwebtoken` that injects `{ resource: { dashboard: 12 }, params: { org_id: session.orgId } }` with a 10-minute expiry window.
Documents Metabase Admin requirements: setting Column Type to 'Category' for customer_tier, and mapping Field Filters to the underlying table columns in the Metabase Query Builder.

Runtime Troubleshooting & Failure Modes

Error: Syntax error at or near "=": SELECT * FROM orders WHERE orders.created_at = (orders.created_at >= '2026-01-01' AND orders.created_at <= '2026-01-31')

Root Cause: The agent authored the native query using an explicit comparison operator before a Field Filter variable: `WHERE orders.created_at = {{created_at}}`. Metabase Field Filters automatically generate the entire column comparison clause.

Resolution Command / Fix:
Change SQL to: `WHERE {{created_at}}` and configure the variable type as 'Field Filter' mapped to `orders.created_at` in the Metabase query editor side panel.
Error: TokenExpiredError: jwt expired OR 403 Forbidden: Metabase embedding signature is invalid

Root Cause: The application backend signed the JWT using an mismatched METABASE_SECRET_KEY or generated an expiration timestamp in milliseconds instead of seconds.

Resolution Command / Fix:
Ensure secret key matches Metabase Admin > Settings > Embedding exactly, and compute exp using seconds: `exp: Math.floor(Date.now() / 1000) + (10 * 60)`.

Frequently Asked Questions (Metabase BI Data Modeling & Interactive Questions SOP)

Q:Can I use Metabase BI Data Modeling & Interactive Questions across Codex, Claude Code, and Cursor simultaneously?

Yes. The skill adheres to the open SKILL.md specification. Once installed in your `.agents/skills` or `.cursor/skills` folder, any compatible runtime (Codex, Claude Code, Cursor, Windsurf) can parse the triggers and apply data modeling constraints automatically.

Q:How does Metabase BI Data Modeling & Interactive Questions prevent context window overflow during long agent sessions?

The skill provides targeted SOP boundaries rather than raw documentation dumps. By enforcing strict formatting rules for Field Filters, foreign key definitions, and JWT payloads directly at trigger invocation, agents avoid iterative trial-and-error prompting that depletes tokens.

Q:Does this skill require escalated root or container permissions?

No. The skill has an audited security score of 98/100. It requires zero shell execution permissions and no network access (`shell_exec: false`, `net_access: false`), operating solely on workspace file authoring and validation.

Ready to equip your autonomous agent with Metabase BI Data Modeling & Interactive Questions?

Copy the complete audited SKILL.md specification or download the 1-click zip bundle directly from our verified registry.

Get 1-Click Install Spec