Relationship Manager
checking deployment Open the app

Agent-native relationship graph

One graph of the people you actually talk to.

Your relationships are spread across Gmail, WhatsApp, your calendar and recorded calls. Every tool that tries to manage them wants you to type data in, which is the one thing you will never do. This reads the graph you already produced, and hands it to your agents.

The hosted deployment is one person's real graph, not a demo tenant. Sign-up closes after the owner account, so read the mechanics here and run your own.

MCP over HTTP REST CLI MIT
identity resolution 5 handles in, 1 person out
  • gmail Anjali Menon <anjali@karve.studio>normalizeEmail
  • calendar AMenon / Karve StudioparseAddress
  • whatsapp 919900822910@c.usdecodeJid
  • linkedin linkedin.com/in/anjali-menonnormalizeLinkedIn
  • fathom Anjali M. (attendee)nameFormMatches
Anjali Menon
karve.studio · 4 meetings · last spoke 6 days ago
1 row

Every handle lands in person_identifiers, the authoritative index. One human, one row, and no duplicate invented when a source writes a number differently.

01  /  the evidence law

Facts are not written. They are earned.

A model never supplies a confidence number. It reports what it observed, and the code decides what that observation is worth. Below is the real ledger, running the real arithmetic from packages/core/src/evidence.ts.

what an agent observed

Tick the observations behind a claim and watch the band it lands in. Overlapping evidence combines, so two weak sightings can outweigh one strong one.

0.000 nothing stored
verified Written straight to the record. The field is applied.
probable Stored as a suggestion. A human accepts or dismisses it.
possible Stored as a suggestion. A human accepts or dismisses it.
below Not stored at all. The guess disappears.

Nothing observed yet. Pick an observation on the left, or start from one of the examples below.

02  /  the agent surface

One contract. Three ways in.

Twenty-three tools, fifteen read and eight write, defined once in packages/core/src/tools.ts. The MCP server, the REST router and the CLI all register from that list, so the tool you read about is the tool an agent calls.

search_peoplereadFind people by name, email, company, domain or handle. Start here when you do not have an id.
get_personreadThe full record: identity, settled facts with their evidence, handles and counts.
prep_briefreadA deterministic markdown brief to read before you talk to someone. No model spent.
person_timelinereadMerged chronology across email, meetings, calls and WhatsApp. Ground truth for when you last spoke.
list_factsreadFacts by status. Proposed is what awaits a human decision; applied is settled.
reconnect_queuereadRanked reconnect list with cohort, signal and a starter draft. Holds stay hidden unless asked for.
connection_statusreadPer-source freshness, so nothing is ever implied to be current that is not.
pipeline_boardreadPeople grouped by the stage you placed them in, newest activity first.
ask_about_personreadA grounded answer from one record, or an honest silence when the record says nothing.
daily_briefreadWho needs attention now, built from follow-ups, undecided facts and the top of the queue.
person_networkreadEveryone a person is connected to, and what each tie actually rests on.
intro_pathreadThe shortest chain of people between you and someone else, hop by hop.
list_companiesreadThe organisations in the graph, by how many people you know or by last touch.
get_companyreadOne company: everyone you know there, and the latest activity across them.
aboutreadWho built this, and honest live counts of what the graph holds.
record_factwriteThe only write path for a learned fact. The ledger scores the evidence you supply.
decide_factwriteAccept or dismiss a suggestion. Accepting freezes that field as human-held.
set_person_stagewriteMove someone on the board. Records position, and sends nothing.
log_outreachwriteRecord an outreach that already happened, and when to review it again.
propose_outreachwriteQueue a draft for a human to approve. The end of an agent's reach.
record_edgewriteTwo people know each other, and who told us. For ties the record cannot see.
import_social_exportwriteOfficial LinkedIn or Instagram export. Handles merge into existing people, never fork.
propose_mergewriteTwo rows that look like one human, queued for a person to confirm.

Reads are open. Any valid key can read the graph, and reading is the majority of the surface.

Writes are opt-in, per key. A read-only key calling a write tool is denied, and the denial is logged like any other call.

There is a kill switch. Pausing agents rejects every agent write immediately, without touching a single key.

Nothing is sent. There is no send tool. An agent drafts, a human approves, and outreach is logged rather than fired.

/mcp streamable HTTP
terminal
claude mcp add --transport http relationship-manager \
  https://<your-worker>/mcp \
  --header "Authorization: Bearer rel_..."

03  /  what a human gets

Two jobs need a person. Only two.

Deciding what is true, and deciding who to reach out to. Everything else in this product is built for an agent to read. Every screenshot is the real app on a real graph.

01

Today

Facts waiting on your call, follow-ups that have come due, and the sources that have gone quiet, named rather than smoothed over.

live countsstale sources named
relationship-manager.everyai-com.workers.dev
Today: people, facts awaiting review, reconnect-ready, messages, meetings and agent calls, above a banner naming the four stale sources.

02

Ask, before you type

Four questions the graph can actually answer, with what the answer will be grounded on stated up front. Never a blank box.

groundedstarters
relationship-manager.everyai-com.workers.dev
Ask's empty state, showing what it is grounded on and four starter questions.

03

Ask, and what it drew on

Answers arrive as they are written, name the people they came from, and say plainly what the record does not contain.

streamingsources shownrefuses to invent
relationship-manager.everyai-com.workers.dev
A streamed answer about stale sources, listing each source with its last sync date, plus the facts and sources it drew on.

04

Connections

One row per toolkit, as many accounts as you like, each enabled or parked on its own line. The app never sees a password.

OAuthmulti-account
relationship-manager.everyai-com.workers.dev
Connections: Add account, Sync now, and per-account enable toggles for Gmail, Google Calendar and Fathom.

05

Connections, freshness

Real row counts, the age of the newest row, and the exact command that refreshes each source locally. A connector cannot claim otherwise.

computed, not self-reported
relationship-manager.everyai-com.workers.dev
Source cards with freshness bars, row counts, last-sync pills and copy-ready refresh commands.

06

Agents

The MCP endpoint, keys with explicit scopes, the full catalogue, the call log and the kill switch, on one screen.

MCPkeyscall logkill switch
relationship-manager.everyai-com.workers.dev
The Agents screen: the MCP endpoint and copy-ready client configurations for Claude Code, Codex and Cursor.

04  /  told straight

What this does not do.

A demo that hides its edges is a worse demo. These are the real limits, written by the people who built it.

It is only as fresh as its last sync

Gmail, Google Calendar and Fathom can be pulled from the cloud on a daily schedule. LinkedIn, Instagram and WhatsApp cannot be live at all: the first two have no API for a personal account, and the third is read from a desktop app on your own machine.

Freshness is a three-day rule

A source that produced rows yesterday and then died still reads as connected for two more days. That is deliberate, because it stops the status flapping, and it is why the dates are always shown next to the label.

Deduplication is heuristic

The same human across email, phone and socials is usually resolved into one row. A person who appears under two unrelated addresses can still arrive twice, so merge those by hand rather than trusting the heuristic blindly.

One graph per deployment

The first account becomes the owner and sign-up closes behind it. There are no per-user partitions. An allowlist lets specific people into the same graph, and that is intentional.

Ask is read-only, and slow on purpose

It cannot draft or send anything, and writes go through the evidence ledger where a person stands in the way. The model behind it reasons, so answers take seconds and sometimes longer.

The evidence weights are unvalidated defaults

They are Phase-0 calibrated, not constants proven against outcomes. The bands are honest about what they are, and the weights live in one file so they can be argued with and changed.

05  /  run it

Yours in one command.

One Worker, one database, one AI binding, in your own Cloudflare account. There is no hosted service in the loop, and the graph starts empty on purpose.

  1. Clone the repository and run npm install.
  2. Copy .dev.vars.example to .dev.vars and fill it in.
  3. Create your database with npm run db:create, then paste the id it prints into wrangler.jsonc.
  4. Apply the schema, covering identity, evidence, socials, auth, pipeline and chat, with npm run db:migrate.
  5. Set BETTER_AUTH_SECRET from openssl rand -hex 32, then build and deploy.
  6. Open the app and create the first account. It becomes the owner, and sign-up closes behind you.
or hand it to an agent
npm run deploy:cloudflare

# finds or creates the database,
# generates the session secret,
# migrates, builds, deploys.

# It will not replace an existing
# database, and it will not rotate
# a secret that already works.