Personal Chief of Staff (MVP)

A multi-agent Chief of Staff: a LangGraph orchestrator coordinates Email, Calendar, Task, Research, and Memory agents to produce a daily Morning Briefing β€” top priorities, why they matter, risks to watch, and recommended next actions β€” with human approval required before any consequential action (sending an email, modifying your calendar) actually happens.

See docs/Multi_Agent_Personal_Chief_of_Staff_MVP_Requirements.pdf and docs/Personal_Chief_of_Staff_Architectural_Considerations_v2.pdf for the full requirements and architecture this implementation follows.

Architecture at a glance

  • Backend: FastAPI + LangGraph (Python), SQLite for structured data + a brute-force cosine-similarity embedding store for semantic memory recall.
  • Model gateway: all agents call a single interface (app/models/gateway.py) backed by LiteLLM. MODEL_PROVIDER (.env) switches between OpenAI (default, gpt-5-nano), Claude (Anthropic API), and a local Ollama model (qwen2.5:7b-instruct). No agent code calls the provider directly β€” swapping providers means changing .env/the gateway, not the agents.
  • Frontend: React + Vite (TypeScript) β€” Morning Briefing, Approvals queue, Ask (chat), and Settings (memory + connection status).
  • Integrations: real Gmail, Google Calendar, and Google Tasks via OAuth; DuckDuckGo web search (no API key) for the Research Agent.
  • Policy: app/policy/guardrails.py is deterministic, non-LLM code that decides which action kinds require human approval. Read actions run automatically; sending email, modifying calendar events, or writing tasks always create a pending approval first.
  • Observability: LangSmith tracing (optional) to monitor agent performance, debug issues, and track token usage across all API calls. See LANGSMITH_SETUP.md.

This MVP intentionally skips Docker/CI, Postgres/pgvector, and formal observability tooling (OpenTelemetry/Phoenix) called out in the architecture doc as later upgrades β€” SQLite and basic logging are sufficient to prove the MVP locally.

Prerequisites

  1. Python 3.14 and Node.js 24+ (already verified on this machine).
  2. A model provider β€” set MODEL_PROVIDER in backend/.env:
    • openai (default): set OPENAI_API_KEY in backend/.env (get a key at platform.openai.com/api-keys). Uses gpt-5-nano by default β€” OpenAI's cheapest current tier, well suited to this app's short structured-output calls.
    • claude: set ANTHROPIC_API_KEY in backend/.env (get a key at console.anthropic.com).
    • ollama: run Ollama locally with a model pulled:
      ollama pull qwen2.5:7b-instruct
      
      Verify it's reachable: curl http://localhost:11434/api/tags
  3. Google Cloud OAuth credentials (see below) β€” required for real Gmail/Calendar/Tasks access. Without this, the app still runs and the briefing gracefully degrades (shows a "source unavailable" notice instead of crashing).

Google Cloud OAuth setup (one-time)

  1. Go to console.cloud.google.com and create a new project (or select an existing one).
  2. Go to APIs & Services β†’ Library and enable these three APIs:
    • Gmail API
    • Google Calendar API
    • Tasks API
  3. Go to APIs & Services β†’ OAuth consent screen. Choose External (unless you have a Workspace org), fill in the required fields (app name, your email), and add yourself as a test user. You don't need to submit for verification for personal/local use.
  4. Go to APIs & Services β†’ Credentials β†’ Create Credentials β†’ OAuth client ID.
    • Application type: Desktop app
    • Name it anything (e.g. "Chief of Staff MVP")
  5. Download the resulting JSON and save it as:
    backend/data/credentials.json
    
  6. The first time the backend needs Google access, it opens a local browser window for you to sign in and grant access (or trigger it manually via Settings β†’ Connect Google account in the app, or POST http://localhost:8000/status/google/authorize). A token is then cached at backend/data/token.json and refreshed automatically.

Scopes requested: gmail.readonly, gmail.send, calendar.readonly, calendar.events, tasks. Reads never require approval; the send/events/tasks write scopes are only exercised after you approve a specific proposed action in the Approvals page.

Running it

Backend

cd backend
python -m venv venv
./venv/Scripts/pip install -r requirements.txt   # Windows; use venv/bin/pip on macOS/Linux
cp .env.example .env                              # adjust if needed
./venv/Scripts/uvicorn app.main:app --reload --port 8000

Frontend

cd frontend
npm install
npm run dev

Open the printed local URL (typically http://localhost:5173).

Tests

cd backend
./venv/Scripts/pytest tests/ -v

The suite covers all 12 MVP acceptance requirements with fixture data β€” no live Ollama, Google, or network access needed to run it.

Using the app

  1. Morning Briefing (/) β€” today's top 3 priorities with explanations, risks to watch, and a plain-language summary. Refresh any time.
  2. Approvals (/approvals) β€” anything consequential the Chief of Staff wants to do (e.g. reply to an email) waits here. You see exactly what will happen before approving or denying; nothing is sent/changed until you click Approve.
  3. Ask (/chat) β€” ask an ad hoc question. Check "needs current external information" to route the request through the Research Agent (web search) instead of your inbox/calendar.
  4. Settings (/settings) β€” connect your Google account, check whether the configured model provider is reachable, and inspect/add/delete stored goals & preferences. A new explicit preference supersedes the previous one of the same kind.

Known MVP-scope trims

  • No Docker/CI pipeline yet β€” run both servers locally as shown above.
  • SQLite instead of Postgres+pgvector β€” fine at personal-use data volumes; swappable later.
  • No OpenTelemetry/Phoenix tracing β€” structured logging only.
  • No formal WCAG audit β€” semantic HTML, keyboard navigation, and visible focus states are followed as baseline practice in the React UI.
Downloads last month

-

Downloads are not tracked for this model. How to track
Inference Providers NEW
This model isn't deployed by any Inference Provider. πŸ™‹ Ask for provider support