# Meeting Notes в Action Items: проверяемый AI-workflow

> Как превратить meeting notes в проверенные action items, не выдавая предложения и догадки модели за реальные обязательства команды.
> Author: Roman Belov · Published: 2026-08-14 · Source: https://futurecraft.pro/ru/blog/meeting-notes-actions/

В транскрипте встречи легко встретить три похожие фразы:

- «Я опубликую checklist к среде».
- «Мы могли бы переделать экран импорта на следующей неделе».
- «Кому-то надо посмотреть на ошибки импорта».

Полноценное обязательство есть только в первой. Слабый промпт превращает в задачи все
три фразы, назначает ответственного в третьей и сам выбирает дату во второй. В трекере
становится аккуратно, но он уже не отражает договорённости команды.

Безопасный workflow не просит LLM «сделать summary и создать задачи». Транскрипция,
extraction, validation, review и запись в tracker должны быть отдельными этапами. У
каждого этапа — небольшой контракт и видимая ошибка.

## Весь workflow на одной схеме

![Синтетический транскрипт создаёт восемь candidates; validation принимает два и отклоняет шесть с явными reason codes](/artifacts/meeting-action-validation/meeting-action-validation-2026-08-27.svg)

Схема построена из
[публичного TypeScript fixture](/ru/artifacts/meeting-action-validation/). В нём нет
вызовов внешних API: только синтетический транскрипт, candidates и проверяемый
validator. Двадцать тестов покрывают evidence gates, некорректный input, сохранённый
JSON, SVG и лицензии.

Production pipeline выглядит так:

```text
recording
  → timestamped transcript
  → candidate decisions and actions
  → deterministic validation
  → human review
  → task tracker and notifications
```

Не объединяйте review и запись. Именно эта граница не даёт убедительному, но неверному
ответу модели превратиться во внешнее действие.

## Сначала контракты, потом выбор инструментов

Провайдера можно заменить. Контракты данных останутся.

| Этап | Обязательный input | Output | Какая ошибка должна быть видна |
|---|---|---|---|
| Capture | разрешение на запись, meeting ID | ссылка на audio или video | нет согласия или записи |
| Transcribe | запись | сегменты со спикерами и временем | плохой или отсутствующий звук |
| Extract | transcript segments | candidates с цитатами | сломанный или неполный output |
| Validate | candidates, transcript, participants | принятые и отклонённые items | reason code для каждого отказа |
| Review | candidates с evidence | approve, edit или reject | reviewer и время решения |
| Write | подтверждённые items | task IDs и notification IDs | API error или duplicate attempt |

Минимальный action candidate:

```json
{
  "id": "candidate-02",
  "title": "Export the failed-import sample",
  "owner": "Jon",
  "dueDate": "2026-09-03",
  "commitmentStatus": "accepted",
  "evidenceQuote": "I will export the failed-import sample by 2026-09-03",
  "sourceSegmentId": "segment-02"
}
```

Цитата здесь не для красоты. Это короткий путь от предлагаемой задачи к фрагменту,
который должен её подтверждать.

## Этап 0: разрешение, retention и доступ

В записи и транскрипте могут быть имена, данные клиентов, коммерческие условия,
медицинская информация или произнесённые вслух credentials. Правила обработки нужно
определить до подключения transcription service или LLM.

Минимальный checklist:

1. Сообщить участникам, когда включается запись или автоматический конспект.
2. Зафиксировать цель обработки и применимое правовое основание.
3. Установить retention для записи, транскрипта, model input и review log.
4. Ограничить доступ людьми и сервисами, которым он действительно нужен.
5. Удалять секреты и лишние персональные данные до отправки в модель.
6. Дать возможность исправить запись и снять ошибочно назначенную задачу.

Точные требования зависят от страны и контекста. Это инженерный checklist, а не
юридическая консультация. Для чувствительных встреч согласуйте запись с ответственным
за privacy или compliance.

## Этап 1: транскрипт, который можно проверить

Сплошной текст неудобен для разбора ошибок. Нужны стабильные segment IDs, timestamps и
speaker labels:

```json
{
  "id": "segment-02",
  "speaker": "speaker-1",
  "startMs": 7100,
  "endMs": 13900,
  "text": "I will export the failed-import sample by 2026-09-03."
}
```

В [model card Whisper](https://github.com/openai/whisper/blob/main/model-card.md)
описаны speech recognition и translation, но там же сказано, что качество зависит от
языка и систему нужно проверять в своём домене. Whisper не даёт подтверждённое
соответствие голоса конкретному человеку. Если attribution важен, тестируйте его
отдельно.

Некоторые сервисы возвращают diarization labels. Например,
[документация Deepgram](https://developers.deepgram.com/docs/diarization) описывает
word-level поле `speaker` и различия между batch и streaming. Но `speaker-0` и
`speaker-1` — это всё ещё условные метки, а не «Майя» и «Джон». Сопоставляйте их по
явному представлению, meeting metadata или через review.

Сохраняйте исходные сегменты. Если назначение задачи оспорят, понадобится оригинальная
фраза с временем, а не только гладкий summary.

## Этап 2: извлекаем candidates, а не готовые задачи

Extraction должен формировать предложения для review. Рабочая основа инструкции:

```text
Извлекай только явные решения и обязательства.
Не придумывай owner и deadline.
Предложения и неясные формулировки классифицируй отдельно.
Копируй короткую подтверждающую цитату из одного source segment.
Возвращай structured output по заданной схеме.
Если поля нет, оставь его пустым.
```

Structured output уменьшает число ошибок парсинга, но не делает содержание истинным.
Модель может вернуть идеальный JSON с придуманной цитатой. Schema — начало validation,
а не её замена.

Длинную встречу можно обрабатывать перекрывающимися группами segments. Сохраняйте их
IDs и объединяйте candidates после extraction. Не делайте предварительный summary
каждого chunk: повторное сжатие убирает формулировки, по которым «я сделаю» отличается
от «мы могли бы».

## Этап 3: сверяем каждый candidate с записью

Публичный fixture применяет пять gates:

1. **Evidence:** нормализованная цитата есть в транскрипте.
2. **Source:** цитата находится в заявленном segment, а не в другом месте.
3. **Owner:** имя совпадает с известным участником.
4. **Deadline и status:** дата существует, а фраза является принятым обязательством.
5. **Deduplication:** одинаковое сочетание title, owner и date встречается один раз.

В проверенный синтетический run поступило восемь candidates. Два прошли validation,
шесть были отклонены:

| Проблема | Reason code |
|---|---|
| предложение выдано за обязательство | `not_explicit_commitment` |
| цитаты нет в транскрипте | `evidence_not_found` |
| owner отсутствует среди участников | `owner_unknown` |
| невозможная календарная дата | `deadline_invalid` |
| повторная задача | `duplicate` |
| реальная цитата привязана не к тому segment | `source_segment_mismatch` |

[Manifest, исходники, тесты и команды запуска](/ru/artifacts/meeting-action-validation/)
доступны публично. Код лицензирован по MIT, checklist и evidence — по CC BY 4.0.

Fixture доказывает поведение validator на заданном синтетическом input. Он не измеряет
качество speech recognition, extraction recall или precision модели. Для этого нужен
репрезентативный и размеченный людьми evaluation set из ваших типов встреч.

## Этап 4: review, которым действительно будут пользоваться

На review screen показывайте по одному candidate:

- предложенные title, owner и due date;
- source quote и соседний контекст транскрипта;
- ссылку на audio в нужном timestamp, если это разрешено policy;
- validation warnings;
- approve, edit, reject и «это не обязательство».

Записывайте reviewer, решение, время и изменения. Corrections нужны не только для
аудита: из них получается evaluation set для следующей версии extractor.

Не пытайтесь превратить каждую сущность в task. Решение может уйти в decision log,
открытый вопрос — в agenda, предложение — остаться предложением. Одна task schema не
подходит для всей речи на встрече.

Подробнее о границах подтверждения — в статье про
[human-in-the-loop для AI agents](/ru/blog/human-in-the-loop/).

## Этап 5: запись в tracker как отдельный side effect

До tracker доходят только подтверждённые items. Writer должен иметь:

- service identity с минимальными правами;
- server-side credentials из environment или secret store;
- idempotency key, например `meetingId + candidateId + destination`;
- постоянное соответствие этого ключа созданному task ID;
- retry, который сначала проверяет это соответствие;
- error queue вместо тихого падения.

Linear предоставляет GraphQL API и отдельно предупреждает: нужно проверять массив
`errors`, даже если HTTP response равен 200. Используйте актуальную
[документацию Linear API](https://linear.app/developers/graphql), а не mutation из
старой статьи.

Для уведомлений метод Slack
[`chat.postMessage`](https://api.slack.com/methods/chat.postMessage) требует destination
и подходящие scopes. При использовании Block Kit добавляйте понятный top-level `text`
для notifications и screen readers. В канал достаточно отправить ссылку на задачу и
источник; не нужно копировать туда весь транскрипт.

Модель не должна получать tracker token или выбирать credential scope. Авторизация
инструментов остаётся в application code. OWASP называет передачу непроверенного
model output во внешние системы
[improper output handling](https://genai.owasp.org/llmrisk/llm052025-improper-output-handling/),
а в рекомендациях по
[excessive agency](https://genai.owasp.org/llmrisk/llm062025-excessive-agency/)
советует human approval и least privilege для значимых действий.

## Метрики без выдуманной истории успеха

Начните с операционных показателей, а не с обещанного процента экономии:

- **candidate acceptance rate:** доля одобренных без изменений;
- **correction rate:** доля items, где reviewer поменял owner, date или формулировку;
- **unsupported-candidate rate:** отказы из-за отсутствующей evidence или неверного segment;
- **duplicate prevention count:** сколько валидных дублей остановлено до записи;
- **write failure rate:** сколько подтверждённых items не попало в tracker;
- **review latency:** время от готового транскрипта до решения;
- **action correction rate:** сколько созданных задач исправили из-за ошибки в meeting record.

Разделяйте показатели по типу встречи, языку, конфигурации transcription и версии
extractor. Sales call, engineering incident и weekly planning используют разную лексику
и имеют разный риск.

Соберите размеченный evaluation set из встреч, которые разрешено использовать. Добавьте
явные обязательства, отклонённые предложения, сарказм, перебивания, неоднозначные имена,
пропущенные даты и переключение языков. Версионируйте set отдельно от production
prompts и прогоняйте его перед каждым изменением системы.

## Безопасный порядок внедрения

1. **Review-only.** Система предлагает candidates, команда сравнивает их с ручными notes.
2. **Evidence validation.** Обязательны quotes, source segments, owners и dates.
3. **Shadow writes.** Payload создаётся, но tracker API ещё не вызывается.
4. **Ограниченная запись.** Одна команда подтверждает задачи в один project.
5. **Расширение.** Scope растёт только после анализа corrections и failures.

Если review queue постоянно игнорируют, не обходите её. Уменьшите число candidates,
покажите evidence понятнее или сузьте workflow до явных обязательств. Неиспользуемый
approval step — продуктовая проблема, а не разрешение убрать safety boundary.

## Чего этот workflow не решает

- Transcription может ошибиться в имени, числе или дате.
- Diarization может перепутать участников.
- Произнесённое обязательство может быть неуместным или неавторизованным.
- Реальная цитата может потерять меняющий смысл контекст.
- Reviewer тоже способен одобрить неверный item.
- Task tracker не гарантирует выполнение работы.

Цель — не идеальная автоматическая память. Нужен прослеживаемый путь от произнесённой
фразы к предлагаемому action item, где человеку хватает evidence и контроля, чтобы
решить, должна ли такая задача существовать.
