# Data analyst on Slack

Wire your warehouse into an agent so anyone on the team can ask plain-English questions in Slack and get tables, analysis, and recommended actions back.



<video src="/docs/data-analyst.mp4" preload="metadata" aria-label="Nairi data-analyst agent answering a Slack question against the warehouse" className="rounded-xl overflow-hidden w-full" />

## Outcome [#outcome]

A Slack agent for ad-hoc data requests. Ask a question in plain English; it writes the SQL, runs it against your warehouse, and posts the result back in the thread.

## Prerequisites [#prerequisites]

* A warehouse with **read-only credentials** scoped to the schemas you want the agent to see. Postgres, Snowflake, BigQuery, or anything else that has an MCP server.
* A Slack workspace connected to Nairi. If you haven't done this yet, see [Connecting Nairi to Slack](/help/integrations/slack).
* An LLM provider connected. Claude Sonnet via the Anthropic integration is what we recommend for this playbook. See [Connecting your LLM provider](/help/integrations/llm-provider).
* (Optional) A Gmail or Drive MCP if you want the agent to email or export reports.

## Step 1 — Add the warehouse MCP [#step-1--add-the-warehouse-mcp]

Warehouses live behind your own credentials, so you'll configure them as a **custom MCP** (paste JSON), not from the OAuth marketplace.

Open [Settings → Artifacts → MCP Configs](https://app.nairi.ai/settings/artifacts) → **New**, mark the config as **sensitive**, and paste the JSON for your warehouse. The credentials sit inside the MCP config; the agent only sees the MCP's tool surface, never the config itself.

### Postgres [#postgres]

[Postgres MCP Pro](https://github.com/crystaldba/postgres-mcp) (Crystal DBA, MIT) is the actively-maintained option. It runs over stdio, supports configurable read/write modes, and works against any Postgres-compatible warehouse (Redshift, Aurora, etc.). Pass `--access-mode=restricted` to lock it to read-only and safe meta queries:

```json
{
  "mcpServers": {
    "postgres": {
      "command": "uvx",
      "args": ["postgres-mcp", "--access-mode=restricted"],
      "env": {
        "DATABASE_URI": "postgresql://analyst:YOUR_PASSWORD@db.your-company.com:5432/analytics?sslmode=require"
      }
    }
  }
}
```

### Snowflake [#snowflake]

[isaacwasserman/mcp-snowflake-server](https://github.com/isaacwasserman/mcp-snowflake-server) (community, GPL-3) is the simplest stdio option and works with username/password or key-pair auth. The PyPI package name uses underscores (`mcp_snowflake_server`):

```json
{
  "mcpServers": {
    "snowflake": {
      "command": "uvx",
      "args": ["--python=3.12", "mcp_snowflake_server"],
      "env": {
        "SNOWFLAKE_ACCOUNT": "xy12345.us-east-1",
        "SNOWFLAKE_USER": "analyst",
        "SNOWFLAKE_PASSWORD": "YOUR_PASSWORD",
        "SNOWFLAKE_ROLE": "ANALYST_RO",
        "SNOWFLAKE_WAREHOUSE": "ANALYTICS_WH",
        "SNOWFLAKE_DATABASE": "PROD",
        "SNOWFLAKE_SCHEMA": "PUBLIC"
      }
    }
  }
}
```

If you want a Snowflake-managed MCP instead of a community one, Snowflake exposes an [official remote MCP](https://docs.snowflake.com/en/user-guide/snowflake-cortex/cortex-agents-mcp) over HTTP with OAuth — heavier setup but supported by Snowflake.

### BigQuery [#bigquery]

[LucasHild/mcp-server-bigquery](https://github.com/LucasHild/mcp-server-bigquery) (MIT) supports the standard BigQuery client auth. The cleanest path is to mount a service-account key file into the agent container and point `BIGQUERY_KEY_FILE` at it; alternatively the MCP falls back to Application Default Credentials if the env var is omitted.

```json
{
  "mcpServers": {
    "bigquery": {
      "command": "uvx",
      "args": ["mcp-server-bigquery"],
      "env": {
        "BIGQUERY_PROJECT": "your-gcp-project",
        "BIGQUERY_LOCATION": "us-central1",
        "BIGQUERY_KEY_FILE": "/etc/gcp/analyst-sa.json"
      }
    }
  }
}
```

Whichever MCP you pick, give the underlying database user the minimum permissions needed: **SELECT on the schemas you care about, no write grants anywhere**. The MCP layer is one safety net; the database grant is the real one.

See the [MCP Tools overview](/help/mcp) for the full custom-config reference. If you want to rotate a credential across multiple MCPs or agents from one place, store it in a [vault](/help/vaults) instead and reference it from the env block with `$CCASECRET_NAME`.

## Step 2 — Create the agent [#step-2--create-the-agent]

Open [Fleet → New agent](https://app.nairi.ai/agents/fleet) and fill in:

* **Name** — `analyst` works well. Slack mentions go to the Nairi bot (`@Nairi`); this name is what shows up in the agent picker and Nairi's dashboard.
* **LLM integration** — Anthropic (Claude Sonnet). Reasoning-heavy SQL benefits from Sonnet over smaller models.
* **MCPs** — attach the warehouse config from Step 1. Optionally also attach Gmail or Drive if you want the agent to email or export reports.
* **Channel** — bind to your analyst Slack channel now, or leave it and let the channel self-bind on the first `@`-mention.

See [How to deploy an agent](/help/building-agents/how-to-deploy) for the full editor walkthrough.

## Step 3 — Base prompt [#step-3--base-prompt]

Keep it short. The prompt sets identity and boundaries; the rules in Step 4 carry the schema and conventions.

```
You are an analyst with read-only access to our warehouse.
When asked a question:
- Write the SQL, run it, and reply in Slack with a 1-sentence
  answer, the query (collapsed in a code block), and a small
  table of the data.
- Round numbers to the precision the audience will actually use.
- If the question is about a change or anomaly, also explain the
  likely cause based on what's in the data.
- If a question is ambiguous, ask one clarifying question before
  running anything expensive.
- Refuse to run anything that mutates state.
```

## Step 4 — Rules to direct the agent [#step-4--rules-to-direct-the-agent]

The base prompt is identity. The rules are the institutional knowledge — the schema, the conventions, the gotchas. Put each topic in its own rule so you can iterate them independently.

Open [Settings → Artifacts → Rules](https://app.nairi.ai/settings/artifacts) and create a few rules, then attach them to the agent. Suggested starting set:

### Schema cheat-sheet [#schema-cheat-sheet]

The most important rule. Without it the agent will guess table and column names and spend tool calls poking around. With it, the first SQL it writes is usually right.

```
# Warehouse schema reference

Use these tables for the questions below. Prefer the listed
canonical table when more than one exists.

## ride_requests
One row per requested ride.
- request_id (pk)
- user_id
- city                  ('austin', 'denver', ...)
- zone                  ('downtown', 'east_austin', 'south_lamar', ...)
- requested_at          (timestamp, UTC)
- accepted_at           (timestamp, nullable — null = no driver)
- wait_time_seconds     (accepted_at − requested_at; null if cancelled)
- status                ('completed', 'cancelled_by_user', ...)
- fare_usd

## drivers_daily
One row per (driver_id, day).
- driver_id
- day                   (date)
- trips_completed
- hours_online

## Conventions
- "this week" means Monday 00:00 local through now.
- All timestamps in the warehouse are UTC. Convert to America/Chicago
  for Austin-area questions.
- "Active driver" = at least one completed trip that day.
```

### Query safety [#query-safety]

```
# Query safety

- Always include a date filter on time-series tables
  (ride_requests, events, sessions). Default to last 7 days
  if the user doesn't specify.
- Cap any unbounded SELECT with LIMIT 1000.
- Never run cross-joins.
- For BigQuery, always use partition columns when available
  to avoid full-table scans.
- If a query would scan more than 100 GB, ask before running.
```

### Definitions [#definitions]

```
# Metric definitions

- "Wait time" is accepted_at − requested_at, not pickup_at − requested_at.
- "Active driver" requires ≥1 completed trip in the day, not just
  hours_online > 0.
- "Revenue" is sum(fare_usd) on rows where status = 'completed'.
  Cancelled rides are not revenue, even if a cancellation fee was
  charged.
- When comparing "this week vs. last week", align days-of-week
  (Mon-Mon, not by-date).
```

### Output format [#output-format]

```
# How to reply in Slack

- Lead with a one-sentence answer.
- Then the table, in markdown.
- Then the SQL, in a collapsed code block.
- If you found an anomaly, end with a one-paragraph diagnosis.
- Keep numbers human: no more than 3 significant figures for
  metrics, no scientific notation for revenue or volume.
- Never paste raw warehouse error messages. Translate them.
```

You don't need all four on day one. Start with the schema cheat-sheet and the safety rules, then add the others as you notice the agent doing things you wish it wouldn't.

See [Adding rules](/help/building-agents/how-to-deploy#adding-rules) for the full editor reference.

## Step 5 — First run [#step-5--first-run]

In your analyst channel:

```
@Nairi how were sign-ups last week vs. the week before?
```

Watch the thread. The agent should:

1. React with `⏳` then `👀` (queued, then running).
2. Reply with a one-sentence answer, a 2-row table (this week vs. last), and the collapsed SQL.
3. Add a diagnosis if there's a clear movement.

If the SQL it writes is wrong, the schema cheat-sheet is almost always the lever to fix it. Add the missing column or convention and try again.

## Customisation [#customisation]

* **Charts.** Add the [charts skill](/help/skills) so the agent posts a PNG alongside the table. Useful when "is it up or down?" is the real question.
* **Recurring digests.** Turn the same prompt into a [scheduled job](/help/scheduled-jobs) that posts a Monday-morning KPI summary. Same agent, no new wiring.
* **Email distribution.** Attach the Gmail MCP from the [marketplace](/help/mcp) so the agent can send a finished report to a stakeholder directly from the thread.
* **Multiple warehouses.** Attach multiple MCP configs to the same agent. Add a rule explaining which warehouse holds what so the agent picks the right one.

## Related [#related]

* [MCP Tools](/help/mcp)
* [How to deploy an agent](/help/building-agents/how-to-deploy)
* [Vaults & Secrets](/help/vaults)
* [Scheduled Jobs & Automations](/help/scheduled-jobs)

***

*Can't find what you're looking for? Email [support@nairi.ai](mailto:support@nairi.ai).*
