Inspiration

This came out of an actual conversation with the organizers behind Code & Coffee Philadelphia. Every recurring meetup or hackathon re-solves the same problems each cycle: who do we ask for sponsorship this time, why did turnout drop last month, what format actually worked. That knowledge lives in one organizer's head and walks out the door with them when they burn out or move on. We wanted to turn that into a system that remembers — and gets sharper the more it's used, the way a recommendation feed learns from what you like and skip, not a static form.

What I learned

The biggest lesson was architectural, not algorithmic: three agents don't need to talk to each other to act like a coordinated system — they just need to share state honestly. Every agent in NextEvent AI reads and writes the same Postgres tables instead of calling each other directly, and that alone gives you free observability (every decision is a row you can inspect), free safety (a rejected draft literally cannot reach a downstream agent, because the query filters on status = 'approved'), and a shared learning signal (a dislike in chat and a reject on the dashboard update the exact same weight table).

I also learned that "smart" doesn't require embeddings or a vector database. With only an Anthropic API key available, matching a "fintech" goal to a contact tagged "banking API" doesn't need a similarity model — it needs an unfiltered candidate pool and a model that's allowed to use judgment instead of a keyword filter.

How I built it

  • Backend: FastAPI + PostgreSQL, multi-tenant from the ground up — every table carries company_id, one shared login per organization, session-cookie auth (not JWT, for real revocability).
  • Three Claude-powered agents, each with one job: Network Intel ranks contacts by relationship strength × a learned weight and drafts (never sends) an intro; Retrospective scores a past event against a rubric; Planning combines the organizer's own first-hand retrospective (treated as the primary signal, not the attendee survey) with sponsor-contribution patterns into a next-event plan.
  • The learning loop: every recommendation is tagged with the features it drew on. A like/approve multiplies that feature's weight by \(1.2\); a dislike/reject multiplies it by \(0.8\), floored at \(0.1\):

$$w_{t+1} = \max(0.1,\ w_t \times m), \quad m = \begin{cases} 1.2 & \text{liked / approved} \ 0.8 & \text{disliked / rejected} \end{cases}$$

Both agents read this same table back in on every run, so feedback compounds instead of just being logged.

  • Frontend: Next.js, a chat interface that routes free text through one classification call into network / planning / create-event / suggestions intents, plus a dashboard for event history, sponsors, and team.
  • Observability: Quirq / XO Space tracks the actual agent development sessions independently of the app's own action_log table.

Challenges I ran into

  • A regex hack that could have shipped a real bug: early on, the reply text embedded "[recommendation #N]" so the frontend could parse out an ID. When I added a "create event" intent, its confirmation message ("Created event #11") false-matched that same pattern and would have pointed a chat message's foreign key at the wrong table entirely. Fixed it properly by having agents return (text, id) as structured data instead of encoding it in the string.
  • A silent truncation bug: one agent's Claude call used a default max_tokens that was too low for a full analysis plus a drafted message, so responses were getting cut off mid-sentence in production — not a UI clipping issue, the text was genuinely incomplete in the database. Caught it by comparing stored content length against the token budget, not by assuming the UI was at fault.
  • A cookie that silently refused to set: the frontend called the backend on 127.0.0.1 while running on localhost — two different origins as far as SameSite=Lax cookies are concerned, so sessions quietly never persisted until the API base URL matched.
  • A third-party install script that fragmented the repo: installing the Quirq/XO tooling from inside the project directory caused it to treat every subfolder as a separate project. Diagnosing and cleanly separating the tool's install location from the actual codebase, without losing any git history, took real care.

Built With

Share this project:

Updates

Submission history