On Agent Rails

Rolodex

Relationship memory for the people you keep meaning to get back to.

Free

Connect it

Add this address in your chat app as a custom connector. The first request that touches your own information answers with a link to sign in; everything before that works signed out.

https://rolodex.rails.so/mcp

This page is the documentation address for that connector.

Things to ask it

What it can do

NameWhat it doesEffectPrice
rolodex.guideThe playbook and the refusal codes, by topic; read start first. Topics are start, sync, classify, morning, refusals, occasions, commitments and view.readFree
rolodex.syncHand Rolodex complete threads you have already read, plus one coverage row per channel you looked at. This is the only way anything enters Rolodex's ledger. Send whole threads: set message_count_declared to how many messages the thread has and complete to true only when you sent them all, because a thread cut short can show the wrong person owing the next move; a short thread is kept as partial and opens no loop on its own. Send the coverage row even when a channel found nothing, so an outage never reads as a quiet week. At most 100 source items (threads plus their messages, occasions and commitments) or 256 KiB per call; past either, page the rest and it refuses with batch_too_large. A message carries a one-line claim, never its body, and message_ref only when you actually read it: a line the person told you, or one you worked out, sends evidence_class user_stated or inferred and no message_ref. Use a different idempotency_key per batch; a repeated key returns its first answer and ingests nothing. A calendar invite or organizer role alone is invited_only. Granola notes from the owner's account are attended with attendance_basis owner_notes and a Granola notes_source; the owner saying they were there is owner_stated.writeFree
rolodex.correctOne correction from the person: an override by type (a keep_warm may carry cadence_days or next_at -- the owner's own rhythm for checking in), the right answer for a field which then holds against sync and the agent, releasing a field, accepting a correction, an un-merge, a dismissed loop with its reason, an undo of a named revision, or the person's own word about who somebody is: promote marks them a contact, wrong_relationship marks them a prospect again, archive hides them, unarchive brings them back, do_not_contact needs a reason and may name a scope, allow_contact lifts it; or the owner joining two people they name (merge; unmerge undoes it) or putting an address on a person they name (attach_identity; an address that already belongs to someone else is refused). The person's own word, so nothing here is pencil.writeFree
rolodex.who.to.askFor a stated goal, the people who could help, ranked by evidence: the person's own label, the band and the score under it, the last real exchange, and what would change the answer. The person's own answer for that goal is read back: not_for_this leaves someone off the list, and ask_carefully or ask_freely comes back as each person's answer.readFree
rolodex.who.to.ask.answerRecord the person's own answer about asking someone for one goal: ask_freely, ask_carefully or not_for_this. It is saved as theirs and dated, one answer per person and goal, and the who-to-ask page writes the same answer. A changed answer replaces the old one; the same answer twice writes nothing. rolodex.who.to.ask reads it back for that goal only. view defaults to commercial, and a personal contact needs view personal. Pass an idempotency_key so a retried call is one answer.writeFree
rolodex.followups.dueWho is waiting on you, soonest first, each line carrying the evidence it was compiled from. The answer always includes the coverage strip: when a channel is down, stale or partial, an empty list means we cannot see, not that you owe nothing, and the headline says so.readFree
rolodex.person.lookupFind one person and everything Rolodex can show about them: how you know each other, what is open, the facts you have confirmed, your own notes, and the evidence behind each line. Search by name, by an exact email or handle, or by a person_key you already have. Several matches come back as several matches, never as a guess.readFree
rolodex.note.addWrite down something the person told you about someone. The note is saved as theirs, verbatim. If you also want to add it to that person's record as a fact, send propose_fact: it lands in pencil and becomes part of the record only when they confirm it with rolodex.loop.resolve. Repeating the same idempotency_key writes the note once.writeFree
rolodex.loop.resolveDecide what happens to a loop or to any pencil proposal. decision=propose writes your suggestion down in pencil and returns a proposal_key for confirmation; use rolodex.link to open its case; decision=confirm inks exactly that proposal, and confirming twice changes nothing the second time; decision=reject leaves it out; decision=undo_merge separates two people that were joined. Nothing a machine concluded becomes part of a record without a confirm.writeFree
rolodex.people.addAdd one to five hundred people, or import a CSV of them, under one source for the batch. A row is a name plus at least one identity (email, phone, x handle, linkedin), or a name plus organization plus source_url. Adds create prospects; a CSV always creates prospects no matter what a column claims, and a row carrying relationship contact becomes one only on the owner's own word. Dedupe runs in order: a known identity becomes a new source on that person, a suppressed identity is held as erased, an exact name-plus-organization match on an unresolved prospect is a pencil merge proposal, and only then is a new person made. Held rows say why: no_identity, not_a_person, erased or guard_refused. Repeating the idempotency_key returns the stored answer and writes nothing.writeFree
rolodex.people.searchFind people by text and filters: relationship (prospect or contact), status (defaults to active -- archived and do_not_contact appear only when asked for), tag, organization, source kind, import id and view. At most 50 per call; pass the returned cursor for the next page. Every match says its relationship and the reason behind it, so 'why is this person a contact' is never a guess.readFree
rolodex.linkRails-provided tool (R2b). Hand over a page the person can open on their phone with no sign-in: purpose rolodex.today for what is waiting on them, rolodex.loop_case with a loop_key for one case with its evidence and its pencil proposal, rolodex.who_to_ask with the goal the page asks about (view defaults to commercial, and a page that may show personal contacts needs view personal), or rolodex.export for the signed download -- the whole installation as JSONL and the people as CSV, never gated. The link opens a page or a file; it never approves anything on its own.readFree

Rolodex loops

How to feed Rolodex conversations and read back who is owed a move and who could be asked.

Rolodex

Rolodex keeps a log of any conversation that builds context on a relationship,
with the source beside every line, and answers two questions from it: who do I
owe, and who could I ask.

This file is the only copy of these instructions. The rolodex.guide tool serves
it by topic, the MCP prompts and resources export it, and rolodex.rails.so/docs
renders it. If you find the same rule written somewhere else, that copy is wrong.

start: what to do first

  1. Read this topic, then sync, before your first call.
  2. Fetch the conversations you can reach. Send them with rolodex.sync.
  3. Ask rolodex.followups.due what the person owes, or rolodex.who.to.ask who

could help with a goal they name.

  1. Offer the rolodex.today link. The page opens on a phone with no login.

25 sync calls are free for the life of an installation. Reads, History,
export and revoke are never charged.

sync: what to send

Send any conversation that builds context on a relationship, not only mail:
message threads, meeting notes, calls, and the attendees of today's and
tomorrow's calendar events. A Granola note is a meeting note; send it.

Send whole conversations. Never a snippet. A thread cut short can show the wrong
person owing the next move, because the messages you left out are exactly the
ones that would change the answer.

With every thread:

also works): how many messages the thread actually has. Rolodex checks it
against the message ids you send. Set complete: true only when you sent them
all. If the thread is short, or complete is missing, it still ingests, and it
is recorded as partial and never opens a loop on its own.

infer it from the channel, content, profession or context, and never label a
person or fact commercial on your own; ask the owner when the view is unknown.
The field is optional in sync: an omitted view is stored as personal for
privacy, which is not the owner's choice and never permission to show a row
commercially. A commercial answer never ranks a personal contact, and a
personal occasion or commitment never counts toward a commercial score.

ids; the mailbox stays yours.

mailbox — something the person told you on a call, or something you worked out
yourself — sends evidence_class of user_stated or inferred and no
message_ref at all. That is allowed and is never refused. A loop built only
from inferred lines is kept, shown with "no source", and never ranked.

occasion_ref, format (one_on_one, small_group, group, async, solo),
medium, initiator and occurred_at; add duration_minutes, where_met,
why_met and citations when you have them. Where and why two people met is
what keeps an event contact from becoming a useless name six months later. An
invitation or an organizer field alone is not evidence that someone attended,
and sync records no separate attendance flag or notes source.

the source_sentence that proves it, quoted as written (Rolodex keeps up to
500 characters, with runs of whitespace collapsed); add due_at only if a
date was named, and citations when you have them.

With every sync call, for each channel you read: the window, the count, any
error, and a status. The status is one of ok (you read it and sent what you
found), empty (you read it and there was genuinely nothing), partial (you
sent less than you found), stale (your last good read is older than the
channel's freshness window), unavailable (you could not reach it at all) or
error (you reached it and it failed). Anything but ok and empty must say
why, in words the person can read.

Send the coverage row even when a channel found nothing. Without it an outage
reads as a quiet week, and that is the one mistake this product cannot make.

At most 100 source items or 256 KiB per call. A source item is a thread plus
each of its messages, occasions and commitments, so a hundred threads of one
message and one thread of a hundred messages are the same size. Past either
limit the call refuses with batch_too_large and you page the rest.

Pass an idempotency_key, and a different one per batch. A key Rolodex has
already answered returns that first answer and ingests nothing, whatever you send
with it, so reusing a key silently drops the batch you thought you sent.

classify: what you are deciding

An introduction is a message where a third party connects two people, or one
person asks permission to make that connection, or a referral arrives naming who
sent it. Kinds: intro, opt_in_request, referral_inbound.

One loop per introduction across channels. The same intro in Gmail and iMessage
is one loop.

For each one, say: the kind; the owner of the next move, one of me, them,
introducer, unclear; the obligation, one of acknowledgment, reply,
scheduling, answer, follow_up; the message id that proves it; one line of
rationale. Recompute ownership on every newer message.

A loop cites its source: a message id, or the person's own statement recorded as
user_stated with its date. A loop with neither is stored as inferred, shown
dashed with "no source", and never ranked. Nothing is refused for lack of a
citation.

For every thread that is not a loop, send one exclusion_reason from this
fixed set, so "nothing owed" can be audited: cold_outreach, recruiter_only,
automation_or_business, fyi, replied, waiting_on_them, social_chatter,
mention_only, public_figure, no_intro_event.

morning: the daily read

Call rolodex.followups.due. Read the owed loops and commitments aloud, each
with its citation. Offer the rolodex.today link.

Then suggest one block for the morning's replies, and **fold it into the block
the person already keeps for daily work** — their existing Todo or timeboxing
block. Update that block in place, and take the line out when nothing is owed.
Never create a separate system-named calendar event. Rolodex does not write
calendars on a third-party host; you do, with your own calendar tool, when the
person asks.

You draft and you send. That is your job, not Rolodex's. When the person asks you
to reply to someone, write it and send it with your own tools; it comes back as
evidence on the next sync.

After a page: poll exercise.status or use link_wait, then read the change
back with rolodex.person.lookup.

refusals: what sync can return

Rolodex is free, so there is nothing to buy and no link; show the sentence
and stop syncing. Lookups, notes, follow-ups, corrections and closing loops
keep working.

never

never wrote to the person.

Example prompts

What a person actually says, and what it asks of you. The first proof is measured
on introductions; the product is not limited to them.

and read the signals back, not just the band.

and the confirmed facts, each with its citation.

rolodex.correct action merge naming both keys. The owner named them, so this
is not a name match. unmerge with the returned merge_key undoes it.

attach_identity. identity_collision means the address is already someone
else's: ask whether they are one person, then merge.

Your own activity, and everything this app has stored for you, is on the app page when you are signed in. You can export it or take it back from there.