Skip to content

yiouli/pixie-for-pm

Repository files navigation

pixie-for-pm

pixie-for-pm is a Discord-triggered, LangGraph-orchestrated product collaboration system with a companion settings surface for managing external integrations per Discord server. The repository now includes the Discord bot, a FastAPI settings API, and a React/Vite frontend that is built into web/dist and served by FastAPI.

Agents

Pixie keeps five internal agent roles:

  • dispatcher
  • product manager
  • market analyst
  • user researcher
  • product designer

The dispatcher is the sole user-entry routing agent. It sends relevant work to a specialist, defaults ambiguous requests to the product manager, and rejects clearly out-of-scope requests directly. The product manager now runs as a handoff-aware Deep Agents controller backed by an OpenAI chat model. For the retention demo flow, it routes the initial question to the user researcher, returns with three hypotheses, and on a follow-up deep dive it drafts a Lenny Rachitsky-style PRD before handing design execution to the product designer. The user researcher also runs as a LangGraph-backed deep agent, requires an active Notion connection, reads product and research context from Notion, follows the interview synthesis handbook workflow, and writes tagging plus synthesis artifacts back to Notion. The product designer now runs as a deep agent for PM handoffs and uses Vercel when available for clickable prototype work. The market analyst still uses a placeholder handler.

Discord exposes a single public bot identity. Users start work by mentioning the bot or replying to a prior bot message. LangGraph can still hand work across internal agents, but those handoffs are not rendered as separate Discord personas or synthetic in-channel messages.

Architecture

The package layout follows explicit boundaries:

pixie_for_pm/
  agents/          # product manager deep agent, placeholder handlers, registry
  config/          # environment loading
  discord/         # routing, bot mention normalization, bot transport shell
  domain/          # typed workflow models shared across layers
  integrations/    # provider registry and credential access helpers
  orchestration/   # LangGraph workflow and runtime
  web/             # FastAPI settings API, auth, routes, encryption
  py.typed

tests/
  pixie_for_pm/    # mirrored unit coverage for config, Discord, web, orchestration

web/
  src/             # React + Vite settings UI source
  dist/            # built SPA served by FastAPI

specs/
  architecture.md  # architecture notes and extension points
  integration-config.md

changelogs/
  initial-scaffold.md

The runtime flow is:

  1. Discord receives a message trigger through a direct mention or reply to a prior bot message.
  2. The Discord adapter normalizes the trigger into a typed dispatch request.
  3. Routing enters the dispatcher entrypoint while preserving whether the trigger came from a direct mention or reply.
  4. The orchestrator resolves the guild-scoped integration connections, expands them into a typed LangGraph tool bundle for the turn, and keeps those live tool objects out of checkpoint state.
  5. LangGraph invokes the dispatcher first, then any internal specialists it needs, and persists checkpoint state to SQLite.
  6. Internal handoffs stay inside the orchestration graph instead of being emitted as Discord messages.
  7. Handoff reasons can carry private working context between internal agents, so PM-led subflows can pass research findings, PRDs, and prototype summaries without exposing them in the public reply.
  8. The Discord adapter reacts with :eyes:, uses an editable placeholder reply for visible progress states such as Thinking and tool fetches, keeps Discord's native typing indicator active while the turn runs, and replaces the placeholder with either the final public response or an explicit error state.
  9. Slash-command interaction responses remain limited to /settings and other configuration flows.

The Discord install flow is:

  1. A user opens / on the FastAPI-hosted web app.
  2. The install page links to /api/discord/install.
  3. FastAPI redirects the browser to Discord's callback-less bot authorization URL with bot applications.commands and the minimum permissions needed for the current e2e loop.
  4. The installer chooses the Discord server in Discord's own authorize UI.
  5. After authorization, the user runs /settings inside that server to enter the authenticated settings flow.

The integration settings flow is:

  1. A Discord user runs /settings in a guild where the bot is installed.
  2. The bot replies with an ephemeral link to /settings?server_id=<guild-id> on the FastAPI-hosted web app.
  3. FastAPI serves the built SPA from web/dist, and the browser loads the settings UI from the same origin as the API.
  4. The settings UI establishes a Discord-backed session, claims the Discord server for the current app user, and loads the guild name/icon for the workspace header when Discord returns them.
  5. The FastAPI server stores encrypted connection credentials in the shared connection store.
  6. The bot initializes a request-scoped integration toolset from that shared store, keyed by Discord server ID, before each LangGraph dispatch.

Persistence

LangGraph persistence is enabled through AsyncSqliteSaver. The checkpoint database path is configured with LANGGRAPH_CHECKPOINT_PATH, which defaults in the example environment to .state/pixie-langgraph.sqlite.

Discord Bot Surface

Pixie uses one installed Discord bot identity for all public communication.

  • inbound triggers are direct bot mentions and replies to prior bot-authored messages
  • internal LangGraph handoffs remain private to the orchestration layer
  • mention- and reply-triggered turns acknowledge receipt immediately with an :eyes: reaction and an editable progress reply while LangGraph runs
  • plain follow-up messages inside a thread continue the conversation once the bot has already participated in that thread
  • startup clears stale global slash commands before syncing guild copies so Discord does not show duplicate entries
  • slash-command status updates should use deferred interaction replies and edits instead of agent-to-agent Discord messages

Local Setup

uv sync
cp .env.example .env
uv run pytest
uv run mypy .
uv run ruff check .
uv run pixie

To run the settings UI locally:

cd web
npm install
npm run build

For active web development, run the frontend build in watch mode in one terminal and the combined backend in another:

cd web
npm install
npm run watch
uv run pixie-web-server

Or run the full local runtime, including the Discord bot, with:

uv run pixie

Open http://localhost:8000. FastAPI serves the latest files from web/dist, so refreshing the page picks up each watched rebuild. npm run dev is no longer the default local workflow for this repo.

The root page at http://localhost:8000/ is the install surface for the Discord bot. The installer now chooses the target server in Discord's authorize UI instead of Pixie preselecting one.

The bot no longer relies on any configured Discord channel. It reacts only when explicitly addressed: a direct bot mention or a reply to a previous bot message.

Create web/.env from web/.env.example. Leave VITE_API_URL empty to use the same origin as FastAPI, or set it explicitly only when the frontend should call a different API host.

The bot entrypoint expects a populated .env file or equivalent environment variables. The product manager and user researcher runtimes require OPENAI_API_KEY, and currently share PRODUCT_MANAGER_MODEL when set or openai:gpt-5.4 by default.

Connected integrations now initialize automatically from the stored server-scoped credentials. Pixie loads live hosted MCP tools for Notion, GitHub, and PostHog at dispatch time, uses direct API-backed tools for Airtable and Fireflies when no hosted MCP server is available, and uses the Vercel REST API (authenticated with a personal access token) to publish prototype deployments. There is no extra *_MCP_SERVER_* enablement configuration.

The settings API expects session and encryption keys plus OAuth client credentials. Supabase remains optional; when it is not configured, both the web app and bot default to the shared local SQLite store at CONNECTION_STORE_SQLITE_PATH so local end-to-end flows work across a single combined process or separate processes.

For Vercel, deploy the ASGI app exposed at api/index.py. That deployment surface serves FastAPI and the built SPA, but it intentionally does not start the long-lived Discord gateway client.

To validate the browser-visible install flow locally, run:

cd web
npm run test:e2e -- tests/e2e/install.spec.ts

For a full manual Discord verification flow, including Discord app setup, bot invite, channel configuration, and message-by-message e2e checks, see docs/discord-e2e.md.

Current Scope

This scaffold now covers the first integration-management slice:

  • Discord transport handles direct bot mentions, replies to bot-authored messages, and the /settings slash command.
  • FastAPI exposes the bot install page/redirect, settings, claim, connection, OAuth callback, and internal credential routes.
  • Credentials are encrypted before storage and decrypted only on the internal server-to-server path.
  • The web frontend provides the initial settings UX for OAuth and API-key providers.
  • Connected provider tools now resolve automatically from hosted MCP servers or direct provider APIs using the stored connection credentials.
  • Notion now uses the MCP-specific OAuth discovery and client-registration flow. Existing Notion connections created before this change should be disconnected and reconnected once so the runtime stores MCP-compatible tokens.
  • The dispatcher now chooses the initial specialist, defaults ambiguous work to the product manager, and rejects out-of-scope requests directly.
  • The product manager path now runs through a handoff-aware Deep Agents controller with an OpenAI model.
  • The user researcher path now runs through LangGraph Deep Agents, requires Notion as the research source of truth, follows the handbook synthesis workflow, and writes tagging plus synthesis outputs back to Notion.
  • The product designer path now runs through Deep Agents for PM handoffs and uses Vercel when available for clickable prototype work.
  • The market analyst still uses placeholder business logic.
  • Each Discord-triggered turn now gets a typed integration tool bundle that can be passed directly to LangGraph agents as tools.

See specs/architecture.md, specs/integration-config.md, and specs/agent-runtime-tooling.md for the implementation outline and extension points.

About

Team of AI agents focused on figuring out what to build

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors