Tasks – everything X3 asks you to do

Alerts („Braucht Dich“, the bell), Pulse recommendations, personal notices, the digest and the MCP tools share one model: a task is a condition about a subject. X3 keeps at most one task per subject and key (for example budget_over:project:2026-10, connect_costs:meta_ads, reporting_failed:meta) and renders its text from the current numbers on every read – a task never shows a figure that was true an hour ago.

States

StateMeaningComes back when
openthe condition holds–
auto_resolvedthe condition stopped holding – with reason, time and who triggered it („Von selbst erledigt: Budget auf 4.000 € angepasst · 14:05“)the condition holds again → open, „Erneut aufgetreten“ (occurrence + 1, history kept)
donea person marked it doneonly when it got materially worse (budget: +10 points) or after 7 days → open, „Trotz Erledigt-Markierung weiter aktuell“. State warnings (lead_unreported, funnel_step_zero, leads_zero, destination_not_live, ad_match_gap, ad_campaign_gap): done means „diesen Stand gesehen“ – they keep the acknowledged evidence (the lead ids, the zero run's first day, the mode, the cause) and open again only when new evidence shows up (another lead, a new zero run after a recovery, another mode or cause; ad_match_gap and ad_campaign_gap also at +20 points), never after the 7 days alone. The list marks them doneMeansSeen
snoozed„Später“ until a time (default tomorrow 08:00)at that time – only if the condition still holds, else it resolves itself
dismissed„Passt nicht“ (optional reason)when the context changes (new month, new campaign) or a person restores it

Numbers use a band against flickering: budget_over opens at ≥ 103 % of the budget's own threshold and resolves below 101 %; cpl_spike opens at +50 % and resolves below +40 % after a day. Reopening within the 7-day cooldown sends no second mail.

Reading and acting

CallScopeWhat
GET /v1/tasksanalytics:readyour projects, organizations and personal tasks; scope=project|org|mine, state=open (default) |snoozed|done|auto_resolved|dismissed|resolved|all, type, kind, limit, cursor, resolvedSince (what resolved itself since then – with your own sign-in only what your changes triggered)
GET /v1/projects/{project}/tasksanalytics:readone project
PATCH /v1/tasks/{id}project tasks config:write or ads:write (recommendations ads:write), org tasks config:write, personal tasks you{"action": "done" | "snooze" | "dismiss" | "restore", "until"?, "reason"?, "note"?} – restore checks the condition at once
GET /v1/tasks/{id}/historyanalytics:readopened, resolved itself (reason, who), done, snoozed, dismissed, occurred again

MCP: tasks_list and tasks_update; alerts_list / alerts_update remain for the alert part. The answer of a change that resolves tasks names them – saving the monthly budget returns resolvedTasks, so the dashboard can say „Damit ist ‚Budget überschritten' erledigt“.

Lists are triage-ordered (problem › attention › opportunity › setup › info, then money at stake, then age), return counts per state for the bell and the „Erledigt“ tab, and mark each task live (rendered from the current evaluation) or not (history of a subject that no longer exists).

Types

Alert rules (Recommendations and alerts) are project tasks with the rule name as type. Recommendations are the type rec (key = the week-independent recommendation key; „Passt nicht“ lasts until the month of the recommendation changes, „Verbinde Plattform“ resolves itself as soon as an account of that platform is connected). Personal notices are type connect_ai (scope person).

Who sees what follows the old rules: agency-internal types (budget, opportunity, connect_costs, numbers_disputed) need ads:read + config:write; recommendations need ads:read (viewers only when the project shows them recommendations).

Operational types

TypeOpens whenResolves itself when
budget_unallocatedthe platform split of this month's budget does not add up (at least 1 € and 0.5 %): „140 € nicht verteilt“ or „Aufteilung 200 € über dem Budget“the split adds up or is removed; the budget card and the budget sheet show the rest with „Rest verteilen“ (one platform, evenly, or without a split)
ad_rejectedan ad of a connected account has the delivery status „abgelehnt“ (one task per ad)the ad runs again or is removed
campaign_paused_organica campaign has been paused for ≥ 3 days, spends nothing and still brings ≥ 2 leads per day (opens at 2.0, stays open down to 1.5 per day)the campaign runs again, or fewer leads arrive for a day
conversion_upload_faileduploads to one destination failed in the last 24 hours (live or test mode; dry runs never) – covers „Meldungen stehen aus“ of the same providera later upload to it succeeds
connect_google_ads, connect_meta_ads, connect_linkedin_ads, connect_tiktok_adspaid visits of the platform without an account, or the account was disconnected („Verbinde Google Ads“); hidden while the alert connect_costs of the platform is openan account of the platform is connected („Von selbst erledigt: Google Ads verbunden“)
traffic_drop, traffic_spikeyesterday's visits left the band of the last 6 same weekdays (median ± 2.5 MAD, at least 20 expected; a drop also under 70 % of the median) – „Weniger Besuche als üblich: Gestern 62 Besuche, an Dienstagen sonst etwa 140. Am stärksten gefallen: Meta (−70).“ Quiet in the first days after the measuring start and while the tracking is down; off with settings.traffic.alerts=false (Visitors and traffic)the next day is back inside the band
setup_tracking, setup_goals, setup_reportingthe setup checklist rows „Einbau“, „Ziele“ and „Meldungen“ are open – so „Später“ and „Passt nicht“ work there toothe first visit arrives, a goal exists, reporting to the platform is set up

Reporting and funnel warnings

Early warnings for leads that silently miss the ad platforms and for funnel steps that silently stop. All four are problems, send a notification when they open and resolve themselves.

TypeOpens whenResolves itself when
lead_unreporteda counted lead of the last 7 days came through an ad platform (its click id or paid channel) whose reporting is switched on, but after 30 minutes it has no conversion or no upload to that platform („Lead von Meta nicht an Meta gemeldet“; one task per platform, the newest lead linked)every such lead is uploaded (or reported earlier for the same person), or older than 7 days
destination_not_livea switched-on destination runs in dry run or test mode – also when the deployment caps it – while its platform spent money in the last 7 daysthe destination is live, or the platform stops spending
funnel_step_zeroa quiz step, CTA/WhatsApp/form/booking or a goal has been at 0 since a day although its baseline (7 days before) makes that improbable (≥ 3 expected, today counted by the share already over) while the step before it – or the visits – stays at ≥ 50 % of normal („Quiz-Antworten: 0 seit 18.10.“)the step happens again
leads_zerono counted lead for days although the 14-day baseline expects ≥ 3 in that time and visits are normal; hides no_leads while opena lead arrives

Recommendations never ask you to scale an ad, ad set or campaign that is paused, rejected, ended or deleted: their task resolves itself with „Anzeige pausiert“ and opens again when the entity runs. Demo projects never raise these types.

When tasks are checked

Every change that can change a condition re-checks the affected types right away and records who triggered it: budget saved, ad account connected, confirmed or disconnected, sync finished, conversion uploaded or failed, preset applied, lead status changed, goal saved, ad delivery status changed (sync or the hourly status check), project settings changed. A job checks every active project every 15 minutes as a fallback (time-based conditions such as „no lead for 52 hours“, snoozes that ran out). Budgets and months are measured in the project's time zone.

In the dashboard

  • Hinweise (/cockpit/alerts): one table with the tabs Offen · Später · Erledigt · Abgelehnt, columns type, subject, since, occurrence („erneut aufgetreten“) and state – sortable, filterable, with chosen columns, saved views and CSV export. Erledigt says „Von selbst erledigt: … · 14:05 · ausgelöst von Anna“ or „Von Dir erledigt“; everything closed can be restored.
  • The bell and the counters refresh right after every write; when your own change resolved a task the dashboard confirms it („Damit ist ‚Budget überschritten‘ erledigt“). Every action has a 10-second undo.
  • „Später“ offers tomorrow morning, Monday, in a week or a chosen day; „Passt nicht“ an optional reason and note. Viewers see the tasks without actions („Darum kümmern sich Inhaber und Admins.“).

For module authors

A module adds its own type with registerTaskType(def, facts) (apps/api/src/platform/task-registry.ts) and fires taskEvent(sql, { projectId, kind, by }) after its writes – it never writes task rows itself. Rows that still live in a module's own table (the behavior alert rules registered through the insights insightExtensions hook) keep working: they appear in the task lists, the bell counters and the Hinweise tabs, and „Erledigt“, „Später“ and „Zurückholen“ answer through PATCH /v1/tasks/{id}.