Skip to main content

Kara: AI Meeting Agent

A real-time meeting-capture product across web, iOS and Android that acts on meetings end to end, from live capture to automated follow-up.

  • Agent Workstream Lead
  • Agent Architecture
  • Guard Rails & Evaluation
  • 3

    enterprise customers

  • 4

    connected systems

  • 2,785

    automated tests

  • 95%

    of the agent service's commits

An agent that works inside meetings

Kara records a meeting, then does the work that follows: searches past meetings and uploaded documents, reads the note on screen, keeps a contact book and to-dos, looks up Google Calendar and Drive, and queries a real-estate CRM. It is now used by three enterprise customers: two banks and a real-estate group.

I led the agent workstream and wrote 95% of the agent service's commits. My slice: the agent service with its tool and guard layer, memory, the knowledge-graph service behind it, the document search service, the Google Calendar connector, the real-estate platform integration, and the quality loop that keeps it honest. The service has 2,785 automated tests.

Kara: app to agent service, tool interceptor, confirmation gate and MCP servers, with a trace-driven eval loopKara appWeb · iOS · AndroidBackend hubforwards chat, screen contextAgent service · FastAPI · SSEContext nodememory · knowledge indexExecute nodeReAct tool loopPostgrescheckpointsrewind unsafe turnsMemoryMem0 on QdrantRedis cacheTool interceptorinjects user & workspace scope · drops model IDshides injected params · opaque ID aliases (Redis)fail-closed on unknown IDs · egress filterUser confirmation gatewrites only · a human yesMCP serversInternal toolsmeetings · documentscontacts · to-dosConnectorGoogle Calendar · Drivestateless, token per callReal-estate CRMplatform MCPintegrationPartner bank CRMSalesforceintegrationBehind the internal toolsDocument searchdense + sparse, RRFon QdrantKnowledge graphper-user · to-do foldingFalkorDBLangfuse traces · eval loopAI Agent Evaluations: role-played scenarios vs baselineHill climbing: daily prod traces → draft merge request
Every tool call passes one server-side interceptor. Writes then pass a user confirmation gate before they reach any connected system.

Three nodes, one tool loop

The assistant is a small graph, not a single prompt: fetch context, then run a tool-calling loop, then end. Tools are served over MCP and every call is routed through the interceptor rather than straight to a backend, so reads and writes follow the same rules.

  • Three-node graphLangGraph runs context, then a ReAct tool loop. Streamed to clients over FastAPI SSE.
  • Postgres checkpointsEvery turn is checkpointed, so a blocked or unsafe turn can be rewound.
  • RedisCaches and the opaque-ID alias ledger.
  • Mem0 on QdrantLong-term memory, admitted through a judge.
  • Document searchDense and sparse retrieval fused with reciprocal rank fusion on Qdrant, in a service I built.
  • LLM gateway and LangfuseAll model calls go through a gateway. Every request is traced, and prompts are managed live.

The model never holds the keys

The interceptor treats the model as an untrusted caller. A prompt, or a hallucination, must never be able to read or write another user's data, so the controls live in server code. I treat hallucinated identifiers as a grounding problem in the architecture, not a thinking problem, so the ID-alias layer removes every identifier the model could invent.

  • Scope injectionThe interceptor sets user, workspace and note scope on the tools that need it, and discards any identifier the model supplies.
  • Hidden parametersInjected parameters are removed from the schema the model sees, so there is nothing for it to fill in.
  • Opaque aliasesInternal IDs never reach the model. It sees short aliases from a per-session ledger, and an unknown ID is rejected.
  • Egress filterID-shaped tokens in the final answer that are not in the ledger are redacted before the user sees them.

Writes need a human yes

The agent proposes and the user decides. Each kind of write has its own confirmation pattern, and connector tokens are never stored in prompts, memory or logs.

  • ContactsSaving a contact returns a confirmation request until the user explicitly agrees. Duplicates are caught first.
  • To-dosThe agent previews the list, the user confirms, and only then are items created. Stale previews are rejected.
  • Screen editsEdits to the note on screen are proposal cards. The agent has no write path; the user taps Apply.
  • Write-state ledgerEach write is marked committed, not sent or unknown, so a write that may have landed is never re-sent.

Memory that forgets on purpose

Conversations are checkpointed in Postgres, and a rolling summary trims long threads. Long-term memory is gated: a judge admits only durable facts the user stated, and each one must be traceable to the user's own words. When an input guardrail blocks a turn, the thread rewinds to the checkpoint before it, leaving no trace. When a streamed answer turns out unsafe, the stored answer is overwritten.

Quality from production

Two loops, both built around Langfuse traces. AI Agent Evaluations has an agent role-play users against the dev environment, judges the resulting traces and compares them with a baseline. A hill-climbing technique reads production traces daily, read-only, screens them cheaply, has an LLM triage the flagged ones, and proposes fixes in tiers. Every proposal ends at a draft merge request that a human reviews.

Four connected systems

The connector layer is stateless: the user's token arrives with each call and is discarded after it. It exposes both REST and MCP entry points.

  • Google CalendarCalendar access through a connector module I built.
  • Google DriveFile lookup through the same connector layer.
  • Real-estate CRM platformSearch and write-back through an MCP integration I led.
  • Partner bank's Salesforce CRMRetrieval and write-back for a banking customer.

Also in my slice

A per-user knowledge graph that links meetings and folds to-dos together, contact insight generated from meeting history, screen-context editing, LLM-gateway routing, live prompt management in Langfuse, and prompts ordered to keep the model's prefix cache warm.

Tech stack

  • Python
  • FastAPI
  • LangGraph
  • MCP
  • FastMCP
  • Postgres
  • Redis
  • Qdrant
  • Mem0
  • FalkorDB
  • Gemini
  • Langfuse
  • SSE
  • pytest
  • Docker
  • Kubernetes
  • GitOps