The outreach data layer for AI agents. Syncs events, replies, and lead attributes from Smartlead, Instantly, Heyreach, PlusVibe, and EmailBison into a local SQLite database your agent can query directly. Use for pipeline views, client briefings, deliverability diagnostics, campaign breakdowns, segment performance, and reply copy insights. Webhook payloads pass through api.outreachmagic.io; your data lives in a local SQLite file on your machine. Free tier: Hermes tracking plus relay (100 events/mo). Pro: unlimited sequencer sync.
Resources
7Install
npx skillscat add outreachmagic/cursor-skill Install via the SkillsCat registry.
Outreach Magic — Pipeline Visibility for Hermes
The simplest pipeline tracker. Hermes auto-logs every outreach action to a local
SQLite database. Free forever. Connect Smartlead, Heyreach, Instantly via paid relay.
Database: ~/.hermes/skills/outreachmagic/databases/outreachmagic.db
Config (single source of truth): ~/.hermes/skills/outreachmagic/config/outreachmagic_config.json
Optional config keys: data_root (e.g. ~/.claude for Claude Code), api_base_url, dev_repo for local development.
Environment variable: OUTREACHMAGIC_AGENT_KEY — overrides the config file agent_key. Set via .env, shell profile, or CI/CD.
First-Time Setup (IMPORTANT — read this first)
On startup, always check if the agent is already connected by running:
python3 ~/.hermes/skills/outreachmagic/scripts/pipeline.py versionThen check whether an agent key exists in the config:
python3 ~/.hermes/skills/outreachmagic/scripts/pipeline.py pullIf pull returns an error like "No agent key or token configured", the user needs to set up.
When setup is needed, tell the user exactly this:
To get started, you need an Agent Key. Two steps:
- Go to https://dev.outreachmagic.io/setup/agent — sign up (or log in) and click "Create Agent Key"
- Copy the key and paste it back here
I'll handle the rest.
Then wait for the user to paste a key (starts with om_agent_). Once they do, run:
python3 ~/.hermes/skills/outreachmagic/scripts/pipeline.py init
python3 ~/.hermes/skills/outreachmagic/scripts/pipeline.py setup --key <PASTED_KEY>init creates the database and project folders (input/, export/, agent_resources/ under ~/.hermes/skills/outreachmagic/project by default). Override with "project_root" in config.
That's it. Don't list other commands, don't offer alternatives. Just: go get a key, paste it, done.
When setup is already done (pull succeeds or returns events), skip setup and go straight to showing data:
python3 ~/.hermes/skills/outreachmagic/scripts/pipeline.py pull
python3 ~/.hermes/skills/outreachmagic/scripts/pipeline.py showNetwork & privacy (Hermes / hub review)
- Default: All lead and pipeline data stays in local SQLite.
- Inbound only:
pullimports webhook/agent events fromapi.outreachmagic.io(user- or cron-initiated). - Outbound upload: Only when the user (or agent following user instruction) runs
pipeline.py sync. Import and local edits never auto-upload. - Update check: The CLI may query GitHub for a newer release tag (read-only, no lead data; at most once per hour). See SECURITY.md.
Version
One version for the whole skill. To see what is installed, always run:
python3 ~/.hermes/skills/outreachmagic/scripts/pipeline.py versionThe version: line in this file is synced from scripts/VERSION on install/update. If unsure, use the command above.
Updates are user-triggered. The CLI may print an update notice (at most once per hour) when a newer GitHub release exists. It never downloads or replaces scripts automatically. Install updates with:
python3 ~/.hermes/skills/outreachmagic/scripts/pipeline.py update
# or
hermes skills updateCheck without installing: pipeline.py update --check. Install a specific release: pipeline.py update --tag v1.4.5.
Install
git clone https://github.com/outreachmagic/hermes-skill.git /tmp/om-hermes
mkdir -p ~/.hermes/skills/outreachmagic
cp -r /tmp/om-hermes/{SKILL.md,scripts,references} ~/.hermes/skills/outreachmagic/
rm -r /tmp/om-hermes
python3 ~/.hermes/skills/outreachmagic/scripts/pipeline.py init
hermes -s outreachmagicLocal dev sync: bash scripts/sync-local.sh from a clone. See docs/install.md.
When to Use
- You are about to send outreach (email, LinkedIn message, WhatsApp, etc.)
- You are researching a prospect and want to track them
- The user asks "show me my pipeline" or "how is outreach going"
- The user says "track this" followed by outreach details
- The user wants to connect a sequencer (paid — requires token)
- The user asks for campaign breakdowns or counts by campaign name
- The user asks about connection status, webhook URLs, or platform health (
status,connections) - The user wants to add or remove a platform connection (
connect-platform,disconnect-platform)
Agent Behavior Rules (Important)
- For bulk enrichment (CSV, spreadsheet export, Apollo/Clay dump): use
import-profiles, not repeatedadd-lead. - Always run
pullfirst before showing pipeline data, history, stats, or campaigns. - After any pull, explicitly report the exact number of new records imported.
- When the user asks about version, read the frontmatter of SKILL.md (version line).
- When the user asks for message content, use the
historycommand on the specific lead. - For copy-performance analysis (full subject/body on positive leads + winner), use
copy-insights. - For campaign counts, use
pipeline.py campaigns(orstats, which includes a campaign section). Do not write raw SQL. - When the user asks about connections, webhook URLs, or platform health, use
statusorconnections. - When the user wants to connect a new platform, use
connect-platform --platform <id>. - NEVER use
python3 -c,sqlite3directly, raw SQL, or any inline script to inspect or modify the database. All database operations must go throughpipeline.pycommands. If a command errors, report the error verbatim and stop — do not attempt to debug by accessing the database directly.
MANDATORY: Always Pull First
Before showing any pipeline data (show, stats, campaigns, history, or any query), you MUST run pull first.
python3 ~/.hermes/skills/outreachmagic/scripts/pipeline.py pullThis fetches the latest events from the relay, so the user always sees current data. The local DB may be stale. Never skip this step — even if the user just asks "how's my pipeline" or "any activity?" — pull first, then show. This applies across sessions: a new session's first pipeline query must pull.
Free Tier
- Unlimited Hermes-originated tracking
- CLI pipeline view + web dashboard
- Pipeline stages with auto-advancement
- 100 relay events/month
Pro Tier ($19/mo)
- Unlimited relay events
- Smartlead, Heyreach, Instantly, PlusVibe, EmailBison sync
- Multi-platform unified pipeline
Sign up at https://outreachmagic.io
Quick Start
python3 ~/.hermes/skills/outreachmagic/scripts/pipeline.py version
python3 ~/.hermes/skills/outreachmagic/scripts/pipeline.py show
python3 ~/.hermes/skills/outreachmagic/scripts/pipeline.py history --id 1
python3 ~/.hermes/skills/outreachmagic/scripts/pipeline.py history --email j@acme.com
python3 ~/.hermes/skills/outreachmagic/scripts/pipeline.py stats
python3 ~/.hermes/skills/outreachmagic/scripts/pipeline.py campaigns
python3 ~/.hermes/skills/outreachmagic/scripts/pipeline.py copy-insights --lead-status interested --json
python3 ~/.hermes/skills/outreachmagic/scripts/pipeline.py import-profiles --file leads.csv
python3 ~/.hermes/skills/outreachmagic/scripts/pipeline.py export-local
python3 ~/.hermes/skills/outreachmagic/scripts/pipeline.py export-local --file changes.csvStatus and connection management
Dashboard-style status, connection management, and webhook URL generation — all from the CLI. These commands talk to the app API and do not require a local database.
# Dashboard overview: plan, usage, per-platform health, routing
python3 ~/.hermes/skills/outreachmagic/scripts/pipeline.py status
# List all connections with webhook URLs and 30-day event counts
python3 ~/.hermes/skills/outreachmagic/scripts/pipeline.py connections
python3 ~/.hermes/skills/outreachmagic/scripts/pipeline.py connections --json
# Generate a webhook URL for a new platform
python3 ~/.hermes/skills/outreachmagic/scripts/pipeline.py connect-platform --platform smartlead
# Remove a platform connection (webhook URL stops working)
python3 ~/.hermes/skills/outreachmagic/scripts/pipeline.py disconnect-platform --platform smartlead
python3 ~/.hermes/skills/outreachmagic/scripts/pipeline.py disconnect-platform --platform smartlead --yesExport local changes for cross-platform sync
Export locally-created leads and events (not from relay) as JSON or CSV. Useful for transferring data between platforms (Cursor, Hermes, Claude Code).
# JSON to stdout (pipe to relay push or save to file)
python3 ~/.hermes/skills/outreachmagic/scripts/pipeline.py export-local
# CSV file (import-profiles compatible)
python3 ~/.hermes/skills/outreachmagic/scripts/pipeline.py export-local --file local_changes.csv
# Filter to a specific workspace
python3 ~/.hermes/skills/outreachmagic/scripts/pipeline.py export-local --workspace leadgenph
# Include all leads (not just locally-created)
python3 ~/.hermes/skills/outreachmagic/scripts/pipeline.py export-local --allPush to relay for cross-platform sync:
python3 ~/.hermes/skills/outreachmagic/scripts/pipeline.py syncsync pushes pending lead snapshots (profile, external_id, company_domain, HQ/location, tags, mailmerge, workspace status, LinkedIn connection flags) plus local events. Other machines run pull --full after a DB reset to restore everything that was synced.
Fresh DB + full CSV round-trip:
pipeline.py import-profiles --file nace.csv --workspace popcam --import-batch-id nace-2026
pipeline.py sync
# new machine:
pipeline.py init && pipeline.py pull --fullFile-based transfer (no server):
# Machine A: export
pipeline.py export-local --file changes.csv
# Machine B: import
pipeline.py import-profiles --file changes.csv --overwriteCampaign breakdown
Relay imports auto-populate campaign names from webhook payloads (Smartlead, PlusVibe, etc.).
python3 ~/.hermes/skills/outreachmagic/scripts/pipeline.py campaigns
python3 ~/.hermes/skills/outreachmagic/scripts/pipeline.py campaigns --jsonstats also includes a campaign section. Use campaigns when the user only wants counts by campaign name.
PlusVibe webhooks (status + sentiment)
Point PlusVibe webhooks at your relay URL (…/plusvibe/{token}). Subscribe separately to:
- Reply events:
ALL_EMAIL_REPLIES(and optionalFIRST_EMAIL_REPLIES,ALL_POSITIVE_REPLIES) - Label/status events:
LEAD_MARKED_AS_INTERESTED,LEAD_MARKED_AS_NOT_INTERESTED,LEAD_MARKED_AS_OUT_OF_OFFICE, plus any customLEAD_MARKED_AS_*labels
Hermes stores each webhook as an event. Interested / not interested / sentiment come from label webhooks, not from reply webhooks alone. OOO is classified as auto-reply (metadata flag, query with --auto-reply true). Bounces set event sentiment invalid but do not auto-move the lead to stage lost (use --sentiment invalid to find them).
After pull, filter the pipeline by current status (latest status-bearing event per lead):
python3 ~/.hermes/skills/outreachmagic/scripts/pipeline.py show --sentiment positive
python3 ~/.hermes/skills/outreachmagic/scripts/pipeline.py show --sentiment invalid
python3 ~/.hermes/skills/outreachmagic/scripts/pipeline.py show --auto-reply true
python3 ~/.hermes/skills/outreachmagic/scripts/pipeline.py show --lead-status interested --jsonFilter by date (created or updated on/after a date):
python3 ~/.hermes/skills/outreachmagic/scripts/pipeline.py show --since today
python3 ~/.hermes/skills/outreachmagic/scripts/pipeline.py show --since 2026-05-26 --json
python3 ~/.hermes/skills/outreachmagic/scripts/pipeline.py lead-table --workspace popcam --since today --jsonThen open full timeline for any lead (all events, not just the status event):
python3 ~/.hermes/skills/outreachmagic/scripts/pipeline.py history --id 1Native copy-performance analysis (full message bodies + best template):
python3 ~/.hermes/skills/outreachmagic/scripts/pipeline.py copy-insights --lead-status interested
python3 ~/.hermes/skills/outreachmagic/scripts/pipeline.py copy-insights --lead-status interested --jsonshow --json and lead-table --json include personalization, tags, and latest_sender when available.
Export full profiles (CSV / JSON)
python3 ~/.hermes/skills/outreachmagic/scripts/pipeline.py export --workspace popcam --tag nace --format csv
python3 ~/.hermes/skills/outreachmagic/scripts/pipeline.py export --workspace popcam --since today --format jsonWrites to export/ by default. CSV uses personalized_first_name, personalized_company_name, plus lead fields, tags, HQ, and latest_sender.
Reset local database (schema upgrade)
rm ~/.hermes/skills/outreachmagic/databases/outreachmagic.db
python3 ~/.hermes/skills/outreachmagic/scripts/pipeline.py init
python3 ~/.hermes/skills/outreachmagic/scripts/pipeline.py pull --fullLinkedIn IDs (v1.17): Public profiles are stored in linkedin_url as linkedin.com/in/handle (no https://). Sales Nav (ACwAA…) and member IDs (urn:li:member:…) are stored as identity aliases and used for matching when the public slug arrives later.
Core Workflow
View a lead's full timeline
python3 ~/.hermes/skills/outreachmagic/scripts/pipeline.py history --id 1
python3 ~/.hermes/skills/outreachmagic/scripts/pipeline.py history --email jane@acme.com
python3 ~/.hermes/skills/outreachmagic/scripts/pipeline.py history --name "Jane Doe"
python3 ~/.hermes/skills/outreachmagic/scripts/pipeline.py history --id 1 --jsonOutputs lead info + numbered event timeline with direction arrows (← inbound, → outbound),
human-readable timestamps, and event details.
Add leads when researching prospects
python3 ~/.hermes/skills/outreachmagic/scripts/pipeline.py add-lead \
--name "Jane Doe" --company "Acme Corp" --title "VP Marketing" \
--industry "Martech" --headcount "50-200" \
--email "jane@acme.com" \
--channel email --stage prospectingTo also associate the lead with a workspace at creation time:
python3 ~/.hermes/skills/outreachmagic/scripts/pipeline.py add-lead \
--name "Jane Doe" --email "jane@acme.com" --company "Acme Corp" \
--workspace thesystemsmethod --stage contacted--workspace is optional on add-lead — creating a lead is an org-wide operation. Use it when you know which workspace the lead belongs to; omit it when just researching.
If lead exists by email or LinkedIn, returns {"status": "exists", "id": N} (does not enrich existing rows — use import-profiles for that).
Bulk import / enrich (CSV, JSON, research dumps)
Use import-profiles for spreadsheets, enriched exports, or batched research — not repeated add-lead calls. Matching uses tiered identities (strongest first): external_id → email → LinkedIn → phone → name+domain → name+company → import_key (name-only rows). CSV columns unified_lead_id / source_id are accepted as aliases and stored as external_id. Fills empty fields only (same as relay/PlusVibe); use --overwrite to replace existing values.
python3 ~/.hermes/skills/outreachmagic/scripts/pipeline.py import-profiles \
--file input/contacts_enriched.csv
python3 ~/.hermes/skills/outreachmagic/scripts/pipeline.py import-profiles \
--file leads.json
python3 ~/.hermes/skills/outreachmagic/scripts/pipeline.py import-profiles \
--json '[{"email":"j@acme.com","name":"Jane","job_title":"VP Marketing","industry":"Martech","headcount":"11-50","company":"Acme"}]'
python3 ~/.hermes/skills/outreachmagic/scripts/pipeline.py import-profiles \
--file contacts.csv --dry-run
# With workspace association, tags, and LinkedIn status tracking
python3 ~/.hermes/skills/outreachmagic/scripts/pipeline.py import-profiles \
--file contacts.csv --workspace default --sender-profile "https://linkedin.com/in/myprofile" \
--source-detail "Q2 Apollo list" --import-batch-id "nace-2026-05"
# Rows with only name + company_domain + unified_lead_id (no email/LinkedIn)
python3 ~/.hermes/skills/outreachmagic/scripts/pipeline.py import-profiles \
--file nace.csv --workspace popcam --import-batch-id nace-2026-05Core profile fields (column aliases — first non-empty wins):
| Canonical field | Aliases | Required |
|---|---|---|
email |
lead_email, work_email |
No (see identity tiers below) |
linkedin |
linkedin_url, lead_linkedin_url, profile_url |
No |
name |
full_name, display_name (or first_name + last_name) |
No |
title |
job_title, role |
No |
company |
company_name, organization, org |
No |
industry |
— | No |
headcount |
company_size, employees, employee_count |
No |
location_city |
city, lead_city |
No |
location_state |
state, region, lead_state |
No |
location_country |
country, lead_country |
No |
Headcount normalization: headcount is stored as-is (text) plus a computed headcount_numeric (integer midpoint). Ranges like "11-50" become 30, "500+" becomes 500, exact numbers pass through. Both leads and companies get the numeric column for sorting/filtering (WHERE headcount_numeric BETWEEN 10 AND 100).
Extra fields (auto-detected from CSV columns):
| Column | Effect |
|---|---|
company_domain |
Stored in companies table, normalized (strips protocol/www/path) |
hq_city / hq_state / hq_country |
Company HQ location, stored on companies table |
mailmerge_first_name |
Auto-populated as first_name in personalization table |
mailmerge_company_name |
Auto-populated as company_name in personalization table |
import_name / list_source |
Attribution + namespace for external_id when value has no : |
external_id |
CRM/list ID in lead_identities (namespaced list_source:id if bare) |
unified_lead_id, source_id |
Import aliases → same as external_id |
import_batch_id (CLI flag) |
Stable dedupe for name-only rows via import_key within a batch |
lead_status |
Requires --workspace; normalized (lowercase, spaces) and set on workspace_leads |
lead_sentiment |
Requires --workspace; normalized (lowercase) and set on workspace_leads |
tags |
Requires --workspace; semicolon or comma separated, normalized (lowercase), stored in workspace_lead_tags |
contact_order |
Requires --workspace; integer priority stored as contact_priority on workspace_leads |
is_connected_linkedin |
Requires --workspace + --sender-profile; true/1/yes sets connected status |
is_linkedin_request_pending |
Requires --workspace + --sender-profile; true/1/yes sets pending status |
Normalization rules:
- Tags: lowercased, whitespace collapsed —
"VIP"and"vip"are the same tag - Status/sentiment: lowercased, underscores to spaces —
"Not_Interested"becomes"not interested" - Headcount: range string preserved + numeric midpoint computed (
"11-50"→ 30) - Location: stored as-is (city/state/country text)
Attribution is automatic: every import sets original_source (immutable first touch) and latest_source (updates each time) on the lead, following the Salesforce/HubSpot model. The --source-detail flag or import_name/list_source columns provide the detail.
Personalization (mail-merge fields)
Store agent-computed normalized values for email templates. Default fields: first_name, company_name. Add custom fields as needed (e.g., icebreaker, ps_line).
# List leads needing personalization (defaults to first_name,company_name)
python3 ~/.hermes/skills/outreachmagic/scripts/pipeline.py personalize-pending --json
python3 ~/.hermes/skills/outreachmagic/scripts/pipeline.py personalize-pending --fields first_name,company_name,icebreaker --json
# Write values (single or batch)
python3 ~/.hermes/skills/outreachmagic/scripts/pipeline.py personalize-set --lead-id 5 --field first_name --value "Spencer"
python3 ~/.hermes/skills/outreachmagic/scripts/pipeline.py personalize-set --batch --json '[{"lead_id":5,"field":"first_name","value":"Spencer"}]'
# Read values / check status
python3 ~/.hermes/skills/outreachmagic/scripts/pipeline.py personalize-get --lead-id 5 --json
python3 ~/.hermes/skills/outreachmagic/scripts/pipeline.py personalize-statusPersonalization syncs across platforms via push/pull. The agent decides normalization logic — pipeline.py only stores values.
Email verification tracking (org-wide)
Record verification results from tools like ZeroBounce, NeverBounce, etc. Results are org-wide (not workspace-scoped). Platform bounces from Smartlead, Instantly, etc. are auto-recorded during relay sync.
# Record a verification result
python3 ~/.hermes/skills/outreachmagic/scripts/pipeline.py verify-email \
--lead-id 5 --status valid --source zerobounce
# Batch verify from JSON
python3 ~/.hermes/skills/outreachmagic/scripts/pipeline.py verify-email --batch \
--json '[{"lead_id":5,"status":"valid","source":"zerobounce"}]'
# Check verification status for a lead
python3 ~/.hermes/skills/outreachmagic/scripts/pipeline.py verify-status --lead-id 5
python3 ~/.hermes/skills/outreachmagic/scripts/pipeline.py verify-status --email j@acme.com
# List leads needing verification
python3 ~/.hermes/skills/outreachmagic/scripts/pipeline.py verify-pending --limit 50 --jsonVerification status values: valid, invalid, catch-all, unknown, spamtrap, abuse, do_not_mail, risky, bounced, soft_bounce
Bounce handling: Platform bounces (from relay sync) are auto-recorded in lead_email_verification with source="platform_bounce". Hard bounces override soft bounces. Tool verifications (ZeroBounce, etc.) take precedence over platform bounces — a tool "valid" result is only overridden by a hard bounce that came after the verification. The consolidated status is materialized on leads.email_verification_status for fast filtering.
Companies and unified lead identity
companiestable — canonical company name, domain, industry, headcount (text + numeric midpoint), HQ location (city, state, country). Leads link viacompany_id(business email domain or company name on ingest).- Match by email and/or LinkedIn — a lead can have email only, LinkedIn only, or both. Relay ingest resolves identity from webhook payload + envelope
leadfield. - Merge duplicates when email and LinkedIn history were separate rows:
- Auto: ingest with both identifiers matching two leads merges them (keeps row with more events).
- Manual:
python3 ~/.hermes/skills/outreachmagic/scripts/pipeline.py merge-leads --keep 12 --merge 34
python3 ~/.hermes/skills/outreachmagic/scripts/pipeline.py merge-leads \
--email j@acme.com --linkedin linkedin.com/in/janedoepython3 ~/.hermes/skills/outreachmagic/scripts/pipeline.py history --linkedin linkedin.com/in/janedoeAfter pull, use campaigns for per-campaign event and lead counts (unchanged).
Log every outreach send
python3 ~/.hermes/skills/outreachmagic/scripts/pipeline.py log-event \
--lead-id 1 --type email_sent --direction outbound \
--subject "Quick intro" --workspace thesystemsmethod--workspace is required in multi-workspace mode. Outreach events are workspace-scoped — they belong to a specific pipeline. In single-workspace mode it falls back to the default workspace.
Update stage and log replies
python3 ~/.hermes/skills/outreachmagic/scripts/pipeline.py update-stage \
--id 1 --stage replied --next-action "Send case study" --workspace thesystemsmethod--workspace is required in multi-workspace mode. Stage is per-workspace — a lead can be "contacted" in one workspace and "interested" in another.
Stages: prospecting -> contacted -> replied -> interested -> proposal -> won | lost
Connect sequencers (paid)
If the user already has a key, skip the browser flow:
python3 ~/.hermes/skills/outreachmagic/scripts/pipeline.py setup --key om_agent_THEIR_KEYGenerate webhook URLs for platforms directly from the CLI (requires agent key):
python3 ~/.hermes/skills/outreachmagic/scripts/pipeline.py connect-platform --platform smartlead
python3 ~/.hermes/skills/outreachmagic/scripts/pipeline.py connect-platform --platform instantly
python3 ~/.hermes/skills/outreachmagic/scripts/pipeline.py connectionsUpdate skill scripts
python3 ~/.hermes/skills/outreachmagic/scripts/pipeline.py updateLead Fields Reference
| Field | CLI flag | Notes |
|---|---|---|
| name | --name |
Required |
| company | --company |
|
| title | --title |
Job title |
| industry | --industry |
e.g. Martech, Fintech, Healthcare |
| headcount | --headcount |
Size band, e.g. 1-10, 50-200, 1000+ |
--email |
Dedup key — unique per lead | |
--linkedin |
LinkedIn profile URL | |
| channel | --channel |
email, linkedin, whatsapp (default: email) |
| stage | --stage |
Pipeline stage (default: prospecting) |
| notes | --notes |
Free-form |
| tags | --tags |
JSON array string like '["vip","enterprise"]' |
| workspace | --workspace |
Optional on add-lead; required on log-event and update-stage in multi-workspace mode |
Privacy & Security
- Local-first data. Pipeline leads, events, and campaign stats live in
~/.hermes/skills/outreachmagic/databases/outreachmagic.dbon your machine. - Relay pass-through. Webhooks hit
api.outreachmagic.io; the CLI imports them locally viapull. We store tokens and usage on our side, not a searchable cloud copy of your outreach archive. - Portal API.
dev.outreachmagic.io(production: app.outreachmagic.io) handles tokens, billing, and optional workspace routing sync when connected. - Credentials. Store relay tokens in
config/outreachmagic_config.jsononly. Never hardcode tokens in SKILL.md or commit them to git. - Read before connect. See repo root SECURITY.md for full data boundaries and vulnerability reporting.
Common Pitfalls
- Always pull before show when checking "latest activity."
- Forgetting add-lead before log-event
- Not updating stage after reply
- Setup requires an Agent Key — get one at https://dev.outreachmagic.io/setup/agent
- Version: run
pipeline.py version— do not guess from SKILL.md frontmatter alone. - Relay archive stays on api.outreachmagic.io;
pulldedupes locally. Usepull --fullafter deleting the local DB. add-leadon an existing email does not enrich — useimport-profilesor rely on relaypullfor fill-if-empty updates.