signalpipe — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited signalpipe (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
SignalPipe gives you a full agentic sales pipeline: signal detection → human review → prospect nurturing → pipeline visibility → sending.
Four subsystems, twenty-nine tools. Use them in sequence.
v2.1.2 — describe one buyer.signalpipe_add_productandsignalpipe_suggest_anchorsnow ask for one buyer, described narrowly, intarget_audienceandvalue_prop. The judges read both fields, and a broad audience makes them keep weak leads.
v2.1.1 — reading keeps up with Reddit's limits. Feeds are read a minute apart (five seconds apart, Reddit answered every feed after the first with HTTP 429), a throttled feed is retried once, and a one-off signalpipe_read_feeds starts the pass in the background and returns at once.v2.1.0 — client-side reading, feed preview, replies, and set-up tools. New toolsignalpipe_read_feedsreads the stations your brain marksread_by: "client"from this machine and sends each feed page to the brain for judging; the brain scores the posts exactly as if its own scout had read them. No credentials and no new dependencies (the RSS/Atom parsing is built in).signalpipe_preview_stationchecks a feed for buyers before it is added.signalpipe_record_replyhands a prospect's reply to the brain, which reads it (intent, objections, do-not-contact, and whether they invited a private message).signalpipe_suggest_anchors,signalpipe_mark_sent,signalpipe_list_stations,signalpipe_update_product,signalpipe_update_stationandsignalpipe_remove_stationcover set-up and upkeep.signalpipe_score_signaltakescontextand returnspanel_verdict.
v2.0.5 — README matches the code. SignalPipe does not read X: your agent brings X posts through your own X API access, and the optional scout reads the RSS or Atom feeds you choose. Install withopenclaw plugins install signalpipe(orclawhub:signalpipe). Private messages go only to someone who asked for one, and the backend never auto-sends an X reply or a DM, whatever your auto-send setting (backend change, 2026-09-25). No tool surface change.
v2.0.3 — score_signal is documented, and the listing says what this is. TheReturnsblock forsignalpipe_score_signalnever mentionedswarm,swarm_ranorsource_hint; the three-judge verdict is the thing that makes the score worth trusting and the contract was silent on it. Now documented as each judge's stance plus asplitflag — a split panel is the case worth a human glance. The panel's internal numerics are not returned and are not documented as though they were. The npm/ClawHub blurb also stopped describing a Reddit scraper:score_signaltakes text from any channel the host agent can read, and the listing now leads with that. No tool surface or behaviour change.
v2.0.0 — the sender lands. SignalPipe v4 splits the work cleanly: the math runs on us, the sending runs on you. The brain still scores, drafts, and approves; the plugin can now ALSO send. Three new tools —signalpipe_start_sender,signalpipe_stop_sender,signalpipe_sender_status— run a background loop that streams pre-approved missions from the brain and postsreddit_comment/reddit_dmon Reddit with the operator's OWN credentials (a Reddit "script" app set via the optionalREDDIT_*env vars).twitter_replymissions are left for the standalonesignalpipe-daemon. The sender contains zero scoring, drafting, or storage — Reddit credentials stay on the operator's machine and are never sent to SignalPipe. Within a running session each mission is posted at most once (no double-send), even across reconnects; daily caps skip (not fail) a capped mission so it stays queued. MCP-only operators who never setREDDIT_*are unaffected — the sender simply stays idle. See Subsystem 3 — Sender below.
v1.6.2 — reject vs delete clarity for stale posts. When a post is gone by the time the operator gets there (deleted by the poster, 404, removed by mods, or stale beyond the reply window), the lead wasn't bad — the opportunity just evaporated. Usesignalpipe_delete_mission(no RL penalty), NOTsignalpipe_reject_mission(not_relevant)(which would penalise a station that did nothing wrong). The tool descriptions and the reject / delete sections below have been clarified accordingly. No tool surface change — this is presentation only, aligning the LLM-facing guidance with mantidae backend v3.7.13 + v3.7.14 (which also added cross-poster dedup and set the judges' temperature to 0.2, raised back to 0.7 in v3.7.17).
v1.6.0 — universal signal scoring. New signalpipe_score_signal exposes the scout's scoring engine for arbitrary text from any channel your host agent can read (Gmail, Slack, Discord, Telegram, LinkedIn, web pages, transcripts). You paste content, you get back score, classification, role, sub-scores, competitor info, and a drafting context block for client-side replies — without polling a feed or creating a mission. Lives in the Companion subsystem because the use-case is multi-channel and mid-funnel.v1.5.0 — response contract + delete_mission. Listings (signalpipe_get_missions,signalpipe_get_pipeline,signalpipe_get_products) return lean payloads by default —include_context=trueis opt-in. Drafting tools are framed as working payloads, not display payloads — use them to write the draft, don't dump them to the user. Newsignalpipe_delete_missionis the silent-cleanup companion tosignalpipe_reject_mission(which teaches the RL loop).
v1.4.0 — Client-side drafting. Mission drafts and prospect messages can be generated using YOUR LLM instead of the SignalPipe backend. Usesignalpipe_draft_mission+signalpipe_upload_draftfor missions, andsignalpipe_get_message_prompt+signalpipe_record_messagefor prospect nurture. The backend-LLM equivalentsignalpipe_get_messagestill works — pick whichever fits.
Mantidae scouts the web for buying signals and queues them as missions for review.
signalpipe_get_missionsFetch all pending missions awaiting human approval.
When to call: User asks "show me my leads", "what needs review", "check the pipeline".
Returns: Array of missions, each with:
id — mission ID (use for approve/reject)product_name — which product this lead is forsignal_score — 0–100 buying-intent score, adaptive based on your approval/rejection historycompetitor_flag — true if a competitor was mentionedchannel — where to reach them (twitter_reply | reddit_dm | manual | etc.)handle — prospect's username/emaillead_snippet — the text that triggered the signalsource_url — direct link to the original post or tweetai_draft — AI-generated reply, ready to sendHow to present missions to the user: Always show: score · channel · handle · snippet · draft. For manual channel missions, always show the source_url as a clickable link — the user needs to open the original post themselves to reply. Label it clearly: "Open post → [URL]" For reddit_dm or twitter_reply, the backend handles delivery — just show the draft for approval.
Example workflow:
User: "Show me today's leads"
→ Call signalpipe_get_missions
→ For each mission present:
Score · Channel · Handle
What they said: [snippet]
Draft: [ai_draft]
(if manual) Open post → [source_url]
→ Ask user to approve, reject, or edit each onesignalpipe_approve_missionApprove a mission and queue it for outreach.
When to call: User says "approve this", "send it", "looks good".
Before calling: Always confirm the mission ID and draft text with the user first. If the user edited the draft, pass their version via draft. Otherwise omit it.
Parameters:
mission_id (required) — the id from signalpipe_get_missionsdraft (optional) — edited message text; omit to use the AI draft unchangedAfter calling: Tell the user it's queued. Offer to move on to the next mission.
signalpipe_reject_missionReject a mission — it was not a real buying signal. Teaches the RL loop.
When to call: User says "skip", "not relevant", "bad lead", "reject" — and you have any opinion on WHY it was bad. If the user just wants the row gone with no learning signal, use signalpipe_delete_mission instead.
DO NOT call when the post is gone. If the user says the post was deleted, 404'd, removed by mods, or has gone stale beyond the reply window — that's signalpipe_delete_mission, not signalpipe_reject_mission. The lead wasn't a bad signal; the opportunity just evaporated. Using reject_mission(not_relevant) here applies an RL penalty to a station that did nothing wrong.
Effect: Sets the mission status to rejected and nudges the RL weight down by a per-reason amount. Accuracy directly improves how the system learns.
| Reason | Penalty | When to pick |
|---|---|---|
spam | heaviest | Bot, promoted, automated post |
not_relevant | heavy | Wrong audience or topic |
wrong_product | light | Real signal, wrong product matched |
too_vague | moderate | Signal too weak to act on |
sarcasm | light | Ironic / venting, not a real buyer |
already_customer | none | They bought — no penalty |
no_reason | moderate | Default if you have no opinion |
Parameters:
mission_id (required)rejection_reason (optional) — pick the closest reason from the table. The reason accumulates into products.rejection_stats for analytics.signalpipe_delete_missionHard-delete a mission row — silent queue cleanup, no learning signal.
When to call: User says "just delete this", "clear it", "I don't care, get rid of it" — or when you want to clear duplicates / accidental scrapes that the RL loop should not learn from.
Canonical case — the post is gone. If the user says the post was deleted by the poster, 404'd, removed by mods, or has gone stale beyond their reply window, signalpipe_delete_mission is the right tool. The lead wasn't wrong, the opportunity just evaporated — there's nothing to teach the station. Using signalpipe_reject_mission here would penalise a station that did nothing wrong.
Effect: Removes the row entirely. The source feed's scoring weight is untouched.
When to prefer `signalpipe_reject_mission` instead: Any time you can categorise WHY the lead was bad. Reject teaches the RL loop with a per-reason penalty; delete throws away the learning signal. Default to reject when in doubt — but DO default to delete when the post is just gone.
Parameters:
mission_id (required)signalpipe_scout_nowTrigger an immediate scouting run.
When to call: User says "check for new leads now", "run a fresh scan", "scout immediately". Scouts run automatically every 30 minutes — only call this for on-demand runs. It scans the user's own products, at most once every 15 minutes; a skipped status with reason cooldown or batch_in_progress is normal, not an error.
No parameters.
signalpipe_mark_sentRecord that the user already replied to a lead by hand.
When to call: The moment the user has posted the reply or sent the message themselves through the platform (most first touches are manual public replies). It marks the mission sent, records the outreach so follow-up drafts know what was said (creating the prospect), and counts as a positive signal for the source feed. signalpipe_approve_mission is different: it queues the mission for the sender.
Parameters: mission_id.
signalpipe_get_productsList all active products being monitored.
When to call: User asks "what products do you track", "show me my products", or before adding a station (you need the product_id).
signalpipe_suggest_anchorsDraft buyer-voice anchor sentences for a product. Call it before signalpipe_add_product.
Flow: ask the user what the product is, who buys it and what it does for them; call this; SHOW the anchors and invite edits (they know their buyers' words better than any model); then add the product with the approved list.
Parameters: name, value_prop, optional target_audience, description, count (default 8).
signalpipe_add_productRegister a new product for lead monitoring.
When to call: User wants to start tracking leads for a new product.
Key parameters:
anchor_sentences — most important field. Every incoming post is scored bysimilarity to these, so they decide what the user does and doesn't see. Write them as the BUYER describing their PROBLEM, not as the seller describing the product:
target_audience and value_prop — describe one buyer, narrowly: whothey are and the problem they would write about. The judges read both fields when deciding whether a post's author is a buyer, so a broad audience ("SaaS founders, agencies, sales teams… and any operator") makes them keep weak leads. If the product has clearly different buyers, add each as its own product.
buy_signal_keywords — leave empty unless you have a specific reason.This is an optional COST filter, not a quality one, and it's an AND-gate: a post that matches NONE of the keywords scores 0 before embedding and before the swarm, with nothing logged. In testing, the same sentence scored 0 when it said "people" and highly when it said "leads" — one word. You cannot enumerate every phrasing a buyer might use, so a keyword list silently deletes real buyers in proportion to how badly you guessed. The embedding floor, vertical gate and 3-judge swarm still filter without it.
competitor_keywords — direct SUBSTITUTES only (tools a buyer would chooseinstead of this product). A buyer-intent mention of one floors the score so switchers always surface. Don't list adjacent-category tools that merely sound similar — you'll surface people who were never in your market.
After calling: Always call signalpipe_reload_products to activate immediately.
signalpipe_update_productEdit a product, or pause and resume it. Only the fields passed change.
When to call: The user wants to change anchors, the description or keywords, or to pause a product (active: false: its stations stop being read and score_signal stops accepting it) or resume it. Anchors follow the add_product rules, and the previous set is kept so a bad edit can be undone. Products are paused, never deleted. Confirm with the user before changing anchors or pausing.
signalpipe_add_stationAdd an RSS feed or search source to monitor for a product.
When to call: User wants to monitor a new subreddit, Hacker News keyword, or RSS feed. Run signalpipe_preview_station on it first, and add it only if the verdict is VIABLE or MARGINAL. The URL must be http(s) on a public host; the reply includes the new station's id.
Common patterns:
https://www.reddit.com/r/SUBREDDIT/new/.rss — use /new/, not thebare /.rss. Bare returns the hot listing (popular, already-answered posts); /new/ returns fresh ones, and scoring rewards recency heavily.
https://hnrss.org/newest?q=YOUR+KEYWORDSChoosing stations matters more than any setting:
keyword or tool-name searches. Broad feeds produce the overwhelming majority of real leads; narrow keyword feeds frequently produce none at all.
founder communities are dense with people building things like the user's product (correctly filtered out as sellers) and thin on actual buyers.
rate-limit; more stations mainly buys more noise.
is the most common cause of an empty queue.
Parameters:
product_id — from signalpipe_get_productsplatform — rss | hn | reddit (active monitoring); twitter_search routes leads to Twitter reply outreach but does not monitor Twitter feeds — X direct monitoring is not yet supportedrss_url — full feed URL (Reddit and HN use RSS URLs; leave empty for twitter_search)signalpipe_list_stationsThe user's feeds with a health readout for the last two weeks.
When to call: The user asks why the queue is quiet, which feeds work, or before editing a feed. Each station shows posts captured, how many reached the queue, empty or rate-limited fetches, read_by (server or this machine) and a plain-language verdict, e.g. "Posts are arriving but none matched your product: change the anchor sentences".
Parameters: optional product_id.
signalpipe_update_stationPause, resume, rename or re-point a feed. Only the fields passed change; a new rss_url is checked before it is saved.
Parameters: station_id (from signalpipe_list_stations), optional active, name, rss_url, keyword.
signalpipe_remove_stationRemove a feed. Confirm with the user first. A feed that never produced a lead is deleted; one that did is switched off instead to keep its history, and the reply says which.
Parameters: station_id.
signalpipe_reload_productsHot-reload the product cache after adding or editing products.
When to call: Always after signalpipe_add_product. No server restart needed.
No parameters.
The Companion nurtures prospects from first contact to close. It tracks a temperature (0–100) for each prospect and selects the right message persona automatically.
| Mode | When | Persona |
|---|---|---|
nurture | New prospect (temperature 10), no engagement yet | Educator — introduce value, no pressure |
sales | Engaged, and temperature reached 50 | Consultant — qualify, show fit, build trust |
closing | Temperature ≥ 75 | Closer — urgency, social proof, clear CTA |
recovery | Cooled after engaging, or an explicit cooling signal (ghosted, not interested, bad timing) | Re-engager — re-spark cold leads, no hard sell |
dead | Asked not to be contacted | None — never message them again; drafting is refused |
Mode is intent-based, not pure temperature: a new prospect stays in nurture until a real signal lands.
signalpipe_score_signalScore arbitrary text against a product profile — the same scoring engine the scout runs on RSS feeds, exposed for any channel.
When to call: User pastes an email, forwarded DM, Slack thread, LinkedIn message, transcript snippet, or any text and asks "is this a real buying signal?" or "is this person interested?". Also use it as a triage step before signalpipe_track_prospect when you're not sure the signal is genuine.
SignalPipe never touches the source platform. You (the host agent) read the content with your other plugins; this tool just classifies the text. The scoring is the exact same pipeline the scout uses on Reddit/HN — embedding similarity to product anchors, urgency / specificity / keyword-density sub-scores, competitor detection, and sarcasm gate. Note: the per-station RL weight (which the scout multiplies into scores from a specific feed) does NOT apply to score_signal calls — there is no "source station" for ad-hoc text from Gmail, Slack, etc., so the raw scoring engine is used directly.
Parameters:
text — content to score (truncated server-side to 4000 chars)product_id — from signalpipe_get_products. Same text scores differently against different productssource_hint (optional) — channel label (gmail | slack | discord | telegram | linkedin | whatsapp | twitter | reddit | …). Affects drafting tone, not the scorecontext (optional) — the post, thread or email the text replies to (up to 2,000 chars). Pass it whenever you score a reply or comment: "same problem here, what did you end up using?" means little alone and is clear under the post it answers. The judges see it as background; the score stays about the text's own authorReturns:
score — 0–100 weighted score (after RL multiplier, clamped)content_score — pre-RL content score (honest about what's in the text)classification — buying_intent · borderline · competitor_mention · noiserole — closer (highest-intent) · advisor (mid-intent) · educator (early-stage)swarm — the judge panel's read: judges (each of skeptic / analyst / optimist asconvinced · on the fence · unconvinced) and split (true when the panel disagreed materially). A split panel is the case worth a human glance — it is exactly where one-shot prompting is unreliable. Stances only; the panel's internal numerics are not returned.
swarm_ran — whether the panel was consulted for this call. Clear-cut text is decided oncontent alone and does not spend three judge calls
panel_verdict — what the judges concluded: kept, rejected or not_run. The judges canraise a score but never lower it, so a post they rejected can still read borderline. Treat rejected as not a lead whatever the score
source_hint — echoed back so you can key off it when routing the replysub_scores — urgency, specificity, keyword_density for explainabilitycompetitor_match, competitor_name, competitor_intent — competitor detection + intent (complaining / replacing / comparing / neutral)sarcastic — boolean; sarcastic text scores 0 regardless of surface signaldrafting_context — only present when score ≥ 40 and not sarcastic; contains product info, signal info, and tone instructions for client-side draftingWhen to use this vs `signalpipe_track_prospect`:
score_signal = does this text contain a buying signal? Pure classification, no state changetrack_prospect = this person took an action, update their temperature. Writes to the pipelineMany flows use both: score the inbound text first, then track the prospect if the signal is real.
signalpipe_track_prospectLog a signal from a prospect and update their temperature.
When to call: Any time a prospect takes an action — ghosts, asks about price, books a demo, etc. Creates the prospect automatically if they are new. When you have the text of their reply, use signalpipe_record_reply instead.
Parameters:
handle — Twitter handle, Reddit username, email, etc.channel — twitter | reddit_dm | whatsapp | telegram | email | discordsignal — what happened:booked_demo | asked_pricingviewed_content | replied | clicked_linknot_interested | bad_timing | ghosted_7_daystoo_expensive | competitor | ghosted_3_days | no_timenot_decision_makeropted_out — they asked not to be contacted; the prospect becomes dead and no further message is draftedproduct_id (optional) — from signalpipe_get_productsmission_id (optional) — if this prospect came from a Mantidae missionReturns: New temperature, mode, and recommended follow-up timing.
signalpipe_record_replyHand a prospect's reply to the brain, which reads it.
When to call: Whenever a tracked prospect writes back (a comment reply, a DM, an email). Paste the reply as they wrote it.
Parameters: prospect_id, reply_text, optional channel.
Returns: intent (buy, interested, objection, not_now, unsubscribe, neutral…), the new mode, updated objections, do_not_contact (true when they asked not to be contacted: stop, never message them again) and invites_private_contact (true only when this reply explicitly asks to continue in private, such as "DM me"). Reddit and X require that consent before an app sends a private message, so never suggest a DM without it.
signalpipe_get_messageGenerate the next outreach message for a prospect.
When to call: User asks "what should I say to @handle", "generate a follow-up", "write me a message for this prospect".
The message is:
Parameters:
prospect_id — returned by signalpipe_track_prospectAfter getting the message: Always present it to the user for review before they send it. Never send autonomously.
signalpipe_get_pipelineGet the full prospect pipeline sorted by temperature.
When to call: User asks "how is my pipeline", "who should I follow up with", "show me my hot prospects", "pipeline summary".
Returns: All prospects sorted hottest first, plus counts per mode (nurture / sales / closing / recovery) and do_not_contact for prospects who asked not to be contacted.
The Sender is the v4 "send" half. The brain scores, drafts, and approves missions; the Sender holds a live stream open to the brain, receives the missions it has already approved, and posts them on Reddit using the operator's OWN credentials. It never scores, drafts, or stores anything — it only sends.
Scope: Reddit only (reddit_comment and reddit_dm). twitter_reply missions are skipped here and left for the standalone signalpipe-daemon. manual missions are always skipped — the operator sends those by hand.
Setup: the Sender needs a Reddit "script" app on the sending account, supplied via optional environment variables (see Environment Variables below). If they aren't set, the Sender stays idle and the rest of the plugin works normally. These credentials stay on the operator's machine and are never sent to SignalPipe.
Safety: the brain only ever streams approved missions. Public Reddit comments, X replies and DMs are never auto-approved, whatever the account's auto-send setting, so each of those waits for a person. The drafts are written by AI: Reddit asks that AI-generated content be disclosed and acts against automated posting, so have the user read and edit each draft before approving it. Within a running session each mission is posted at most once — a dropped connection is always safe to recover from. Daily caps pace sending; a capped mission is skipped (stays queued for after the next local-midnight reset), not failed.
signalpipe_start_senderStart the background Reddit sender.
When to call: User says "start sending", "turn on the sender", "go live", "start posting approved replies".
Before calling: Confirm with the user before starting a live (non-dry-run) sender — it will post to Reddit. Suggest a dry_run first to confirm the stream connects and missions arrive.
Parameters:
dry_run (optional) — log intended sends without posting to Reddit or acking the brain. Default false.After calling: The loop runs in the background until signalpipe_stop_sender or a gateway restart. Tell the user it's running and offer signalpipe_sender_status to check on it.
signalpipe_stop_senderStop the background Reddit sender.
When to call: User says "stop sending", "turn off the sender", "pause posting".
Effect: Closes the mission stream cleanly. Missions already posted are unaffected; unsent approved missions stay queued on the brain and deliver next time the sender runs. Stopping and restarting is always safe.
No parameters.
signalpipe_sender_statusReport the sender state.
When to call: User asks "is the sender running", "how many has it sent", "is it connected", or right after starting it to confirm it connected.
Returns: A local block (running, connected, paused, sent / failed / skipped counts this session, last event, last error) and a brain block (queue depth, auto-fire threshold, version). Present the local loop state first (running? connected? counts), then the brain queue depth.
No parameters.
Some stations can be read from the operator's own machine instead of by the brain: /stations/list marks them read_by: "client". The reader fetches those feeds from here and hands each page to the brain, which scores the posts as if its own scout had read them. It needs no credentials and contains no scoring.
signalpipe_read_feedsRead the stations marked for this machine and send the posts to the brain for judging.
When to call: The user asks to read their feeds now, or /stations/list shows stations with read_by: "client". Call it with no parameters: it starts one pass in the background (about a minute per feed, because Reddit limits how fast one machine may read) and returns at once; call it again a few minutes later for the counts.
Parameters:
every_minutes (optional, integer, 10 or more): keep reading in the background on this interval. The brain's own scout runs every 30 minutes.stop (optional, boolean): stop the background reader.Returns: The reader's state: status (started, or busy while a pass runs), reading_now, running (background reading on), interval, passes, and last_counts for the last finished pass (client stations, feeds sent, posts sent, empty feeds, skipped, rate-limited, errors). A feed the brain judged a few minutes ago is skipped on cooldown, and a feed Reddit is throttling is retried once and otherwise read on the next pass; both are normal.
After calling: Missions from these posts reach the queue like any other; offer signalpipe_get_missions.
signalpipe_preview_stationCheck a feed for buyers before adding it as a station.
When to call: Before signalpipe_add_station, or when the user asks whether a community is worth listening to. The feed is read on this machine, the brain scores its fresh posts, and the three judges read the best-matching ones (default 8, one judgement each). Nothing is saved.
Parameters: product_id, rss_url, optional sample (1-12).
Returns: a verdict fixed by pre-set thresholds — VIABLE (worth adding), MARGINAL (a trickle), ON-TOPIC, NOT IN-MARKET (topic talk, no buyers: try a different community), NO BUYERS, or NO DATA (nothing could be judged; the explanation says why, such as an empty or stale feed or keywords that blocked every post) — with an explanation, feed counts, and a sample of judged posts (kept or rejected, with the judges' stances). Suggest adding the feed only for VIABLE or MARGINAL.
1. signalpipe_get_missions → show user pending leads
2. User reviews each → reject, or edit the draft in their own words
3a. User replies by hand → signalpipe_mark_sent (records the send, creates the prospect)
3b. Or the sender should post it → signalpipe_approve_mission (with the edited draft)
4. The person writes back → signalpipe_record_reply (prospect_id, reply_text)
→ temperature, mode, objections and do-not-contact update from what they said
5. signalpipe_get_message → a follow-up that fits their reply
6. Present the message to the user for review1. signalpipe_get_pipeline → show sorted prospects (skip anyone in do_not_contact)
2. User picks a prospect to message
3. signalpipe_get_message → generate context-aware message
4. User reviews and sends
5. They reply → signalpipe_record_reply; they go quiet → signalpipe_track_prospect (ghosted_3_days / ghosted_7_days)1. Ask what it is, who buys it, and what it does for them
2. signalpipe_suggest_anchors → show the anchors, let the user edit them
3. signalpipe_add_product → with the approved anchors (leave buy_signal_keywords empty)
4. signalpipe_reload_products → activate immediately
5. Ask where their buyers complain; for each candidate feed:
signalpipe_preview_station → add only VIABLE or MARGINAL feeds with signalpipe_add_station
6. signalpipe_scout_now → run first scan immediately
7. signalpipe_get_missions → review first batch of leads1. signalpipe_list_stations → read each feed's verdict
2. "Posts are arriving but none matched" → signalpipe_update_product (better anchors)
3. "No posts captured" → check the URL, or signalpipe_update_station (new rss_url)
4. A feed that only ever produces noise → signalpipe_preview_station on alternatives,
then signalpipe_update_station (active=false) or signalpipe_remove_station1. (one-time) Set REDDIT_CLIENT_ID/SECRET/USERNAME/PASSWORD in the environment
2. signalpipe_start_sender (dry_run=true) → confirm it connects and missions arrive
3. signalpipe_sender_status → verify connected=true
4. signalpipe_stop_sender, then signalpipe_start_sender → go live
5. signalpipe_sender_status → watch sent / failed / skipped counts1. signalpipe_read_feeds → starts one pass in the background; call again for the counts
2. signalpipe_read_feeds (every_minutes=30) → keep reading in the background
3. signalpipe_get_missions → review what the judges surfacedWhen SignalPipe loads (i.e., when OpenClaw starts with the plugin installed), the plugin registers its 29 tools and connects to the SignalPipe managed backend. You will see this in the OpenClaw logs:
[SignalPipe] Plugin v2.1.2 loaded — 29 tools registered (acquisition + companion + sender + reader)The brain scouts your active products every 30 minutes. It scores signals, drafts replies, and queues approved missions for outreach execution — all on managed infrastructure. Your OpenClaw LLM key stays inside OpenClaw and is never shared with SignalPipe.
Set before starting the OpenClaw gateway:
| Variable | Required | Description |
|---|---|---|
SIGNALPIPE_API_URL | Yes | URL of your SignalPipe backend — provided at signup |
SIGNALPIPE_OPERATOR_KEY | Yes | Your secret operator key — provided at signup from signalpipe.io |
REDDIT_CLIENT_ID | Sender only | Reddit "script" app client id (sending account) |
REDDIT_CLIENT_SECRET | Sender only | Reddit "script" app secret |
REDDIT_USERNAME | Sender only | Reddit username of the sending account |
REDDIT_PASSWORD | Sender only | Reddit password of the sending account |
REDDIT_USER_AGENT | No | Defaults to signalpipe-plugin/2.0 |
MAX_REDDIT_COMMENTS_PER_DAY | No | Daily comment cap. Default 15 |
MAX_REDDIT_DMS_PER_DAY | No | Daily DM cap. Default 5 |
The two SIGNALPIPE_* vars are all the plugin needs for scoring, drafting, and review — your OpenClaw LLM key stays inside OpenClaw and is never shared with SignalPipe. The REDDIT_* vars are optional and only needed to run the in-plugin Sender (Subsystem 3); they stay on your machine and are never sent to SignalPipe. MCP-only operators can ignore them entirely.
If a tool call returns an error, follow this decision tree before doing anything else:
SIGNALPIPE_OPERATOR_KEY is wrong or not set. Tell the user: "Authentication failed — please check SIGNALPIPE_OPERATOR_KEY is set correctly and matches the backend OPERATOR_KEY."{"status":"online"} at /health.signalpipe_get_missions returns empty arraysignalpipe_add_product fails with HTTP 400name, anchor_sentences.signalpipe_get_message returns the fallback message ("Just following up…")signalpipe_track_prospect, the smarter the temperature model gets.~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.