# Reply to every LinkedIn conversation

You have access to your own LinkedIn session, a company registry,
a team messaging tool, and one table you can read and write. Run this
**[four times a day, for example morning, midday, afternoon and
evening]** on **[your own LinkedIn account]**.

## 0. Set up (skip if you're already connected)

If you don't already have live tool access for this, connect it
first. This prompt is only as real as the tools behind it:

1. Get a Tulina account: book a demo at https://tulina.ai/book.
2. Add Tulina's MCP server to your assistant: https://mcp.tulina.ai/mcp
3. In Tulina, connect your own API keys for the tools this
   prompt uses: your LinkedIn account, company registry data, and
   your team's messaging tool.

Once connected, your assistant has real tool access and the rest of
this prompt runs as written.

## 0b. Already on Tulina? Three things around the run

An account and the MCP server are not the whole setup. Two of these come
before the run below and one after it, and together they turn this from a
one-off answer into a process your workspace keeps:

1. **Activate this process's connectors first.** Call
   `oto_connector(op="list")`, match it against the tools named in step 3
   above, and `oto_connector(op="select", name="...")` every one that
   isn't active yet. Selecting a connector does not mount its tools in the
   conversation you're already in — reach them through `oto_call` for this
   run, or open a fresh conversation once they're all on.
2. **Attach the work to an existing project.** `oto_project(op="list")`
   shows your active org's projects: pick the one this work belongs to
   rather than opening another, and keep its id. The project is where this
   process, the tables it writes to and the connectors it uses hang
   together.
3. **When the run is done, save it as a process — with its graph.** Write
   the body with `oto_procedure(op="set", ...)`, then attach it with
   `oto_project(op="link", project_id=..., target_type="procedure",
   target_ref="<your slug>")`. The body has to carry a drawing: read
   `oto_guide(op="read", slug="procedure-flowchart")` and follow it
   exactly — ONE untagged fenced block in that grammar, opening with the
   trigger and a quoted example of what you'd type to start a run. Tulina
   parses that drawing back into the graph it renders as the process's
   default view, which is what makes it come out in the same style as
   every other process in the app; a drawing the grammar can't read falls
   back to raw characters instead. Saving a process needs org-admin
   rights — without them, hand the finished body to someone who has them.

## 1. Page the inbox back to the last pass

### Before the first pass

- **Your own id.** Read your own LinkedIn profile and store the
  provider id of the connected account. Step 2 compares every thread
  against it and step 9 looks for it; nothing else on a message
  reliably says who wrote it.
- **The workspace.** Pass the workspace that holds the LinkedIn
  connection explicitly on every call. A scheduled session that
  starts elsewhere does not resolve it and fails as if the account
  were not connected.
- **The log table.** One table keyed on the thread's chat id, with
  `contact`, `profile_url`, `last_message_at`, `delivered_at`,
  `status`, `draft`, `actual_reply` and `learned`. It also holds two
  kinds of control rows: one `__watermark__` row and one
  `__run__<timestamp>` row per pass. A table an agent creates can
  belong to that person by default even inside a shared workspace:
  move it to the workspace straight away, or the next scheduled
  session will not find it and will create a second one.
- **The DM channel.** Look yourself up in the messaging tool by the
  email you use there (often not the one your other accounts sign in
  with), open a direct message, and store the channel id.
- **Your style notes.** Read a few dozen of your own sent LinkedIn
  messages (the ones whose sender id is yours) and write down how you
  actually write: length, how you open, whether you sign off, how
  you end. Step 6 starts from these, and step 9 corrects them.

- Read the `__watermark__` row: its `last_message_at` is the newest
  message the previous pass handled.
- **No watermark means the last 50 threads, and nothing more.** A
  first pass that surfaces two years of threads is a digest nobody
  reads.
- List threads 20 at a page, newest first, and keep paging with the
  cursor for as long as the last thread on the page is newer than the
  watermark. The first page that falls behind it is the last one
  read. Larger pages have been refused outright on real accounts, and
  20 is also the default.
- **A hard cap of 200 threads a pass.** Past it, deliver what you
  have and say so in the DM: a pass that never finishes delivers
  nothing.
- A page of 20 threads is too large to read whole. Extract only the
  chat id, the attendee's name, headline and profile URL, the last
  message's time, sender id and text. When the attendee names come
  back with an error status, the name lookup did not run: fall back on
  the thread's own name or the last message's sender rather than
  concluding there is nobody on the other end.

## 2. Keep threads where they wrote last

- A thread is waiting on you when the last message's sender id is
  **not** your provider id.
- **Never use the message's "is sender" flag.** It has been observed
  false on every thread of an account, including the ones where the
  account itself wrote last. Trusting it surfaces the whole inbox.
- **The unread count is not a criterion either.** It reads 0 on a
  thread you opened on your phone and did not answer, which is
  exactly the thread this process exists to catch.
- You wrote last: nothing is waiting on you. Following up on silence
  after your own message is a different process.

## 3. Read and classify each thread

- Read the whole thread. "Yes, interested" means nothing without
  knowing what was proposed three messages up.
- A last message that is only a voice note cannot be transcribed:
  flag it in the DM and draft a line asking for the gist in writing.
  Never invent what the note said.

| Class | Looks like | The draft |
|---|---|---|
| Refusal | "no thank you", "not interested" | Short and gracious. No nudge, no pitch. |
| Question | A real question about your offer, how it works, the price | Answers it, then offers a slot. |
| Interest | "sounds good", "send it over", "let's talk", a thumbs-up on a pitch | **[Your calendar link]**, or a light next step. |
| Off-topic | An inbound pitch, spam, an automated sequence | Flagged, draft left empty: you decide. |
| Other | Neither sale nor refusal: a recruiting thread ending on a pleasantry, a congratulation | A minimal draft if one makes sense, and the DM says it was not forced into a class. |

## 4. Qualify the sender's company first

"Why not", "you never know" and "send it anyway" are not interest.
They are a door left ajar out of politeness, and a calendar link
closes it. For these threads, and for any thread where the person
runs an identifiable company, qualify the company before writing:

- **The registry.** Search the company by name to get its
  registration number, then read its identity: headcount band,
  activity code, open establishments. Read its directors and its
  filed accounts; the latest filing can be a simplified one with no
  revenue line, so walk back to the first year that carries one
  before writing "no revenue". In France this is the national company
  registry; elsewhere, use your country's equivalent.
- **The company page** on LinkedIn: current headcount, twelve-month
  growth, industries, and the words the company uses about itself.
  Company lookups are cached for a few hours and their quota is
  small, so qualify the threads that need it, not the whole inbox.
- **Match the person to the company before using any of it**: their
  name among the directors, or their headline naming the company. The
  facts of a namesake company are worse than no facts.

## 5. Draft a reply in your style

**The general rules**, from your style notes:

- One to three sentences, never a paragraph.
- Open on the first name. No "Dear", no "I hope this finds you
  well", no signature.
- End on a question or a link.
- Write in the thread's language.
- A proof point only when selling, and only **[your citable proof
  point]**, never a figure made up for the occasion.

**The lukewarm format**, for the threads step 4 qualified:

- One play, never a list: the one that touches their P&L, worked out
  from how the company makes money rather than from your catalogue.
- Never use their trade's vocabulary unless you are sure of it. A
  term used slightly wrong in front of someone who has done the job
  for fifteen years costs more than the proposal earns.
- Offer a deliverable, not a capability: "I'll send you [the result]
  for one of your [sites] by [day], you take a look" beats "AI could
  automate [task]". End on a question answerable in three words.
- No conditional tense, no bullet points, no "etc.".
- Keep the hook of your first message. If you opened on something
  personal, it has to survive into the reply.
- Proofread.
- Deliver **two variants**: one that commits to a dated deliverable,
  one that costs them nothing and lets them choose the ground. This
  format runs past three sentences on purpose: it only applies to
  threads worth a real message.

## 6. Deliver each draft in a direct message

Post to the stored DM channel, one block per thread:

```text
*<Name>* — <headline>
<profile link>
Received <date>: "<last message>"
Draft: <text ready to copy>
```

- For a lukewarm thread, add one factual line about the company
  before the draft (headcount, trend, sites, revenue when filed) and
  label the two variants.
- Above roughly four thousand characters the messaging tool splits
  the message and says so in its response. Read that before
  re-posting: a message can be deleted but not edited, so a re-post is
  a duplicate.
- **An empty pass still sends one line**: "nothing waiting". Silence
  cannot be told apart from a broken run.

## 7. Log each thread, move the watermark

- One row per delivered thread, keyed on the chat id: contact,
  profile URL, when the last message arrived, `delivered_at`, the
  class in `status`, the exact `draft` as delivered, `actual_reply`
  empty and `learned` false. Store the draft verbatim, or step 9 has
  nothing to compare against.
- **Then move the watermark** to the newest message time seen this
  pass, even when no thread was kept, or the next pass rescans the
  same window. Move it only after the DM went out: a pass that failed
  to deliver leaves the mark where it was.
- Write a `__run__<timestamp>` row with threads scanned, kept and
  delivered. A scheduled run that finishes green has not necessarily
  done its job; this dated line makes the history readable.
- The watermark is the only thing preventing duplicates. Do not fire
  a manual pass while a scheduled one is running.

## 8. Send the reply yourself

You copy the draft, edit it or ignore it, and answer on LinkedIn.
This process never sends a LinkedIn message: keep the send action
out of the scheduled run's allowed tools entirely. It writes to no
CRM, and it never nudges threads where you wrote last.

## 9. Learn from what you actually sent

The DM has no checkbox to tick. The signal that you handled a thread
is LinkedIn itself.

- Take the log rows where `learned` is not true, skipping the control
  rows.
- Read each thread and look for a message whose sender id is yours
  and whose time is **after** the row's `delivered_at`.
- Nothing found: try again next pass. After **[7 days]** with no
  reply, set `learned` to true with a status saying so, so a dead
  thread is not rechecked forever.
- Found: write it to `actual_reply` and compare it with the draft.
  Identical or nearly: nothing to learn. Different: note what changed
  (length, opener, tone, what you kept, cut or added). Either way set
  `learned` to true.
- **A style rule changes only when three or more deltas point the
  same way.** Then update the rules in step 5, with the date and the
  threads that established the pattern. One edit on one thread is
  not a pattern.

## Output

Each pass: one DM with a block per waiting thread, or a single
"nothing waiting" line, plus voice notes that could not be read and
whether the 200-thread cap was hit. In the log table: one row per
delivered thread, the moved watermark, a dated run line, and, as you
reply, what you actually sent next to what was drafted.
