{"id":71096,"plugin_id":"plugin_asdk_app_6ace449b600481918cb156ac87e6bf4e","kind":"skill","collection_source":"plugin_package","comparison_source":null,"observed_at":"2026-10-29T19:12:50.635Z","digest":"96cd32b30b3858ffbaf9045f51caa0d10ae30bbe15f42cc4ab0246e93863cc30","against":null,"payload":{"description":"Use when the user wants warm introductions, intro paths, or network-based outreach to a person or company — discovering who can introduce them to a prospect, checking if they're already connected to someone, finding their best intro opportunities, tracking intro progress, or writing outreach that name-drops mutual connections. Triggers include \"warm intro\", \"who can introduce me to\", \"am I connected to\", \"best paths\", \"intro opportunities\", \"namedrop mutual connection\", and any work against Draftboard targets/connections. Requires the hosted Draftboard MCP server at https://mcp.draftboard.com.","included_files":[{"relative_path":"AGENTS.md","size_in_bytes":1313},{"relative_path":"references/setup.md","size_in_bytes":3886},{"relative_path":"references/tools.md","size_in_bytes":28370},{"relative_path":"references/user-stories.md","size_in_bytes":12254}],"name":"draftboard-intros","skill_md_contents":"---\nname: draftboard-intros\ndescription: Use when the user wants warm introductions, intro paths, or network-based outreach to a person or company — discovering who can introduce them to a prospect, checking if they're already connected to someone, finding their best intro opportunities, tracking intro progress, or writing outreach that name-drops mutual connections. Triggers include \"warm intro\", \"who can introduce me to\", \"am I connected to\", \"best paths\", \"intro opportunities\", \"namedrop mutual connection\", and any work against Draftboard targets/connections. Requires the hosted Draftboard MCP server at https://mcp.draftboard.com.\n---\n\n# Draftboard intros\n\nHelp the user get **warm introductions** using their Draftboard network data, through Draftboard's\nhosted MCP server (`https://mcp.draftboard.com`). Draftboard's core idea is **relationship\nproximity**: the shortest path from the user to a prospect (a **target**) runs through a mutual\n**connection** (a **connector**), scored 0–100 by **rank**.\n\n## Before anything else\n\n1. Confirm the Draftboard tools are available. If they are missing, the connection has not been\n   made — point the user to `references/setup.md`: it is one address and a browser approval, with\n   nothing to install.\n2. Call **`get_me`** once to confirm whose account this is (`customer.name` / `customer.user`). For\n   \"through my teammate\" requests, the team roster is here too: match the teammate's name in\n   `customer.teamMembers[]` and pass their `id` as `ownerIds`.\n3. If a call comes back unauthorized, do **not** retry it and do not ask for a key — there is\n   none. The connection was revoked or expired; tell the user to reconnect (`references/setup.md`),\n   or to check **Settings → Connected apps** if they did not expect it to be gone.\n\n## Pick the right tool\n\nPrefer the **outcome tools** — they do the multi-step work and return a `telemetry` block so you\nknow how complete the answer is. Drop to **thin tools** only when no outcome tool fits.\n\n| User wants… | Use |\n|-------------|-----|\n| Best intro opportunities right now | `find_top_paths` — one ranked call, one path per target |\n| Paths through a specific teammate's network | `find_top_paths` with `ownerIds` |\n| Several connectors for the SAME target (not just the strongest) | `get_target_connections` — `find_top_paths` returns only one (the strongest) path per target |\n| **Paths only through people I'd actually ask** (\"use my supporters\", \"only my 4–5 star people\") | `find_top_paths` with **`ratings: [4,5]`** (2–5; one call — never cross-check a starred list against targets by hand). For one person: `get_target_connections` with `ratings` |\n| Whether ONE named person is already a target (and their `targetId`) | `resolve_target` — one lookup, never a page walk |\n| Whether they're already connected to people (by LinkedIn URL) | `check_if_connected` (a batch of URLs) |\n| Progress of intros (new / completed / stopped) | `intro_status_overview` |\n| Cold email that name-drops a mutual connection | `find_top_paths` (`includeRankDetails: true`), use `rankDetails` |\n| Who can a specific connector introduce me to? | `get_connector_intros` (connector-first) |\n| **Star / rate a connection** (\"star this person\", \"mark them as a go-to\", \"rate them 5\") | `set_connector_tier` with **`rating` 1–5, higher is better** (5 = ★★★★★ \"ask anytime\", 1 = ★ \"don't ask\" — which also hides them; `tier: 0` clears) |\n| **My / a teammate's / the team's LinkedIn connections** (\"my connections\", \"who does Alice know\", export a network) | `get_me` → take the id (yours: `customerProfileId`; a teammate's: `teamMembers[].id`; if the name fits several people or none exactly, ask which one) → `list_network_connections` with `ownerIds`, paging until `nextPage` is 0; each row's `owners` says who on the team knows them |\n| **List my starred / closest connections** (\"who did I rate 5\", \"my go-tos\") | `list_network_connections` with **`ratings: [5]`** (or `[4,5]`) |\n| **Paths through a group** (\"paths to Stripe through our investors\", \"intros via my close friends\") | `find_top_paths` with **`connectorLabels: [\"investor\"]`** (for one target: `get_target_connections` with `connectorLabels`) |\n| **People in my network by label** (\"my investors\", \"who are my advisors\") | `list_network_connections` with `labels` |\n| **How many** (\"how many investors do I know?\", \"how is my network labelled?\", \"how many haven't I rated?\") | `get_label_counts` — one call; then `list_network_connections` with the same filters to see the people |\n| **Label a person** (\"mark Anna as a mentor\", \"she's an investor\") | `set_connector_labels` with `{ add: [\"mentor\"] }` — but \"make them a supporter\" is a **rating**: `set_connector_tier` |\n| **Label a company** (\"Sequoia is an investor\", \"Acme is a customer\") | `find_network_companies` (name → `id`, show every row with its `connectorsCount`) → `set_company_labels` |\n| Hide connections I'd never ask | `set_connector_tier` with `rating: 1` — a rating of 1 hides them |\n| List the ones I already hid | `list_network_connections` with `ratings: [1]` — the rating filter *is* the \"Hidden\" scope; the default listing omits them |\n| How do these two know each other? (connector ↔ target) | `get_target_connections` / `get_connector_intros` / `find_top_paths` — read `relationships` + `relationshipDetails`, and fall back to `scoreDetails` |\n| Account-level view (companies with targets) | `list_accounts` |\n| My saved leads at a specific company | `list_accounts` (name→`id`), then `list_targets` with `accountId` |\n| My saved leads with a specific title/role | `list_targets` with `title` (a title/position substring; optionally + `accountId`) |\n| Best intros to my targets at a specific company | `list_accounts` (name→`id`), then `find_top_paths` with `accountId` |\n| Find NEW people by role at companies I name (I don't have the names) | `search_accounts` (adds targets automatically, paths charged) → wait → `find_top_paths`; the rest via `list_pool` → `confirm_pool` |\n| Find NEW people by role through people I know (\"who can Alice get me to?\") | `search_supporters` (nothing charged, everyone found waits in the pool) → later `list_pool` (its `campaignId`) → tell the user confirming takes them on and charges their paths → `confirm_pool` the ones they want |\n| …and only at companies like my ideal customer (\"VPs of Sales at B2B SaaS companies in the US, through my investors\") | `search_supporters` with `icp` (only what the user said; not with `companies`) → later `list_pool` (`campaignId` + `minIcpFit: 50`) → show the user who fits → `confirm_pool` the ones they pick |\n| Move an intro forward (sent / made / declined) | `set_intro_status` |\n| Raw target / connection / tag data | `list_targets`, `get_target_connections`, `list_tags` |\n| Add new people / supporters to track | `import_targets`, `import_supporters` |\n\n**\"Star\" means the `rating`, and only the `rating`.** It is 1–5, higher is better, and it is the\nonly thing with ★ glyphs. `tier` is the same setting spelled as the raw wire number (1–5, **lower**\nis better) — pass it only when the user already holds tier numbers, and never describe it in stars.\nThe `preferred` flag is a third thing entirely and is **not** a star.\n\n**Legacy — `preferred` and `excluded` (still wired, still work).** The product moved both onto the\nrating, so reach for `set_connector_tier` / `ratings` for every set-and-search intent, and use these\ntwo only when the user explicitly asks for those flags:\n- `set_connector_preferred` (set) and `list_network_connections` with `preferred` (search) drive a separate\n  boolean column. `set_connector_tier` **never writes it** — `rating: 5` does not mark someone\n  preferred, and marking someone preferred does not give them a rating.\n- `set_connector_excluded` hides a connector like `rating: 1` does, but the sync runs **one way**:\n  writing a rating updates the flag, while `excluded: false` does *not* clear a `rating: 1`. To\n  un-hide someone, give them a `rating` of 2–5 — don't un-exclude.\n\nTools marked WRITE change Draftboard data; the host approves each call, but still confirm\ndestructive ones (`archive_target` is **not reversible**) with the user first.\n\nThe full 12-pain playbook — including the jobs the Integration API does **not** yet support and the\nclosest workarounds — is in `references/user-stories.md`. The tool catalog with arguments is in\n`references/tools.md`.\n\n## How to work\n\n- **Labels say who someone is; the rating says whether to ask them.** Labels (`investor`,\n  `close_friend`, …) are set with `set_connector_labels` / `set_company_labels`; \"supporter\" is the\n  2–5 star **rating**, never a label write. `do_not_contact` is only a label and hides nobody — leave\n  those people out only when the user asks. A label count of 0 means nobody has been labelled yet,\n  not that the network holds no such people. Before labelling a company, tell the user how many\n  people it will reach (`connectorsCount`). Token list: `references/tools.md` → **Labels**.\n- **`find_top_paths` is one ranked call, not a scan.** It asks the server for the strongest open\n  paths — one per target, already excluding paths you've requested — and returns at most `limit`\n  (default 20, max 100). Narrow with `accountId`, `tagNames`, `title`, or `ownerIds` to focus the\n  ranked list on what the user actually asked about, not to bound cost. If `telemetry.truncated` is\n  true, more qualifying paths exist than were returned — say so, and raise `limit` or narrow further\n  rather than presenting the page as everything.\n- **Company questions → scope by `accountId`, don't scan.** For \"who do I have at company X\" or\n  \"best intros at company X\", resolve the company with `list_accounts` (name → `id`) and pass\n  `accountId` to `list_targets` / `find_top_paths`. Without it, `find_top_paths` ranks across the\n  whole book and returns only `limit` opportunities — a company's real but weaker paths can be\n  crowded out by stronger ones elsewhere. `accountId` scopes the ranking pool to that company so\n  they surface.\n- **Describe `basis` honestly.** Every opportunity from `find_top_paths` carries a `basis`:\n  `overlap_both_sides` and `overlap_connector_target` are a real shared employer or school — call\n  those strong. `other_quality_signal` is a real, qualifying path with **no** work/school overlap —\n  describe it only from `rankDetails` (e.g. \"you both know 500 people\") and never call it \"strong\".\n- **Company-first discovery adds targets on its own — say so before launching.** `search_accounts`\n  (companies + titles) only *starts* a search and returns a `campaignId` — it does not return people.\n  People it finds are normally added as targets **automatically**, up to a limit per company, and their\n  warm paths are charged like any target's; only the ones beyond that limit wait in the pool for review.\n  Everyone arrives asynchronously with no completion signal. The review step: `list_pool` (filter by that\n  `campaignId`), then `confirm_pool` the ones the user wants (charged the same way) and `reject_pool` the\n  rest. An empty pool right after a search means results may not be ready yet — it does not mean the search has finished. **Every call\n  launches a new search** — never repeat one to retry or to check on it.\n- **Supporter-first discovery puts everyone in the pool — the charge comes at `confirm_pool`.**\n  `search_supporters` (supporters' LinkedIn profile URLs + titles, optionally companies) searches the\n  networks of people the user knows. Launching it charges nothing and takes nobody on: everyone it\n  finds waits in the pool for review. Someone the user rejected earlier stays rejected. It returns\n  `status`, `errors`, a `campaignId` and counts of supporters accepted / not accepted — not the people\n  found, who arrive over time with no completion signal. Check back later with `list_pool` (filter by\n  that `campaignId`); an empty pool soon after means results may not be ready yet — it does not mean the search has finished. **Before\n  `confirm_pool`,** tell the user that confirming takes those people on as targets and their warm paths\n  are then charged; confirm the ones they want in one batch and `reject_pool` the rest. **Every call\n  launches a new search** — never repeat one to retry or to check on it. It does not change anyone's\n  rating.\n- **An ideal customer scores everyone a supporter search finds — it hides nobody.** `search_supporters`\n  takes an optional `icp` (`industry`, `companySize`, `location`, `description`, at least one). Take\n  it **only from what the user said** — never infer or fill in an ideal customer they did not\n  describe. It cannot be combined with `companies`. Each pool row then carries `icpFits`\n  (`campaignId`, `percent` 0–100, `reason`); no `percent` means the search **could not assess** that\n  person — not a poor fit, and not 0. A person **fits** when `percent` is 50 or more — that is the\n  product's threshold; do not invent others. The pool returns everyone whatever their fit; to keep a\n  review short, read `list_pool({ campaignId, minIcpFit: 50 })` (`minIcpFit` needs `campaignId`, and\n  leaves out the people the search could not assess) rather than paging through everyone. Show the\n  user who fits and say the rest are a poor fit or could not be assessed; confirm only the people\n  they choose — never on the fit alone.\n- **Stay inside these tools.** They are the only sanctioned way to reach Draftboard. If a request\n  isn't possible with them, say so plainly and stop (or point to the app) — never run raw API\n  calls, read API keys from config/files, query a database, or brute-force by paging thousands of\n  records. Don't import people as targets just to answer an exploratory question (that changes the\n  user's data) without explicit approval.\n- **Be honest about coverage.** Always surface counts from `telemetry` (e.g. \"returned 20 of 142\n  qualifying paths\"). Never imply you saw every opportunity when `truncated` is true.\n- **Connector by name (e.g. \"paths through Jane Smith\").** The API filters connections by team\n  member (`ownerIds`), not by connector name. Run `find_top_paths`, then filter the opportunities\n  client-side on the `connector` field, and say you did.\n- **An import is accepted, not finished — and there are TWO waits, not one.** Getting this wrong is\n  how a perfectly good import gets reported to the user as a failure.\n  1. **The target row: about half a minute.** Confirm with `resolve_target`, which finds a saved\n     target as soon as the batch lands. `check_if_connected` reports it as `import_pending` until\n     then and tells you when to look again.\n  2. **Its warm-intro paths: minutes** — 14 minutes on a large network. Only after that does the\n     person appear in `list_targets` or carry connectors.\n\n  So `list_targets` answers neither question right after an import: it returns only targets that\n  **already have a path**. \"Not in `list_targets`\" never means \"not saved\" — say the paths are\n  still being computed, and re-check, rather than reporting the person as missing or path-less.\n- **Name-drop responsibly.** A connector's `rankDetails`/`scoreDetails` (shared history) describes the\n  **connector↔target** relationship — why *that* connector can introduce *that* target. It is **not**\n  the user's own background and not the user↔connector history. Use it for the warm line about that\n  specific intro, mention only real returned facts, and never present it as a fact about the user or\n  invent a shared connection. (The teammate↔connector tie is a bare score with no reason exposed.)\n  **The same rule covers `relationships` and `relationshipDetails`**: `current_colleague` means the\n  connector and the *target* work together now, and an `employment.company` is *their* shared\n  employer — never the user's. Don't say \"you both worked at X\" off these fields.\n- **A missing `relationships`/`relationshipDetails` is not a weak connector.** Both keys are present\n  when Draftboard holds that signal for the pair and simply **absent** when it does not (never `[]`),\n  so read them as `connection.relationships ?? []`. Absence means \"no structured signal for this\n  pair\", **not** \"these two have no relationship\": **promote on the signal, never demote on its\n  absence** — never drop, downrank, or apologise for a connector on that basis, and keep using\n  `scoreDetails`, which carries the human-readable summary (read it as `scoreDetails ?? []` — it too\n  is omitted when there is nothing to say). The three `relationships` values are exactly\n  `current_colleague`, `former_colleague`, `university_classmate`. The two fields are independent —\n  a shared-contacts-only signal gives a `relationshipDetails` record and **no** `relationships`\n  entry — so never derive or align one from the other. Details in `references/tools.md` →\n  **Field notes**.\n- **Tagging or describing connectors/supporters — don't invent a backstory.** The tools return a\n  connector's name, LinkedIn URL, position, `rank`, and (for an intro) `rankDetails` — **not** their\n  bio, seniority, or personal background. When you tag, rate, or describe a supporter, use only\n  user-provided facts or fields actually returned; never infer *whose* network it is, their role, or a\n  shared history with the user. If asked to tag supporters \"by <something>\" you can't verify from\n  returned data, say what you're basing the tag on (e.g. the user's own words) rather than guessing.\n\n## Output\n\nLead with the answer (the top opportunities, the yes/no, the status numbers), then the supporting\ndetail. For each intro opportunity, name the **connector**, the **target**, the **rank**, and the\n**reason** (`rankDetails`). Keep it skimmable.\n"},"changes":[],"summary":"First saved snapshot. No earlier version is available for comparison.","summary_kind":"deterministic","summary_metadata":{}}