Join the Agent Deck Discord Server!
Check out the Agent Deck community on Discord – hang out with 357 other members and enjoy free voice and text chat.
Paste a LinkedIn and a public Instagram. An AI agent reads both, builds a profile, then dates every other agent on that person's behalf and ranks who fits them best.
SocialTypeScript · CSSGitHub @ananjaygoelConnection unstableOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
No updates detected yet. GitHub releases will appear here.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Run /nomorevibe verify in your project folder to verify ownership and manage the introduction yourself.
Verify in one minuteAsk about other verification options
Agents that date on your behalf: LinkedIn + Instagram in, cited profile, agent-to-agent dates, rankings out.
Taken from the repository README
Loading the full README. The saved excerpt is shown below.
Proxima: agents that date on your behalf
Paste a LinkedIn and a public Instagram. An AI agent reads both, writes a profile where every claim cites its source, then goes on dates with every other person's agent on that person's behalf. You get a ranking of who fits each person best, plus the transcripts behind it.
• Live site: https://proxima-dating.vercel.app, where you can paste your own links at /add
• Finished demo (already run): https://proxima-dating.vercel.app/demo: a season of 25 simulated people (see below)
• Video (3 min): VIDEO_URLRead the full README ↗Paste a LinkedIn and a public Instagram. An AI agent reads both, writes a profile where every claim cites its source, then goes on dates with every other person's agent on that person's behalf. You get a ranking of who fits each person best, plus the transcripts behind it.
VIDEO_URLflowchart TD
L[LinkedIn<br/>public profile] --> S
I[Instagram<br/>public profile] --> S
S[Scrape<br/>Apify actors] --> R1[LinkedIn pass<br/>cited notes]
S --> R2[Instagram pass<br/>captions + photos, vision]
R1 --> P[Profile page<br/>needs · hobbies · interests · values · personality]
R2 --> P
P --> SD[Round 1: speed dates<br/>every agent meets every agent]
SD --> FD[Round 2: first dates<br/>each agent takes its top 3 out]
FD --> D[Debriefs<br/>each agent reports to its person]
SD --> RK[Ranking<br/>who fits each person best]
D --> RK
The finished demo is 25 fictional people. We didn't want to publish dating profiles of real people who never agreed to it, so their public LinkedIn and Instagram content was generated instead (scripts/synth/): an LLM writes each person's headline, about, roles, education, LinkedIn posts, Instagram bio and 8 captioned posts from a short seed, and an image model makes the 8 Instagram photos plus an illustrated avatar. From that point on they go through exactly the same pipeline as a real person: the reading agent looks at every photo and caption, writes the cited profile, and the agents speed-date and first-date each other. The site labels them "Fictional" everywhere.
The live site runs the full pipeline on real people: paste a real LinkedIn and public Instagram on /add, and that person's agent dates the whole demo season and gets a ranking.
Each person, and each person's agent, has exactly two sources of information: their public LinkedIn and their public Instagram. There's no questionnaire and no other site.
| Source | Primary | Fallback |
|---|---|---|
| LinkedIn profile | Apify actor harvestapi/linkedin-profile-scraper: headline, about, full experience with descriptions, education, skills, languages, certifications, volunteering, projects. No cookies or login. | The public profile page's JSON-LD (<script type="application/ld+json">), which LinkedIn serves to logged-out visitors for many profiles |
| LinkedIn posts | Apify actor harvestapi/linkedin-profile-posts: the person's 10 most recent own posts | (posts are optional) |
Apify actor apify/instagram-profile-scraper: bio, link, counts, and the latest 12 posts (caption, hashtags, mentions, location, timestamp, likes, image URL, alt text). Public accounts only. | Instagram's public web endpoint api/v1/users/web_profile_info (best effort: Instagram now often demands a login there, so Apify is the real path) | |
| Photos | Downloaded server-side and resized with sharp (≤1024 px JPEG), stored in Postgres. The agent's vision input and the page's images are the same file. | — |
The actors are called through Apify's REST API (run-sync-get-dataset-items) from src/lib/scrape/. Output is normalised into one LinkedInData / InstagramData shape (src/lib/types.ts), so the agents never depend on which scraper ran. Private Instagram accounts are rejected.
src/lib/agent/read.ts makes three model calls (OpenAI gpt-6.1-sol, strict structured outputs validated with Zod), split into two jobs (read, then write the profile):
li:about, li:exp:0, li:post:2, …). The agent writes 8–14 notes, each with a verbatim quote and what that item says about the person as a partner.ig:post:5). The agent first describes what is actually in each photo, then writes notes across the bio, captions, photos and the grid as a whole.Passes 1 and 2 run in parallel and write their notes to the database as they finish, so the profile page shows the reading as it happens. On the profile page, every evidence chip links to the exact post or role it came from.
The profile also contains the agent's private brief: the person's voice (from how they write captions and posts), what to look for in a match, what it must find out on a date, and true things it may share.
src/lib/agent/date.ts, src/lib/agent/persona.ts
Each agent knows only its own person. Its system prompt is its person's full dossier. Before a date it sees only the other person's public card (name, tagline, city, work, three hobbies, three interests). Needs, dealbreakers and everything else have to come out in conversation.
Every turn is a separate model call made as that agent. The call contains its own dossier, the other person's card, the spoken conversation so far, and the agent's own earlier private notes, but never the other agent's notes. Each turn returns:
say: what it says out loud (1–3 sentences)gesture: an optional stage directionprivate_note: what it just learned, for its own person (shown on the site, hidden from the other agent)vibe: how it's going for its person, −2 to +2Round 1, speed dating. Every agent meets every other agent: 4 messages at a "four-minute table", then each agent privately scores the fit for its own person (0–100) and says whether it would book a real date. 25 people means 300 speed dates.
Round 2, first dates. For each person, the top 3 from speed dating go on a real date. The keener agent asks the other out with a concrete plan built from both people (place, area, time, why it fits). The other agent replies and may tweak the plan. A narrator writes three scene beats (arrival, midpoint, goodbye), then the agents talk for 12 turns in phases: opening, getting to know each other, going deeper on what the person needs, and goodbye, where they say honestly whether they want a second date.
Debrief. Each agent writes privately to its person: five scores (shared interests, values, lifestyle, chemistry, needs met), each of its person's needs checked against what happened on the date, dealbreakers checked, the best moment quoted verbatim, the main concern, a second-date call, and an overall fit (0–100, calibrated so 50 means unclear and 80+ is rare).
Guardrails in every agent prompt: only say true things about your person (if the dossier doesn't cover it, say so); never raise or speculate about orientation, religion, ethnicity, health, politics or money; keep it PG.
score(P, X) = 0.65 × P's agent's fit for X + 0.35 × X's agent's fit for P
src/lib/jobs.ts): scrape → read → plan → speed_date… → full_date…. Workers claim jobs with FOR UPDATE SKIP LOCKED under a lease, so any number of workers can drain it in parallel and a crashed job is picked up again./api/tick runs the worker inside a Vercel function for up to about 4.5 minutes and re-invokes itself while jobs remain. Pages that are being watched start a tick if no worker heartbeat is recent. For a whole season, npm run worker drains the same queue from a laptop with no time limit.openai SDK: client.responses.parse with Zod output schemas (zodTextFormat, strict), vision for Instagram photos, reasoning.effort per stage (medium for reading, the profile and debriefs, low for date turns), and prompt caching of each agent's dossier: every call an agent makes starts with the same instructions and carries prompt_cache_key: agent:<id>, so its dossier is billed at the cached rate on every turn of every date after the first. Models are configurable per stage (MODEL_READ, MODEL_DATE, MODEL_SPEED, MODEL_DEBRIEF).src/
lib/scrape/ linkedin.ts, instagram.ts, apify.ts, images.ts, urls.ts
lib/agent/ schemas.ts (all Zod schemas), read.ts (the reading), persona.ts, date.ts (the harness)
lib/ pipeline.ts (job handlers, season planning), jobs.ts (queue), rank.ts, views.ts, db.ts
app/ pages: /, /people, /p/[id], /dates, /d/[id], /rankings, /live, /add, /how, /demo, /admin
app/api/ people, dates, tick, img, admin
scripts/ worker.ts, cli.ts (add-bulk, season, status, cost), fixtures.ts (local testing only)
brew install postgresql@17 && brew services start postgresql@17 && createdb proxima
npm install
cp .env.example .env.local # add OPENAI_API_KEY, APIFY_TOKEN, ADMIN_KEY
npm run dev # http://localhost:3000
npm run worker # in a second terminal: drains the job queue
People join the demo by opening an invite link, /add?invite=<INVITE_CODE>, and adding their own two links (with consent). As each person's profile is written, their agent books speed dates with everyone already in the season. When the speed dates settle, first dates are booked for each person's top picks. No one has to press anything. /admin (with ADMIN_KEY) adds people in bulk, shows the queue and the model spend, and retries failures.
Locally, the same flow runs with the worker:
npm run cli -- add-bulk people.txt # one "linkedin-url instagram-url" per line
npm run worker # scrape, read, then date (the season books itself)
npm run cli -- status # progress
npm run cli -- cost # token spend so far
About $0.02 per speed date, $0.08 per first date and $0.15 to read a person (photos included), with each agent's dossier billed at the cached-input rate after its first call. A 25-person season (300 speed dates, ~50 first dates) comes to roughly $15. A visitor who adds themselves costs about $1. Daily caps on visitors and live dates are configurable.
noindex. Whoever added a profile can delete it (profile, photos, dates) from its page.