Draft outreach
Produces send-ready outreach copy (LinkedIn, email, InMail) from user intent and optional networking-strategist handoffs. Invokes writer. Prior communication history is folded in by default when mail/calendar connectors exist—via contact-context and ContactContextBrief—unless the user skips or the message is truly generic/cold with no named recipient.From its SKILL.md
npx -y skills add tmargolis/career-navigator --skill draft-outreachAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 14 stars14 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
5.6 KB, as published. Nobody here has run it
Invoke writer in draft-outreach mode.
Invocation
- Use the exact agent name
writer. Retry once with the same name if invocation fails.
Workflow
Application data uses the split layout defined in references/tracker-schema.md — read it before any read or write.
-
Prior communication history (enrichment — default for named recipients): Outreach to a specific person or known contact at a company should be grounded in real mail/calendar context when the host allows—not guesswork.
- If a ContactContextBrief is already in chat → use it as-is (full block to
writer). - Else if Gmail/M365 inbox and/or calendar tools appear in this session → run
contact-contextend-to-end before invokingwriter, unless the user explicitly says to skip history (“no prior thread,” “brand-new contact,” “template only”) or the ask is purely generic with no named recipient yet. Do not invent threads. - Else (no mail/calendar tools in session) → still invoke
writer, but pass a single line:Prior communication:not retrieved — inbox/calendar tools not available in this session; do not imply prior email or meetings.
If the user says they sent mail but the address was wrong or search is empty, follow
contact-context“User said they sent”;email_address_notescarries address candidates. Includecalendar_notes,upcoming_meetings, andwarm_networkingin the handoff when present—ifupcoming_meetingsis non-empty, outreach should not read as a cold first touch. - If a ContactContextBrief is already in chat → use it as-is (full block to
-
Read
{user_dir}/CareerNavigator/profile.mdand{user_dir}/CareerNavigator/voice-profile.md(create stub if missing). -
Voice preflight: If
voice-profile.mdhas no user-pasted block under## User writing samplesor## User writing samples (launch)(substantive excerpts), ask before invokingwriter: paste 2–5 LinkedIn posts or short professional writing; mention optional launch voice harvest (résumé/CV/cover text from disk); user may reply skip (low voice match). If they paste, append a dated## User writing samplessection. If samples already exist, skip this ask. -
From conversation, capture: channel, recipient archetype (title/company if known), objective (info chat, referral check-in, post-event ping), and any StrategistHandoff, ContactContextBrief, or facts the user pasted.
-
Pass a structured brief to
writerindraft-outreachmode. Required: include the full## ContactContextBriefmarkdown block when available, or thePrior communication:fallback from step 0.writermust thread summary, open_loops, hooks_for_writer, calendar_notes, upcoming_meetings, and warm_networking into the draft when present—seeagents/writer/AGENT.md. Do not draft final copy in this skill—delegate. -
Present
writeroutput (variants if offered). Remind: connectors support warm threading when available. -
Sent confirmation + auto-track: After presenting the copy, say:
"Let me know when you've sent this and I'll log it to your tracker."
When the user confirms (e.g. "sent", "I sent it", "done", "sent it just now"), write the multi-file transaction from references/tracker-schema.md — never update one file and leave the others stale:
- Read
{user_dir}/CareerNavigator/tracker.json(summary rows only) and find a row for the same company - If a matching row exists, load
{user_dir}/CareerNavigator/+ itscontacts_file(contacts/<company-slug>.json) — take the path from the row, never derive the slug yourself. Find the entry whosenamematches the recipient and whoseapplicationequals the row'sapplicationlabel, and append to that contact'sinteractions[]:
If the row has no{ "date": "YYYY-MM-DD", "type": "linkedin | email", "notes": "Sent outreach: {one-line summary of message objective}" }contacts_file, or the person is not in it yet, add the contact per the schema's Adding or updating a contact rules (createcontacts/<slug>.jsonif needed, setapplicationto the row's label, recomputecontact_countin both the file and the row). Also append tonotes[]in{user_dir}/CareerNavigator/+ the row'sdetail_file(applications/<application_id>.json):{ "date": "YYYY-MM-DD", "text": "Outreach sent via {channel} to {recipient} — {objective}" }, then set the row'snotes_countto the new array length Update the summary row'snext_stepto "Await response" - If no matching application exists but the recipient is at a target company: offer to log a new networking entry in
networking.jsonundernetworking[] - Confirm:
Logged: outreach to {recipient} at {company} ({channel}) — {date}
- Read
Notes
- If the user only has strategy questions, point them to
networking-strategy/network-mapfirst, then return here for copy.