Что получится в результате
Соберем ИИ-агента для BI и аналитики, который отвечает на вопросы по утвержденным метрикам, показывает источник цифры, объясняет изменения, находит аномалии, готовит weekly summary и создает задачи аналитикам. Это не “чат с базой данных”, а контролируемый слой поверх BI, semantic layer, dashboards и безопасных read-only запросов.
Рабочая версия будет делать так:
- настройки хранятся в `settings`;
- бизнес-домены хранятся в `business_domains`;
- пользователи и роли хранятся в `analytics_users`;
- источники данных хранятся в `data_sources`;
- наборы данных хранятся в `dataset_catalog`;
- утвержденные метрики хранятся в `metric_catalog`;
- измерения и фильтры хранятся в `dimension_catalog`;
- права доступа хранятся в `access_rules`;
- BI-дашборды хранятся в `dashboard_catalog`;
- безопасные SQL-шаблоны хранятся в `query_templates`;
- пользовательские вопросы пишутся в `question_inbox`;
- план запроса пишется в `query_plan`;
- рассчитанные результаты пишутся в `query_results`;
- проверки качества данных пишутся в `data_quality_checks`;
- аномалии пишутся в `anomaly_log`;
- объяснения метрик пишутся в `metric_explanations`;
- выводы и гипотезы пишутся в `insight_queue`;
- задачи аналитикам пишутся в `analytics_task_queue`;
- спорные действия уходят в `approval_queue`;
- одобренные действия попадают в `execution_queue`;
- результаты отчетов пишутся в `report_snapshots`;
- еженедельная сводка пишется в `weekly_bi_report`;
- все решения пишутся в `audit_log`;
- ошибки API, SQL и прав пишутся в `error_log`.
В первой версии агент не выполняет произвольный SQL, не меняет dashboards, не создает новые KPI, не показывает данные вне прав пользователя, не записывает изменения в хранилище и не делает управленческие выводы без evidence. Он читает утвержденные данные, объясняет результат и отправляет спорные действия на review.
Что понадобится
- n8n Cloud или self-hosted n8n.
- Google Sheets для управляющих таблиц MVP.
- Power BI REST API, Metabase API, Looker API или другой BI-инструмент.
- Read-only доступ к BI, dashboards или SQL warehouse.
- Каталог утвержденных метрик и формул.
- Список ролей и прав доступа.
- 3-5 готовых dashboards, которые команда уже использует.
- Канал approval: Telegram, Slack, Teams или email.
- API-ключ LLM-провайдера.
- BI-аналитик или владелец данных, который подтверждает формулы, права и спорные выводы.
Шаг 1. Выберите первый BI-сценарий
Не начинайте с агента, который “отвечает на любые вопросы по бизнесу”. Для MVP выберите один сценарий.
Подходящие варианты:
- ответы по утвержденным KPI;
- объяснение dashboard;
- weekly summary по продажам или продукту;
- поиск аномалий;
- проверка качества данных;
- подготовка задачи аналитику;
- объяснение, откуда взялась цифра.
Самый безопасный старт: `вопрос -> проверка прав -> выбор метрики -> расчет по шаблону -> data quality check -> объяснение -> audit log`.
Проверка: сценарий можно руками пройти на одном dashboard и 5 метриках.
Шаг 2. Запретите опасные действия
В первой версии запретите агенту:
- выполнять произвольный SQL от пользователя;
- писать в production-базу;
- менять semantic layer;
- менять формулы KPI;
- менять dashboards;
- показывать данные вне прав пользователя;
- выгружать персональные данные;
- считать финансы по неутвержденной формуле;
- создавать управленческие задачи без evidence;
- отправлять отчет внешним получателям;
- менять refresh schedule;
- удалять отчеты или dataset.
Разрешите агенту:
- читать утвержденные dashboards;
- читать semantic models;
- выполнять allowlist SQL-шаблоны;
- объяснять метрики;
- проверять качество данных;
- находить аномалии;
- готовить weekly summary;
- создавать draft-задачи;
- отправлять спорные вопросы в approval;
- логировать каждый ответ.
Проверка: любое действие, которое меняет BI, формулу, права или внешний отчет, должно попадать в `approval_queue`.
Шаг 3. Создайте Google Sheet проекта
Создайте таблицу `bi_agent_mvp`.
Добавьте листы:
settings
business_domains
analytics_users
data_sources
dataset_catalog
metric_catalog
dimension_catalog
access_rules
dashboard_catalog
query_templates
question_inbox
query_plan
query_results
data_quality_checks
anomaly_log
metric_explanations
insight_queue
analytics_task_queue
approval_queue
execution_queue
report_snapshots
weekly_bi_report
audit_log
error_log
Проверка: названия листов совпадают один в один, потому что n8n будет обращаться к ним по имени.
Шаг 4. Заполните settings
В `settings` добавьте колонки:
key
value
description
Добавьте строки:
llm_model | gpt-4.1-mini | модель для объяснений и гипотез
default_bi_tool | metabase | основной BI-инструмент
max_rows_per_query | 500 | лимит строк результата
max_query_window_days | 90 | максимальный период для MVP
allow_free_sql | false | произвольный SQL запрещен
allow_pii_export | false | персональные данные не выгружаем
allow_dashboard_write | false | изменение dashboards запрещено
approval_channel | telegram | канал согласований
report_channel | email | канал отчетов
data_quality_required | true | проверка качества обязательна
Проверка: `allow_free_sql=false`, `allow_pii_export=false`, `allow_dashboard_write=false`.
Шаг 5. Заполните business_domains
В `business_domains` добавьте колонки:
domain_id
name
description
owner
allowed_roles
status
Пример:
DOM-SALES | Продажи | выручка, сделки, конверсия, план | revenue_ops | manager,analyst,ceo | active
DOM-PRODUCT | Продукт | активность, retention, funnels | product_analytics | product,analyst,ceo | active
DOM-SUPPORT | Поддержка | тикеты, SLA, CSAT | support_ops | support_lead,analyst,ceo | active
Проверка: у каждого домена есть владелец данных.
Шаг 6. Заполните analytics_users
В `analytics_users` добавьте колонки:
user_id
display_name
email_hash
role
department
allowed_domains
status
Пример:
USR-001 | Иван | sha256:... | manager | sales | DOM-SALES | active
USR-002 | Ольга | sha256:... | analyst | analytics | DOM-SALES,DOM-PRODUCT,DOM-SUPPORT | active
Проверка: пользователь не получает доступ к домену, которого нет в `allowed_domains`.
Шаг 7. Заполните data_sources
В `data_sources` добавьте колонки:
source_id
domain_id
source_type
name
connection_ref
read_mode
contains_pii
owner
status
Пример:
SRC-CRM | DOM-SALES | warehouse_table | crm_deals_mart | warehouse:crm_deals_mart | read_only | yes | revenue_ops | active
SRC-META | DOM-PRODUCT | bi_dataset | product_usage_model | powerbi:dataset:123 | read_only | no | product_analytics | active
Проверка: `contains_pii=yes` запрещает выгрузку строковых персональных данных в LLM.
Шаг 8. Заполните dataset_catalog
В `dataset_catalog` добавьте колонки:
dataset_id
source_id
domain_id
name
grain
primary_date_field
refresh_schedule
last_refresh_at
owner
status
Пример:
DS-SALES-DAILY | SRC-CRM | DOM-SALES | daily_sales_mart | day,manager,stage | date | daily 06:00 | 2026-05-23 06:05 | revenue_ops | active
Проверка: у dataset есть grain и дата обновления.
Шаг 9. Создайте metric_catalog
В `metric_catalog` добавьте колонки:
metric_id
domain_id
name
business_name
formula
numerator
denominator
dataset_id
default_period
owner
status
Пример:
MET-REVENUE | DOM-SALES | revenue | Выручка | sum(paid_amount) | paid_amount | - | DS-SALES-DAILY | month | revenue_ops | active
MET-WIN-RATE | DOM-SALES | win_rate | Win rate | won_deals / closed_deals | won_deals | closed_deals | DS-SALES-DAILY | month | revenue_ops | active
Проверка: формула, numerator и denominator утверждены владельцем метрики.
Шаг 10. Создайте dimension_catalog
В `dimension_catalog` добавьте колонки:
dimension_id
domain_id
name
business_name
dataset_id
allowed_values
pii_risk
status
Пример:
DIM-MANAGER | DOM-SALES | manager_id | Менеджер | DS-SALES-DAILY | internal_id_only | medium | active
DIM-REGION | DOM-SALES | region | Регион | DS-SALES-DAILY | ru,kz,by | low | active
Проверка: измерения с `pii_risk=high` не отправляются в LLM как сырые значения.
Шаг 11. Создайте access_rules
В `access_rules` добавьте колонки:
access_id
role
domain_id
dataset_id
metric_id
allowed_dimensions
row_filter
can_export
status
Пример:
ACL-SALES-MANAGER | manager | DOM-SALES | DS-SALES-DAILY | MET-REVENUE,MET-WIN-RATE | region,stage | manager_id={{user_id}} | no | active
ACL-CEO | ceo | * | * | * | * | none | yes | active
Проверка: агент проверяет `access_rules` до запроса к BI или SQL.
Шаг 12. Создайте dashboard_catalog
В `dashboard_catalog` добавьте колонки:
dashboard_id
domain_id
bi_tool
dashboard_name
dashboard_url
owner
main_metrics
refresh_period
status
Пример:
DASH-SALES-MAIN | DOM-SALES | metabase | Продажи: план и факт | https://metabase/dashboard/12 | revenue_ops | MET-REVENUE,MET-WIN-RATE | daily | active
Проверка: dashboard связан с доменом и основными метриками.
Шаг 13. Создайте query_templates
В `query_templates` добавьте безопасные шаблоны запросов.
Колонки:
template_id
domain_id
metric_id
name
sql_template
allowed_params
max_days
requires_approval
status
Пример:
QT-REVENUE-BY-DAY | DOM-SALES | MET-REVENUE | revenue by day | select date, sum(paid_amount) as revenue from daily_sales_mart where date between :date_from and :date_to group by date order by date | date_from,date_to | 90 | no | active
Проверка: пользователь не может передать произвольный SQL, только параметры allowlist.
Шаг 14. Подключите BI-инструмент в n8n
Создайте workflow `BI Agent MVP`.
Добавьте узлы:
- `Manual Trigger`;
- `Read settings`;
- `Read analytics_users`;
- `Read access_rules`;
- `Read metric_catalog`;
- `Read dashboard_catalog`;
- `Read query_templates`;
- `Classify question`;
- `Build query plan`;
- `Execute safe query`;
- `Run data quality checks`;
- `Explain result`;
- `Write audit_log`.
Проверка: первый запуск работает на одном пользователе и одном вопросе.
Шаг 15. Подключите Power BI REST API
Если используете Power BI, начните с read-only:
- получить workspaces;
- получить reports;
- получить dashboards;
- получить datasets или semantic models;
- получить refresh history;
- сохранить ссылки в `dashboard_catalog`.
Проверка: service principal не имеет прав на изменение reports и dataset.
Шаг 16. Подключите Metabase API
Если используете Metabase, начните с:
- получить collections;
- получить dashboards;
- получить cards/questions;
- выполнить сохраненный question;
- прочитать результат;
- сохранить dashboard URL.
Проверка: агент использует saved questions, а не произвольные native SQL cards без review.
Шаг 17. Подключите Looker API
Если используете Looker, начните с:
- dashboards;
- looks;
- explores;
- queries;
- LookML model metadata;
- user permissions.
Проверка: агент опирается на LookML semantic layer, а не придумывает формулы сам.
Шаг 18. Создайте question_inbox
В `question_inbox` добавьте колонки:
question_id
user_id
domain_hint
question_text
requested_period
status
created_at
Статусы:
new
needs_clarification
planned
answered
blocked_by_access
needs_approval
error
Проверка: вопрос связан с пользователем, чтобы проверить права.
Шаг 19. Настройте prompt для классификации вопроса
Prompt:
Ты BI-аналитик. Разбери вопрос пользователя.
Правила:
1. Не считай метрики сам.
2. Не придумывай формулы.
3. Определи домен, метрику, период, фильтры и нужный формат ответа.
4. Если вопрос неясный, верни needs_clarification.
5. Если нужна персональная выгрузка, верни needs_approval.
question:
{{$json.question}}
metric_catalog:
{{$json.metric_catalog}}
dashboard_catalog:
{{$json.dashboard_catalog}}
Верни JSON:
{
"status": "ready | needs_clarification | needs_approval",
"domain_id": "...",
"metric_ids": ["..."],
"period": {"date_from": "...", "date_to": "..."},
"filters": {},
"answer_format": "short | table | chart_summary | weekly_report",
"clarifying_question": ""
}
Проверка: если метрики нет в `metric_catalog`, агент не должен ее изобретать.
Шаг 20. Создайте query_plan
В `query_plan` добавьте колонки:
plan_id
question_id
user_id
domain_id
metric_ids
template_ids
params_json
access_status
data_quality_required
status
created_at
`access_status`:
allowed
blocked_by_domain
blocked_by_metric
blocked_by_dimension
needs_approval
Проверка: запрос не выполняется, если `access_status` не `allowed`.
Шаг 21. Выполняйте только безопасные query_templates
В n8n добавьте Code-узел перед SQL/BI API:
const template = $json.template;
const params = $json.params;
for (const key of Object.keys(params)) {
if (!template.allowed_params.includes(key)) {
throw new Error(`Param not allowed: ${key}`);
}
}
if (params.date_to < params.date_from) {
throw new Error('Invalid date range');
}
return [{ json: { template_id: template.template_id, params } }];
Проверка: пользовательский текст не попадает в SQL напрямую.
Шаг 22. Создайте query_results
В `query_results` добавьте колонки:
result_id
plan_id
template_id
metric_id
period_start
period_end
result_json
row_count
source_url
created_at
Проверка: `row_count` не больше `max_rows_per_query`.
Шаг 23. Создайте data_quality_checks
В `data_quality_checks` добавьте колонки:
check_id
result_id
dataset_id
check_type
status
evidence
severity
created_at
Проверяйте:
- dataset обновлен;
- нет пустого периода;
- нет резкого падения row_count;
- нет дублей;
- нет отрицательных значений там, где они запрещены;
- denominator не равен нулю;
- timezone корректный;
- период сравнения одинаковый.
Проверка: если data quality failed, агент не дает уверенный вывод.
Шаг 24. Создайте anomaly_log
В `anomaly_log` добавьте колонки:
anomaly_id
metric_id
domain_id
period
value
baseline_value
change_percent
severity
evidence
status
created_at
`severity`:
low
medium
high
critical
Проверка: аномалия создается только по рассчитанным данным и baseline.
Шаг 25. Настройте prompt для объяснения результата
Prompt:
Ты BI-аналитик. Объясни результат пользователю.
Правила:
1. Отделяй факт от гипотезы.
2. Покажи период, метрику и источник.
3. Не делай выводов, если data_quality failed.
4. Не называй причину без evidence.
5. Если данных мало, скажи, что нужна проверка аналитика.
6. Не показывай строки с персональными данными.
question:
{{$json.question}}
query_results:
{{$json.results}}
data_quality:
{{$json.data_quality}}
metric_catalog:
{{$json.metrics}}
Верни JSON:
{
"status": "answered | needs_data | needs_analyst",
"answer": "...",
"facts": ["..."],
"hypotheses": ["..."],
"source_links": ["..."],
"recommended_actions": ["..."]
}
Проверка: ответ содержит источник и не смешивает facts с hypotheses.
Шаг 26. Создайте metric_explanations
В `metric_explanations` добавьте колонки:
explanation_id
question_id
result_id
answer_text
facts
hypotheses
source_links
status
created_at
Проверка: если `source_links` пустой, ответ не показывается как подтвержденный.
Шаг 27. Создайте insight_queue
В `insight_queue` добавьте колонки:
insight_id
domain_id
metric_id
topic
observation
hypothesis
evidence
confidence
recommended_action
status
created_at
`confidence`:
high
medium
low
needs_data
Проверка: insight с `needs_data` не отправляется руководителю как вывод.
Шаг 28. Создайте analytics_task_queue
В `analytics_task_queue` добавьте колонки:
task_id
source
source_id
task_type
title
description
priority
owner
status
created_at
`task_type`:
check_data_quality
confirm_metric_formula
build_dashboard
review_anomaly
create_report
fix_access
clarify_question
Проверка: задача имеет владельца и конкретный следующий шаг.
Шаг 29. Создайте approval_queue
В `approval_queue` добавьте колонки:
approval_id
source
source_id
action_type
action_text
risk_level
payload_json
approver
status
requested_at
approved_at
decision_comment
В approval отправляйте:
- новый KPI;
- изменение формулы;
- выгрузку персональных данных;
- доступ к новому домену;
- отправку отчета наружу;
- создание dashboard;
- изменение dashboard;
- управленческий вывод high impact;
- задачу команде без уверенного evidence;
- запуск тяжелого SQL.
Проверка: `approval_queue.status` не может сразу быть `approved`.
Шаг 30. Сделайте Telegram approval
В n8n добавьте Telegram-узел после записи в `approval_queue`.
Сообщение:
BI Agent approval
Action: {{$json.action_type}}
Risk: {{$json.risk_level}}
Source: {{$json.source}} {{$json.source_id}}
{{$json.action_text}}
Approve: /approve {{$json.approval_id}}
Reject: /reject {{$json.approval_id}}
Review: /review {{$json.approval_id}}
Проверка: команда `/approve` меняет только одну строку по `approval_id`.
Шаг 31. Создайте execution_queue
В `execution_queue` добавьте колонки:
execution_id
approval_id
action_type
payload_json
status
executor
started_at
finished_at
result_url
error_message
В первой версии используйте `executor=manual`.
Проверка: агент не создает dashboard и не отправляет внешний отчет сам.
Шаг 32. Создайте report_snapshots
В `report_snapshots` добавьте колонки:
snapshot_id
dashboard_id
domain_id
period
metrics_json
data_quality_status
source_url
created_at
Проверка: report snapshot хранит период и ссылку на BI-источник.
Шаг 33. Создайте weekly_bi_report
В `weekly_bi_report` добавьте колонки:
report_id
domain_id
period
summary
key_changes
anomalies
data_quality_issues
open_questions
next_week_actions
status
created_at
Пример summary:
За неделю выручка выросла на 12% к прошлой неделе, но win rate снизился с 28% до 22%. Data quality ok, refresh без задержек. Главная гипотеза: рост лидов из нового канала снизил среднее качество pipeline. На следующей неделе проверить конверсию по источникам и причины проигрыша.
Проверка: отчет содержит не только цифры, но и next actions.
Шаг 34. Настройте audit_log
В `audit_log` добавьте колонки:
audit_id
run_id
actor
action
entity_type
entity_id
before_json
after_json
reason
created_at
Логируйте:
- вопрос пользователя;
- проверку доступа;
- выбор метрики;
- выбор query template;
- выполнение запроса;
- data quality check;
- объяснение результата;
- создание insight;
- отправку в approval;
- weekly report.
Проверка: по `audit_log` можно восстановить, почему агент дал конкретный ответ.
Шаг 35. Настройте error_log
В `error_log` добавьте колонки:
error_id
run_id
node_name
error_type
message
payload_sample
retry_count
status
created_at
Типы ошибок:
access_denied
metric_not_found
template_not_found
bi_api_error
sql_error
data_quality_failed
invalid_json
pii_blocked
refresh_stale
Проверка: access denied и data quality failed не маскируются под обычный ответ.
Шаг 36. Протестируйте на одном вопросе
Добавьте вопрос:
Q-001 | USR-001 | DOM-SALES | Почему выручка за неделю просела? | 2026-05-16..2026-05-23 | new | 2026-05-23
Добавьте метрику `MET-REVENUE`, шаблон `QT-REVENUE-BY-DAY`, dashboard `DASH-SALES-MAIN` и тестовый результат.
Ожидаемый результат:
- в `query_plan` есть метрика и template;
- `access_status=allowed`;
- в `query_results` есть период и source URL;
- `data_quality_checks` прошли;
- в `metric_explanations` есть facts и hypotheses отдельно;
- в `insight_queue` есть вывод с evidence;
- в `audit_log` есть все шаги;
- в `error_log` нет ошибок.
Шаг 37. Проверьте негативные сценарии
Проведите проверки:
- задайте вопрос по домену без доступа;
- убедитесь, что ответ `blocked_by_access`;
- попросите выгрузить клиентов с email;
- убедитесь, что создано `pii_blocked`;
- попросите метрику, которой нет в каталоге;
- убедитесь, что создана задача `confirm_metric_formula`;
- передайте stale dataset;
- убедитесь, что data quality failed;
- попробуйте произвольный SQL;
- убедитесь, что он заблокирован;
- передайте невалидный JSON от LLM;
- убедитесь, что workflow остановился и записал `invalid_json`.
Проверка: BI-агент должен быть полезным аналитиком, но не обходить права и утвержденные формулы.
Что нельзя автоматизировать в первой версии
Не автоматизируйте сразу:
- произвольный SQL;
- запись в warehouse;
- создание новых KPI;
- изменение формул;
- изменение dashboards;
- массовые выгрузки;
- персональные данные;
- внешнюю отправку отчетов;
- изменение refresh schedule;
- управленческие решения без review;
- выдачу данных вне прав пользователя;
- удаление datasets и reports.
Минимальный хороший MVP: агент отвечает на 5-10 типовых вопросов по утвержденным метрикам, проверяет права, выполняет только allowlist query templates, делает data quality check, показывает источник цифры и пишет audit log.
Частые вопросы
Что лучше подключить первым: BI API или прямой SQL?
Если в BI уже есть semantic layer и утвержденные dashboards, начните с BI API. Прямой SQL полезен позже, но только через query templates, права, лимиты и data quality checks.
Может ли агент сам придумывать KPI?
Нет. Он может предложить новый KPI как идею и отправить ее в `approval_queue`, но считать и использовать KPI можно только после добавления в `metric_catalog`.
Как защитить данные от лишнего доступа?
Проверяйте `analytics_users`, `access_rules`, домен, dataset, метрику и измерения до выполнения запроса. Если пользователь не видит dashboard в BI, агент не должен пересказывать эти данные.
Почему LLM не должна считать метрики?
LLM может объяснять и формулировать гипотезы, но расчеты должны делать SQL, BI или код. Иначе невозможно проверить denominator, фильтры, период, timezone и версию данных.
Что считать готовым результатом MVP?
MVP готов, если агент по одному домену отвечает на типовые вопросы, показывает источники, не нарушает права, не выполняет свободный SQL, фиксирует data quality и оставляет понятный `audit_log`.