run-campaign
Skill0 starsChanged 57 days agoMITView on GitHub
Run a consent-based ThunderPhone outbound campaign to people who agreed to be called (appointment reminders, callbacks, follow-ups) - create it, load contacts, start, pause, stop, monitor, or troubleshoot. Use when someone asks about campaign setup, contact CSV or JSON imports, calling windows, consent and compliance controls, consent_to_charge, campaign actions, or stats.
- Reads credentials
- Sends data out
2 other projects use a version of this.
Adopted by
Most recently taken up by
- Walsworth-Group/physkittheir own version, first seen Nov 8, 2026
- alebgl77/claude-inctheir own version, first seen Jul 28, 2026
Other versions2 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 2
- alebgl77/claude-inc★ 21same name
- Walsworth-Group/physkit★ 7same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository21 other files it gives its agents.
- AGENTS.mdAGENTS.md
- add-knowledgeSkill
- build-tool-integrationSkill
- create-agentSkill
- embed-web-widgetSkill
- get-phone-numberSkill
- handle-inbound-callsSkill
- iterate-on-agentSkill
- migrate-from-blandSkill
- migrate-from-elevenlabsSkill
- migrate-from-retellSkill
- migrate-from-vapiSkill
- place-outbound-callsSkill
- setup-api-keySkill
- setup-webhooksSkill
- test-agentSkill
- thunderphone-mcp-setupSkill
- thunderphone-prompt-builderSkill
- use-with-livekitSkill
- use-with-openai-realtimeSkill
- use-with-pipecatSkill
The file
We split this skill into the rules it gives an agent
11 rules. About 0 are common, 4 are distinctive, and 7 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈4
Distinctive · estimate
This author's own choices. Worth a look.
7
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 13
Establish the legal and operational basis: Document audience, purpose, consent/lawful basis, suppression handling, caller identity, …
- Very specific: line 16
Validate the agent and number: Use a tested deployed agent and an outbound-capable from_number.
- Very specific: line 95
Only first attempts are texted.
- Very specific: line 99
Load contacts: Use POST /v1/campaigns/{campaign_id}/contacts with CSV or JSON.
- Very specific: line 104
Review the dry state: Read GET /v1/campaigns/{campaign_id} and sample contacts.
- Very specific: line 107
Start explicitly: Call POST /v1/campaigns/{campaign_id}/start with consent_to_charge: true only after an authorized operator approves the …
- Very specific: line 120
Use a pool of local numbers sized so daily calls per number stay under max_calls_per_number_per_day.
- Very specific: line 122
Keep window_timezone_mode: "contact" and retry_strategy: "spread".
- Distinctive: line 146
Follow outbound campaigns, campaign API, and outbound calling laws.
- Distinctive: line 147
Never start a campaign without explicit authority for its reviewed audience and spend.
- Distinctive: line 149
Do not claim delivery or conversation success from a queued/contact count.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Run an outbound campaign
- Establish the legal and operational basis. Document audience, purpose, consent/lawful basis, suppression handling, caller identity, recording rules, time zones, and permitted calling windows. Do not infer consent from a list.
- Validate the agent and number. Use a tested deployed agent and an
outbound-capable
from_number. Check balance andGET /v1/outbound-tcpa-confirmationbefore loading production contacts. - Create the campaign.
POST /v1/campaignsrequires a name, agent, and a source number (from_number) or a pool of them (from_numbers), plus a daily start/end window. For more than a few dozen calls a day, use a pool of local numbers: each contact is called from the number it was last called from, else one with its area code, else one in its time zone, else the least used, andmax_calls_per_number_per_day(default 75) keeps each number under carrier spam thresholds. Contacts wait, never fail, when every number is at its limit;blocked_reasonsays so. New campaigns call in each contact's local time (window_timezone_mode: "contact", by area code) and spread retries across days and times of day (retry_strategy: "spread").double_dial: trueredials once, 30-60 seconds after a ring-out, without using an attempt. Keep the campaign paused while loading and reviewing contacts.
{
"name": "May win-back",
"agent": 12,
"from_numbers": ["${FROM_NUMBER}", "${SECOND_FROM_NUMBER}"],
"max_calls_per_number_per_day": 75,
"window_timezone_mode": "contact",
"retry_strategy": "spread",
"double_dial": true,
"timezone": "America/Los_Angeles",
"daily_window_start": "09:00",
"daily_window_end": "17:00"
}curl --fail-with-body -X POST https://api.thunderphone.com/v1/campaigns \
-H "Authorization: Bearer $THUNDERPHONE_API_KEY" \
-H "Content-Type: application/json" \
-H "X-ThunderPhone-Client: skills/run-campaign@1.0" \
--data-binary @campaign.jsonimport json, os, requests
with open("campaign.json", encoding="utf-8") as f:
payload = json.load(f)
r = requests.post("https://api.thunderphone.com/v1/campaigns", json=payload,
headers={"Authorization": f"Bearer {os.environ['THUNDERPHONE_API_KEY']}",
"X-ThunderPhone-Client": "skills/run-campaign@1.0"}, timeout=30)
r.raise_for_status()
print(r.json())import { readFile } from "node:fs/promises";
const body = await readFile("campaign.json", "utf8");
const response = await fetch("https://api.thunderphone.com/v1/campaigns", {
method: "POST", headers: { Authorization: `Bearer ${process.env.THUNDERPHONE_API_KEY}`,
"Content-Type": "application/json", "X-ThunderPhone-Client": "skills/run-campaign@1.0" }, body,
});
if (!response.ok) throw new Error(await response.text());
console.log(await response.json());Optional: text each contact a few minutes before the first call
(text-then-call). The MCP create_campaign tool does not take these fields
yet, so set them with PATCH /v1/campaigns/{campaign_id}. The sender must be
an SMS-capable number on the customer's own Twilio or Telnyx account (never
a ThunderPhone number), US local numbers need approved A2P 10DLC, and every
contact must have consented to texts as well as calls. A blank template uses
the default; pre_call_sms_lead_minutes is 1-60.
{
"pre_call_sms_enabled": true,
"pre_call_sms_from_number": "${SMS_FROM_NUMBER}",
"pre_call_sms_template": "Hi {{first_name}}, this is {{org_name}}. We'll call you in a few minutes from {{call_from_number}}. Reply STOP to opt out of texts.",
"pre_call_sms_lead_minutes": 2
}Only first attempts are texted; a failed or skipped text never blocks the
call. Read a pre_call_sms_sender_not_ready entry in warnings (contacts are
called without a text until it clears) and each contact's pre_call_sms
outcome in GET /v1/campaigns/{campaign_id}.
4. Load contacts. Use POST /v1/campaigns/{campaign_id}/contacts with CSV or
JSON. Imports are capped per request; split larger lists (the API reference
gives the current limit). Every contact must have agreed to be called. Normalize
E.164 numbers, time zones, required variables, and suppression state before
upload. Deduplicate outside the campaign too.
5. Review the dry state. Read GET /v1/campaigns/{campaign_id} and sample
contacts. Confirm windows, agent, number, variable mapping, counts, and stop
conditions.
6. Start explicitly. Call POST /v1/campaigns/{campaign_id}/start with
consent_to_charge: true only after an authorized operator approves the
reviewed batch. The action endpoint also supports pause and cancel.
7. Monitor. Poll GET /v1/campaigns/{campaign_id}/stats, reconcile signed
call events, watch balance and failure rate, and pause on unexpected behavior.
8. Verify. Begin with a small controlled contact set. Inspect audio,
transcripts, outcomes, opt-outs, time-window behavior, and stats before
increasing volume.
Deliverability checklist
Carriers label numbers as spam from how they call. Before a large campaign:
- Use a pool of local numbers sized so daily calls per number stay under
max_calls_per_number_per_day; number health flags over 50 calls a day. - Keep
window_timezone_mode: "contact"andretry_strategy: "spread". - Set the agent to leave a voicemail (
voicemail_actionpromptormessage, nothangup) and give each number an inbound agent so callbacks reach someone. - Register caller names and Twilio numbers for spam filters on Phone
Numbers, and turn on Text before calling (
pre_call_sms_enabled) for contacts who agreed to texts. - Watch
GET /v1/phone-numbers/healthwhile it runs. Retire a number that gets labeled; never add fresh numbers to hide it.
See get outbound calls answered.
Errors
| Symptom | Cause | Fix |
| Campaign will not start | Missing attestation, balance, contacts, or charge consent | Read the error, resolve the named gate, and review before retrying. |
| Contacts are rejected | Invalid number, missing required column, or import too large | Normalize and validate; split imports at the documented limit. |
| Calls occur at the wrong local time | The campaign uses window_timezone_mode: "campaign", or contacts lack a US/Canadian area code | Use "contact"; split contacts without an area code into a campaign with their timezone. |
Running but not dialing, blocked_reason set | Every pool number reached its daily limit | Wait, add numbers to the pool while paused, or raise max_calls_per_number_per_day. |
| Failure rate rises | Agent, carrier, number, or contact data is unhealthy | Pause first, inspect samples and telemetry, then fix the cause. |
Source and safety rules
- Follow outbound campaigns, campaign API, and outbound calling laws.
- Never start a campaign without explicit authority for its reviewed audience and spend.
- Honor suppression, opt-out, identity, calling-window, and recording requirements.
- Do not claim delivery or conversation success from a queued/contact count.
See references/campaign-gates.md.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

