Analyst Agent Manual
Everything you need to know about your always-on AI Data Analyst — how to ask questions, define metrics, set up alerts, connect Slack, and search your query history.
1. What the Analyst Agent does
The Analyst Agent connects to your SQL databases and data warehouses, indexes the full schema, and answers business questions in plain English. You ask a question in the chat panel; it writes the SQL, runs it safely, and returns a result table or chart — usually in under 5 seconds.
Beyond ad-hoc queries, you can define custom metrics (e.g. "DAU = distinct users in the last 24 hours from the events table"). The agent evaluates these automatically on a schedule, detects anomalies (changes >20%), and sends instant alerts by email and Slack. It also keeps a memory of your past queries and your data model, so it gets smarter the more you use it.
Supported sources
| Source | Type string | Notes |
|---|---|---|
| PostgreSQL | postgres | Full schema indexing, all tables and columns |
| MySQL / MariaDB | mysql | Full schema indexing |
| Google BigQuery | bigquery | Project + dataset required; batched schema indexing |
| Snowflake | snowflake | Database + schema required; sequential DESC TABLE |
| ClickHouse | clickhouse | DESCRIBE TABLE; database + schema required |
2. Connecting your data sources
On your session page, click Add source and fill in the connection details. The agent will attempt to connect immediately and index the schema. Schema indexing can take 10–60 seconds for large databases; you'll see a Pending → Indexed status change.
Required fields by source type
| Source | Host | Port | Database | Schema | Credentials |
|---|---|---|---|---|---|
| PostgreSQL | ✅ | 5432 | ✅ | public (default) | user + password |
| MySQL | ✅ | 3306 | ✅ | — | user + password |
| BigQuery | — | — | project ID | dataset name | service account JSON |
| Snowflake | account ID | — | ✅ | ✅ | user + password |
| ClickHouse | ✅ | 8123 | ✅ | ✅ | user + password (or none) |
SELECT statements, but limiting permissions is good practice. On PostgreSQL: GRANT SELECT ON ALL TABLES IN SCHEMA public TO analyst_readonly;3. Asking questions in plain English
Type your question in the chat panel exactly as you would ask a colleague. The agent uses the indexed schema to figure out which tables and columns are relevant, then generates a safe read-only SQL query and runs it.
Example questions
| Question | What the agent does |
|---|---|
| "Top 10 products by revenue last month" | Finds the orders table, groups by product, filters to last calendar month, returns sorted table |
| "Chart daily active users over the past 90 days" | Writes a DATE_TRUNC query, returns line chart with trend |
| "Which users haven't logged in for 30+ days?" | Queries login events, filters by last_seen < now - 30d, returns user list ready to export |
| "Compare conversion rates by acquisition channel" | Joins users → events, groups by channel, returns grouped bar chart |
| "Describe the orders table" | Returns full column list with types — no query needed |
| "How many rows does each table have?" | Runs COUNT(*) across all indexed tables |
How the agent picks the right table
The agent uses the indexed schema (table names, column names, types) plus your conversation history to identify the right table. If it's ambiguous, it asks. You can make it faster by naming the table explicitly: "from the events table, how many signups per day last week?"
Query limits and safety
| Limit | Value | Why |
|---|---|---|
| Query timeout | 30 seconds | Prevents runaway queries on large tables |
| Max rows returned | 10,000 | Charts and tables work best under this limit |
| Query type | SELECT only | Agent cannot INSERT, UPDATE, DELETE, or ALTER |
| Schema visibility | All indexed tables | The agent only sees schemas it has indexed |
4. Charts and visualizations
The agent automatically picks the right chart type based on your question. You can also request a specific type.
| Chart type | Best for | Example question |
|---|---|---|
| Line | Time series, trends | "Chart revenue by day last quarter" |
| Bar | Categorical comparison | "Top 10 products by orders" |
| Area | Cumulative trends | "Cumulative signups over 6 months" |
| Scatter | Correlation between two metrics | "Plot session length vs. conversion rate by user segment" |
| Pie | Part-to-whole breakdown | "Revenue split by product category" |
Charts render inline in the chat panel. To get a standalone image, ask: "Give me this chart as a PNG."
5. Defining custom metrics
Custom metrics let the Analyst Agent monitor specific KPIs automatically on a schedule. Once defined, the agent evaluates each metric every check interval, stores the result, and compares it to the previous value to detect anomalies.
How to define a metric
Go to your session page, open the Metrics tab, and click Add metric. Fill in:
| Field | What to enter |
|---|---|
| Name | Short human name, e.g. "Daily Active Users" |
| Formula | A SQL aggregate expression, e.g. COUNT(DISTINCT user_id) |
| Table hint | The table to run the formula against, e.g. events |
| Source | Which connected source to query |
COUNT(), SUM(), AVG(), MAX(), MIN(), COUNT(DISTINCT ...). The agent wraps your formula as SELECT <formula> AS __value__ FROM <table_hint>. If you need a filter, include it in the formula using a subquery.Good metric examples
-- Daily Active Users COUNT(DISTINCT user_id) -- table_hint: events (must have a created_at column and user_id) -- Total revenue today SUM(amount_cents) / 100.0 -- table_hint: orders -- Failed payment rate (as a percentage) ROUND(100.0 * SUM(CASE WHEN status = 'failed' THEN 1 ELSE 0 END) / NULLIF(COUNT(*), 0), 2) -- table_hint: payments -- Open support tickets COUNT(*) WHERE resolved_at IS NULL -- ⚠ Don't use WHERE in the formula — use a subquery: -- (SELECT COUNT(*) FROM tickets WHERE resolved_at IS NULL) -- table_hint: tickets (but formula must be a standalone expression)
6. Anomaly detection and alerts
After the second evaluation of each metric, the agent starts comparing the current value to the previous one. If the change exceeds a threshold, it fires an alert.
Alert thresholds
| Change | Severity | Example |
|---|---|---|
| Value dropped to 0 (was non-zero) | critical | DAU dropped to 0 — metric may have stopped computing |
| Absolute change ≥ 50% | critical | Revenue dropped 63% vs. previous check |
| Absolute change ≥ 20% | warning | Signups increased 28% — unusual but not critical |
| Value returned NULL | warning | Metric query returned no rows |
How alerts are delivered
When an alert fires, the agent sends:
- An email to your configured alert address (if set) with an HTML table of all alerts that fired in that check
- A Slack message to your connected channel (if configured) — see Section 7
Multiple alerts in the same check are bundled into one message. Email and Slack fire independently — you can use either, both, or neither.
No metrics, no alerts
The anomaly detector only runs for metrics you have defined. Ad-hoc chat queries do not trigger alerts. To start monitoring a value automatically, add it as a custom metric in the Metrics tab.
7. Slack integration
Connect a Slack incoming webhook to receive insight alerts and daily digests directly in your channel — no email required.
Setting up the webhook
- Go to api.slack.com/apps and create (or open) a Slack app for your workspace.
- Enable Incoming Webhooks and add a webhook to the channel you want alerts posted to.
- Copy the webhook URL (starts with
https://hooks.slack.com/services/…). - On your session page, go to the Alerts tab → Slack notifications, paste the URL, and click Save.
- Click Send test message to verify — you should see a test card in your Slack channel within a few seconds.
What gets posted to Slack
| Event | When it fires | Content |
|---|---|---|
| Insight alert | When a metric anomaly is detected | Card with metric name, source, severity, change description |
| Daily digest | Once per day (morning) | Summary card: query count, connected sources, source health |
| Test message | When you click "Send test message" | Confirmation card with timestamp |
8. Query history and conversation memory
Query history
Every question you ask and every SQL query the agent runs is saved to your session history. You can search and replay past queries from the History tab on your session page.
The history search supports keyword matching across your questions and the SQL queries that were generated. Use it to find an insight you remember from last week, or to reuse a complex query with different parameters.
Conversation memory
The Analyst Agent keeps a rolling memory of your last 50 conversation turns. This means it remembers:
- Which tables you've asked about before
- How you refer to business concepts ("DAU", "conversion", "churned users")
- Which source you prefer when multiple sources have similar tables
- Previous queries in the same session, so follow-up questions ("filter that by premium users") work naturally
Memory is stored in SapixDB and persists across sessions. Error responses are excluded from memory to prevent bad queries from contaminating future context.
9. Daily digest email
Once per day, the agent emails a digest with:
| Section | Content |
|---|---|
| Queries run today | Total number of questions answered in the last 24 hours |
| Connected sources | How many sources are active and schema-indexed |
| Source health | Status of each source (Indexed / Pending) |
| Tip | How to reach the agent — chat panel or agent email address |
The digest fires at your configured time each morning. If you have Slack configured, a summary card is also posted to your channel. If no alert email is set but Slack is configured, only the Slack card fires.
10. Tier capabilities
| Feature | Starter | Pro | Studio |
|---|---|---|---|
| Data sources | 1 | Up to 5 | Unlimited |
| Natural language queries | ✅ | ✅ | ✅ |
| Schema indexing | ✅ | ✅ | ✅ |
| Bar, line, pie charts | ✅ | ✅ | ✅ |
| Custom metric definitions | ✅ | ✅ | ✅ |
| Anomaly detection + email alerts | ✅ | ✅ | ✅ |
| Slack integration | ✅ | ✅ | ✅ |
| Conversation memory | ✅ | ✅ | ✅ |
| Query history search | ✅ | ✅ | ✅ |
| Daily digest email | ✅ | ✅ | ✅ |
| BigQuery + Snowflake support | ✅ | ✅ | ✅ |
| MCP server support | ❌ | ❌ | ✅ |
| Priority support | ❌ | ❌ | ✅ |
11. Troubleshooting
The agent says it can't find my table
This usually means schema indexing hasn't completed yet, or the source was added without a schema field. On the session page, check the source status — it should say Indexed. If it says Pending, the agent is still indexing. Wait 30–60 seconds and try again. If it's been more than 5 minutes, disconnect and reconnect the source.
My query timed out
Queries time out after 30 seconds. This happens on large tables without proper indexes or with expensive aggregations. Try:
- Adding a time filter: "show me this for last week only"
- Asking for a sample first: "show me 100 rows from orders"
- Asking the agent to add a LIMIT to the query
My metric keeps alerting even though the value is normal
If your metric has high natural variance (e.g. page views that swing 30% daily), the 20% change threshold will fire frequently. Consider defining the metric as a 7-day rolling average instead of a raw count — this smooths natural variance while still catching true anomalies.
The Slack test message didn't arrive
Check that the webhook URL is complete (starts with https://hooks.slack.com/services/ and has three path segments). Webhook URLs are channel-specific — if the channel was deleted or the app was removed, you need to generate a new URL in Slack's app settings.
I asked a follow-up question but the agent forgot context
Conversation memory stores up to 50 turns. If you've had a very long session, the oldest turns are dropped. To restore context, re-state the key details: "Earlier we were looking at the orders table — can you now break that down by region?"
Snowflake schema indexing is slow
Snowflake schema indexing runs DESC TABLE sequentially for each table (up to 300) to avoid session-level deadlocks. On large warehouses with hundreds of tables, this can take 2–5 minutes. The status will show Pending until complete. Indexing only runs once per connection — subsequent queries use the cached schema.