Skip to Content
Action Items

Action Items

[To Build]

Action Items are one-time strategic tasks generated alongside the deliverable plan to support goal achievement. Unlike Deliverable Templates (which produce recurring monthly activities), Action Items represent foundational or milestone work that only needs to happen once — such as a technical SEO audit, profile optimisation, or competitor analysis.


Where They Fit in the Pipeline

Context (approved) └─► strategy-writer └─► Strategy (approved) └─► deliverable-planner ├─► Goals[] ├─► DeliverableTemplate[] (recurring, monthly) └─► ActionItem[] (one-time, period-assigned) └─► Plan approved └─► activity-planner (per period) ├─► Activities from DeliverableTemplates └─► Activities from ActionItems assigned to this period

Concept

ConceptDescription
Deliverable TemplateRecurring work — e.g., “8 blog posts/month”. Generates activities every period.
Action ItemOne-time work — e.g., “Technical SEO Audit”. Generates activities once in a specific period.
Suggested PeriodPeriod number (1, 2, 3…) relative to planStartDate. Claude assigns this based on goal sequencing logic.
planStartDateSet to the calendar month when the deliverable plan is approved. Period 1 = that month, Period 2 = next month, etc.

Why separate from Deliverable Templates?

Deliverable Templates have a monthlyVolume — they are fundamentally recurring. Action Items have no volume; they execute once. Mixing them into the same model would require awkward isOneTime flags and break the activity planner’s period logic.


Data Model

model ActionItem { id String @id @default(cuid()) deliverablePlanId String deliverablePlan DeliverablePlan @relation(fields: [deliverablePlanId], references: [id]) tenantId String goalId String? goal Goal? @relation(fields: [goalId], references: [id]) title String description String agentQueue String // e.g. "agent__seo-optimizer" suggestedPeriod Int // 1-based relative period number rationale String // Claude's reasoning for the suggested period estimatedCost Int // credits status ActionItemStatus @default(pending_review) assignedPeriodId String? // set when activity-planner runs for that period deliverablePeriod DeliverablePeriod? @relation(fields: [assignedPeriodId], references: [id]) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt @@index([deliverablePlanId]) @@index([tenantId]) } enum ActionItemStatus { pending_review // awaiting plan approval approved // plan approved, waiting for its period to be reached in_progress // activity-planner has created activities for this item done // all activities completed skipped // DM manually skipped it }

DeliverablePlan gets a new relation:

model DeliverablePlan { // ... existing fields actionItems ActionItem[] planStartDate DateTime? // set on plan approval }

Deliverable Planner Changes

Prompt Addition

The deliverable planner prompt gains a new output section instructing Claude to generate action items:

## Action Items List one-time strategic tasks needed to achieve the goals above. These are NOT recurring — each executes once in a specific period. Rules: - Suggest the period number (1 = first month of the plan) based on sequencing logic - Front-load foundational work (audits, research, setup) in periods 1-2 - Sequence action items so dependencies come before execution tasks - Link each to the goal it supports (use the goal's position index) - Only include tasks that require an agent — no manual human tasks - Maximum 8 action items per plan Output as JSON array under key "actionItems".

Output Schema Addition

interface DeliverablePlannerOutput { goals: Goal[] deliverableTemplates: DeliverableTemplate[] actionItems: ActionItemOutput[] // new monthlyCostEstimate: number planningNotes: string } interface ActionItemOutput { title: string description: string goalIndex: number | null // index into goals array agentQueue: string suggestedPeriod: number // 1-based rationale: string estimatedCost: number }

DB Write

After saving goals and templates, the worker saves action items:

await db.actionItem.createMany({ data: actionItems.map(item => ({ deliverablePlanId: plan.id, tenantId, goalId: item.goalIndex !== null ? savedGoals[item.goalIndex].id : null, title: item.title, description: item.description, agentQueue: item.agentQueue, suggestedPeriod: item.suggestedPeriod, rationale: item.rationale, estimatedCost: item.estimatedCost, status: "pending_review", })) })

Period Mapping

When the deliverable plan is approved (POST /tenant/v1/deliverable-plan/:planId/approve), planStartDate is set to the first day of the current calendar month:

const planStartDate = `${year}-${month}-01` // string formatting, not toISOString() await db.deliverablePlan.update({ where: { id: planId }, data: { status: "approved", planStartDate } })

Period number → calendar month:

function resolvePeriodDate(planStartDate: string, periodNumber: number): string { const [year, month] = planStartDate.split("-").map(Number) const targetMonth = month + periodNumber - 1 const y = year + Math.floor((targetMonth - 1) / 12) const m = ((targetMonth - 1) % 12) + 1 return `${y}-${String(m).padStart(2, "0")}-01` }

All action items are updated to approved status on plan approval. Their suggestedPeriod is already stored — no further mapping needed until the activity planner runs.


Activity Planner Integration

When the activity planner runs for a period, it fetches action items assigned to that period:

const periodNumber = computePeriodNumber(plan.planStartDate, periodStart) const actionItemsForPeriod = await db.actionItem.findMany({ where: { deliverablePlanId: plan.id, suggestedPeriod: periodNumber, status: "approved", } })

These are passed to the activity planner prompt as an additional section:

## One-Time Action Items for This Period The following one-time tasks must also be sequenced this period: | # | Title | Description | Agent Queue | |---|---|---|---| | 1 | Technical SEO Audit | Full crawl and issue report | agent__seo-optimizer | Treat these as regular activities. Assign due dates and dependencies as appropriate. Flag them with isOneTime: true in the output.

After activity creation, action items are updated to in_progress. When all their activities complete, they move to done.


DM Period Override

DM can change the suggested period for any approved action item before its period is reached. This is available on the /strategy/deliverable-plan page.

API endpoint:

PATCH /tenant/v1/action-items/:id Body: { suggestedPeriod: number }

Rules:

  • Cannot change period if status is in_progress or done
  • Cannot set to a period that has already passed (i.e., resolvePeriodDate(period) < today)

Approval Flow

Action items follow the deliverable plan approval — no separate approval gate:

deliverable-planner generates action items (status: pending_review) └─► Shown on /strategy/deliverable-plan alongside goals and templates └─► DM reviews, optionally edits suggestedPeriod └─► Client approves plan └─► All action items → status: approved └─► Each period: activity-planner picks up items for that period └─► status: in_progress → done

Plan Refresh Safety

When the deliverable plan is refreshed (new channels, strategy revision), action items are only regenerated if their status is pending_review. Items that are approved, in_progress, or done are preserved unchanged.

// On refresh: delete only pending_review action items before re-running planner await db.actionItem.deleteMany({ where: { deliverablePlanId: planId, status: "pending_review" } })

UI Changes

/strategy/deliverable-plan — new section

A third section is added below Deliverable Templates:

[ Goals ] [ Deliverable Templates ] [ Action Items ] ← new ┌─────────────────────────────────────────────────────┐ │ Title │ Goal │ Period │ Rationale │ │ Tech SEO Audit │ +40% traffic│ Month 1 │ "Must run…" │ │ Profile Optim. │ +25% social │ Month 1 │ "Before…" │ └─────────────────────────────────────────────────────┘ DM can edit the Period column inline before approving.

/goals — optional chip

Each goal card shows a small badge: “2 action items” linking back to the plan page. Read-only.

/deliverables — automatic

Once an action item’s activities are created for a period, they surface in the deliverables page naturally — no changes needed.


Cost Estimation

The deliverable plan summary shows two cost lines:

Monthly recurring cost: ₹ 4,200 (from deliverable templates) One-time action items: ₹ 800 (sum of all action item estimatedCost)

The monthlyCostEstimate field on DeliverablePlan is not changed — it remains recurring-only. A new actionItemsCostEstimate field is added.


Key Code Locations

FileRole
packages/db/prisma/schema.prismaAdd ActionItem model + planStartDate to DeliverablePlan
packages/agents/src/workers/strategy.worker.tsDeliverable planner — add action items to prompt + output parsing + DB write
packages/agents/src/workers/activity.worker.tsActivity planner — fetch + inject action items for current period; update status
packages/queue/src/types.tsNo changes needed (same job data)
apps/api/src/routers/tenant/main.tsPlan approve endpoint — set planStartDate, approve action items
apps/api/src/routers/tenant/main.tsNew PATCH /tenant/v1/action-items/:id for DM period override
apps/api/src/services/strategy.service.tsapproveDeliverablePlan() — include action item approval + planStartDate
apps/dashboard/src/app/(dashboard)/strategy/deliverable-plan/Add Action Items section to plan viewer
apps/dm/src/app/(dm)/strategy/deliverable-plan/Same — DM can edit period inline
apps/dashboard/src/app/(dashboard)/goals/Optional: add action item count chip to goal cards

© 2026 Leadmetrics — Internal use only