outreachmagic

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Outreach Magic

Outreach Magic

Your agent goes blind after send. We sync Smartlead, Instantly, HeyReach, and 5 more sequencers into one local SQLite database your agent can query directly.
The full suite: Pair with lead-enrich for Serper-based person research and email-finder for waterfall email enrichment. Both work standalone or together.
你的Agent在发送消息后会失去后续数据视野。我们将Smartlead、Instantly、HeyReach及另外5种序列器的数据同步到本地SQLite数据库,让你的Agent可以直接查询。
完整套件: 搭配基于Serper的人物调研工具lead-enrich,以及瀑布式邮箱富集工具email-finder使用。两者既可以独立运行,也可以配合使用。

CLI convention

CLI 约定

All commands below use the pipeline CLI in this skill's
scripts/
directory (run from the skill root, or use absolute paths from
pipeline.py paths
):
bash
python3 scripts/pipeline.py <command>
Resolve install paths anytime:
bash
python3 scripts/pipeline.py paths
Optional config keys:
data_root
(share one DB across platforms),
api_base_url
,
dev_repo
for local development.
以下所有命令均使用本skill的
scripts/
目录中的pipeline CLI(从skill根目录运行,或使用
pipeline.py paths
返回的绝对路径):
bash
python3 scripts/pipeline.py <command>
随时查看安装路径:
bash
python3 scripts/pipeline.py paths
可选配置项:
data_root
(跨平台共享一个数据库)、
api_base_url
、用于本地开发的
dev_repo

Platform install

平台安装

Install from outreachmagic/outreachmagic — pin a release tag; download and verify SHA256 before running locally:
bash
OM_VERSION=v1.1.0
INSTALL_DIR=$(mktemp -d)
curl -fsSL "https://github.com/outreachmagic/outreachmagic/releases/download/${OM_VERSION}/install.sh" -o "${INSTALL_DIR}/install.sh"
curl -fsSL "https://github.com/outreachmagic/outreachmagic/releases/download/${OM_VERSION}/SHA256SUMS" -o "${INSTALL_DIR}/SHA256SUMS"
grep ' install.sh$' "${INSTALL_DIR}/SHA256SUMS" | (cd "${INSTALL_DIR}" && shasum -a 256 --check)
bash "${INSTALL_DIR}/install.sh" --platform hermes --tag "${OM_VERSION}"
Installs outreachmagic, lead-enrich, and email-finder. Agent guide: AGENTS-INSTALL.md.
Use
--platform cursor
or
--platform claude
for other agents. Setup: https://app.outreachmagic.io/onboarding
outreachmagic/outreachmagic安装——固定一个版本标签;在本地运行前下载并验证SHA256:
bash
OM_VERSION=v1.1.0
INSTALL_DIR=$(mktemp -d)
curl -fsSL "https://github.com/outreachmagic/outreachmagic/releases/download/${OM_VERSION}/install.sh" -o "${INSTALL_DIR}/install.sh"
curl -fsSL "https://github.com/outreachmagic/outreachmagic/releases/download/${OM_VERSION}/SHA256SUMS" -o "${INSTALL_DIR}/SHA256SUMS"
grep ' install.sh$' "${INSTALL_DIR}/SHA256SUMS" | (cd "${INSTALL_DIR}" && shasum -a 256 --check)
bash "${INSTALL_DIR}/install.sh" --platform hermes --tag "${OM_VERSION}"
安装outreachmagic、lead-enrich和email-finder。Agent指南:AGENTS-INSTALL.md
针对其他Agent,使用
--platform cursor
--platform claude
。设置页面:https://app.outreachmagic.io/onboarding

Hermes profiles

Hermes 配置文件

  • Real install:
    ~/.hermes/skills/
    — profiles symlink only (
    ../../../skills/<skill>
    )
  • Verify:
    pipeline.py paths
  • New profile:
    bash install.sh --platform hermes --profile <name>
  • Update:
    pipeline.py update
    writes the global install; all profiles pick it up via symlink
  • 正式安装路径:
    ~/.hermes/skills/
    ——仅创建配置文件符号链接(
    ../../../skills/<skill>
  • 验证:
    pipeline.py paths
  • 新建配置文件:
    bash install.sh --platform hermes --profile <name>
  • 更新:
    pipeline.py update
    会写入全局安装包;所有配置文件会通过符号链接自动获取更新

Cursor

Cursor

Install to
~/.cursor/skills/outreachmagic/
. Invoke with
/outreachmagic
or ask about your pipeline in plain English.
安装到
~/.cursor/skills/outreachmagic/
。通过
/outreachmagic
调用,或用自然语言询问你的流水线状态。

Claude Code

Claude Code

Install to
~/.claude/skills/outreachmagic/
. SKILL.md is the source of truth.
Environment variable:
OUTREACHMAGIC_AGENT_KEY
— overrides the config file
agent_key
. Set via
.env
, shell profile, or CI/CD.
安装到
~/.claude/skills/outreachmagic/
。SKILL.md为权威文档。
环境变量:
OUTREACHMAGIC_AGENT_KEY
——覆盖配置文件中的
agent_key
。可通过
.env
、Shell配置文件或CI/CD设置。

First-Time Setup (read this first)

首次设置(请先阅读)

On startup, always check if the agent is already connected by running:
bash
python3 scripts/pipeline.py version
Then check whether an agent key exists in the config:
bash
python3 scripts/pipeline.py pull
If
pull
returns an error like "No agent key or token configured", the user needs to set up.
When setup is needed, run
pipeline.py login
— a browser opens on the user's machine for sign-in. Tell the user: "I'm opening Outreach Magic sign-in — come back when you're done and I'll continue." Never paste secrets into chat.
If the skill is not installed yet, point them to https://app.outreachmagic.io/onboarding or https://app.outreachmagic.io/agent, then connect.
Account access error: If login fails with an account error (
account_revoked
in CLI/API), tell the user there was a sign-in problem and direct them to support@outreachmagic.io for help.
启动时,务必通过以下命令检查Agent是否已连接
bash
python3 scripts/pipeline.py version
然后检查配置中是否存在Agent密钥:
bash
python3 scripts/pipeline.py pull
如果
pull
返回类似"No agent key or token configured"的错误,用户需要进行设置。
需要设置时,运行
pipeline.py login
——用户设备上会打开浏览器用于登录。告知用户:"我正在打开Outreach Magic登录页面——完成后请返回,我会继续操作。" 切勿在聊天中粘贴密钥。
账户访问错误: 如果登录时出现账户错误(CLI/API中显示
account_revoked
),告知用户登录出现问题,并引导他们联系support@outreachmagic.io寻求帮助。

Common workflows (plain English)

常见工作流(自然语言对应)

User saysYou do
"Show my pipeline"
pull
show
"Import my Sales Nav / Vayne CSV"
import-profiles --file … --workspace W --dry-run
first, then import (auto-syncs)
"Find emails for these leads"import if needed →
email-finder-candidates
batch-find --workspace W --yes
"Export to Google Sheets"
whoami --json
share_email
, then
sheets export --workspace W --share-email …
"Connect Smartlead / Instantly"
connections create --platform …
and share webhook URL
pipeline.py whoami --json
returns account email, org, and plan.
init
creates the database under
<skill_home>/databases/
. Dashboard API keys sync to
<skill_home>/config/agent_secrets.env
(next to
outreachmagic_config.json
). CSVs and exports live under
outreachmagic/imports/
and
outreachmagic/exports/
relative to your workspace directory (where the agent runs commands). Set
"project_root"
in config to pin a fixed folder instead of cwd. Run
pipeline.py paths
for resolved paths (
batches/
,
sheets/
,
archive/
,
logs/
too).
If
pull
returns auth errors after a revoked key, ask Outreach Magic to log in again.
That's it. Don't list other commands, don't offer alternatives. Just connect via login, done.
When setup is already done (pull succeeds or returns events), skip setup and go straight to showing data:
bash
python3 scripts/pipeline.py pull
python3 scripts/pipeline.py show
用户提问你执行的操作
"展示我的流水线"
pull
show
"导入我的Sales Nav / Vayne CSV"先执行
import-profiles --file … --workspace W --dry-run
,再执行导入(自动同步)
"为这些线索查找邮箱"如需导入则先导入 →
email-finder-candidates
batch-find --workspace W --yes
"导出到Google Sheets"
whoami --json
share_email
,然后执行
sheets export --workspace W --share-email …
"连接Smartlead / Instantly"
connections create --platform …
并分享webhook URL
pipeline.py whoami --json
返回账户邮箱、组织和套餐信息。
init
会在
<skill_home>/databases/
下创建数据库。Dashboard API密钥会同步到
<skill_home>/config/agent_secrets.env
(位于
outreachmagic_config.json
旁)。CSV和导出文件存储在**
outreachmagic/imports/
outreachmagic/exports/
目录下,路径相对于你的工作区目录**(Agent运行命令的目录)。可在配置中设置
"project_root"
来固定文件夹,而非使用当前工作目录。运行
pipeline.py paths
查看解析后的路径(还包括
batches/
sheets/
archive/
logs/
)。
如果密钥失效后
pull
返回认证错误,请让用户重新登录Outreach Magic。
操作到此为止。不要列出其他命令,不要提供替代方案。只需通过登录完成连接即可。
当已完成设置时
pull
成功或返回事件),跳过设置步骤直接展示数据:
bash
python3 scripts/pipeline.py pull
python3 scripts/pipeline.py show

Network & privacy (Hermes / hub review)

网络与隐私(Hermes / hub 审核)

  • Default: All lead and pipeline data stays in local SQLite.
  • Inbound only:
    pull
    imports webhook/agent events from
    api.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.
  • 默认规则: 所有线索和流水线数据都存储在本地SQLite中。
  • 仅入站:
    pull
    api.outreachmagic.io
    导入webhook/Agent事件(由用户或定时任务触发)。
  • 仅出站上传: 仅当用户(或Agent遵循用户指令)运行**
    pipeline.py sync
    **时才会上传。导入和本地编辑不会自动上传。
  • 版本检查: CLI可能会查询GitHub获取更新版本标签(只读,不涉及线索数据;每小时最多一次)。详见SECURITY.md

Version

版本

One version for the whole skill. To see what is installed, always run:
bash
python3 scripts/pipeline.py version
The
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:
bash
python3 scripts/pipeline.py update
整个skill使用统一版本。要查看已安装的版本,请始终运行:
bash
python3 scripts/pipeline.py version
本文件中的
version:
行在安装/更新时会从
scripts/VERSION
同步。如有疑问,请使用上述命令查询。
更新由用户触发。当GitHub上存在更新的正式版本时,CLI可能会打印更新通知(每小时最多一次)。它不会自动下载或替换脚本。使用以下命令安装更新:
bash
python3 scripts/pipeline.py update

or

hermes skills update

Check without installing: `pipeline.py update --check`. Install a specific release: `pipeline.py update --tag v1.1.0`.

Install commands for each platform are in **Platform install** above. After install, run `python3 scripts/pipeline.py login`.
hermes skills update

仅检查更新不安装:`pipeline.py update --check`。安装特定版本:`pipeline.py update --tag v1.1.0`。

各平台的安装命令见上文**平台安装**部分。安装后,运行`python3 scripts/pipeline.py login`。

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 for workspace inventory (counts by tag, LinkedIn connection accepted by sender)
  • 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
    )
  • 你即将发送拓展消息(邮件、LinkedIn消息、WhatsApp等)
  • 你正在调研潜在客户并想要跟踪他们
  • 用户询问"展示我的流水线"或"拓展进展如何"
  • 用户说"跟踪这个"并附上拓展细节
  • 用户想要连接序列器(付费功能——需要令牌)
  • 用户询问活动细分或按活动名称统计数量
  • 用户询问工作区清单(按标签统计数量、按发送者统计LinkedIn通过的请求数量)
  • 用户询问连接状态、webhook URL或平台健康状况(使用
    status
    connections
    命令)
  • 用户想要添加或移除平台连接(使用
    connect-platform
    disconnect-platform
    命令)

Agent Behavior Rules (Important)

Agent行为规则(重要)

  • For bulk enrichment (CSV, spreadsheet export, Apollo/Clay dump): use
    import-profiles
    , not repeated
    add-lead
    .
  • Reads (analytics, counts, time windows): use
    pipeline.py query
    presets first — one query, max two attempts. See references/query-guide.md. Do not tour
    workspace_lead_events
    when the question is relay volume (use
    events
    ).
  • Writes: only
    pipeline.py
    mutation commands (
    add-lead
    ,
    import-profiles
    ,
    log-event
    ,
    sync
    , personalize, tags, etc.). Never
    INSERT
    /
    UPDATE
    /
    DELETE
    via ad-hoc scripts.
  • After any
    pull
    , explicitly report the exact number of new records imported.
  • When the user asks about version, run
    pipeline.py version
    (authoritative).
  • When the user asks for message content, use
    history
    on the specific lead.
  • For copy-performance analysis (full subject/body on positive leads + winner), use
    copy-insights
    .
  • For all-time campaign totals (no time window), use
    campaigns
    or
    stats
    . For last N hours/days by campaign, use
    query engagement
    or
    query replies
    — not
    campaigns
    .
  • For tag counts or LinkedIn connection counts by sender, use
    workspace summary --workspace <slug> --json
    . On large workspaces (>2,000 leads), add
    --tags-only
    for faster tag rollups. Do not use
    export
    or custom Python to aggregate.
  • Tags (
    workspace_lead_tags
    ) and LinkedIn connection state (
    workspace_lead_linkedin_status
    ,
    is_connected
    per sender) are different.
  • When the user asks about connections, webhook URLs, or platform health, use
    status
    or
    connections
    .
  • When the user wants to connect a new platform, use
    connect-platform --platform <id>
    .
  • If the user reports slowness, disk use, or pipeline oddities: run
    db-health
    first (local, no network).
  • Never run
    sync
    unless the user asked.
    Never run
    archive --purge
    without explicit confirmation after
    --dry-run
    .
  • Before adding platforms or debugging vendor event types, run
    pipeline.py platform-map --json
    .
  • Answer format for analytics: (1) human table, (2) preset name or SQL used, (3) freshness note (local DB; offer
    pull
    if they need latest relay data).
  • 对于批量富集(CSV、电子表格导出、Apollo/Clay数据):使用**
    import-profiles
    **,不要重复调用
    add-lead
  • 读取操作(分析、统计、时间窗口): 优先使用**
    pipeline.py query
    预设——一次查询,最多尝试两次。详见references/query-guide.md。当问题涉及消息量时,不要遍历
    workspace_lead_events
    (使用
    events
    **命令)。
  • 写入操作: 仅使用
    pipeline.py
    的变更命令(
    add-lead
    import-profiles
    log-event
    sync
    、个性化设置、标签等)。切勿通过临时脚本执行
    INSERT
    /
    UPDATE
    /
    DELETE
    操作。
  • 任何
    pull
    操作后,明确报告导入的新记录的确切数量。
  • 当用户询问版本时,运行**
    pipeline.py version
    **(权威来源)。
  • 当用户询问消息内容时,对特定线索使用
    history
    命令。
  • 对于文案效果分析(获取有意向线索的完整主题/正文及最优模板),使用
    copy-insights
    命令。
  • 对于全时段活动总计(无时间窗口),使用
    campaigns
    stats
    命令。对于最近N小时/天的活动统计,使用**
    query engagement
    query replies
    **——不要使用
    campaigns
  • 对于标签统计按发送者统计LinkedIn连接数量,使用**
    workspace summary --workspace <slug> --json
    。对于大型工作区(>2000条线索),添加
    --tags-only
    **以加快标签汇总速度。不要使用
    export
    或自定义Python脚本进行聚合。
  • 标签
    workspace_lead_tags
    )和LinkedIn连接状态
    workspace_lead_linkedin_status
    、每个发送者的
    is_connected
    )是不同的概念。
  • 当用户询问连接状态、webhook URL或平台健康状况时,使用
    status
    connections
    命令。
  • 当用户想要连接新平台时,使用
    connect-platform --platform <id>
    命令。
  • 如果用户报告速度慢、磁盘占用高或流水线异常:首先运行**
    db-health
    **(本地操作,无需网络)。
  • 除非用户要求,否则切勿运行
    sync
    除非在
    --dry-run
    后得到明确确认,否则切勿运行
    archive --purge
  • 在添加平台或调试供应商事件类型之前,运行
    pipeline.py platform-map --json
  • 分析结果的回复格式: (1) 人性化表格,(2) 使用的预设名称或SQL,(3) 数据新鲜度说明(本地数据库;如果用户需要最新的中继数据,可提供
    pull
    操作)。

Which table? (read path)

选择哪个表?(读取路径)

User intentUse
Replies / engagement / campaign breakdowns (time window)
query engagement
or
events
+
campaigns
Lead list with stage/sentiment
show
/
lead-table
Tag counts, LinkedIn connected-by-sender
workspace summary --json
Message bodies / copy winners
history
,
copy-insights
Workspace ingest audit (rare)
workspace_lead_events
not for volume analytics
workspace_lead_events
is a subset; full relay timelines are in
events
.
用户意图使用命令/表
回复/互动/活动细分(带时间窗口)
query engagement
events
+
campaigns
带阶段/情感的线索列表
show
/
lead-table
标签统计、按发送者统计LinkedIn连接数量
workspace summary --json
消息正文/最优文案
history
,
copy-insights
工作区导入审计(罕见场景)
workspace_lead_events
——不要用于流量分析
workspace_lead_events
是子集;完整的中继时间线存储在**
events
**中。

Fast analytics (preferred)

快速分析(推荐)

bash
python3 scripts/pipeline.py query engagement --workspace <slug> --since 48h --json
python3 scripts/pipeline.py query replies --workspace <slug> --since 7d --json
python3 scripts/pipeline.py query interested --workspace <slug> --since 48h --json
Advanced:
pipeline.py query --sql 'SELECT …' --params '["popcam |%"]' --json
(read-only).
Read commands print data freshness on stderr (and
last_pull
/
stale_minutes
in
--json
). If data is a few minutes old, tell the user before running
pull
unless they asked for up-to-the-minute.
User intentCommand
Reply/engagement counts in a time window
query replies
/
query engagement --since … --json
Lead rows / pipeline detail
show
(use
--limit
; avoid
--json
unless needed)
All-time totals
stats
/
campaigns --json
Fresh webhook events
pull
or
pull --kind events
bash
python3 scripts/pipeline.py query engagement --workspace <slug> --since 48h --json
python3 scripts/pipeline.py query replies --workspace <slug> --since 7d --json
python3 scripts/pipeline.py query interested --workspace <slug> --since 48h --json
高级用法:
pipeline.py query --sql 'SELECT …' --params '["popcam |%"]' --json
(只读)。
读取命令会在stderr中打印数据新鲜度
--json
格式中会包含
last_pull
/
stale_minutes
)。如果数据已过时几分钟,在运行
pull
前告知用户,除非用户明确要求实时数据。
用户意图命令
时间窗口内的回复/互动统计
query replies
/
query engagement --since … --json
线索行/流水线详情
show
(使用
--limit
;除非必要,否则避免使用
--json
全时段总计
stats
/
campaigns --json
最新webhook事件
pull
pull --kind events

Pull policy (when to refresh)

Pull策略(何时刷新)

Do not run
pull
before local time-window analytics
(
last 48h
,
since today
, engagement by campaign) unless the user asks for latest/refresh or you need relay catch-up.
Run
pull
first
when showing live pipeline activity the user expects to be current (
show
,
history
for “what just happened”), or when they say sync/refresh/latest.
bash
python3 scripts/pipeline.py pull
python3 scripts/pipeline.py pull --if-stale 5m   # skip when last_pull is within 5 minutes
python3 scripts/pipeline.py pull --force         # always network (ignore --if-stale)
If routing sync times out but you only need webhook events, use:
bash
python3 scripts/pipeline.py pull --skip-routing-sync
This fetches the latest events from the relay. Skip for offline/local analytics; use for fresh activity timelines.
Relay sync progress (stdout): When interpreting
pull
/
sync
output or
outreachmagic/logs/batch_sync.log
, use the log legend in docs/relay-sync-progress.md. Short version:
  • ↓ pull / ↑ push — cloud → local vs local → cloud
  • Event, Lead, Workspace, Company — four streams (Lead = org lead core; Workspace = per-workspace lead overlay, not routing config)
  • Pending banner:
    ~
    on counts/page estimate once per stream start, e.g.
    [02:10] ↓ Event : ~12,400 pending (~13p @ 1000/p) ...
  • Per page:
    [02:11] ↓ Event : p13/62 — 1,000 this page, 13,000/62,400 (20%) ...
    (pull, no
    ok
    )
  • pull --probe
    :
    backlog only (
    limit=1
    /stream, no ingest) — use before a large catch-up pull
  • pull --skip-snapshots
    :
    webhook events only (recommended after events catch-up; avoids slow snapshot phase)
  • pull --reset-snapshot-cursors
    :
    zero snapshot cursors before pull (after DB delete or hung pull left config ahead of local leads)
  • pull --kind events
    :
    same as
    --skip-snapshots
    when you only need the event cursor advanced
  • Push page:
    [03:56] ↑ Event : p2/13 — ok 7.9s, 5,000 this page (10,000/62,093 (16%))
    then
    done — N in Mp (Xs)
  • batch_sync.log
    :
    outer
    batch 1/46
    = lead-id walk; inner
    pN/M
    = HTTP pages inside one
    sync
    . Do not confuse them.
Relay sync limits: Same endpoints always —
POST /push
and
GET /pull
. No separate bulk URLs.
  • sync
    (upload):
    When local
    cloud_pending
    snapshots ≥ 2500, uses 5000 entries per
    /push
    ; otherwise routine batch size (default 200, max 500 per request).
  • pull
    (download):
    1000 rows/page for events and all snapshots (D1 + local ingest). Progress shows
    p2/118
    and
    % remaining
    after a one-time pending probe per snapshot kind. Use
    pull --kind events
    if snapshots are already synced.
  • Filter downloaded data locally (
    show --since
    , workspace queries) — the relay does not filter by date or workspace.
在进行本地时间窗口分析前(如
最近48小时
今日以来
、按活动统计互动),不要运行
pull
,除非用户要求最新/刷新数据,或你需要补集中继数据。
当展示用户预期为实时的流水线活动时(如
show
、查询“刚刚发生了什么”的
history
),或用户提到同步/刷新/最新时,先运行
pull
bash
python3 scripts/pipeline.py pull
python3 scripts/pipeline.py pull --if-stale 5m   # 当最后一次pull在5分钟内时跳过
python3 scripts/pipeline.py pull --force         # 始终进行网络请求(忽略--if-stale)
如果路由同步超时但你只需要webhook事件,使用:
bash
python3 scripts/pipeline.py pull --skip-routing-sync
这会从中继获取最新事件。离线/本地分析时跳过;用于获取新鲜活动时间线时使用。
中继同步进度(标准输出): 解读
pull
/
sync
输出或
outreachmagic/logs/batch_sync.log
时,请参考docs/relay-sync-progress.md中的日志图例。简化版本:
  • ↓ pull / ↑ push —— 云端→本地 与 本地→云端
  • Event, Lead, Workspace, Company —— 四个数据流(Lead = 组织核心线索;Workspace = 每个工作区的线索覆盖层,不是路由配置)
  • Pending提示: 每个数据流启动时,计数/页数估算前会显示
    ~
    ,例如
    [02:10] ↓ Event : ~12,400 pending (~13p @ 1000/p) ...
  • 每页进度:
    [02:11] ↓ Event : p13/62 — 1,000 this page, 13,000/62,400 (20%) ...
    (pull操作,无
    ok
    标记)
  • pull --probe
    仅查看积压数据(每个数据流
    limit=1
    ,不导入)——在大型补全pull前使用
  • pull --skip-snapshots
    仅获取webhook事件(建议在事件补全后使用;避免缓慢的快照阶段)
  • pull --reset-snapshot-cursors
    在pull前重置快照游标(在删除数据库或pull挂起导致配置超前于本地线索时使用)
  • pull --kind events
    --skip-snapshots
    作用相同,当你只需要推进事件游标时使用
  • Push页进度:
    [03:56] ↑ Event : p2/13 — ok 7.9s, 5,000 this page (10,000/62,093 (16%))
    然后显示
    done — N in Mp (Xs)
  • batch_sync.log
    外层
    batch 1/46
    = 线索ID遍历;内层
    pN/M
    = 单次
    sync
    中的HTTP分页。不要混淆两者。
中继同步限制: 始终使用相同的端点——
POST /push
GET /pull
。没有单独的批量URL。
  • sync
    (上传):
    当本地
    cloud_pending
    快照≥2500时,每次
    /push
    请求发送5000条数据;否则使用常规批量大小(默认200,最大500条/请求)。
  • pull
    (下载):
    事件和所有快照(D1 + 本地导入)每页1000行。进度会在每个快照类型的一次性pending探测后显示
    p2/118
    剩余百分比
    。如果快照已同步,使用
    pull --kind events
  • 本地过滤下载的数据(
    show --since
    、工作区查询)——中继不支持按日期或工作区过滤。

Workspace inventory

工作区清单

workspace summary
reads local SQLite only (fast, works offline). Use when the user asks for counts by tag or LinkedIn sender connection state. Optional
pull
first if they need freshly synced tags/connection imports.
bash
python3 scripts/pipeline.py workspace summary --workspace <slug> --json
python3 scripts/pipeline.py workspace summary --workspace <slug> --json --tags-only
Example JSON keys:
lead_count
,
last_pull
,
tags
(
tag
,
lead_count
),
linkedin_senders
(
sender_slug
,
connected
,
pending
),
linkedin_connected_leads
. With
--tags-only
, LinkedIn keys are empty arrays/zero.
Companion attempt tags:
serper_attempted
(lead-enrich),
trykitt_attempted
/
icypeas_attempted
(email-finder),
mv_attempted
(MillionVerifier bulk — verification status still in
email_verification_status
). Found email is represented by
leads.email
,
latest_source
, and
email_verification_status
— not a separate tag.
Tag-only (same tag data as summary):
pipeline.py tag list --workspace <slug>
.
**
workspace summary
**仅读取本地SQLite(速度快,可离线使用)。当用户询问按标签或LinkedIn发送者连接状态统计数量时使用。如果用户需要最新同步的标签/连接数据,可先执行
pull
bash
python3 scripts/pipeline.py workspace summary --workspace <slug> --json
python3 scripts/pipeline.py workspace summary --workspace <slug> --json --tags-only
示例JSON键:
lead_count
last_pull
tags
tag
lead_count
)、
linkedin_senders
sender_slug
connected
pending
)、
linkedin_connected_leads
。使用
--tags-only
时,LinkedIn相关键为空数组/零值。
配套尝试标签:
serper_attempted
(lead-enrich)、
trykitt_attempted
/
icypeas_attempted
(email-finder)、
mv_attempted
(MillionVerifier批量验证——验证状态仍存储在
email_verification_status
中)。找到的邮箱通过
leads.email
latest_source
email_verification_status
表示——不是单独的标签。
仅查看标签(与summary中的标签数据相同):
pipeline.py tag list --workspace <slug>

Free Tier

免费版

  • Unlimited local tracking, enrichment, queries, and exports
  • 1,000 webhook events / period (sequencer webhooks + cloud sync)
  • 1 sequencer connection, single workspace
  • 无限制本地跟踪、富集、查询和导出
  • 每个周期1000条webhook事件(序列器webhook + 云端同步)
  • 1个序列器连接,单个工作区

Pro Tier ($9/mo)

专业版($9/月)

  • 50,000 webhook and sync events / month
  • All sequencers, multi-workspace routing
  • 每月50,000条webhook和同步事件
  • 支持所有序列器,多工作区路由

Agency Tier ($29/mo)

企业版($29/月)

  • 250,000 webhook and sync events / month
  • All sequencers, unlimited workspaces, priority support
  • 每月250,000条webhook和同步事件
  • 支持所有序列器,无限制工作区,优先支持

What counts

计费规则

Only webhook and sync traffic: sequencer webhooks and
pipeline.py sync
uploads to the cloud (one event per sync batch, not per lead). Local tracking (
log-event
,
add-lead
), enrichment dedup, email finding, queries, and exports do not count.
仅对webhook和同步流量计费:序列器webhook和
pipeline.py sync
上传到云端的流量(每个同步批次计为一个事件,而非每条线索)。本地跟踪(
log-event
add-lead
)、富集去重、邮箱查找、查询和导出不计费

Over limit

超出限额

Sequencer webhooks are always accepted. Over-quota events are buffered and delivered on your next
pull
or when the quota resets. Events are only rejected if the buffer cap is reached. Check status with
pipeline.py status
.
序列器webhook始终会被接收。超出配额的事件会被缓冲,并在下次
pull
或配额重置时交付。仅当缓冲区上限达到时才会拒绝事件。使用
pipeline.py status
查看状态。

Quick Start

快速开始

bash
python3 scripts/pipeline.py version
python3 scripts/pipeline.py query engagement --workspace <slug> --since 48h --json
python3 scripts/pipeline.py show
python3 scripts/pipeline.py history --id 1
python3 scripts/pipeline.py history --email j@acme.com
python3 scripts/pipeline.py stats
python3 scripts/pipeline.py campaigns
python3 scripts/pipeline.py platform-map --json
python3 scripts/pipeline.py workspace summary --workspace <slug> --json
python3 scripts/pipeline.py copy-insights --lead-status interested --json
python3 scripts/pipeline.py import-profiles --file leads.csv
python3 scripts/pipeline.py agent-changes
python3 scripts/pipeline.py agent-changes --file changes.csv
bash
python3 scripts/pipeline.py version
python3 scripts/pipeline.py query engagement --workspace <slug> --since 48h --json
python3 scripts/pipeline.py show
python3 scripts/pipeline.py history --id 1
python3 scripts/pipeline.py history --email j@acme.com
python3 scripts/pipeline.py stats
python3 scripts/pipeline.py campaigns
python3 scripts/pipeline.py platform-map --json
python3 scripts/pipeline.py workspace summary --workspace <slug> --json
python3 scripts/pipeline.py copy-insights --lead-status interested --json
python3 scripts/pipeline.py import-profiles --file leads.csv
python3 scripts/pipeline.py agent-changes
python3 scripts/pipeline.py agent-changes --file changes.csv

Status 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.
bash
undefined
通过CLI实现仪表盘式状态查看、连接管理和webhook URL生成——所有操作都无需本地数据库。
bash
undefined

Dashboard overview: plan, usage, per-platform health, routing

仪表盘概览:套餐、使用情况、各平台健康状况、路由

python3 scripts/pipeline.py status
python3 scripts/pipeline.py status

List all connections with webhook URLs and 30-day event counts

列出所有连接,包含webhook URL和30天事件统计

python3 scripts/pipeline.py connections python3 scripts/pipeline.py connections --json
python3 scripts/pipeline.py connections python3 scripts/pipeline.py connections --json

Generate a webhook URL for a new platform

为新平台生成webhook URL

python3 scripts/pipeline.py connect-platform --platform smartlead
python3 scripts/pipeline.py connect-platform --platform smartlead

Remove a platform connection (webhook URL stops working)

移除平台连接(webhook URL将失效)

python3 scripts/pipeline.py disconnect-platform --platform smartlead python3 scripts/pipeline.py disconnect-platform --platform smartlead --yes
undefined
python3 scripts/pipeline.py disconnect-platform --platform smartlead python3 scripts/pipeline.py disconnect-platform --platform smartlead --yes
undefined

Agent-created changes (cross-platform sync)

Agent创建的变更(跨平台同步)

Show locally-created leads and events (not from relay) as JSON or CSV. Useful for transferring data between platforms (Cursor, Hermes, Claude Code).
bash
undefined
以JSON或CSV格式展示本地创建的线索和事件(非来自中继)。适用于在平台间传输数据(Cursor、Hermes、Claude Code)。
bash
undefined

JSON to stdout (pipe to relay push or save to file)

输出JSON到标准输出(可管道到中继推送或保存到文件)

python3 scripts/pipeline.py agent-changes
python3 scripts/pipeline.py agent-changes

CSV file (import-profiles compatible)

输出到CSV文件(与import-profiles兼容)

python3 scripts/pipeline.py agent-changes --file local_changes.csv
python3 scripts/pipeline.py agent-changes --file local_changes.csv

Filter to a specific workspace

过滤特定工作区

python3 scripts/pipeline.py agent-changes --workspace leadgenph
python3 scripts/pipeline.py agent-changes --workspace leadgenph

Include all leads (not just locally-created)

包含所有线索(不仅是本地创建的)

python3 scripts/pipeline.py agent-changes --all

**Push to relay for cross-platform sync:**

```bash
python3 scripts/pipeline.py sync
sync
pushes pending lead snapshots (profile,
external_id
,
company_domain
, HQ/location, tags, mailmerge, workspace status, LinkedIn connection flags) plus local events, and quarantine resolutions (
skip
/
assign
) to the relay. Large backlogs use 5000 entries per
/push
automatically (see relay sync limits above). At the end of the same command it may POST aggregate local DB health to the portal (file size, row counts, top tables — throttled ~6h). Skip with
sync --no-health-report
. Other machines run
pull --full
after a DB reset to restore everything that was synced.
python3 scripts/pipeline.py agent-changes --all

**推送到中继以实现跨平台同步:**

```bash
python3 scripts/pipeline.py sync
sync
会将待处理的线索快照(资料、
external_id
company_domain
、总部/位置、标签、邮件合并、工作区状态、LinkedIn连接标记)以及本地事件和隔离区解决方案
skip
/
assign
)推送到中继。大型积压数据会自动使用每次
/push
请求5000条数据
(见上文中继同步限制)。在同一命令的最后,可能会将本地数据库健康状况的聚合数据(文件大小、行数、顶级表)发送到门户(每约6小时限流一次)。使用
sync --no-health-report
跳过。其他机器在重置数据库后运行
pull --full
以恢复所有已同步的数据。

Quarantine (multi-workspace)

隔离区(多工作区)

Unmapped webhook events land in
unmapped_campaign_queue
. Resolve locally, then
sync
so other machines and
pull --full
stay consistent.
No campaign id/name: New webhook events are quarantined automatically. Legacy rows in
events
with
campaign_id IS NULL
are backfilled on
init
into quarantine and auto-skipped (no workspace mapping possible). Use
history
to inspect event details if needed. Manual:
quarantine backfill-no-campaign
.
bash
python3 scripts/pipeline.py quarantine list [--json] [--status all]
python3 scripts/pipeline.py quarantine skip --id QUEUE_ID
python3 scripts/pipeline.py quarantine skip --campaign-id CAMPAIGN_ID
python3 scripts/pipeline.py quarantine skip --reason REASON
python3 scripts/pipeline.py quarantine assign --id QUEUE_ID --workspace WORKSPACE_SLUG
python3 scripts/pipeline.py quarantine replay
python3 scripts/pipeline.py sync
  • skip
    — ignore junk/test events on the relay (permanent after sync).
  • assign
    — route future pulls to a workspace (ingested on next
    pull
    , not immediately).
  • replay
    — bulk re-ingest pending rows locally after adding
    campaign-map
    rules (no relay resolution).
Relay stores resolutions in D1 (
queue_resolutions
). The first event page of each
pull
requests them (
include_queue_resolutions=1
); later pages reuse the in-memory map.
sync --status
counters:
recommended_mode
is
bulk
when
cloud_pending_leads
≥ 2500 (else
push
).
relay_untracked_leads
= imported/local leads with no relay pull history (normal after CSV; data is still in the shared DB).
cloud_pending_leads
= rows waiting to push — run
sync
.
local_agent_events
= agent-originated events not yet on relay.
未映射的webhook事件会进入
unmapped_campaign_queue
。在本地解决后,运行
sync
以确保其他机器和
pull --full
保持一致。
无活动ID/名称: 新的webhook事件会自动进入隔离区。
events
campaign_id IS NULL
的旧行会在
init
时回填到隔离区并自动跳过(无法进行工作区映射)。如有需要,使用
history
查看事件详情。手动操作:
quarantine backfill-no-campaign
bash
python3 scripts/pipeline.py quarantine list [--json] [--status all]
python3 scripts/pipeline.py quarantine skip --id QUEUE_ID
python3 scripts/pipeline.py quarantine skip --campaign-id CAMPAIGN_ID
python3 scripts/pipeline.py quarantine skip --reason REASON
python3 scripts/pipeline.py quarantine assign --id QUEUE_ID --workspace WORKSPACE_SLUG
python3 scripts/pipeline.py quarantine replay
python3 scripts/pipeline.py sync
  • skip
    —— 忽略中继上的垃圾/测试事件(同步后永久生效)。
  • assign
    —— 将未来的pull路由到指定工作区(在下次pull时导入,不会立即导入)。
  • replay
    —— 添加
    campaign-map
    规则后,批量重新导入本地待处理行(不涉及中继解决)。
中继将解决方案存储在D1(
queue_resolutions
)中。每次
pull
的第一页事件会请求这些解决方案(
include_queue_resolutions=1
);后续页面会复用内存中的映射。
sync --status
计数器:
cloud_pending_leads
≥2500时,
recommended_mode
bulk
(否则为
push
)。
relay_untracked_leads
= 已导入/本地线索但无中继pull历史(CSV导入后正常;数据仍在共享数据库中)。
cloud_pending_leads
= 等待推送的行——运行
sync
local_agent_events
= 源自Agent但尚未同步到中继的事件。

Local database health

本地数据库健康

bash
python3 scripts/pipeline.py db-health
python3 scripts/pipeline.py db-health --json
python3 scripts/pipeline.py db-health --full
Read
healthStatus
,
rulesTriggered
(each has a
hint
),
rowCounts
, and
tableBreakdown
. Cloud copy:
GET /api/agent/status
localDb
after user has run
sync
.
bash
python3 scripts/pipeline.py db-health
python3 scripts/pipeline.py db-health --json
python3 scripts/pipeline.py db-health --full
查看
healthStatus
rulesTriggered
(每个都有
hint
)、
rowCounts
tableBreakdown
。云端副本:用户运行
sync
后,
GET /api/agent/status
localDb

Archive a workspace (local only)

归档工作区(仅本地)

bash
python3 scripts/pipeline.py archive --workspace acme_corp --dry-run
python3 scripts/pipeline.py archive --workspace acme_corp --output ~/archives/acme_corp.db
python3 scripts/pipeline.py archive --workspace acme_corp --output ~/archives/acme_corp.db --purge
Fresh DB + full CSV round-trip:
bash
pipeline.py import-profiles --file nace.csv --workspace acme_corp --import-batch-id nace-2026
pipeline.py sync
bash
python3 scripts/pipeline.py archive --workspace acme_corp --dry-run
python3 scripts/pipeline.py archive --workspace acme_corp --output ~/archives/acme_corp.db
python3 scripts/pipeline.py archive --workspace acme_corp --output ~/archives/acme_corp.db --purge
全新数据库 + 完整CSV往返:
bash
pipeline.py import-profiles --file nace.csv --workspace acme_corp --import-batch-id nace-2026
pipeline.py sync

new machine:

新机器:

pipeline.py init && pipeline.py pull --full

**File-based transfer (no server):**

```bash
pipeline.py init && pipeline.py pull --full

**基于文件的传输(无需服务器):**

```bash

Machine A: export

机器A:导出

pipeline.py agent-changes --file changes.csv
pipeline.py agent-changes --file changes.csv

Machine B: import

机器B:导入

pipeline.py import-profiles --file changes.csv --overwrite
undefined
pipeline.py import-profiles --file changes.csv --overwrite
undefined

Workspace inventory

工作区清单

Counts by tag and LinkedIn connection accepted/pending per sender. Local DB only — no relay call;
last_pull
in output shows data freshness.
bash
python3 scripts/pipeline.py workspace summary --workspace <slug> --json
python3 scripts/pipeline.py workspace summary --workspace <slug>
python3 scripts/pipeline.py tag list --workspace <slug>
按标签和LinkedIn连接通过/待处理状态(按发送者)统计数量。仅本地数据库——无需调用中继;输出中的
last_pull
显示数据新鲜度。
bash
python3 scripts/pipeline.py workspace summary --workspace <slug> --json
python3 scripts/pipeline.py workspace summary --workspace <slug>
python3 scripts/pipeline.py tag list --workspace <slug>

Campaign breakdown

活动细分

Relay imports auto-populate campaign names from webhook payloads (Smartlead, PlusVibe, etc.).
bash
python3 scripts/pipeline.py campaigns
python3 scripts/pipeline.py campaigns --json
stats
also includes a campaign section. Use
campaigns
when the user only wants counts by campaign name.
中继导入会自动从webhook负载中填充活动名称(Smartlead、PlusVibe等)。
bash
python3 scripts/pipeline.py campaigns
python3 scripts/pipeline.py campaigns --json
stats
也包含活动部分。当用户仅需要按活动名称统计数量时,使用
campaigns

PlusVibe webhooks (status + sentiment)

PlusVibe webhooks(状态 + 情感)

Point PlusVibe webhooks at your relay URL (
…/plusvibe/{token}
). Select all event types and category labels in PlusVibe — including any custom categories in the user’s instance. Standard ones to verify:
  • EMAIL_SENT
    ,
    ALL_EMAIL_REPLIES
    ,
    BOUNCED_EMAIL
  • LEAD_MARKED_AS_INTERESTED
    ,
    LEAD_MARKED_AS_NOT_INTERESTED
    ,
    LEAD_MARKED_AS_OUT_OF_OFFICE
    ,
    LEAD_MARKED_AS_AUTOMATIC_REPLY
  • LEAD_MARKED_AS_MEETING_BOOKED
    ,
    LEAD_MARKED_AS_MEETING_COMPLETED
    ,
    LEAD_MARKED_AS_WRONG_PERSON
    ,
    LEAD_MARKED_AS_CLOSED
Do not enable
ALL_POSITIVE_REPLIES
(duplicates
ALL_EMAIL_REPLIES
) or
FIRST_EMAIL_REPLIES
(subset of
ALL_EMAIL_REPLIES
). Leave “Skip out of office replies” and “Skip autoreplies” unchecked.
Each webhook is stored 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).
将PlusVibe webhook指向你的中继URL(
…/plusvibe/{token}
)。在PlusVibe中选择所有事件类型和类别标签——包括用户实例中的任何自定义类别。需验证的标准类型:
  • EMAIL_SENT
    ,
    ALL_EMAIL_REPLIES
    ,
    BOUNCED_EMAIL
  • LEAD_MARKED_AS_INTERESTED
    ,
    LEAD_MARKED_AS_NOT_INTERESTED
    ,
    LEAD_MARKED_AS_OUT_OF_OFFICE
    ,
    LEAD_MARKED_AS_AUTOMATIC_REPLY
  • LEAD_MARKED_AS_MEETING_BOOKED
    ,
    LEAD_MARKED_AS_MEETING_COMPLETED
    ,
    LEAD_MARKED_AS_WRONG_PERSON
    ,
    LEAD_MARKED_AS_CLOSED
不要启用
ALL_POSITIVE_REPLIES
(与
ALL_EMAIL_REPLIES
重复)或
FIRST_EMAIL_REPLIES
ALL_EMAIL_REPLIES
的子集)。取消勾选“跳过外出回复”和“跳过自动回复”。
每个webhook都会存储为一个事件。感兴趣/不感兴趣/情感来自标签webhook,而非仅来自回复webhook。外出回复被归类为自动回复(元数据标记,使用
--auto-reply true
查询)。退信会将事件情感设置为
invalid
不会自动将线索移至
lost
阶段(使用
--sentiment invalid
查找此类线索)。

EmailBison webhooks

EmailBison webhooks

Point EmailBison webhooks at your relay URL (
…/emailbison/{token}
). In EmailBison, go to Settings → Webhook, paste the URL, and toggle the events below. Enable all seven:
  • email.sent
    — sent from sender to lead
  • email.bounced
    — delivery failure (hard and soft bounces)
  • lead.replied
    — lead replied to an email
  • lead.interested
    — lead marked as interested (replies with positive intent)
  • lead.unsubscribed
    — lead unsubscribed from the campaign
  • tag.attached
    — a tag was added to the lead
  • tag.removed
    — a tag was removed from the lead
All event types are accepted and stored. lead.interested sets stage to
interested
locally. lead.replied sets stage to
replied
. Bounces are recorded in the bounce events table with EmailBison-specific bounce field paths (
data.bounce.type
,
data.bounce.reason
,
data.lead.mx_provider
). Tags are stored as
tag_attached
/
tag_removed
event types with their raw vendor type preserved.
Campaign id/name are extracted from
data.campaign.id
/
data.campaign.name
in the payload.
After
pull
, filter the pipeline by current status (latest status-bearing event per lead):
bash
python3 scripts/pipeline.py show --sentiment positive
python3 scripts/pipeline.py show --sentiment invalid
python3 scripts/pipeline.py show --auto-reply true
python3 scripts/pipeline.py show --lead-status interested --json
Filter by date (created or updated on/after a date):
bash
python3 scripts/pipeline.py show --since today
python3 scripts/pipeline.py show --since 2026-05-26 --json
python3 scripts/pipeline.py lead-table --workspace acme_corp --since today --json
Then open full timeline for any lead (all events, not just the status event):
bash
python3 scripts/pipeline.py history --id 1
Native copy-performance analysis (full message bodies + best template):
bash
python3 scripts/pipeline.py copy-insights --lead-status interested
python3 scripts/pipeline.py copy-insights --lead-status interested --json
show --json
and
lead-table --json
return
{"leads": [...], "data": [...], ...}
with
personalization
,
tags
, and
latest_sender
when available.
将EmailBison webhook指向你的中继URL(
…/emailbison/{token}
)。在EmailBison中,进入设置→Webhook,粘贴URL,然后启用以下七个事件:
  • email.sent
    —— 从发送者发送给线索
  • email.bounced
    —— 投递失败(硬退信和软退信)
  • lead.replied
    —— 线索回复邮件
  • lead.interested
    —— 线索被标记为感兴趣(带有积极意图的回复)
  • lead.unsubscribed
    —— 线索取消订阅活动
  • tag.attached
    —— 为线索添加标签
  • tag.removed
    —— 移除线索的标签
所有事件类型都会被接受并存储。lead.interested会将本地阶段设置为
interested
lead.replied会将阶段设置为
replied
。退信会记录在退信事件表中,包含EmailBison特定的退信字段路径(
data.bounce.type
,
data.bounce.reason
,
data.lead.mx_provider
)。标签会以
tag_attached
/
tag_removed
事件类型存储,并保留其原始供应商类型。
活动ID/名称从负载中的
data.campaign.id
/
data.campaign.name
提取。
pull
后,按当前状态过滤流水线(每条线索的最新状态事件):
bash
python3 scripts/pipeline.py show --sentiment positive
python3 scripts/pipeline.py show --sentiment invalid
python3 scripts/pipeline.py show --auto-reply true
python3 scripts/pipeline.py show --lead-status interested --json
按日期过滤(在指定日期或之后创建/更新):
bash
python3 scripts/pipeline.py show --since today
python3 scripts/pipeline.py show --since 2026-05-26 --json
python3 scripts/pipeline.py lead-table --workspace acme_corp --since today --json
然后查看任意线索的完整时间线(所有事件,不仅是状态事件):
bash
python3 scripts/pipeline.py history --id 1
原生文案效果分析(完整消息正文 + 最优模板):
bash
python3 scripts/pipeline.py copy-insights --lead-status interested
python3 scripts/pipeline.py copy-insights --lead-status interested --json
show --json
lead-table --json
返回
{"leads": [...], "data": [...], ...}
,包含
personalization
tags
latest_sender
(如有)。

Export full profiles (CSV / JSON)

导出完整资料(CSV / JSON)

bash
python3 scripts/pipeline.py export --workspace acme_corp --tag nace --format csv
python3 scripts/pipeline.py export --workspace acme_corp --since today --format json
Writes to
outreachmagic/exports/
under your workspace by default. CSV uses
personalized_first_name
,
personalized_company_name
, plus lead fields, tags, HQ, and
latest_sender
.
Not for Google Sheets
export
writes local files only. For a hosted Google Sheet, use
sheets export
or
review export
(below).
bash
python3 scripts/pipeline.py export --workspace acme_corp --tag nace --format csv
python3 scripts/pipeline.py export --workspace acme_corp --since today --format json
默认写入工作区下的
outreachmagic/exports/
目录。CSV使用
personalized_first_name
personalized_company_name
以及线索字段、标签、总部信息和
latest_sender
不适用于Google Sheets ——
export
仅写入本地文件。如需托管在Google Sheets,使用
sheets export
review export
(见下文)。

Reset local database (schema upgrade)

重置本地数据库(架构升级)

Prefer the guarded refresh command (syncs first, backs up, then rebuilds):
bash
python3 scripts/pipeline.py refresh --yes
Preview tag fixes without writing:
bash
python3 scripts/pipeline.py tag repair --dry-run
python3 scripts/pipeline.py tag repair
Manual equivalent (no pre-sync backup):
bash
rm <skill_home>/databases/outreachmagic.db  # see pipeline.py paths
python3 scripts/pipeline.py init
python3 scripts/pipeline.py pull --full
Tell your agent (rare): “Run
pipeline.py refresh --yes
to back up, sync local changes to the relay, wipe the local DB, and re-import from the cloud. Do not use
pull --full
alone — it skips already-imported rows.”
pull --full
only re-downloads relay pages; it does not clear
relay_ingested
. Use
refresh
when you need a true rebuild.
LinkedIn 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.
优先使用受保护的刷新命令(先同步,备份,然后重建):
bash
python3 scripts/pipeline.py refresh --yes
预览标签修复而不写入:
bash
python3 scripts/pipeline.py tag repair --dry-run
python3 scripts/pipeline.py tag repair
手动等效操作(无预同步备份):
bash
rm <skill_home>/databases/outreachmagic.db  # 查看pipeline.py paths
python3 scripts/pipeline.py init
python3 scripts/pipeline.py pull --full
告知你的Agent(罕见场景): “运行
pipeline.py refresh --yes
以备份、将本地变更同步到中继、清空本地数据库并从云端重新导入。不要单独使用
pull --full
——它会跳过已导入的行。”
pull --full
仅重新下载中继页面;它不会清除
relay_ingested
。当你需要真正重建时,使用
refresh
LinkedIn ID(v1.17): 公开资料存储在
linkedin_url
中,格式为
linkedin.com/in/handle
(无
https://
)。Sales Nav(
ACwAA…
)和会员ID(
urn:li:member:…
)存储为身份别名,当公开slug稍后到达时用于匹配。

Core Workflow

核心工作流

View a lead's full timeline

查看线索的完整时间线

bash
python3 scripts/pipeline.py history --id 1
python3 scripts/pipeline.py history --email jane@acme.com
python3 scripts/pipeline.py history --name "Jane Doe"
python3 scripts/pipeline.py history --id 1 --json
Outputs lead info + numbered event timeline with direction arrows (← inbound, → outbound), human-readable timestamps, and event details.
bash
python3 scripts/pipeline.py history --id 1
python3 scripts/pipeline.py history --email jane@acme.com
python3 scripts/pipeline.py history --name "Jane Doe"
python3 scripts/pipeline.py history --id 1 --json
输出线索信息 + 带方向箭头的编号事件时间线(← 入站,→ 出站)、人性化时间戳和事件详情。

Add leads when researching prospects

调研潜在客户时添加线索

bash
python3 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 prospecting
To also associate the lead with a workspace at creation time:
bash
python3 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, LinkedIn, or (when both are missing) case-insensitive
name+company
, returns
{"status": "exists", "id": N}
.
bash
python3 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 prospecting
创建线索时同时关联到工作区:
bash
python3 scripts/pipeline.py add-lead \
  --name "Jane Doe" --email "jane@acme.com" --company "Acme Corp" \
  --workspace thesystemsmethod --stage contacted
--workspace
add-lead
中是可选的——创建线索是组织级操作。当你知道线索所属工作区时使用;仅调研时可省略。
如果线索已通过邮箱、LinkedIn或(当两者都缺失时)不区分大小写的
name+company
存在,返回
{"status": "exists", "id": N}

Bulk import / enrich (CSV, JSON, research dumps)

批量导入 / 富集(CSV、JSON、调研数据)

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.
bash
python3 scripts/pipeline.py import-profiles \
  --file outreachmagic/imports/contacts_enriched.csv

python3 scripts/pipeline.py import-profiles \
  --file leads.json

python3 scripts/pipeline.py import-profiles \
  --json '[{"email":"j@acme.com","name":"Jane","job_title":"VP Marketing","industry":"Martech","headcount":"11-50","company":"Acme"}]'

python3 scripts/pipeline.py import-profiles \
  --file contacts.csv --dry-run
对于电子表格、富集约或批量调研数据,使用
import-profiles
——不要重复调用
add-lead
。匹配使用分层身份(优先级从高到低):
external_id
→ 邮箱 → LinkedIn → 电话 → name+domain → name+company →
import_key
(仅含名称的行)。CSV列
unified_lead_id
/
source_id
会被视为别名并存储为
external_id
。仅填充空字段(与中继/PlusVibe相同);使用
--overwrite
替换现有值。
bash
python3 scripts/pipeline.py import-profiles \
  --file outreachmagic/imports/contacts_enriched.csv

python3 scripts/pipeline.py import-profiles \
  --file leads.json

python3 scripts/pipeline.py import-profiles \
  --json '[{"email":"j@acme.com","name":"Jane","job_title":"VP Marketing","industry":"Martech","headcount":"11-50","company":"Acme"}]'

python3 scripts/pipeline.py import-profiles \
  --file contacts.csv --dry-run

With workspace association, tags, and LinkedIn status tracking

关联工作区、添加标签并跟踪LinkedIn状态

python3 scripts/pipeline.py import-profiles
--file contacts.csv --workspace default --sender-profile "https://linkedin.com/in/myprofile"
--source csv_import --source-detail "Q2 Apollo list" --import-batch-id "nace-2026-05"
python3 scripts/pipeline.py import-profiles
--file sales_nav_export.csv --source sales_navigator --source-detail "Q2 Sales Nav list"
python3 scripts/pipeline.py import-profiles
--file contacts.csv --workspace default --sender-profile "https://linkedin.com/in/myprofile"
--source csv_import --source-detail "Q2 Apollo list" --import-batch-id "nace-2026-05"
python3 scripts/pipeline.py import-profiles
--file sales_nav_export.csv --source sales_navigator --source-detail "Q2 Sales Nav list"

Rows with only name + company_domain + unified_lead_id (no email/LinkedIn)

仅含名称 + company_domain + unified_lead_id的行(无邮箱/LinkedIn)

python3 scripts/pipeline.py import-profiles
--file nace.csv --workspace acme_corp --import-batch-id nace-2026-05

**`verify-email`:** Records LEV rows locally and sets `cloud_pending` — run `sync` to push verification fields to the relay (same as other lead mutations).

**Email-finder batch save (known `lead_id` on every row):** email-finder calls `apply-email-find-results` — updates email, workspace tags, and provider verification in one pass. Requires `--workspace`. Run `sync` after batch-find when COMPLETE shows pending snapshots. Manual recovery:

```bash
python3 scripts/pipeline.py apply-email-find-results \
  --workspace your_workspace --source trykitt --source-detail "email-finder/batch" \
  --file import.json
Use
import-profiles
when rows lack
lead_id
/ need tiered matching or CSV-only fields (personalization columns,
import_batch_id
, etc.).
Core profile fields (column aliases — first non-empty wins):
Canonical fieldAliasesRequired
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):
ColumnEffect
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. Use
--source
for the machine-readable channel (
sales_navigator
,
trykitt
,
lead_enrich
,
csv_import
, …). Use
--source-detail
or
import_name
/
list_source
columns for list/campaign labels. Per-row
list_source
overrides the CLI
--source
default when present.
python3 scripts/pipeline.py import-profiles
--file nace.csv --workspace acme_corp --import-batch-id nace-2026-05

**`verify-email`:** 在本地记录LEV行并设置`cloud_pending`——运行`sync`以将验证字段推送到中继(与其他线索变更操作相同)。

**Email-finder批量保存(每行都有已知`lead_id`):** email-finder调用`apply-email-find-results`——一次性更新邮箱、工作区标签和供应商验证信息。需要`--workspace`。当COMPLETE显示待处理快照时,在batch-find后运行`sync`。手动恢复:

```bash
python3 scripts/pipeline.py apply-email-find-results \
  --workspace your_workspace --source trykitt --source-detail "email-finder/batch" \
  --file import.json
当行缺少
lead_id
/ 需要分层匹配或仅CSV字段(个性化列、
import_batch_id
等)时,使用
import-profiles
核心资料字段(列别名——第一个非空值优先):
标准字段别名必填
email
lead_email
,
work_email
否(见下文身份分层)
linkedin
linkedin_url
,
lead_linkedin_url
,
profile_url
name
full_name
,
display_name
(或
first_name
+
last_name
title
job_title
,
role
company
company_name
,
organization
,
org
industry
headcount
company_size
,
employees
,
employee_count
location_city
city
,
lead_city
location_state
state
,
region
,
lead_state
location_country
country
,
lead_country
员工人数标准化:
headcount
按原样存储(文本),同时计算出
headcount_numeric
(整数中点)。范围如
"11-50"
会变为
30
"500+"
变为
500
,精确数字直接保留。线索和公司都会获得该数字列用于排序/过滤(
WHERE headcount_numeric BETWEEN 10 AND 100
)。
额外字段(从CSV列自动检测):
列名效果
company_domain
存储在
companies
表中,已标准化(去除协议/www/路径)
hq_city
/
hq_state
/
hq_country
公司总部位置,存储在
companies
表中
mailmerge_first_name
自动填充到personalization表的
first_name
字段
mailmerge_company_name
自动填充到personalization表的
company_name
字段
import_name
/
list_source
当值不含
:
时,为
external_id
添加归属 + 命名空间
external_id
CRM/列表ID,存储在
lead_identities
中(如果是裸ID,则命名空间为
list_source:id
unified_lead_id
,
source_id
导入别名 → 与
external_id
相同
import_batch_id
(CLI标志)
通过批次内的
import_key
为仅含名称的行提供稳定的去重标识
lead_status
需要
--workspace
;标准化(小写、空格替换)并设置在workspace_leads中
lead_sentiment
需要
--workspace
;标准化(小写)并设置在workspace_leads中
tags
需要
--workspace
;分号或逗号分隔,标准化(小写),存储在
workspace_lead_tags
contact_order
需要
--workspace
;整数优先级存储为workspace_leads中的
contact_priority
is_connected_linkedin
需要
--workspace
+
--sender-profile
true
/
1
/
yes
设置连接状态
is_linkedin_request_pending
需要
--workspace
+
--sender-profile
true
/
1
/
yes
设置待处理状态
标准化规则:
  • 标签: 小写,合并空格 ——
    "VIP"
    "vip"
    视为同一标签
  • 状态/情感: 小写,下划线替换为空格 ——
    "Not_Interested"
    变为
    "not interested"
  • 员工人数: 保留范围字符串 + 计算数字中点(
    "11-50"
    → 30)
  • 位置: 按原样存储(城市/州/国家文本)
归属自动设置: 每次导入都会在线索上设置
original_source
(不可变的首次接触来源)和
latest_source
(每次更新),遵循Salesforce/HubSpot模型。使用**
--source
指定机器可读渠道(
sales_navigator
trykitt
lead_enrich
csv_import
等)。使用
--source-detail
**或
import_name
/
list_source
列指定列表/活动标签。当存在每行的
list_source
时,会覆盖CLI默认的
--source

Personalization (mail-merge)

个性化设置(邮件合并)

Lead fields (
first_name
, contact-specific lines): per lead. Company fields (
company_name
,
company_*
): org-wide, one write per account.
Raw fieldMail-merge fieldScope
name
first_name
lead
company
/
companies.name
company_name
company
bash
undefined
线索字段
first_name
、特定联系人信息):每条线索单独设置。公司字段
company_name
company_*
):组织级设置,每个账户仅需设置一次。
原始字段邮件合并字段范围
name
first_name
线索
company
/
companies.name
company_name
公司
bash
undefined

Lead

线索

python3 .../pipeline.py personalize-pending --fields first_name --json python3 .../pipeline.py personalize-set --lead-id 5 --field first_name --value "Jane" python3 .../pipeline.py personalize-set --lead-id 5 --field upcoming_event --value "SaaStr talk" --date 2026-09-10
python3 .../pipeline.py personalize-pending --fields first_name --json python3 .../pipeline.py personalize-set --lead-id 5 --field first_name --value "Jane" python3 .../pipeline.py personalize-set --lead-id 5 --field upcoming_event --value "SaaStr talk" --date 2026-09-10

Company (org-wide)

公司(组织级)

python3 .../pipeline.py company-personalize-pending --fields company_name,company_icebreaker --json python3 .../pipeline.py company-personalize-set --domain acme.com --field company_name --value "Acme" python3 .../pipeline.py company-personalize-set --domain acme.com --field company_icebreaker --value "..."
python3 .../pipeline.py company-personalize-pending --fields company_name,company_icebreaker --json python3 .../pipeline.py company-personalize-set --domain acme.com --field company_name --value "Acme" python3 .../pipeline.py company-personalize-set --domain acme.com --field company_icebreaker --value "..."

Read merged (export uses same shape: personalized_* columns)

读取合并后的数据(导出使用相同格式:personalized_*列)

python3 .../pipeline.py personalize-get --lead-id 5 --json

Import: `mailmerge_first_name` → lead; `mailmerge_company_name`, `mailmerge_company_*` → company. Sync pushes lead and company snapshots separately; merge is local.
python3 .../pipeline.py personalize-get --lead-id 5 --json

导入时:`mailmerge_first_name` → 线索;`mailmerge_company_name`, `mailmerge_company_*` → 公司。同步会分别推送线索和公司快照;合并操作在本地完成。

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.
bash
undefined
记录来自ZeroBounce、NeverBounce等工具的验证结果。结果是组织级的(非工作区范围)。来自Smartlead、Instantly等平台的退信会在中继同步时自动记录。
bash
undefined

Record a verification result

记录验证结果

python3 scripts/pipeline.py verify-email
--lead-id 5 --status valid --source zerobounce
python3 scripts/pipeline.py verify-email
--lead-id 5 --status valid --source zerobounce

Batch verify from JSON

从JSON批量验证

python3 scripts/pipeline.py verify-email --batch
--json '[{"lead_id":5,"status":"valid","source":"zerobounce"}]'
python3 scripts/pipeline.py verify-email --batch
--json '[{"lead_id":5,"status":"valid","source":"zerobounce"}]'

Check verification status for a lead

检查线索的验证状态

python3 scripts/pipeline.py verify-status --lead-id 5 python3 scripts/pipeline.py verify-status --email j@acme.com
python3 scripts/pipeline.py verify-status --lead-id 5 python3 scripts/pipeline.py verify-status --email j@acme.com

List leads needing verification

列出需要验证的线索

python3 scripts/pipeline.py verify-pending --limit 50 --json

**Verification 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.
python3 scripts/pipeline.py verify-pending --limit 50 --json

**验证状态值:** `valid`, `invalid`, `catch-all`, `unknown`, `spamtrap`, `abuse`, `do_not_mail`, `risky`, `bounced`, `soft_bounce`

**退信处理:** 平台退信(来自中继同步)会自动记录在`lead_email_verification`中,`source="platform_bounce"`。硬退信覆盖软退信。工具验证(ZeroBounce等)优先级高于平台退信——工具的"valid"结果仅会被之后的硬退信覆盖。合并后的状态会在`leads.email_verification_status`中具体化,以便快速过滤。

Companies and unified lead identity

公司与统一线索身份

  • companies
    table
    — canonical company name, domain, industry, headcount (text + numeric midpoint), HQ location (city, state, country). Leads link via
    company_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
    lead
    field.
  • 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:
bash
python3 scripts/pipeline.py merge-leads --keep 12 --merge 34
python3 scripts/pipeline.py merge-leads \
  --email j@acme.com --linkedin linkedin.com/in/janedoe
  • companies
    —— 标准公司名称、域名、行业、员工人数(文本 + 数字中点)、总部位置(城市、州、国家)。线索通过
    company_id
    关联(导入时通过商务邮箱域名或公司名称匹配)。
  • 通过邮箱和/或LinkedIn匹配 —— 线索可以仅含邮箱、仅含LinkedIn,或两者都有。中继导入会从webhook负载 + 信封
    lead
    字段解析身份。
  • 合并重复项当邮箱和LinkedIn历史属于不同行时:
    • 自动合并: 导入时同时匹配两个线索的标识符会合并它们(保留事件更多的行)。
    • 手动合并:
bash
python3 scripts/pipeline.py merge-leads --keep 12 --merge 34
python3 scripts/pipeline.py merge-leads \
  --email j@acme.com --linkedin linkedin.com/in/janedoe

Dedup (batch duplicate find + merge)

去重(批量查找重复项 + 合并)

bash
python3 scripts/pipeline.py dedup find --workspace popcam --tag campaign --output outreachmagic/exports/candidates.json
python3 scripts/pipeline.py dedup merge --candidates outreachmagic/exports/candidates.json          # dry-run
python3 scripts/pipeline.py dedup merge --candidates outreachmagic/exports/candidates.json --commit   # apply
bash
python3 scripts/pipeline.py dedup find --workspace popcam --tag campaign --output outreachmagic/exports/candidates.json
python3 scripts/pipeline.py dedup merge --candidates outreachmagic/exports/candidates.json          # 试运行
python3 scripts/pipeline.py dedup merge --candidates outreachmagic/exports/candidates.json --commit   # 应用

Google Sheets export (lead review)

Google Sheets导出(线索审核)

To export leads to an editable Google Sheet (two-way sync), use
sheets export
or
review export
— not
export --format csv
.
Requires
pipeline.py login
. Sheets are created on
app.outreachmagic.io
(no local Google credentials).
bash
python3 scripts/pipeline.py sheets export --workspace popcam --title "NACE Leads"
要将线索导出到可编辑的Google Sheets(双向同步),使用**
sheets export
review export
**——不要使用
export --format csv
需要
pipeline.py login
。表格会在
app.outreachmagic.io
创建(无需本地Google凭据)。
bash
python3 scripts/pipeline.py sheets export --workspace popcam --title "NACE Leads"

equivalent:

等效命令:

python3 scripts/pipeline.py review export --template lead-review --workspace popcam
--tag nace --detail standard --title "NACE Leads"

See **Lead review sheet** below for sync-back workflow.
python3 scripts/pipeline.py review export --template lead-review --workspace popcam
--tag nace --detail standard --title "NACE Leads"

见下文**线索审核表格**了解同步回传工作流。

Dedup review (hosted Google Sheets)

去重审核(托管Google Sheets)

Requires
pipeline.py login
. Sheets are created on
app.outreachmagic.io
and shared to your org owner email (or
--share-email
). Check Merge? in the sheet, then sync.
bash
python3 scripts/pipeline.py review export --input outreachmagic/exports/candidates.json --title "Popcam Dedup"
python3 scripts/pipeline.py review sync --sheet-id SHEET_ID --dry-run
python3 scripts/pipeline.py review sync --sheet-id SHEET_ID --commit
需要
pipeline.py login
。表格会在
app.outreachmagic.io
创建并共享给你的组织所有者邮箱(或
--share-email
指定的邮箱)。在表格中勾选Merge?,然后同步。
bash
python3 scripts/pipeline.py review export --input outreachmagic/exports/candidates.json --title "Popcam Dedup"
python3 scripts/pipeline.py review sync --sheet-id SHEET_ID --dry-run
python3 scripts/pipeline.py review sync --sheet-id SHEET_ID --commit

Lead review sheet (export → edit → sync)

线索审核表格(导出 → 编辑 → 同步)

Requires login. Sheets are created on
app.outreachmagic.io
with edit/lock header icons (no column colors). All usage notes live in the
lead_id
header cell note; freeze row and dropdowns apply before the export URL is returned. Detail levels:
--detail basic|standard|full|custom
. Use
review presets
for the current column catalog (full adds
lev_*
,
be_*
,
latest_source*
,
linkedin_sender_<handle>
keys). Dropdowns:
workspace_stage
,
lead_sentiment
. Export prints row progress and API timing to stderr.
bash
python3 scripts/pipeline.py review presets --template lead-review
python3 scripts/pipeline.py review export-payload --workspace popcam --tag nace --detail standard
python3 scripts/pipeline.py review export --template lead-review --workspace popcam \
  --tag nace --detail standard --title "NACE Review"
python3 scripts/pipeline.py review sync --template lead-review --workspace popcam \
  --sheet-id SHEET_ID --detail standard --dry-run
python3 scripts/pipeline.py review sync --template lead-review --workspace popcam \
  --sheet-id SHEET_ID --detail standard --commit
需要登录。表格会在
app.outreachmagic.io
创建,带有编辑/锁定表头图标(无列颜色)。所有使用说明都在
lead_id
表头单元格的备注中;在返回导出URL前会应用冻结行和下拉菜单。详情级别:
--detail basic|standard|full|custom
。使用
review presets
查看当前列目录(full会添加
lev_*
,
be_*
,
latest_source*
,
linkedin_sender_<handle>
键)。下拉菜单:
workspace_stage
,
lead_sentiment
。导出时会在stderr中打印行进度和API耗时。
bash
python3 scripts/pipeline.py review presets --template lead-review
python3 scripts/pipeline.py review export-payload --workspace popcam --tag nace --detail standard
python3 scripts/pipeline.py review export --template lead-review --workspace popcam \
  --tag nace --detail standard --title "NACE Review"
python3 scripts/pipeline.py review sync --template lead-review --workspace popcam \
  --sheet-id SHEET_ID --detail standard --dry-run
python3 scripts/pipeline.py review sync --template lead-review --workspace popcam \
  --sheet-id SHEET_ID --detail standard --commit

Email-finder candidates (safe domain export)

Email-finder候选线索(安全域名导出)

Never use
COALESCE(domain, company)
— use this command to emit batch-find JSON with real
companies.domain
only:
bash
python3 scripts/pipeline.py email-finder-candidates --workspace popcam --tag nace \
  --no-email --require-domain --never-contacted
切勿使用
COALESCE(domain, company)
——使用此命令仅输出含真实
companies.domain
的batch-find JSON:
bash
python3 scripts/pipeline.py email-finder-candidates --workspace popcam --tag nace \
  --no-email --require-domain --never-contacted

Scope to a CSV batch (returns scanned / skipped_has_email / candidates)

限定CSV批次范围(返回扫描数 / 已含邮箱的跳过数 / 候选线索数)

python3 scripts/pipeline.py email-finder-candidates --workspace popcam --file outreachmagic/batches/find-batch.json

`export` also supports `--never-contacted`, `--no-email`, and `--require-domain`. Force large relay snapshot pages with `sync --bulk` (or `sync --no-bulk` for routine sizes).

```bash
python3 scripts/pipeline.py history --linkedin linkedin.com/in/janedoe
After
pull
, use
campaigns
for per-campaign event and lead counts (unchanged).
python3 scripts/pipeline.py email-finder-candidates --workspace popcam --file outreachmagic/batches/find-batch.json

`export`也支持`--never-contacted`, `--no-email`, 和`--require-domain`。使用`sync --bulk`强制获取大型中继快照页面(或`sync --no-bulk`使用常规大小)。

```bash
python3 scripts/pipeline.py history --linkedin linkedin.com/in/janedoe
pull
后,使用**
campaigns
**获取每个活动的事件和线索统计(无变化)。

Log every outreach send

记录每一次拓展消息发送

bash
python3 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.
bash
python3 scripts/pipeline.py log-event \
  --lead-id 1 --type email_sent --direction outbound \
  --subject "Quick intro" --workspace thesystemsmethod
在多工作区模式下,
--workspace
必填项。拓展事件是工作区范围的——它们属于特定流水线。在单工作区模式下会回退到默认工作区。

Update stage and log replies

更新阶段并记录回复

bash
python3 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
bash
python3 scripts/pipeline.py update-stage \
  --id 1 --stage replied --next-action "Send case study" --workspace thesystemsmethod
在多工作区模式下,
--workspace
必填项。阶段是工作区范围的——一条线索在一个工作区中可能处于"contacted"阶段,在另一个工作区中处于"interested"阶段。
阶段流程:
prospecting
->
contacted
->
replied
->
interested
->
proposal
->
won
|
lost

Connect sequencers (paid)

连接序列器(付费)

If the user already has a key, skip the browser flow:
bash
python3 scripts/pipeline.py login
Generate webhook URLs for platforms directly from the CLI (requires agent key):
bash
python3 scripts/pipeline.py connect-platform --platform smartlead
python3 scripts/pipeline.py connect-platform --platform instantly
python3 scripts/pipeline.py connections
如果用户已有密钥,跳过浏览器流程:
bash
python3 scripts/pipeline.py login
直接从CLI为平台生成webhook URL(需要Agent密钥):
bash
python3 scripts/pipeline.py connect-platform --platform smartlead
python3 scripts/pipeline.py connect-platform --platform instantly
python3 scripts/pipeline.py connections

Update skill scripts

更新skill脚本

bash
python3 scripts/pipeline.py update
bash
python3 scripts/pipeline.py update

Lead Fields Reference

线索字段参考

FieldCLI flagNotes
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
--email
Dedup key — unique per lead
linkedin
--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
字段CLI标志说明
name
--name
必填
company
--company
title
--title
职位
industry
--industry
例如:Martech、Fintech、Healthcare
headcount
--headcount
规模区间,例如:1-10、50-200、1000+
email
--email
去重键——每条线索唯一
linkedin
--linkedin
LinkedIn资料URL
channel
--channel
email、linkedin、whatsapp(默认:email)
stage
--stage
流水线阶段(默认:prospecting)
notes
--notes
自由文本
tags
--tags
JSON数组字符串,如'["vip","enterprise"]'
workspace
--workspace
add-lead
中可选;多工作区模式下
log-event
update-stage
必填

Privacy & Security

隐私与安全

  • Local-first data. Pipeline leads, events, and campaign stats live in local SQLite (
    pipeline.py paths
    database
    ).
  • Relay pass-through. Webhooks hit
    api.outreachmagic.io
    ; the CLI imports them locally via
    pull
    . We store tokens and usage on our side, not a searchable cloud copy of your outreach archive.
  • Portal API.
    app.outreachmagic.io
    handles tokens, billing, and optional workspace routing sync when connected.
  • Credentials. Store relay tokens in
    config/outreachmagic_config.json
    only. Never hardcode tokens in SKILL.md or commit them to git.
  • Read before connect. See SECURITY.md for full data boundaries and vulnerability reporting.
  • 本地优先数据。流水线线索、事件和活动统计存储在本地SQLite中(
    pipeline.py paths
    database
    )。
  • 中继中转。Webhook命中
    api.outreachmagic.io
    ;CLI通过
    pull
    将其导入本地。我们在服务器端存储令牌和使用情况,而非你的拓展存档的可搜索云端副本。
  • 门户API
    app.outreachmagic.io
    处理令牌、计费和连接时的可选工作区路由同步。
  • 凭据。仅在
    config/outreachmagic_config.json
    中存储中继令牌。切勿在SKILL.md中硬编码令牌或提交到git。
  • 连接前阅读。详见SECURITY.md了解完整的数据边界和漏洞报告流程。

Common Pitfalls

常见陷阱

  1. Time-window analytics: use
    query engagement
    (no pull). Latest activity: pull before
    show
    /
    history
    .
  2. Forgetting add-lead before log-event
  3. Not updating stage after reply
  4. Setup/auth errors (including 401 Unauthorized) should run
    python3 scripts/pipeline.py login
    in terminal.
  5. Version: run
    pipeline.py version
    — do not guess from SKILL.md frontmatter alone.
  6. Relay archive stays on api.outreachmagic.io;
    pull
    dedupes locally. Use
    refresh --yes
    for a true rebuild (sync + backup + wipe +
    pull --full
    ).
    pull --full
    alone only helps after deleting the DB manually.
  7. Tags: plain names (
    nace
    ,
    vip
    ) — not JSON list strings like
    ['nace']
    . Run
    tag repair
    for bracket-form tags.
  8. add-lead
    on an existing email does not enrich
    — use
    import-profiles
    or rely on relay
    pull
    for fill-if-empty updates.
  9. ModuleNotFoundError: data_freshness
    — run
    pipeline.py update
    .
  10. Large
    import-profiles
    batches
    — chunked 200 rows; if save times out, re-run with
    --file
    on your export JSON/CSV.
  1. 时间窗口分析: 使用
    query engagement
    (无需pull)。最新活动:
    show
    /
    history
    前执行pull。
  2. 在log-event前忘记add-lead
  3. 回复后未更新阶段
  4. 设置/认证错误(包括401 Unauthorized)应在终端运行
    python3 scripts/pipeline.py login
  5. 版本: 运行
    pipeline.py version
    ——不要仅从SKILL.md前置内容猜测。
  6. 中继存档保留在api.outreachmagic.io;
    pull
    在本地去重。使用
    refresh --yes
    进行真正的重建(同步 + 备份 + 清空 +
    pull --full
    )。单独使用
    pull --full
    仅在手动删除数据库后有用。
  7. 标签: 使用纯名称(
    nace
    ,
    vip
    )——不要使用JSON列表字符串如
    ['nace']
    。运行
    tag repair
    修复括号格式的标签。
  8. 对已有邮箱执行add-lead不会富集数据——使用
    import-profiles
    或依赖中继
    pull
    进行空字段填充更新。
  9. ModuleNotFoundError: data_freshness
    ——运行
    pipeline.py update
  10. 大型
    import-profiles
    批次
    ——按200行分块;如果保存超时,重新运行并指定导出的JSON/CSV文件。

Pull Troubleshooting Runbook

Pull故障排查手册

When relay flow appears stale, diagnose before using destructive reset commands:
bash
python3 scripts/pipeline.py pull --diagnose
python3 scripts/pipeline.py pull --full --diagnose
Diagnostic verdicts:
  • relay empty
    — no events returned for the current cursor window.
  • relay has events but deduped
    — relay returned events already recorded in local
    relay_ingested
    .
  • cursor advanced
    — event cursor moved forward (
    last_max_id
    increased).
  • cursor stalled
    — relay returned a full page but cursor did not advance; inspect relay pagination.
  • Pull uses id cursors only:
    last_max_id
    (webhooks) and per-table snapshot cursors (
    last_snapshot_core_after_id
    ,
    last_snapshot_workspace_after_id
    ,
    last_snapshot_company_after_id
    ). No
    since
    on relay pull.
If events were ingested but still seem missing, inspect a specific lead timeline:
bash
python3 scripts/pipeline.py history --email "<lead_email>" --json
当中继流程似乎停滞时,在使用破坏性重置命令前先诊断:
bash
python3 scripts/pipeline.py pull --diagnose
python3 scripts/pipeline.py pull --full --diagnose
诊断结论:
  • relay empty
    —— 当前游标窗口无事件返回。
  • relay has events but deduped
    —— 中继返回的事件已记录在本地
    relay_ingested
    中。
  • cursor advanced
    —— 事件游标已推进(
    last_max_id
    增加)。
  • cursor stalled
    —— 中继返回完整页面但游标未推进;检查中继分页。
  • Pull仅使用ID游标:
    last_max_id
    (webhooks)和每个表的快照游标(
    last_snapshot_core_after_id
    ,
    last_snapshot_workspace_after_id
    ,
    last_snapshot_company_after_id
    )。中继pull不支持
    since
    参数。
如果事件已导入但仍显示缺失,查看特定线索的时间线:
bash
python3 scripts/pipeline.py history --email "<lead_email>" --json