Studio kinds
plungeai-campaign-agent
Design and emit ONE PlungeAI (Ocean Studio) campaign agent — a long-running, list-driven, resumable agent that works an owned ledger of items in short scheduled runs until the current cycle is exhausted — as CNL YAML (a claim task plus a `type: batch` with `ledger: campaign`) and a campaign-config…
Design and emit ONE PlungeAI (Ocean Studio) campaign agent — a long-running, list-driven, resumable agent that works an owned ledger of items in short scheduled runs until the current cycle is exhausted — as CNL YAML (a claim task plus a type: batch with ledger: campaign) and a campaign-config block (list source, cycle, schedule, max_attempts, then, deliver). Use when the Studio Think composer has "Campaign agent" selected, or when a user asks for an agent that works through a list, a backlog, a catalog, "N things to check", "run until the list is done", "start again every week", or "then move to the next list". NOT for single scheduled reports (plungeai-bot-agent), interactive agents (plungeai-agentic-agent) or multi-step pipelines (plungeai-workflows).
Download zip (opens in a new tab) · View raw SKILL.md (opens in a new tab)
Used by Studio: Ocean Studio's agent builder loads this skill by its id.
A campaign is a task list with an owner. Each run claims a slice of the not-yet-done items, works them at bounded concurrency, and records every outcome before it ends; the scheduler re-fires runs until the cycle is exhausted. Runs are short by law — the platform cannot hold one invocation past ~10 minutes — so never design a run that "keeps going". Repetition is the schedule's job, resumption is the ledger's job.
The conversation (before any YAML)
- Unit. What is one item? A product, a lead, a URL, a document. Name the key that identifies it.
- List source. Exactly one: a Task-app table + filter (point-and-pick; never raw SQL), an agent op
that returns a JSON array (discover the id with
registry_search, never from memory), a CSV the user will upload in the Task app after save, or an inline list for a handful of items. - Per-item job. A plain agent op when the item is "call one agent, store one row" (cheapest). A harness
mission only when the item genuinely needs a tool loop; then the same rules as a bot: no
ask_user, noplatform_action,effort: quickunless argued, mission ends with the task_complete sentence. The job MUST upsert by{item.key}+{item.cycle}— say so in the mission or pass both to the op. - Cycle.
once(a backlog),hourly | daily | weekly | monthly(a recurring pass),continuous(restart as soon as exhausted).cycle_start: resetreuses the same keys;refillre-queries the source. - Schedule. When runs may happen — a 5-field cron. Propose a window that finishes the list with margin:
batch_size × seconds per item ÷ concurrency ≤ 600 s, then enough ticks to cover the list. - Deliver. Where the cycle summary and alerts go — same channels and pairing rules as a bot.
Confirm, then emit BOTH blocks.
Output contract — two fenced blocks, in this order
workflow:
name: "<short campaign name>"
description: "<one line: what one item is and how often the list is worked>"
tasks:
- type: task
id: claim
agent: data-table-agent
operation: campaignClaim
campaign_id: "<written by Step-2 at save>"
batch_size: 40
- type: batch
id: work
items_from: claim
concurrency: 5
ledger: campaign
tasks:
- type: task # or type: harness when a tool loop is needed
id: one
agent: <agent id>
operation: <op>
key: "{item.key}"
cycle: "{item.cycle}"list:
table: { project: <project>, table: <table>, filter: { <column>: <value> }, key: <column> }
cycle: weekly
cycle_start: refill
schedule: "*/5 9 * * 1"
max_attempts: 2
then: ""
deliver:
- channel: inapp
local: falseRules the lint enforces — violating them makes the save fail:
- Exactly one top-level claim task (
agent: data-table-agent,operation: campaignClaim) and exactly onetype: batchwithitems_from: claim,ledger: campaign, andconcurrency≤ 5. - Inner tasks are unattended: no
ask_user, noplatform_action; a harness inner task MUST includetask_completeinallowed_toolsand end its mission with the task_complete sentence. - The per-item task must reference
{item.key}(warning if it looks insert-only — the ledger is at-least-once). max_attemptsis required. Nomemory_owner. No emails or ids in the YAML — recipients belong indeliver.local: trueonly with a harness inner task pinned toagent: harness-agent, and in BOTH blocks.
campaign-config fields
list— one oftable {project, table, filter, key},agent {id, operation},csv: true,inline: [...].cycle—once | hourly | daily | weekly | monthly | continuous. Calendar cycles never restart inside their bucket.cycle_start—reset | refill. Defaultrefillfor table/agent sources,resetfor csv/inline.schedule— 5-field cron; each tick is one run (an empty claim returns in about a second).max_attempts— dead-letter threshold on explicit failures; required.then— optional campaign id to start when a cycle completes. Never chain a dependent report onto a collection campaign; keep reports time-triggered.deliver— as for bots (inapp,email,slack,telegram,whatsapp,discord).local— run-on-my-computer, as for bots.
Worked examples for all four use cases plus the full field reference: references/campaign-config.md.
Outside Studio the same campaign ships over MCP (https://mcp.plungeai.com/v1): plungeai_schedule
with action: create, job_type: workflow creates the scheduler job against the saved campaign
workflow. Discover the agent ids you name in the per-item task live — plungeai_list_agents from a
client, or registry_search inside the loop — never from memory.