Skip to main content
Glama
README.md
# pm-agents

A multi-agent product-management copilot that automates a PM's operating rhythm: morning briefings, metrics answers, grounded knowledge lookups over an Obsidian vault, and PRD/ticket drafting — each a specialised backend agent with real integrations and hard guardrails.

Built and used daily by a working product manager. Runs locally on Windows against a Claude subscription (no per-token API billing) by driving the logged-in `claude` CLI in print mode, with tools exposed as a local stdio MCP server.

## Agents

A single-agent orchestrator (all tools) plus four specialists:

| Specialist | Does | External creds |
|-----------|------|----------------|
| `knowledge` | Vault Q&A grounded in a local RAG index; guarded note upkeep | none (local only) |
| `metrics` | PostHog + Jira analytics, anomaly/OKR watch (read-only) | PostHog, Jira |
| `briefing` | Morning briefing + EOD dump written into the daily notes | Jira, Slack, Notion, PostHog, Gmail |
| `prd_ticket` | Draft + create PRDs (Notion) and Jira tickets, on confirmation | Notion, Jira |

## Architecture notes

- **Print-mode + MCP, not the streaming SDK.** The Agent SDK's streaming stdio transport does not complete its control handshake with the native `claude.exe` on Windows (verified: hangs on initialize). `claude -p` works reliably, so the runner drives that directly and exposes the Python tools via `--mcp-config` pointing at `pm_agents.mcp_server`. Pragmatism over purity.
- **Allowlist-only tool execution.** Tools are pre-approved through an explicit `--allowedTools` allowlist plus `--strict-mcp-config` — no blanket permission bypass. Each specialist gets the minimum tool set for its job.
- **Guardrails in code, not prompts** (`pm_agents/guardrails.py`): production-database references are hard-blocked by regex before any tool executes; write operations require explicit confirmation. The model is never trusted to self-police.
- **Grounded-only answers.** The knowledge agent must quote retrieved chunks; if retrieval returns nothing it says so instead of improvising.
- **One agent, one prompt file.** Each agent's behaviour lives in a single markdown file under `pm_agents/prompts/` — reviewable, diffable, no prompt spaghetti.
- **Scheduling:** Windows Task Scheduler entries (`scripts/schedule_tasks.ps1`) drive the morning/EOD/weekly runs.

## Setup

```bash
python -m venv .venv && .venv/Scripts/activate
pip install -r requirements.txt
cp .env.example .env   # fill in your own tokens — nothing is committed
python scripts/smoke_test.py
```

## Layout

```
pm_agents/
  agents/          # the four specialists
  integrations/    # jira, notion, slack, gmail, posthog clients (thin, typed)
  prompts/         # one behaviour file per agent
  tools/           # vault + RAG tools
  guardrails.py    # hard safety checks (prod-DB block, allowlists)
  mcp_server.py    # stdio MCP server exposing the tools
scripts/           # entrypoints: morning brief, EOD, weekly, chat, diagnostics
```