Building Custom Tracing Tools and Development Infrastructure for AI-Powered Meeting Notes
granola · Tech · 2026 · source Agentic: yes · promotional bias: med · source-backed · extracted with prompt 0.5.5 (schema v2)
Generated from extraction.json — do not edit by hand. Every claim cites verbatim source evidence; stated means the quote directly asserts the claim, implied means it supports it indirectly.
Problem
Domain: AI-powered meeting notes and development tooling
Granola needed to ship LLM-based meeting notes and chat features without treating the model as a black box. Real users exposed web-search cost spikes, provider regressions, role-specific output expectations, and desktop-app testing friction. The team needed internal observability for tool calls, reasoning, and cost, plus a faster way to preview and test AI feature variants despite shipping an Electron app.
Constraints:
- Granola's desktop app can normally run only one instance at a time, making parallel feature testing hard.
- Web search can inflate context and cost enough to become infeasible at millions-of-users scale.
- Provider-side model or web-search updates can degrade behavior overnight outside Granola's control.
- Different user roles need different summaries, action items, and integrations, so one generic prompt cannot serve everyone.
- The tracing interface needed to work for product, data, customer experience, founders, and engineers, not just backend developers querying logs.
Architecture
Granola built custom tracing around its LLM features and separately turned the Electron renderer into a web-deployable shell. The tracing layer wraps the AI SDK, records tool calls, search and reasoning steps, and costs to a database, and exposes a purpose-built frontend so internal users can inspect an agent loop from start to finish without CloudWatch queries. The development-infrastructure layer abstracts Electron IPC/system APIs to fall back to web standards, adapts React routing/session/query layers for web execution, and deploys the renderer online. CI creates a preview link for each PR, and Cursor tests the preview and uploads screenshots to the pull request, allowing multiple variants to be experienced in practice before shipping.
Diagram confidence: reconstructed (reconstructed from prose).
flowchart LR granola-desktop-app[Granola desktop app] --> audio-capture[Audio capture] granola-desktop-app --> manual-notes[Manual notes] granola-desktop-app --> llm-meeting-summary[LLM meeting summary] granola-desktop-app --> chat-feature[Chat feature] granola-desktop-app --> electron-main-process[Electron main process] granola-desktop-app --> electron-render-process[Electron render process] audio-capture --> real-time-transcription[Real-time transcription] real-time-transcription --> llm-meeting-summary real-time-transcription --> chat-feature manual-notes --> llm-meeting-summary llm-meeting-summary --> tracing-wrapper[Tracing wrapper] chat-feature --> web-search-tool[Web search tool] chat-feature --> tracing-wrapper tracing-wrapper --> trace-database[Trace database] trace-database --> trace-ui[Trace UI] trace-ui --> internal-reviewers[Internal reviewers] electron-main-process --> ipc-abstraction[IPC abstraction] electron-render-process --> ipc-abstraction electron-render-process --> web-shell[Web shell] ipc-abstraction --> web-standards-adapters[Web standards adapters] web-shell --> ci-preview-deployment[CI preview deployment] web-shell --> cursor-test-agent[Cursor test agent] cursor-test-agent --> pull-request[Pull request]
Components
| Component | Role | Interacts with |
|---|---|---|
Granola desktop app |
Electron meeting-notes application installed on the user's dock. | Audio capture, Manual notes, LLM meeting summary, Chat feature, Electron main process, Electron render process |
Audio capture |
System and microphone audio capture feeding real-time transcription. | Real-time transcription |
Real-time transcription |
Meeting transcript generated from audio and combined with user notes. | LLM meeting summary, Chat feature |
Manual notes |
User-written notes that steer the final generated summary toward what the user would naturally write. | LLM meeting summary |
LLM meeting summary |
LLM feature that generates meeting notes from transcript and manual annotations. | Tracing wrapper |
Chat feature |
LLM chat feature for asking questions about current, past, or shared meeting context. | Web search tool, Tracing wrapper |
Web search tool |
External search capability whose cost, context impact, and provider behavior need monitoring. | — |
Tracing wrapper |
Internal instrumentation layer around AI SDK that captures tool calls, reasoning, search, and cost. | Trace database |
Trace database |
Storage for structured trace events used by internal debugging UI. | Trace UI |
Trace UI |
Purpose-built frontend for employees to follow agent loops and diagnose failures. | Internal reviewers |
Internal reviewers |
Engineers, product managers, data analysts, CX, and founders who use traces for debugging. | — |
Electron main process |
Electron process that works with system APIs. | IPC abstraction |
Electron render process |
Frontend process that Granola made agnostic to Electron so it can run as a web app. | IPC abstraction, Web shell |
IPC abstraction |
Platform abstraction that falls back to web standards outside Electron. | Web standards adapters |
Web standards adapters |
Adapted routing, sessions, and query-layer behavior for browser execution. | — |
Web shell |
Deployed web version of the Electron frontend used for previews and testing. | CI preview deployment, Cursor test agent |
CI preview deployment |
Continuous integration path that creates preview links for pull requests. | — |
Cursor test agent |
AI-assisted testing step that opens PR previews, tests changes, and uploads screenshots. | Pull request |
Pull request |
Code review artifact containing preview link and AI-generated test screenshots. | — |
Data flow
During a meeting, Granola captures system audio and microphone audio, produces real-time transcription, and lets users add manual notes. At summary or chat time, the LLM feature may call tools such as web search and reason over meeting context. The tracing wrapper around the AI SDK stores each tool call, reason, search action, and cost in a trace database. Internal users open the trace UI to follow the agent loop from beginning to end and identify the exact failure point. For development, a pull request triggers CI to deploy the Electron renderer as a web shell; reviewers and an AI testing agent open the preview, exercise the change, and attach screenshots back to the PR.
4 supporting quotes
Why this architecture
Granola chose custom tracing because generic logs and SaaS observability did not match how product, data, CX, founders, and engineers needed to inspect LLM behavior. Owning the trace schema and UI let them move from vague output complaints to exact failure points in agent loops. The web-shell architecture solved a different bottleneck: Electron made variant testing and coworker review slow, while deploying the renderer as a web app gave Granola web-style preview links and made AI-assisted self-verification practical on every PR.
4 supporting quotes
Models used: LLMs · AI SDK · Cursor
Scale
- A complex web-search chat can cost about 10 pence.“each chat could be costing you like 10 pence.”transcript, stated
- At millions of users, those per-chat search costs become infeasible.“at scale when you have millions of users, this is not really feasible.”transcript, stated
- Granola wanted to test one feature in four different variants for different users.“one feature looking very different in four different users.”transcript, stated
- The desktop architecture normally allowed only one app instance at a time.“you can only run one instance of the app at a time.”transcript, stated
- Every PR can get a CI preview link.“whenever we open a PR, we get a preview link”transcript, stated
- Electron's architecture was described as two processes.“there's obviously a main process and a render process.”transcript, stated
Alternatives considered (roads not taken)
Use generic SaaS tracing or CloudWatch queries.
Rejected because: The team wanted a trace schema and UI that matched its own employees' debugging workflows rather than requiring complex log queries.
Treat web search as a one-line LLM tool.
Rejected because: Web search introduced token blowups, costs, provider behavior changes, and loss of control that affected user experience.
Keep Electron-only local testing.
Rejected because: Local Electron setup required dependencies and blocked quick coworker testing, parallel variants, and web-style preview links.
Re-platform from Electron to Tauri.
Rejected because: Granola had tried Tauri and discussed it, but did not see the performance gains they cared about.
Patterns
observability-tracing (operations)
Granola records the full LLM interaction lifecycle, including tool calls, reasons, search use, and costs, then exposes it through an internal trace UI.
tool-use-orchestration (architecture)
The chat feature uses tools such as web search, and tracing makes tool-call behavior inspectable so the team can debug provider and workflow failures.
cost-aware-routing (operations)
Granola treats web-search token growth and per-chat cost as first-class trace data because provider tools can make chat interactions economically infeasible at scale.
eval-driven-development (evaluation)
The web-shell preview flow lets humans and Cursor test AI-feature changes in practice on every PR before release.
feedback-loop-iteration (operations)
Granola emphasizes tracing and preview infrastructure as feedback loops for iterating with LLMs rather than relying on one-shot prompts.
Tradeoffs
Build custom tracing tools.
Chose A purpose-built trace schema and UI wrapped around AI SDK over Generic SaaS tracing or CloudWatch-based debugging.
Rationale: Custom tooling required some engineering work, but LLM-assisted development made it feasible and gave Granola exactly the trace structure and UI its internal teams needed.
Wrap AI SDK and save traces to a database.
Chose A basic internal implementation with custom frontend emphasis over Waiting for a sophisticated observability platform to cover the exact use case.
Rationale: The most important part was the frontend people used for diagnosis; the backend trace capture could remain simple.
Turn the Electron renderer into a web shell.
Chose Abstract IPC and React platform concerns to web standards over Keeping all testing inside the installed desktop app.
Rationale: This allowed browser previews, parallel variant testing, and AI-assisted PR screenshots without abandoning the Electron product.
Stay with Electron rather than ship Tauri.
Chose Electron plus renderer/web-shell abstraction over Re-platforming to Tauri.
Rationale: The team had tried Tauri and discussed it, but did not see the performance gains it cared about.
Gotchas (what bit them)
A one-shot chat implementation breaks down with real user requests.
Root cause: Users ask for web search, personalized emails, coaching, cross-meeting context, and role-specific outputs that a generic chatbot was not designed to handle.
Resolution: Granola built tracing to understand exact failures and iterated toward use-case-specific behavior.
3 supporting quotes
Provider-managed web search can change underneath the product.
Root cause: LLM provider updates can degrade search behavior without exposing enough detail for the application team to diagnose or control.
Resolution: Granola built internal tracing and kept provider switching/control visible rather than treating web search as a black box.
Generic summaries do not satisfy every role.
Root cause: Sales, engineering, and HR users look for different information structures and downstream actions.
Resolution: Granola uses tracing and iteration to customize behavior instead of assuming one prompt can cover every role.
CloudWatch and generic logs were too high-friction for broad debugging.
Root cause: Non-engineering internal users need to inspect LLM failures, but complex log queries block product, data, CX, and founder workflows.
Resolution: Granola built a custom trace UI structured for internal users.
Electron app testing made AI-feature variants slow to validate.
Root cause: The desktop app could only run one instance, and local testing required dependencies and setup for each reviewer.
Resolution: Granola made the renderer Electron-agnostic, deployed it as a web shell, and generated PR preview links.
3 supporting quotes
Evaluation
Granola evaluates AI features through internal trace inspection, role-specific output debugging, PR preview deployments, AI-assisted screenshot testing, and hands-on variant testing in the web shell. The aim is to identify exact LLM/tool failure points and validate user experience before release.
Metrics: Tool-call sequence visibility · Reasoning/tool-call explanations · Search tool usage · Cost per interaction · Context blowup from web search · PR preview availability · AI-generated screenshot feedback · Variant testing across feature designs · Internal user ability to pinpoint exact failure
3 supporting quotes
Outcomes
- Granola gained complete internal visibility into LLM tool calls, reasons, search use, and costs
- non-engineering internal users could inspect failures without CloudWatch queries
- the founder could follow agent loops front-to-back to pinpoint failures
- the Electron frontend could run as a web app for PR preview links
- Cursor could test pull requests and upload screenshots
- the team could test multiple feature variants in practice before shipping
The case mentions each complex web-search chat costing about 10 pence, millions-of-users infeasibility, one feature appearing differently for four users, one-instance desktop app constraints, preview links on every PR, and Electron's main/render two-process architecture.