---
id: casos/agente-slack
area: AI
usage: widely used
effort: medium
grain: One semantic table per purpose, with a stated grain; one document per domain
---

# Data agent on Slack or WhatsApp

The team asks in plain language on Slack or WhatsApp and gets the official number, with the metric, the period and the last load date, or hears that the data does not exist.

## Executive summary

**For:** Teams that ask for numbers in chat every day and want the official answer without opening the BI tool or waiting on the data team.

**What it solves**

- The same question gets the same number, for anyone and in any channel.
- The agent says which metric it used, for which period and when the data was last updated.
- People without access to a piece of data do not get it, and the agent says where to look.

**Why it matters:** An agent without written rules confidently returns the wrong number: it reads gross instead of net, converts the time zone of a date that is already the business day, invents a cause for a drop. The first time leadership catches an error, the channel loses trust. What separates a reliable agent from a chatbot is the semantic layer and the answer protocol, not the model.

**Business questions it answers**

- How much did we sell yesterday, net, and how does it compare with the same day last week?
- What is this week's average ticket by branch?
- How many leads came in this month and from which channels?
- Which branches are below this month's target?
- Is yesterday's number already up to date?

**What you need**

- The main metrics in gold tables, with closed rules
- Context documents with definitions, routing by topic and an answer protocol
- The channel (Slack, WhatsApp, CRM chat) connected to an agent with the Nekt MCP

**What you get**

- Semantic tables per purpose, with columns annotated for the AI
- An entry index that tells which document to read for each topic
- Tokens scoped by audience: leadership, manager, team
- A question and answer log and a test set to measure the agent

## Detailed

### The problem

The agent gets access to every table and picks on its own. It reads a test table with a name close to the official one, averages a column that is already an average, treats a day that has not loaded yet as zero and explains the drop with a cause that exists nowhere. Two people ask the same question and get different numbers, and nobody can audit where each one came from.

### Business rules

1. **One semantic table per business question.** Create consumption tables per purpose (daily sales by branch, funnel by month, revenue by customer), with the grain stated in one sentence in the description. When the rule is complex, the table already carries the result in a column (for example, a boolean that says whether the row counts toward the metric) and the document tells the agent to use that column instead of rewriting the formula. Scratch tables (prefixes debug_, test_, tmp_, suffixes _log, _dryrun, names with dates) are never a source of numbers. (Avoid: Give the agent access to the whole lakehouse.)
2. **Annotate every column for the AI.** Start the column description with a tag: @pk (grain key), @fk (foreign key), @measure additive (sums across any dimension), @measure non_additive (average ticket, percentage, rate), @grain. Then state the origin, the rule and the pitfall. Every monetary measure says whether it is gross or net. Document the table, not only the transformation: whoever looks for the data finds the table. (Avoid: A total_sales column without saying whether it is gross or net.)
3. **An entry index with 'Read when'.** A root document lists every document with one line saying when to read it. The agent reads every document that matches the request; chained metrics are read together (NRR also reads MRR and churn). If no document covers the request, the agent says so instead of improvising. In semantic search, ask for the concept and the metric: a proper name surrounded by weak words makes the search return zero documents. The name is for filtering in SQL. (Avoid: Dozens of loose documents, with no index, searched by client name.)
4. **Context before SQL, numbers only from the query.** Fixed order: fetch context with the original question, read the documents, check the last load, generate and run the query, check the order of magnitude against a reference number in the document. The agent never answers a number without running the query and never refuses for lack of data before reading the table structure. Null is absence, not zero. Metrics flagged 'to be validated' are not inferred. (Avoid: Answering from memory or estimating when the query fails.)
5. **Every answer states metric, cut and load.** The answer names the metric (net or gross), the period with start and end dates and the date and time of the last load. The current day is partial: compare only closed days. An open month does not count as actuals; use the table's closed-month flag when there is one. (Avoid: Answering 'we sold R$ X' without saying what or up to when.)
6. **Business dates take no time zone.** ERP date fields stored as midnight UTC are already the business day. The agent computes today and yesterday in local time and compares directly, without converting the field. The rule is written in the column description and in the protocol. (Avoid: Converting to local time a field that is already the day.)
7. **Facts, not causes.** The agent breaks the change down (volume versus ticket, which branch explains the difference in reais), but does not explain why it fell or recommend action without data to back it. A comparison base of zero or very small becomes 'low base', with the change in reais. Rates change in percentage points. Percentages and averages are not summed across rows: recompute the ratio from the totals. (Avoid: Explaining a drop by team productivity in a base that only has sales.)
8. **Access by audience, with token and view.** Each audience has its own MCP token with table scope: leadership reads the whole network, a manager reads the view of their own branch. A catalog folder is organization, not security. Data that identifies a person (operator, contact, student) stays out of broad views. An access error is the scope working: the agent says where the answer lives, without asking for new permissions. (Avoid: One admin token for everyone and the branch filter in the prompt.)
9. **Documents have an owner and a date; the query wins.** Rules are stable; counts (active customers, number of tables, totals) are a snapshot of a date and age within days. If the document disagrees with the query, the query wins. Every document carries an owner, a status (validated or not) and the last review date. When the agent uses an unvalidated rule, it says so. (Avoid: Copying numbers into the document and never reviewing it.)
10. **Measure the agent with test questions and a log.** Keep a set of real questions with the expected answer and run it on every document change. Store the channel history pairing each question with the final answer. Intermediate messages ('analyzing your question') do not count as an answer or toward response time. (Avoid: Validating the agent with two questions on launch day.)

### The documents the agent reads

Each one has a role. On conflict, the domain document wins on calculation and the protocol wins on form.

- **Lists the documents and when to read each one** → Entry index
- **Number rules, cut, what never to invent** → Answer protocol
- **How to compute each metric, with a reference number** → Domain
- **Which table answers each type of question** → Routing
- **Structure of a recurring deliverable** → Playbook
- **Definitions and scopes specific to a client or branch** → Exceptions

### Definitions

| Metric | Definition |
|---|---|
| Valid numeric answer | number returned by a query run in the conversation, with metric, period and last load date stated |
| Last load | latest business date or update time (_nekt_sync_at) of the queried table, in local time |
| Closed day | any day before the current one in local time; the current day is always partial |
| Low base | comparison base of zero, negative or less than a quarter of the current value; the change is shown in reais, with no percentage |
| Agent hit rate | test set questions answered with the expected number / questions in the set, measured on every document change |
| Response time | from the question to the agent's final answer in the channel, excluding intermediate messages |
| Audience scope | tables and views granted on that audience's MCP token |

### Pitfalls

- **Gross read as net.** The agent returned a store's gross sales as net and was off by six digits on a single day. How to avoid: State gross or net on every monetary column and set the default in the protocol.
- **Zero sales on a busy day.** The agent converted the time zone of a field that was already the business day and returned zero sales on a high-sales day. How to avoid: Write in the column description that the date takes no time zone.
- **Invented cause.** The agent blamed a drop on team productivity and recommended action, in a base that only had sales, cancellations and sign-ups. How to avoid: Protocol: facts, not causes; close with what the base cannot answer.
- **Scratch table as source.** With no index, the agent aggregated an investigation table whose name was close to the official one. How to avoid: List the consumption tables in the index and mark scratch prefixes as forbidden.
- **Stale branch view.** The branch views were created with a manual trigger and went more than a week without refreshing while the source was up to date. How to avoid: Event trigger and load date in every answer.
- **Search found nothing by name.** Questions made of a proper name and weak words returned no documents, and the agent answered with no rules. How to avoid: Search by concept and metric; use the name only to filter in SQL.

### Acceptance test

- [ ] On a set of at least 30 real questions with expected answers, the agent gets the number right on every official-metric question and says the data does not exist on the ones the base does not cover.
- [ ] The same question asked by two people, in two channels, returns the same number and the same load date.
- [ ] With a manager's token, querying another branch's view returns an access error.
- [ ] Every numeric answer in the log carries metric, period and last load date.
- [ ] Net sales for a closed day returned by the agent match the official ERP report for the same day.

### Context document

```text
Data agent protocol
- Before any SQL, fetch context with the original question and read the documents listed in the index <index name>.
- Use only the listed consumption tables: <list>. Never use tables with prefix debug_, test_, tmp_ or suffix _log, _dryrun.
- Do not answer a number without running the query. Do not refuse for lack of data before reading the table structure.
- Every numeric answer carries the metric, the period with start and end dates and the date and time of the last load.
- 'How much did we sell' = <default metric, e.g. net sales>. Gross only when asked.
- Business dates take no time zone conversion. Today and yesterday in America/Sao_Paulo.
- The current day is partial: compare only closed days. Count as actuals only months with <closed-month flag> true.
- Percentages, averages and ticket are not summed across rows: recompute from the totals.
- Comparison base of zero, negative or less than a quarter of the current value: write 'low base' and show the change in reais.
- State the fact, never the cause. Do not recommend action. Close with what the base cannot answer.
- Null is absence, not zero. Metrics flagged 'to be validated' are not inferred.
- List people only when asked, up to 50 rows, without phone, email or ID number.
- Access error: say it is outside your scope and where the answer lives.
- If a number written in a document disagrees with the query, the query wins.
Client exceptions:
- <client>: 'lead' with no qualifier = <definition>.
- <client>: managers read only <branch view>; leadership reads <network view>.
- <client>: reference number for <closed month>: <metric> = <value>.
```

### Variations

- **Per-client agent:** At agencies and consultancies, a routing document per client and a precedence order between global rule and exception.
- **Alert agent:** The same protocol, triggered on a schedule: it reads the scoreboard and only speaks when something goes out of range.
- **Agent that acts:** With the MCP live tools, the agent also performs actions in the tools, such as settling an installment in the ERP or adjusting a campaign, always with confirmation.
