Skip to content

Repository files navigation

Event Organizer

Event Organizer is moving to an agent-first operating model.

The product direction is:

  • /agent is the primary authenticated workspace
  • Modal is the execution authority for all agent logic and guardrails
  • Convex stores product state, thread history, artifacts, and approvals
  • Attio remains the CRM system of record for identity and speaker workflow
  • Discord is a second client of the same agent runtime, not a separate automation path

Architecture

The system is split into three layers:

Layer Responsibility
fe+convex/ Next.js app surfaces, Convex queries/mutations, authenticated UI for /agent and dashboard drill-downs
agent/ Modal-hosted agent runtime, MCP adapters, Attio/Convex integration helpers, Anthropic Agent SDK harness
Attio + Convex Persistent business state: Attio for CRM truth, Convex for application state and agent interaction history

Current MVP Direction

The active MVP is the agent-first workspace:

  • add a full-page /agent surface
  • route all agent execution through Modal endpoints
  • use Anthropic Agent SDK inside Modal as the agent harness
  • keep Next.js and Discord thin clients
  • preserve existing dashboard pages as precise drill-down tools
  • prune unrelated engineering from the MVP backlog

For the authoritative product and data-contract details, read:

  • PLAN.md for system contracts and ownership
  • AGENTS.md for operator/runtime rules
  • IMPLEMENTATION.md for the parallel execution plan
  • DESIGN.md for shared dashboard and monochrome UI guidance
  • WORK_ATTRIBUTION.md for contribution attribution based on closed GitHub pull requests

Repository Layout

event_organizer/
├── fe+convex/              # Next.js 16 app + Convex functions
├── agent/                  # Modal runtime, Attio helpers, MCP server, tests
├── PLAN.md                 # Architecture and data-contract source of truth
├── AGENTS.md               # Operator and runtime integration guide
├── IMPLEMENTATION.md       # Implementation workstreams and dependency plan
├── DESIGN.md               # Frontend layout and design-system rules
└── WORK_ATTRIBUTION.md     # Closed-PR contribution attribution record

Prerequisites

Install these before starting local development:

Tool Install
Node.js 20+ brew install node
Bun curl -fsSL https://bun.sh/install | bash
Python 3.11+ brew install python@3.11
uv curl -LsSf https://astral.sh/uv/install.sh | sh
Doppler CLI brew install dopplerhq/cli/doppler
Modal CLI python -m pip install modal

Secrets

Secrets are managed through Doppler. Do not create repo-local .env files.

One-time setup:

doppler login
cd /Users/sean_lai/event_organizer
doppler setup

Useful validation:

doppler secrets

Local Development

Most work needs three terminals.

1. Convex

cd /Users/sean_lai/event_organizer/fe+convex
doppler run -- npx convex dev

2. Next.js

cd /Users/sean_lai/event_organizer/fe+convex
doppler run -- bun dev

The web app runs at http://localhost:3000.

3. Modal / Agent Runtime

Install Python dependencies:

cd /Users/sean_lai/event_organizer/agent
uv sync

Run the packaged local MCP server if you are working on tool adapters:

cd /Users/sean_lai/event_organizer/agent
doppler run -- uv run python -m apps.mcp.server

Inspect MCP tools interactively:

cd /Users/sean_lai/event_organizer/agent
doppler run -- npx @modelcontextprotocol/inspector uv run python -m apps.mcp.server

The Modal runtime starts that same MCP server over stdio through the Claude agent SDK. The current tool surface is:

  • Attio people (identity only): search_people, get_person, upsert_person, append_person_note
  • Attio speakers (workflow): search_speakers, get_speaker, ensure_speaker_for_person, update_speaker_workflow
  • Compatibility read aliases: search_contacts, get_contact
  • Convex reads: list_events, get_event, get_event_inbound_status, get_event_outreach, get_attendance_dashboard, get_event_attendance, get_event_room_booking
  • Approval-gated Convex writes: create_event, update_event_safe
  • OnceHub live reads: find_oncehub_slots (Leslie eLab Lean/Launchpad, always live)
  • Approval-gated OnceHub writes: book_oncehub_room (booking under the shared club profile; upserts event_room_bookings and stickies events.room_confirmed)

Deploy or serve Modal functions from the agent/ package as needed for runtime work.

Environment Variables

These live in Doppler.

Variable Used by Description
ATTIO_API_KEY agent/ Attio API token
BETTER_AUTH_URL fe+convex/ Auth base URL
BETTER_AUTH_SECRET fe+convex/ Better Auth signing secret
CONVEX_DEPLOYMENT fe+convex/ Convex deployment URL
NEXT_PUBLIC_CONVEX_URL fe+convex/ Browser Convex URL
NEXT_PUBLIC_MODAL_ENDPOINT fe+convex/ Base URL used by Next route handlers to proxy /api/agent/* requests to the Modal runtime
CONVEX_URL agent/ Convex HTTP endpoint for Modal-side access
CONVEX_DEPLOY_KEY agent/ Convex deploy key for server-side mutations
ANTHROPIC_API_KEY agent/ Anthropic API key for the Modal runtime
MODAL_TOKEN_ID agent/ Modal auth
MODAL_TOKEN_SECRET agent/ Modal auth
EVENT_ORGANIZER_CONFIG_PATH agent/ Optional path to a mounted YAML config file; defaults to agent/config.yaml
ONCEHUB_PAGE_URL agent/ Optional emergency override for oncehub.page_url
ONCEHUB_ROOM_LABEL agent/ Optional emergency override for oncehub.room_label

OnceHub uses the internal browser API (no API key required). The runtime reads page, room, and shared club booking-profile settings from agent/config.yaml, so Modal does not need one environment variable per identity field. ONCEHUB_PAGE_URL and ONCEHUB_ROOM_LABEL remain small emergency overrides for rotations, but the normal production path is to edit or mount the YAML file. Before book_oncehub_room sends a real booking request, the runtime validates that required identity fields are no longer blank or FILL_IN placeholders.

YAML path Required? What to fill
oncehub.page_url Yes OnceHub booking page URL, e.g. https://go.oncehub.com/NYULeslie.
oncehub.room_label Yes Pinned room label; current default is Lean/Launchpad.
oncehub.booking_profile.first_name Yes First name for the shared club booking identity.
oncehub.booking_profile.last_name Yes Last name for the shared club booking identity.
oncehub.booking_profile.email Yes NYU email address that should receive or own booking correspondence.
oncehub.booking_profile.net_id Yes NetID associated with the booking identity.
oncehub.booking_profile.organization Yes Club or organization name shown on the room request.
oncehub.booking_profile.graduation_year Yes Graduation year value expected by the OnceHub form.
oncehub.booking_profile.location Yes Event location value; current default is 16 Washington Place.
oncehub.booking_profile.affiliation_id Yes OnceHub dropdown id; current default 457707 means Undergrad.
oncehub.booking_profile.school_id Yes OnceHub dropdown id; current default 453247 means Tandon.
oncehub.booking_profile.event_name No Optional default event-name field; if blank or placeholder, runtime uses the requested event title.
oncehub.booking_profile.pronouns_id No Optional pronouns dropdown id; leave blank to skip.

subject and num_attendees are supplied by the booking request at runtime, so those defaults are retained only for local/template readability.

Testing

Frontend:

cd /Users/sean_lai/event_organizer/fe+convex
doppler run -- bun run lint

Agent runtime:

cd /Users/sean_lai/event_organizer/agent
doppler run -- uv run pytest tests -v

Convex schema/codegen refresh:

cd /Users/sean_lai/event_organizer/fe+convex
doppler run -- npx convex dev --once

Working Rules

  • Keep agent orchestration logic on the Modal side.
  • Do not move tool policy or guardrails into Next.js or Discord handlers.
  • Do not write speaker workflow state onto Attio people.
  • Keep dashboard UI monochrome and consistent with DESIGN.md.
  • If PLAN.md changes in a way that affects runtime behavior, update AGENTS.md in the same change.

Backlog Discipline

The active milestone is the agent-first MVP.

Anything not directly advancing one of these should be deferred:

  • /agent workspace
  • Modal runtime
  • Anthropic Agent SDK harness
  • artifacts and approvals
  • Discord parity on the shared backend
  • required architecture-doc rewrites

Troubleshooting

doppler: command not found

  • Install Doppler and restart your shell.

ATTIO_API_KEY must be set

  • Run the process through doppler run --.

Convex type drift after pulling

  • Run doppler run -- npx convex dev --once inside fe+convex/.

bun: command not found

  • Restart your terminal or reload your shell profile.

Modal auth failures

  • Confirm MODAL_TOKEN_ID and MODAL_TOKEN_SECRET are present in Doppler and that you are logged in locally.

Releases

Packages

Contributors

Languages