Skip to main content

ADR-0206: Navin Enterprise Meeting Intelligence Agent, authorized capture and meeting intelligence above the Control Plane

  • Status: proposed (2026-11-05)
  • Deciders: Navin Enterprise AI platform team, brief 02 mission (agent_uses_cases/tel_note_meeting/02_NAVIN_AGENT_MEETING_EQUIVALENT_LEEXI.md)
  • References: ADR-0176 (UC-00 model whose generic modules are copied), ADR-0177 (rule of the agents: never a second installation of a shared service), ADR-0173 (telephony platform Asterisk, Kamailio, LiveKit), ADR-0205 (Notes product, destination of pages and tasks), ADR-0101 (licence policy), product conventions navin-enterprise-meeting/CONVENTIONS.md, OPA package eai.meetings (deploy/policies/opa/meetings.rego, tests meetings_test.rego, key meetings of deploy/policies/opa/data.json), OpenFGA fragment deploy/policies/openfga/products/meetings.fga (+ meetings.tests.fga.yaml, meetings.tuples.yaml), Manager card navin-meeting-agent (navin-manager/agent-templates/navin-meeting-agent.yaml, status planned until the Service Template is built, never published without an explicit decision of the customer).

Context​

Brief 02 asks for a meeting intelligence agent for the teams of one tenant: authorized capture of meetings (video conferencing, in person, telephony), calendar and participants, media processing, transcription, diarization, summaries, decisions and action items, meeting library, sourced questions and answers, clips and sharing, follow ups, CRM synchronization, multi meeting reports and coaching. The functional target is parity with the usages of a Leexi like tool; nothing proprietary is copied: no code, no model, no brand, and no parity is announced until a real test proves it (section 28 of the brief). The product never records without the legal basis and the consent state its mode requires, never bypasses a waiting room or a recording policy of a provider, and every read, search, export, clip, share, live session and background job re-checks permissions server side (sections 7, 19 and 26 of the brief).

Decision​

  1. Separate product navin-enterprise-meeting/ (product id meeting, sector cross_industry) with its own Next.js 16
    • React 19 + MUI 9 frontend (transcript studio, synchronized player, live interface) instead of the shared shell of ADR-0180; no root product.manifest.json. FastAPI backend navin_meeting (hatchling, Python 3.12, same pins as UC-00), PostgreSQL schema meeting with RLS forced through meeting.current_tenant() / meeting.current_project(), roles navin_meeting_migrate, navin_meeting_app (no BYPASSRLS) and navin_meeting_worker, Alembic with named revisions, Redis prefixed meeting:{instance_id}:.
  2. Reuse of the shared services of the Control Plane through the enterprise_ai SDK, never a second copy: the media store (upload, ClamAV/YARA-X scan, classification, encryption at rest), speech to text (faster-whisper or an OpenAI compatible endpoint through LiteLLM, word timestamps, DLP on transcripts), diarization (pyannote 3.1 when installed and the Hugging Face token of the customer is configured), LiveKit rooms and the realtime voice protocol (tokens checked server side, consent rows), the connector broker (short lived credentials for Google, Microsoft Graph, Zoom, Webex, CRM and task tools, refresh tokens in OpenBao), the channels of the tenant (email, chat) for follow ups, LiteLLM for the LLM and embeddings, Qdrant/Cognee for the semantic index, the Notes API as destination of pages and tasks. Telephony recordings are imported by reference from client.telephony, never recorded a second time. Only the pure VAD logic (Silero ONNX, MIT) is embedded in the worker, which must run without the Control Plane package; ffmpeg/ffprobe are system binaries called as processes, never linked nor bundled.
  3. Honest provider matrix (section 8 of the conventions), exposed by the API and the UI with its status planned|implemented|tested|partial|blocked and its reason: livekit (native bot participant, one track per participant hence verified speaker attribution) and in_person (browser capture) aim at tested; jitsi is partial (no headless participant without a browser, Jibri import when configured); google_meet, teams, zoom and webex are partial for the import of cloud recordings after the meeting and blocked for the live bot (no approved bot framework delivered); telephony is tested with a fake. A denial by the provider (lobby, locked room, policy) is a typed error and a FAILED attempt with its reason.
  4. Consent modes carried by the instance and decided by OPA before any recording: explicit_all (every known participant granted), host_declares (a host_declared event logged), announce_only (an announced event logged); denied when the adapter reports recording_method = none, denied under legal hold, consent log, logged pause and resume, "recording on" indication in the UI.
  5. Two layer authorization through the Control Plane: OpenFGA for relations (meeting_instance, meeting_library, meeting, meeting_clip, meeting_report, meeting_template; the backend only checks the can_* relations; can_export = can_view but not guest; can_record = host or owner; the viewer: user:* of a clip is written only by the sharing service) and OPA eai.meetings for the decisions above the relations: recording start (consent, method, legal hold), auto join (external event denied without a rule), external and link sharing (domain, classification, guest), export (legal hold for media, guest, format), clips, CRM write (approval, allowed connector), follow up (approval and checked recipients), task assignment to an external participant (always denied), retranscription and permanent deletion (legal hold, retention), retention change (roles), AI indexing (restricted denied unless the instance allows it, secret always denied), individual scorecard (sales manager or the person scored). Fail closed, sorted reasons, every decision audited.
  6. Evidence based AI: every summary, decision, action item, answer and score cites the transcript segments it comes from; a guessed speaker name is never shown as verified; the model neither decides nor executes: CRM writes, task sync and email sending are proposals approved by a human and announced only after the confirmation of the destination API; transcript text is untrusted data (prompt injection) and is never logged.
  7. Legal hold and retention per tenant, project and type: a legal hold freezes recording, retranscription, clips, media export and permanent deletion; the semantic index is fed only after the ACL snapshot is taken and never for restricted meetings without the authorization of the instance.
  8. Manager integration through six components runtime, migrate, backend, worker, live, web (dedicated strategy, service navin-meeting-agent), development ports web 3490, API 8490, worker health 8491, live 8492, Redis 6410. The registry card stays planned then prepared / published: false; artifacts are pending until really built.

Consequences​

  • The product depends on the availability and quotas of the multimodal, realtime, connectors and channels domains of the Control Plane; in exchange it hosts no STT model, no diarization, no connector secret, and benefits from the same controls (antivirus, DLP, audit, kill switch).
  • The provider matrix shows partial and blocked statuses: parity with a universal bot is not promised; importing cloud recordings after the meeting is the realistic path for Google Meet, Teams, Zoom and Webex.
  • Every new sensitive action goes through a can_* relation and an eai.meetings decision; an action missing from the policy is refused (unknown_action).
  • The live process is one more component to supervise (health, metrics, WebSocket sessions); the consistency of PostgreSQL + media store is verified by the restore test.
  • The card stays absent from the catalog until an explicit validation is given.

Security​

  • Identity and delegation: the bot and the workers carry a workload identity and the delegation context of the user, never a raw password; LiveKit tokens are checked server side, development defaults are refused in production; identity never comes from the browser.
  • Threats of section 26 of the brief covered by denial tests: malicious invitation and unauthorized auto join (OPA rule meetings.join.auto), spoofed webhook (verification by the connector broker), link leak (meetings.share.link denied for classified content, short signed URLs), malicious media payload (media store scan), prompt injection in the transcript (untrusted content, tools checked against the permissions of the caller), cross tenant retrieval (RLS and ACL filters of the index), synthetic speaker attribution (never shown as verified), unauthorized CRM write (mandatory approval).
  • Append only audit of every decision and side effect; DLP mask on exports; legal hold and retention enforced by the policy and by the deletion jobs.

Alternatives considered​

  • STT and diarization models embedded in the product: rejected (ADR-0177); the Control Plane already provides them with DLP, quotas and audit, and a second copy of the weights would double the maintenance and licence surface.
  • Universal bot joining any video conference through a headless browser: rejected; it bypasses the approved frameworks of the providers and their recording policies; the product delivers a native LiveKit bot, cloud recording import and browser capture, and shows blocked where no approved framework exists.
  • Grafana, Loki and Tempo for observability: refused, AGPL licence (ADR-0101); Prometheus, Alloy, OpenSearch, Jaeger and Opik are used.
  • A second semantic index owned by the product: rejected, Qdrant/Cognee through the Control Plane stay the only source with ACL filters.
  • Shared frontend shell of ADR-0180: rejected, a transcript studio synchronized with the media cannot be described by a shell driven manifest.

Open questions​

  • Zoom Meeting SDK app: required for a live Zoom bot, not delivered; decision of the customer on publishing an app in their Zoom account.
  • Teams bot registration (Azure Bot Service, Graph application permissions): out of scope until the tenant grants the permissions; only the import of Graph recordings and transcripts is planned.
  • Gated pyannote weights: the customer must accept them on their Hugging Face account and configure EAI_HF_TOKEN on the Control Plane; without it diarization is unavailable and the per track LiveKit attribution stays the only verified attribution.
  • Jibri for Jitsi: capture is possible only if the customer runs Jibri and exposes the recordings directory or the finalize webhook; manual upload otherwise.
  • Brief: agent_uses_cases/tel_note_meeting/02_NAVIN_AGENT_MEETING_EQUIVALENT_LEEXI.md (sections 2, 7, 19, 26)
  • Conventions: navin-enterprise-meeting/CONVENTIONS.md
  • Policies: deploy/policies/openfga/products/meetings.fga, deploy/policies/opa/meetings.rego
  • Card: navin-manager/agent-templates/navin-meeting-agent.yaml
  • French version: docs/architecture/ADRs/ADR-0206-navin-enterprise-meeting-agent.md