ReleaseCode / SDK · ActionableHabr AI→ original

Bot running anonymous Chrome in Docker recorded 1,170 meetings and delivers summaries in 4.6 minutes

A Habr author built an internal meeting bot as an alternative to Copilot. In four months, it recorded about 1,170 meetings and 920 hours of speech from 93 organizers. The median time from the end of a recording to a summary with action items is 4.6 minutes. Recognition and speaker diarization run on the company's own servers, so audio never leaves its perimeter. There are two pipelines: a bot installed in a team for Teams channel meetings, and anonymous Chrome running in a container for everything else.

AI-processed from Habr AI; edited by Hamidun News
Bot running anonymous Chrome in Docker recorded 1,170 meetings and delivers summaries in 4.6 minutes
Source: Habr AI. Collage: Hamidun News.
Listen to article
Article Fact Sheet & Key Figures
ParameterDetails
Primary sourceHabr AI ↗
Editor-in-Chief
Key metric #1Native Teams transcription for Russian loses two-thirds of the text: 26–37 words per minute versus 99–108
Key metric #2Names from Teams VTT files combined with diarization assign the correct name to 94–99% of segments
Key metric #3Graph API cannot see on-prem Exchange, so the calendar had to be read through EWS

Meeting decisions tend to survive only until the next meeting. Nobody keeps minutes, and a week later participants remember about 10% of what was said. The second problem is newer: the company uses AI agents, but they know only what has been recorded and indexed. Anything decided verbally does not exist for them. The author of the Habr article set out to close both gaps with a custom meeting assistant and shared production figures.

Why not Copilot or native transcription

Copilot works only for people with a subscription, which makes it unsuitable for automating the process across every team without manual intervention. It also does not cover external tenants, Telemost, MTS Link, or TrueConf. In addition, the company wanted audio from client meetings to be processed on its own servers.

The author was also dissatisfied with Teams' native Russian transcription. For the same meetings, it produced 26–37 words per minute, while normal business speech runs at about 100 and the author's pipeline delivered 99–108. Teams also renders technical terms phonetically, writing “add button” as “ed batton.” The sample is small, and the author candidly describes the comparison as a reference point rather than a benchmark.

Two pipelines instead of one

A universal solution proved impractical because Teams meetings come in two forms.

Channel meetings—dailies, planning sessions, and retrospectives—are recorded automatically under company policy and stored in SharePoint. They do not have a conventional group chat: messages live in a thread beneath the channel's root post, and anonymous guests cannot enter it. A bot is therefore installed in the team. It reads the channel and catches the CallRecording service event with a Success status. It downloads the MP4, converts it to 16 kHz WAV, sends it for recognition, and publishes the summary in the meeting thread. This requires the ChannelMessage.Read.Group RSC permission, granted by the team owner without an administrator granting access across the entire tenant.

All other meetings are handled by “Meeting Assistant.” It is added to the invitation like a regular participant, and anonymous Chrome running in Docker joins when the meeting begins. Recording occurs only with explicit consent: if the assistant was invited and admitted, it records; otherwise, it does not. The pipelines are physically separated, with their own registrations, applications, and permissions, so a leaked key from one cannot compromise the other.

Pitfalls worth remembering

Recording race condition. State was initially stored in JSON files, and during the first week the listener and a fallback cron job submitted the same recording twice. The fix was Postgres with INSERT … ON CONFLICT DO NOTHING and SELECT … FOR UPDATE; the claim operation returns one of four modes: new, retake, attach, or skip.

Transcript dead ends. The ChannelMeetingTranscript.Read.Group RSC permission returned 403, SharePoint rejected an app-only token without a certificate, and Graph's onlineMeetings/transcripts endpoint requires an application access policy for the organizer. The pipeline is therefore built around MP4 files and in-house recognition, with Teams VTT used as an auxiliary source.

Speaker names. The number of speakers—the num_speakers hint—and their names come from the VTT file. Segments are then matched to diarization clusters by time lag. Across three manually checked meetings, 94–99% of segments received the correct name. Any failed match is labeled “Anonymous”: a wrongly attributed line is worse than an anonymous one.

Graph API also cannot see the calendar in on-prem Exchange, so the developers had to use EWS. The browser-based poster's session would silently expire because of a session cookie, while the active-speaker detector captured only a quarter of the speech until the implementation switched from events to state polling.

What this means in practice

If you are building something similar, the conclusion is straightforward. Do not try to cover every platform with one solution: Teams channel meetings are cheaper to handle with a bot installed in the team, while everything else is better served by joining the conversation. Store state in a database with locking, not in files. Tailor summary prompts to the meeting type—daily, retrospective, or planning—and load them for every submission so they can be edited without a restart. Most importantly, transcripts indexed by the platform give agents a memory of decisions made verbally. That is the foundation for proactive agents.

There are limitations. Pipeline 1 does not support private channels; in external meetings, someone must admit the bot from the lobby; and Teams itself has bugs that can cause the bot to stop receiving channel updates (msteams-docs issue #11106). The figures also come from a single company and have not been independently verified, but four months in production with 93 organizers is compelling evidence.

Story

Key Questions Answered

Why not Copilot or native transcription?

Copilot works only for people with a subscription, which makes it unsuitable for automating the process across every team without manual intervention. It also does not cover external tenants, Telemost, MTS Link, or TrueConf. In addition, the company wanted audio from client meetings to be processed on its own servers. The author was also dissatisfied with Teams' native Russian transcription.

What are the key details on Two pipelines instead of one?

A universal solution proved impractical because Teams meetings come in two forms. Channel meetings—dailies, planning sessions, and retrospectives—are recorded automatically under company policy and stored in SharePoint. They do not have a conventional group chat: messages live in a thread beneath the channel's root post, and anonymous guests cannot enter it. A bot is therefore installed in the team. It reads the channel and catches the CallRecording service event with a Success status.

What are the key details on Pitfalls worth remembering?

Recording race condition. State was initially stored in JSON files, and during the first week the listener and a fallback cron job submitted the same recording twice. The fix was Postgres with INSERT … ON CONFLICT DO NOTHING and SELECT … FOR UPDATE; the claim operation returns one of four modes: new, retake, attach, or skip. Transcript dead ends.

ZK
Zhemal Khamidun — CPO at Alpina Digital, product manager of AlpinaGPT. Building AI products since 2019. Hamidun News is a pet project that grew into a production aggregator with 6,000+ readers.
✦ Hands-On AI Engineering · Hamidun Academy

Build & Ship Production AI Agents Without Boilerplate Code

Start your free 72-hour trial at Hamidun Academy (academy.hamidun.com) — interactive lessons on Claude Code & Cursor, live Tech Radar, and production agent templates.

Start 72h Free Trial →Vibe-Coding Intensive
What do you think?
Loading comments…