schedule-ads
Manage paid ads on AdManage.ai from declarative config - default schedules launches across Meta/TikTok/Snapchat/Pinterest/LinkedIn (always PAUSED); create…
Skill by aeonfun
Install
Works with Claude Code, Claude apps, Codex, Cursor, Gemini CLI, GitHub Copilot, VS Code, OpenCode, Goose, Windsurf. Read the repository before you give any tool access to your data.
npx agentmarket install skill/aeonfun-schedule-ads
Asks which of your tools to add it to (Claude Code, Codex, Cursor, VS Code, Windsurf, Gemini CLI, Claude Desktop) and shows the change first. See https://agentmart.dev/cli.
Get the weekly diff
The weekly diff: one email a week with new agent tools, notable updates and grade changes, plus security alerts for tools you follow. Double opt-in, one-click unsubscribe.
About
Use cases: marketing
Reviews
Write a reviewNo reviews yet. Installed it? Reviews come from verified installers only. How reviews work
Permissions
What this skill can do and what it asks for, from its SKILL.md. Checked Oct 25, 2026.
- Tools
- No tools found
- Secrets
- None asked for
- Install scripts
- None found
Network hosts it talks to 1
codeload.github.com· found in install command
Files it touches
~/.claude/skills/schedule-ads
What's inside
- Skill name
schedule-ads- Description
- Manage paid ads on AdManage.ai from declarative config - default schedules launches across Meta/TikTok/Snapchat/Pinterest/LinkedIn (always PAUSED); create provisions Meta campaigns and ad sets.
- License
- MIT
- Metadata
- var: Selects which flow runs (parse from ${var}): - empty / unset (default) → SCHEDULE branch: read config.yaml, pick schedule entries matching today, and launch those ads in-run via AdManage.ai. Launches PAUSED by default; dailySpendCap circuit-breaker; never auto-activates live spend. - "create" → CREATE branch: read config.create.yaml, diff against .admanage-state/campaigns.json, and create the missing Meta campaigns + ad sets in-run. On-demand; creates entities PAUSED; returned IDs are written back into state so the schedule branch can launch into them. · title: Schedule Ads · commits: true · category: productivity
- Instructions
- 435 lines in SKILL.md · view on GitHub
Files (3)
- SKILL.md
- config.create.example.yaml
- config.example.yaml
SKILL.md (first lines)
> **${var}** selects the flow. Empty/unset = **schedule** (launch ads into existing ad sets). `create` = **create-campaign** (provision Meta campaigns + ad sets). Both are config-driven, PAUSED-by-default, and make the AdManage API calls **in-run** via `./secretcurl` (the `{ADMANAGE_API_KEY}` placeholder keeps the key off the command line), behind fail-closed spend guardrails.
Reads a declarative config, computes what to do, and makes the AdManage.ai API calls **in-run** via `./secretcurl`. The calls are an irreversible outbound side-effect (real ad spend), so they are each branch's **final** actions and run only behind the guardrails below (PAUSED-by-default, `dailySpendCap` circuit-breaker, dry-run). `ADMANAGE_API_KEY` is injected in-run via this skill's `requires:` — always write it as the `{ADMANAGE_API_KEY}` placeholder, never a bare `$ADMANAGE_API_KEY` (the Bash permission layer refuses that).
## Preamble (both branches)
1. Read `memory/MEMORY.md` for context. Read the last ~3 days of `memory/logs/` for recent launch / provisioning activity — don't re-report a signal already logged.
2. Parse `${var}`:
- empty / unset → run the **Schedule branch** below.
- `create` → run the **Create branch** below.
- anything else → log `SCHEDULE_ADS_UNKNOWN_SELECTOR: <value>` and exit cleanly (no notify).
3. Both branches spend real money on ad platforms. The shared safety posture (see each branch) is: PAUSED by default, config-only (never invent campaigns/creative/targeting), dry-run available, and exit silently when there's nothing to do.
---
# Schedule branch (default — empty `${var}`)
Reads `skills/schedule-ads/config.yaml`, picks schedule entries matching today, and launches those ads **in-run** via AdManage.ai (`POST /v1/launch` through `./secretcurl`), behind the spend guardrails below.
## Safety defaults (schedule)
This branch **spends real money on ad platforms**. Guardrails, in priority order:
1. **PAUSED by default.** Every launch request sets the entity to PAUSED. The operator has to resume manually in the AdManage dashboard before spend starts. `launchPaused: false` in config is the explicit opt-out.
2. **Daily spend cap.** Before launching, the branch checks `GET /v1/spend/daily` for today. If spend ≥ `dailySpendCap` in the config, all launches are skipped and a warning is notified. If the spend figure can't be verified (malformed / empty response), **fail closed** — skip and notify, don't launch. This is a circuit breaker, not a budget enforcer — platform budgets still apply.
3. **Dry-run mode.** If `DRY_RUN=true` in env or `dryRun: true` in config, the branch builds the payloads, writes them to `.pending-admanage/dryrun/`, notifies what *would* launch, and exits without calling the API.
4. **Config-only.** The branch does not invent campaigns, creative, or targeting. If there's no schedule for today, it exits cleanly with no API calls.
5. **Single source of truth.** All ads/campaigns/targeting live in `config.yaml`. The branch never generates new creative on the fly.
## Network note (schedule)
Launching ads is an irreversible outbound side-effect (real ad spend), so it is the branch's **final** action and runs only after the guardrails above pass:
- Auth'd calls go through `./secretcurl` with the `{ADMANAGE_API_KEY}` placeholder — never a bare `$ADMANAGE_API_KEY` (the Bash permission layer refuses that). `ADMANAGE_API_KEY` is injected in-run via `requires:`.
- The branch checks the daily spend cap (`GET /v1/spend/daily`), then per batch calls `POST /v1/launch`, polls `GET /v1/batch-status/{id}` to a terminal state, and reports via `./notify`.
- If `ADMANAGE_API_KEY` is unset, or the launch/spend call fails, skip the launch and notify — do not retry blindly. There is no deferred postprocess fallback.
## Steps (schedule)
1. **Load config.** Read `skills/schedule-ads/config.yaml`. If the file doesn't exist, log `SCHEDULE_ADS_NOT_CONFIGURED` and exit cleanly (no notify, no error). The example template lives next to this file as `config.example.yaml`.
2. **Validate config shape.** Required top-level keys: `defaults` (with `adAccountId`, `workspaceId`, `page`), and `schedules` (array). If either is missing, file an issue in `memory/issues/` per the CLAUDE.md issue tracker convention, notify once, and exit.
3. **Pick today's schedule entries.** For each entry in `schedules`, match against today's date:
- `when.everyDay: true` → always matches.
- `when.dayOfWeek: monday` (or any weekday name, lowercase) → matches if today is that weekday (UTC).
- `when.date: "2026-04-25"` → matches only on that exact date.
- `when.dates: ["2026-04-25", "2026-05-02"]` → matches if today is in the list.
- `when.cron: "0 8 * * 1"` → (advanced) matches if today satisfies the cron. Optional — skip if it's too much parsing effort.
If no entries match today, log `SCHEDULE_ADS_NOTHING_TODAY` and exit cleanly (no notify).
4. **Build launch payloads.** For each matching schedule entry, construct the AdManage `POST /v1/launch` body:
```json
{
"ads": [
{
"adName": "<templated from ad.adName, {date} replaced>",
"adAccountId": "<from defaults or entry override>",
"workspaceId": "<from defaults or entry override>",
"title": "<from ad>",
"description": "<from ad>",
"cta": "<from ad or defaults.cta>",
"link": "<from ad>",
"page": "<from defaults>",
"insta": "<from defaults, Meta only>",
"adSets": [ { "value": "<id>", "label": "<name>" } ],
"media": [ { "url": "<media url>" } ],
"status": "PAUSED"
}
]
}
```
Enforce `status: PAUSED` on every ad unless `defaults.launchPaused` is explicitly `false`. Never strip it silently.
Template substitutions inside string fields:
- `{date}` → today's ISO date (YYYY-MM-DD)
- `{dateHuman}` → "April 21, 2026" style
5. **Pre-flight validation.** For each payload:
- `media[*].url` must be an absolute `https://` URL. Reject entries with local paths or obviously broken URLs.
- `adSets[*].value` must be a non-empty string. If missing, skip the entry with a warning in the log.
- For Meta entries (`adAccountId` starts with `act_`): `page` and `insta` must be set. TikTok/Snapchat/etc. have their own requirements — don't block on Meta-specific fields for other platforms.
- `title` and `description` must be non-empty.
Drop invalid entries, keep going. Log which ones were skipped and why.
6. **Handle dry-run.** If `DRY_RUN=true` or `config.dryRun: true`:
- Write payloads to `.pending-admanage/dryrun/{schedule-name}-{timestamp}.json`.
- Notify a preview (see step 9) but with `[DRY RUN]` prefix.
- Skip step 7.
- This mode exists for the operator to sanity-check before arming real launches.
7. **Launch in-run.** This is the branch's final action — spends real money, so run the guardrails first. Only `./secretcurl`, `jq`, `date`, `echo`, `mkdir`, `grep`, `python3`, and the `Write` tool are available.
a. **Config check.** `[ -n "${ADMANAGE_API_KEY:+x}" ]` (the `${VAR:+x}` form — a bare `$ADMANAGE_API_KEY` trips the secret-expansion analyzer and reads as unset). If unset → notify "ads computed but ADMANAGE_API_KEY missing — nothing launched" and stop.
b. **Daily spend circuit-breaker (once).** Take the strictest `dailySpendCap` (`CAP`) across today's payloads. If set, read today's spend and **fail closed** unless it's a clean number *below* the cap:
```bash
SPEND=$(./secretcurl -sS --max-time 30 -H "Authorization: Bearer {ADMANAGE_API_KEY}" \
"https://api.admanage.ai/v1/spend/daily?startDate=$TODAY&endDate=$TODAY" | jq -r '.metadata.totalSpend // ""')
echo "$SPEND" | grep -qE '^[0-9]+(\.[0-9]+)?$' || { echo "spend unverifiable — fail closed"; exit 0; }
echo "$CAP" | grep -qE '^[0-9]+(\.[0-9]+)?$' || { echo "dailySpendCap not numeric — fail closed"; exit 0; }
python3 -c "import sys; sys.exit(0 if float(sys.argv[1])>=float(sys.argv[2]) else 1)" "$SPEND" "$CAP" \
&& { echo "daily spend cap tripped (today=$SPEND cap=$CAP) — launching nothing"; exit 0; }
```
c. **Per batch: launch, then poll.** For each payload `{ ads: [ ... ] }`:
```bash
RESP=$(./secretcurl -sS --max-time 60 -w 'http=%{http_code}\n' -X POST "https://api.admanage.ai/v1/launch" \
-H "Authorization: Bearer {ADMANAGE_API_KEY}" -H "Content-Type: application/json" -d "$PAYLOAD")
# success => .success==true and .adBatchId set; else record FAILED (.message/.error) and continue.
# Poll GET /v1/batch-status/$BATCH_ID (~90s, 5s interval) until .summaryStatus is success|error.
```
Record each batch's outcome (ok / error / still-running-after-timeout) for the notify. Ads launch **PAUSED** (the payload sets it) unless `launchPaused: false`.
8. **Write artifact to `output/.chains/schedule-ads.md`** so downstream chain consumers can read what was queued. Format:
```markdown
# Schedule Ads — ${today}From aeonfun/aeon, MIT.
More from aeonfun/aeon
- 0.722score
anatomy
aeonfun
Build crafted, highly detailed, interactive isometric SVG figures that explain a technical idea as a real physical object (a test rig, a dial gauge, a cabinet…
SkillAFreshness: A★ 782Claude Code +9 - 0.719score
base-mcp
aeonfun
Access a Base Account via the Base MCP server (mcp.base.org) - wallet, portfolio, sending, swapping, signing, x402 payments, batched calls, and transaction…
SkillAFreshness: A★ 782Claude Code +9 - 0.718score
aeon
aeonfun
Set up and run an Aeon agent instance - get started from scratch, pick which skills to turn on or install more from packs, reschedule or change what runs…
SkillAFreshness: A★ 782Claude Code +9 - 0.717score
hunter-22
aeonfun
Scan the ClawHunter agent bounty marketplace for opportunities that genuinely match this agent's real capabilities (code, security research, writing) and…
SkillAFreshness: A★ 782Claude Code +9 - 0.717score
get-started
aeonfun
First-run setup for the Aeon plugin.
SkillAFreshness: A★ 782Claude Code +9 - 0.715score
seo-audit
aeonfun
Daily on-page and technical SEO audit of every page on a site - discovers URLs from the sitemap, scores each page, adds cross-page checks (duplicate titles…
SkillAFreshness: A★ 782Claude Code +9 - 0.714score
fetch-tweets
aeonfun
Search and curate X/Twitter behind one selector - keyword, topic roundup, a single or tracked-account digest, an X list, or the AI-agent buzz preset -…
SkillAFreshness: A★ 782Claude Code +9 - 0.714score
github-trending
aeonfun
Curated trending across GitHub repos and the Hugging Face Hub (models, datasets, spaces) - filtered, clustered, and labeled by momentum with a one-line…
SkillAFreshness: A★ 782Claude Code +9 - 0.714score
bd-radar
aeonfun
Business-development radar across your product family - find who's building, forking, integrating, and mentioning your products, ranked into a…
SkillAFreshness: A★ 782Claude Code +9 - 0.714score
digest
aeonfun
Generate and send a digest on a configurable topic, optionally pulling RSS/Atom feeds as an input source alongside web + X signal
SkillAFreshness: A★ 782Claude Code +9 - 0.714score
feedback-builder
aeonfun
Point Aeon at a service's /feedback endpoint - pull what agents reported (bugs, missing features), triage and cluster it, then build the best accepted request…
SkillAFreshness: A★ 782Claude Code +9 - 0.714score
heartbeat
aeonfun
Ambient fleet-health check that surfaces anything worth attention (default), or an on-demand priority brief - the 3 things to focus on, why now, and what…
SkillAFreshness: A★ 782Claude Code +9
Signals
- Stars
- 782
- Forks
- 292
- Open issues
- 0
- Last commit (this folder)
- Oct 2, 2026 (26 days ago)
- Last release
- Jul 9, 2026 (3 months ago)
From GitHub (fetched Oct 24, 2026).
Details
- License
- MIT
- Repository
- github.com/aeonfun/aeon
- Website
- www.aeon.fun/
- First seen
- Oct 24, 2026
- Last checked
- Oct 24, 2026
- Source
- GitHubgithub-graphql
More from aeonfun
- 0.722score
anatomy
aeonfun
Build crafted, highly detailed, interactive isometric SVG figures that explain a technical idea as a real physical object (a test rig, a dial gauge, a cabinet…
SkillAFreshness: A★ 782Claude Code +9 - 0.719score
base-mcp
aeonfun
Access a Base Account via the Base MCP server (mcp.base.org) - wallet, portfolio, sending, swapping, signing, x402 payments, batched calls, and transaction…
SkillAFreshness: A★ 782Claude Code +9 - 0.718score
aeon
aeonfun
Set up and run an Aeon agent instance - get started from scratch, pick which skills to turn on or install more from packs, reschedule or change what runs…
SkillAFreshness: A★ 782Claude Code +9 - 0.717score
get-started
aeonfun
First-run setup for the Aeon plugin.
SkillAFreshness: A★ 782Claude Code +9 - 0.717score
hunter-22
aeonfun
Scan the ClawHunter agent bounty marketplace for opportunities that genuinely match this agent's real capabilities (code, security research, writing) and…
SkillAFreshness: A★ 782Claude Code +9 - 0.715score
seo-audit
aeonfun
Daily on-page and technical SEO audit of every page on a site - discovers URLs from the sitemap, scores each page, adds cross-page checks (duplicate titles…
SkillAFreshness: A★ 782Claude Code +9
Cite this page
schedule-ads skill. Agent Mart. https://agentmart.dev/skills/aeonfun-schedule-ads (last updated 2026-10-24)