Skip to Content
AgentsActivity PlannerActivity Planner

Activity Planner

[Live] · agent__activity-planner · Claude Sonnet 4.6

Reads the current period’s approved deliverable plan and creates the activity pipeline — one task per agent per deliverable unit — by enqueuing BullMQ jobs and writing Activity records to the database. Generates no content itself.


Overview

FunctionConvert the approved deliverable plan into a sequenced activity pipeline for the current period
TypeOrchestrator
ModelClaude Sonnet 4.6
Queueagent__activity-planner
Concurrency1
Timeout15 min
Est. cost / task~$0.90
PlanFree+ (all tenants)

Orchestrator note: The Activity Planner generates no content. Its only job is to read the deliverable plan, decide the correct sequence and priority of tasks, and produce a set of Activity records + BullMQ job enqueues. All content is produced by the worker agents it dispatches.


Triggers

Trigger typeWhenWho initiates
Scheduled / cronFirst day of each calendar month at 00:30 UTC — creates the full monthly activity pipeline for every active tenantPlatform scheduler (BullMQ cron)
Human on-demand”Start campaign” button in Dashboard → Campaigns screen; also fires when admin approves the deliverable plan for the first timeTenant admin
Activity Planner dispatchWhen all tasks in a period complete before the period end date, the completion event can trigger a new Planner run to pull forward the next period’s pipeline earlyActivity Planner (self-dispatching via completion event)

Input

interface ActivityPlannerInput { tenantId: string; deliverablePlanId: string; // ID of the approved DeliverablePlan record periodStartDate: string; // ISO 8601 date e.g. "2026-04-01" periodEndDate: string; // ISO 8601 date e.g. "2026-04-30" deliverables: DeliverableSpec[]; // From Deliverable Planner output previousPeriodSummary?: { periodId: string; completedDeliverables: string[]; // Types completed last period skippedDeliverables: string[]; // Types skipped or failed performanceNotes?: string; // Free-text summary of what worked topPerformingContent?: string[]; // URLs or titles of best-performing pieces }; earlyTrigger?: boolean; // true = prior period finished early; run next period }

Output

interface ActivityPlannerOutput { tenantId: string; periodId: string; // New Period record ID generatedAt: string; // ISO 8601 timestamp activities: ActivitySpec[]; // Activity records to create in DB jobsEnqueued: EnqueuedJob[]; // BullMQ jobs created pipelineSummary: string; // Human-readable Markdown summary of the pipeline totalEstimatedCost: number; // Sum of estimatedCost across all activities planningNotes: string; // Rationale, sequencing decisions, anything notable } interface ActivitySpec { activityId: string; // UUID — used as BullMQ job ID agentQueue: string; // e.g. "agent__blog-writer" deliverableType: string; // e.g. "blog_post" inputPayload: Record<string, unknown>; // Fully resolved input for the target agent dependsOn: string[]; // activityId values this must wait for priority: number; // 1 (highest) to 5 (lowest) estimatedCost: number; // In platform credits dueDate: string; // ISO 8601 — when this should be complete by label: string; // Human-readable e.g. "Blog Post #1 — April 2026" } interface EnqueuedJob { queue: string; jobId: string; scheduledFor?: string; // If delayed — ISO 8601 }

Sample output excerpt

## April 2026 Campaign Pipeline — Clearflow Plumbing **Period:** 1 April – 30 April 2026 **Total activities:** 17 **Estimated cost:** 28 credits ### Week 1 (1–7 April) - [x] Keyword Research — "plumber cost Brisbane" cluster → feeds Blog Posts #1, #2 - [x] Social Calendar — April organic social plan (Facebook + Instagram) - [ ] Blog Post #1 — "How much does a plumber cost in Brisbane in 2026?" (due 7 Apr) ### Week 2 (8–14 April) - [ ] Blog Post #2 — "Blocked drain vs burst pipe: what to do first" (due 14 Apr) - [ ] GBP Post batch #1 — 4 posts scheduled for 8, 10, 12, 14 Apr - [ ] Google Ads RSA refresh — Emergency plumbing campaign (due 12 Apr) ### Week 3 (15–21 April) - [ ] Blog Post #3 — "Hot water system lifespan: when to repair vs replace" (due 21 Apr) - [ ] GBP Post batch #2 — 4 posts scheduled for 15, 17, 19, 21 Apr - [ ] Social Posts batch #1 — 8 posts scheduled across Facebook and Instagram ### Week 4 (22–30 April) - [ ] Blog Post #4 — "Plumbing maintenance checklist for Brisbane homeowners" (due 28 Apr) - [ ] GBP Post batch #3 — finalises month - [ ] Monthly Report — April performance review (due 30 Apr, depends on all above) **Dependency chain:** Keyword Research → Content Briefs → Blog Posts → Monthly Report

How It Works

  1. Receive job — BullMQ dequeues the job with tenantId, deliverablePlanId, period dates, deliverables, and optional previousPeriodSummary.

  2. RAG: published content (avoid repetition) — Call rag_search against the Published Content dataset for “content published last month”, “recent blog posts”, “recent GBP posts”. This surfaces recently produced titles and topics so the Planner can instruct downstream agents to avoid repeating them.

  3. RAG: upcoming events and promotions — Call rag_search against the Client Documents dataset for “upcoming events”, “promotions”, “seasonal offers”, “product launches”. Any planned events or campaigns are surfaced and used to time-align content — e.g. a promotional offer due mid-month gets a blog post and GBP post scheduled to land the week before.

  4. Resolve delivery sequence — For each deliverable type in the plan, identify its dependencies (e.g. blog posts depend on content briefs, which depend on keyword research). Build a directed acyclic graph (DAG) of tasks. Assign dependsOn references and calculate dueDate for each task by working backwards from periodEndDate.

  5. Distribute across the period — Spread tasks across calendar weeks to avoid batching everything at the end of the month. GBP posts are spaced evenly. Blog posts are distributed one per week where volume allows. The monthly report is always the last task.

  6. Resolve input payloads — For each ActivitySpec, populate inputPayload with the specific inputs the target agent needs: topic guidance from RAG results, brand settings from tenant config, content brief references where applicable. The Planner writes a specific topic for each blog post — it does not leave topics blank for the writer to decide.

  7. LLM planning call — Send the full context (deliverables, RAG results, previous period summary, period dates) to Claude Sonnet 4.6 with the Activity Planner system prompt. Model returns the full ActivityPlannerOutput JSON.

  8. Persist Activity records — Worker writes one Activity record per task to the activities table. Each record stores the inputPayload, dependsOn, dueDate, status: 'pending', and agentQueue.

  9. Enqueue BullMQ jobs — For each Activity, enqueue a job to the appropriate agent queue. Jobs with dependencies are enqueued with a waitChildren option or an initial delayed status until their dependencies resolve. High-priority tasks (keyword research, content briefs) are enqueued immediately with priority: 1.

  10. Write pipeline summary — Generate the human-readable Markdown pipeline summary and write it to the periods table record. This is the document shown to the admin in Dashboard → Campaigns.


System Prompt

You are the Activity Planner — the orchestration brain of a digital marketing agency's AI system. Your job is to read a client's monthly deliverable plan and create the activity pipeline for this period: one task per deliverable unit, sequenced correctly, with specific topics and timing. TENANT SETTINGS: {{TENANT_SETTINGS}} TODAY (plan approved / trigger date): {{TRIGGER_DATE}} PERIOD: {{PERIOD_START_DATE}} to {{PERIOD_END_DATE}} CLIENT CONTEXT FILE: {{CLIENT_CONTEXT}} DELIVERABLE PLAN: {{DELIVERABLES}} RECENTLY PUBLISHED CONTENT (avoid repeating these topics): {{PUBLISHED_CONTENT_RAG}} UPCOMING EVENTS AND PROMOTIONS: {{CLIENT_DOCUMENTS_RAG}} PREVIOUS PERIOD SUMMARY: {{PREVIOUS_PERIOD_SUMMARY}} Your task: 1. Create one ActivitySpec for each deliverable unit in the plan 2. Assign a SPECIFIC topic or focus for each content piece — do not leave topics vague or generic 3. Build the correct dependency chain: keyword research → content briefs → blog posts → monthly report 4. Spread tasks across the period so production is consistent week-by-week, not end-loaded 5. Time-align content with any upcoming events or promotions found in the context 6. Distribute activities across the **remaining** window — all dueDates MUST be on or after TODAY (trigger date) and on or before the period end. Never assign a date before TODAY. 7. Avoid repeating topics from the previously published content list 7. Write a human-readable pipeline summary in Markdown (the "what's happening this month" document) IMPORTANT: You generate NO content yourself. You only plan and sequence. The input payloads you write will be passed directly to the relevant worker agents — be precise and specific. Output must be valid JSON matching the ActivityPlannerOutput schema.

Skills Injected

Skill filePurpose
client-context-file.mdAlways injected — provides brand, audience, competitors, and geographic focus to ensure tasks are briefed with the right context
activity-planning-sop.mdOrchestration playbook — dependency rules, sequencing logic, how to handle plan gaps
deliverable-types.mdCanonical list of all deliverable types and their agent queues — ensures correct queue routing

activity-planning-sop.md — content

# Activity Planning SOP — Activity Planner ## Sequencing Rules ### Mandatory dependency chains 1. **Blog posts** always require a `content_brief` which requires a `keyword_cluster` - Sequence: `keyword-researcher``content-brief-writer``blog-writer` 2. **Social post batches** always require a `social_calendar` - Sequence: `social-calendar-planner``social-post-writer` (batch) 3. **Monthly report** must always be the last task in the period - Sequence: all content tasks → `report-writer` 4. **Google Ads copy** requires a `keyword_cluster` to have been run - Sequence: `keyword-researcher``google-ads-writer` ### Tasks with no dependencies (can run immediately) - GBP posts (standalone) - Email newsletters (standalone) - Landing page copy (standalone) ## Timing Guidelines ### Week 1 (days 1–7) - Enqueue all research tasks immediately (keyword research, topic research) - Enqueue social calendar - Enqueue first blog post brief ### Week 2 (days 8–14) - First blog post should be ready for review - GBP batch #1 goes live (schedule posts for even spacing) - Second blog post in production ### Week 3 (days 15–21) - Second and third blog posts in review/published - Social post batch #1 scheduled - Ads copy refresh in production if planned ### Week 4 (days 22–30) - Final blog posts - Remaining GBP posts - Monthly report triggered after all content tasks complete ## Topic Selection Rules - Never repeat a topic that has been published in the last 90 days - Blog topics should align with the keyword clusters identified in strategy - GBP posts rotate through: service spotlight, seasonal tip, promotion, testimonial reference - For the first period, default to the top content gap identified in the competitor analysis ## Priority Scores 1. Keyword research (everything depends on it) 2. Content briefs (blog posts depend on them) 3. Blog posts (highest SEO value) 4. GBP posts (consistent local presence) 5. Social posts (brand building) 6. Ads copy (paid channel support) 7. Monthly report (end-of-period; depends on all above) ## Handling Plan Gaps If a deliverable type in the plan has no viable topic (all obvious topics recently covered), create the activity with a `topicNote: "Select a fresh angle — all primary topics recently covered"` in the input payload and flag it in `planningNotes`.

RAG Usage

DatasetQuery exampleWhen used
Published Content"blog posts published last month", "recent GBP posts", "published content last 90 days"Step 2 — avoids topic repetition; informs what has already been covered
Client Documents"upcoming events", "promotions", "product launches", "seasonal campaigns"Step 3 — time-aligns content with the client’s business calendar
Website ContentNot queriedNot applicable at pipeline creation stage
Competitor ResearchNot queriedCompetitor context already captured in Client Context File

Tools Required

ToolMethodPurposeRequired?
rag_searchsearchQuery Published Content to avoid topic repetitionYes
rag_searchsearchQuery Client Documents for upcoming events and promotionsYes

The Activity Planner has no external web tools. It reads from the database context (via RAG and job payload) and writes Activity records and BullMQ jobs. All external calls are made by the worker agents it dispatches.


HITL Gates

Gate 0 — DM pipeline review (optional, per-tenant or global) When requireActivityApproval is enabled, the activity planner pauses after writing Activity records and sets the DeliverablePeriod to dm_review instead of immediately dispatching jobs. A DM reviewer must approve before any agent runs.

The value is resolved in order: TenantDeliverableConfig.requireActivityApproval (per-tenant override, set in Manage → Tenants → [Tenant] → Deliverable Config) → PlatformSetting("requireActivityApproval") (global, set in Manage → System → Deliverable Settings) → true (default ON).

DM reviewer actions (DM portal → Pipeline screen):

  • Review the full list of planned activities (label, type, priority, due date)
  • Edit any activity’s label, priority, or due date
  • Delete any activity from the pipeline
  • Add a new ad-hoc activity (type dropdown → auto-routes to correct agent queue)
  • Approve — enqueues dependency-free activities; period moves to active
  • Reject — enter a rejection reason; all current activities are deleted; period moves to rejected; activity planner is re-enqueued with rejectionFeedback injected into the Claude prompt

Rejection reasons are stored in DeliverablePeriodLog with event: "dm_rejected" and rejectionReason field, so the timeline is auditable. The feedback is passed to the re-enqueued job as rejectionFeedback in ActivityPlannerJobData.

Auto-approve after timeout: Planned for a future iteration — not currently implemented. See TODO in Deliverable Settings screen.

Gate 1 — Pipeline preview (first run and on-demand, when DM approval is off) After the pipeline is created, it is surfaced in Dashboard → Campaigns as a timeline view before any worker jobs are processed. The admin sees:

  • A week-by-week breakdown of all planned tasks
  • The specific topic assigned to each blog post and content piece
  • Total credit estimate for the period

Admin actions:

  • Edit the topic for any specific task before it runs
  • Remove a task from this period (“skip this month”)
  • Add an ad-hoc task (e.g. “I need a landing page for a new service”)
  • Approve the pipeline (“Start producing”)

Jobs are not dispatched to worker queues until the admin approves the pipeline (first run). On scheduled monthly runs, the pipeline auto-approves after 48 hours if the admin has not reviewed it.

Gate 2 — Mid-period block If a critical-path task fails after all retries and blocks downstream tasks (e.g. keyword research fails → all blog posts blocked), an in-app notification is sent to the admin and the blocked tasks are surfaced in the Campaigns screen with the failure reason. The admin can:

  • Retry the failed task
  • Manually provide the input the failed task was supposed to produce
  • Cancel the blocked tasks for this period

Guardrails

  • activities array must contain at least 1 entry.
  • Every blog post activity must have a content_brief activity in its dependsOn list.
  • The monthly report activity (if present) must have dependsOn referencing all other activities in the period.
  • No two activities may have the same topic or title (checked against both the current pipeline and recently published content).
  • inputPayload for every activity must be a non-empty object — the Planner must provide specific inputs, not empty shells.
  • agentQueue values must exactly match canonical queue names.
  • Total estimatedCost must not exceed the tenant’s monthly credit limit + 10% tolerance.

Tenant Settings Used

SettingHow it’s used
tenantIdKeys all Activity and Period records created
planConstrains which deliverable types can be in the pipeline
connectedChannelsExcludes tasks for channels without active OAuth connections
companyNameUsed in task labels and pipeline summary heading
industryInforms topic selection logic and seasonal relevance
brandColorsPassed in social post and ads activity payloads for downstream agents

Cost Profile

Avg input tokens~14,000 (deliverable plan + RAG results + previous period summary + system prompt)
Avg output tokens~2,200 (large output — full pipeline with resolved payloads for every task)
Est. cost / task~$0.90

Error Handling

ErrorResponse
No approved deliverable plan foundFail immediately; surface error in Dashboard: “No deliverable plan has been approved for this tenant. Go to Strategy → Deliverable Plan to approve one.”
deliverables array is emptyFail; same message as above
All topics already published (nothing new to plan)Flag in planningNotes; create activities with topicNote: "All primary topics recently covered — agent must select a fresh angle" rather than blocking
RAG returns no published contentProceed without repetition-check; note in planningNotes
RAG returns no client documents (no upcoming events)Proceed without event-alignment; standard week-by-week distribution
LLM returns malformed JSONInternal retry (up to 2 Claude calls): attempt 2 sends a JSON-only correction prompt with the previous output preview. After both internal attempts fail, the BullMQ job fails and is retried up to 4 times total (exponential backoff). After all attempts exhausted, failure email + in-app notification sent to client and DM reviewers.
Job enqueue fails for a specific queueRetry 3 times; if still failing, mark that Activity as status: 'enqueue_failed' and surface in HITL; remaining activities are enqueued normally
Period already has an active pipelineAbort; log: “A pipeline already exists for period [periodId]. Use the Campaigns screen to manage it.”
Credit limit would be exceededRe-prompt model to reduce volumes; if still over after retry, surface hard warning in pipeline preview and require explicit admin override to proceed

Re-triggering After Failure

If the activity planner fails after all retries, the plan stays approved in the DB but no DeliverablePeriod is created. A “Regenerate Activities” button in the Manage portal (tenant detail → Activities tab) lets superadmins manually re-enqueue the activity planner:

  • Endpoint: POST /admin/v1/tenants/:tenantId/retrigger-activity-planner
  • Clears the stale BullMQ dedup key and removes any failed job before re-enqueueing
  • Requires an approved deliverable plan to exist for the tenant

© 2026 Leadmetrics — Internal use only