Two links in. An agent that dates for you out.
Every person is represented by an agent. Each agent is only allowed two sources — the person's public LinkedIn and public Instagram — and dates every other agent on that person's behalf.
You paste a LinkedIn URL and a public Instagram URL. Both sites block plain server requests, so scraping runs on Apify actors (headless browsers on residential proxies):
- Instagram —
apify/instagram-profile-scraper: bio, category, link-in-bio, follower counts and the latest 12 posts (captions, hashtags, locations, alt-text, image URLs). Private accounts are rejected. - LinkedIn —
harvestapi/linkedin-profile-scraper(no cookies, public profile): headline, about, location, experience with descriptions, education, skills, languages, certifications, volunteering, honors — plus recent posts viaharvestapi/linkedin-profile-posts.
Scraped data is normalized into one schema, stored with the person, and nothing else is ever fetched about them.
The agent reads each source separately and writes reading notes: a concrete signal (a quote, a role, a photo) → what it infers about them as a partner, tagged hobby / interest / value / need / lifestyle / personality. On Instagram it looks at the actual photos of recent posts, not just captions.
Guardrails: it never infers orientation, religion, politics, health, ethnicity or appearance, and never invents facts.
From the notes, the agent writes the profile page: needs (what they need from a partner, and why), hobbies, interests, values, six personality traits, lifestyle, communication style, green flags, friction points, dealbreakers, ideal partner and dates. Every need, hobby, interest and value cites evidence from a source. It also checks the LinkedIn and Instagram plausibly belong to the same person.
The profile becomes the agent's private dossier. On a date, each agent only sees its own dossier, the other person's public card, and the conversation. Every line is a separate model call, so the two agents genuinely talk to each other — neither can read the other's needs or dealbreakers. Agents speak as their person's stand-in, in their voice, and have a job: find out if this person fits their person.
- Round 1 · Speed dates. Every pair of agents meets for six lines. Then each agent privately scores the other for its own person: chemistry, values, lifestyle, shared interests, needs met, overall 0-100, and whether it would book a second date.
- Round 2 · Full dates. Each person's top mutual matches go on a real date. The two agents plan it together (each proposes something its person would love). A Date Host agent — the only one who sees both dossiers — runs three acts: sets the scene, drops a question card that tests a real friction point, then throws a curveball (rain, closed kitchen, a choice they must make together). Afterwards each agent writes a private debrief to its person.
For every person P and every candidate Q:
myView = P's agent's score of Q (full date 65% + speed date 35%) theirView = Q's agent's score of P (same blend) fit = 0.65 · myView + 0.35 · theirView (+5 if both want a 2nd date)
P's own needs dominate, but a match only counts if it's mutual.
Round 3 · the agent decides. The formula only produces a shortlist, P's top 8. P's agent then reviews them side by side: its own scorecards from each date, and what each candidate's agent concluded about P. It commits to a final order with a reason for each, and writes P a note naming its pick (★). When two agents independently pick each other, it's a mutual #1 pick. Every ranking entry links to the date it came from.
- Next.js (App Router) + TypeScript + Tailwind, deployed on Vercel
- LLM calls walk a cheapest-first chain (Groq gpt-oss → DeepSeek → OpenAI nano → Anthropic Haiku) with key rotation. Calls that include photos go to a model with vision, and each scorecard records its model so the ranking can calibrate scores across models.
- Apify actors for Instagram + LinkedIn scraping
- Upstash Redis for people added live; the finished 25-person example ships as JSON in the repo
- Server-Sent Events stream every scraping step, reading note and date line to the browser as it happens
- Play matchmaker (/swipe): a swipe deck of real pairs. Guess whether one agent put the other in its top 3, then see the agent's actual reasoning.
- Be the Date Host: on any date, type a twist. The host narrates it into the date, both agents react in character (each is a separate call with its own private profile), then each gives its person a gut-check score change.
- Listen in: dates play back as audio (OpenAI
gpt-4o-mini-tts). Every agent has its own voice and the host narrates. - The afterparty (/afterparty): after the night, the agents gossip in a group chat (each message comes from that agent, knowing only its own night), write a kind rejection text to their worst match, and draft future Instagram captions for the mutual #1 couples.