/ MM Ads Autopilot — Troubleshooting Runbook Internal
MM Ads Autopilot

Autopilot Troubleshooting
Runbook

Version 1.0  ·  For day-to-day usage see the user guide ↗
⚠️
This runbook is for Teddi. If something is broken, describe the symptom to Teddi and reference the section number — don't attempt infrastructure fixes yourself.

Quick diagnosis — start here

SymptomSectionMost likely cause
No Slack messages on Monday morningSection 1Cron didn't fire, or Vercel function timed out
Slack messages appeared but all say "0 actions"Section 2MCP data returned empty — auth or parsing issue
Clicked Approve but nothing changed in Google AdsSection 3Writer MCP auth, API access, or SIMULATION_MODE still true
ClickUp tasks not createdSection 4ClickUp API token expired or list ID wrong
Bot not responding to @mentions in SlackSection 5Event subscription not configured or app not in channel
Anomaly alerts not firingSection 6Daily cron not set up, or daily_snapshots table empty
One specific client fails, others workSection 7Client config — missing customer ID, GSC URL, or GA4 property
Everything worked but recommendations are poorSection 8Rules engine thresholds or sub-agent prompts need tuning
1

No Slack messages on Monday morning

Check the Vercel function logs

Go to: vercel.com/teddi-coder/mm-google-ads-autopilot/logs ↗

Filter by the cron time (Sunday 20:00 UTC = Monday 7:00am AEST). Look for:

  • No log entries at all — the cron didn't fire. Check vercel.json has the correct schedule.
  • Log entries with errors — the function started but crashed. Read the error message.
  • FUNCTION_INVOCATION_TIMEOUT — hit Vercel's 300 second limit. A single client should take 90–130 seconds. The MCP server may be slow or unresponsive.

Check Vercel cron configuration

In vercel.json, each client should have its own cron entry staggered 3 minutes apart. If all clients run at once, they will all timeout.

Check the Supabase runs table

Go to Supabase → Table Editor → runs. Filter by today's date. If there are run records with status "error", the function ran but failed mid-pipeline.

Manual trigger to test

curl -X POST https://mm-google-ads-autopilot.vercel.app/api/run-client   -H "Authorization: Bearer YOUR_API_KEY"   -H "Content-Type: application/json"   -d '{"client_name": "Ultra Tune North Ryde"}'

If this returns a response, the app is working and the issue is with the cron schedule.

2

Slack messages appeared but 0 actions proposed

The pipeline ran but the rules engine and AI agents found nothing to recommend. This is either correct (healthy accounts) or a data problem.

Check if data actually came through

In Vercel logs, look for lines like:

[fetchAllClientData] Results for Ultra Tune North Ryde:
campaigns: 814 chars
keywords: 3002 chars

If all values show "0 chars" or are missing, the MCP server returned empty data.

MCP server returning empty data

Test the MCP server directly:

python3 -c "
import asyncio
from fastmcp import Client
async def main():
  async with Client('https://mechanic-mcp-server.fly.dev/mcp') as c:
    r = await c.call_tool('account_snapshot', {'customer_id': '2106714025'})
    print(r)
asyncio.run(main())
"

If this returns data but the app doesn't, check MCP_MM_SERVER_TOKEN in Vercel env vars matches the bearer token on the MCP server. Token: 748e3cc9c5a1bba9 (rotate if compromised).

MCP server itself is down

flyctl status -a mechanic-mcp-server
# If stopped or crashed:
flyctl deploy -a mechanic-mcp-server
3

Clicked Approve but nothing changed in Google Ads

Check SIMULATION_MODE

In Vercel environment variables, check SIMULATION_MODE=false. If this is "true" or not set, the app logs actions as "simulated" but never calls the writer.

🚨
This was the issue during initial testing. SIMULATION_MODE=true is the most common reason approved actions don't appear in Google Ads.

Check the writer MCP

flyctl status -a hedgehog-ads-writer

Check MCP_ADS_WRITER_TOKEN in Vercel matches the token on the writer server.

Check the audit log

In Supabase → audit_log, find the action you approved. Check:

  • status — should be "executed" or "failed", not "simulated" or "pending"
  • error_message — if status is "failed", the error will tell you what went wrong
ℹ️
Changes made via the API take 30 seconds to 5 minutes to appear in the Google Ads UI. Change History can take up to 3 hours. Wait before concluding it didn't work.
4

ClickUp tasks not being created

  • Check CLICKUP_API_TOKEN in Vercel env vars. ClickUp personal API tokens can expire or be revoked. Generate a new one at Settings → Apps → API Token in ClickUp.
  • Check the client's clickup_list_id in Supabase → clients table. If it's null, the app doesn't know where to create the task.
  • Check Vercel logs for ClickUp errors — look for HTTP 401 (auth), 404 (list not found), or 429 (rate limited).
5

Bot not responding to @mentions

Check Slack app event subscriptions

In api.slack.com/apps ↗ → Your App → Event Subscriptions:

  • Events must be enabled
  • "app_mention" event must be subscribed
  • Request URL must be: https://mm-google-ads-autopilot.vercel.app/api/slack/events
  • The URL must be verified (green checkmark)

Check bot is in the channel

The bot must be a member of #mm-ads-autopilot. Invite it with /invite @autopilot if needed.

⚠️
The bot has a rate limit of 20 questions per hour. If it's been asked many questions, it may be silently rate-limited. Check the Vercel logs for rate limit messages.
6

Anomaly alerts not firing

Check the daily cron

In vercel.json, the anomaly check should be:

{ "path": "/api/anomaly-check", "schedule": "0 21 * * 1-5" }

This is 8:00am AEST Tuesday through Saturday.

Check daily_snapshots table

The anomaly check compares today's snapshot against a 7-day rolling average. If there are fewer than 7 days of snapshots, the check has no baseline to compare against.

Thresholds may be too high

The default thresholds are conservative (CPA 50% above average = critical). If client accounts are volatile, these thresholds may never trigger. Check src/lib/analysis/anomaly-detection.ts.

7

One client fails, others work fine

Check the clients table in Supabase

The failing client may have:

  • Missing googleAdsCustomerId — MCP server can't pull data without it
  • Missing gscSiteUrl — GSC calls will fail (but shouldn't block the rest)
  • Missing ga4PropertyId — GA4 calls will fail (but shouldn't block the rest)
  • Missing clickupListId — ClickUp tasks won't be created for this client
  • is_active = false — client is disabled and will be skipped

Check the cron for that client

Each client has its own cron entry in vercel.json. If the entry is missing or has a typo, that client won't run.

8

Recommendations are poor quality

Rules engine thresholds

Key thresholds to check in src/lib/analysis/rules-engine.ts:

  • Keyword pause: $50+ spend with 0 conversions in 14 days
  • CPA threshold: 3x above ad group average
  • CTR threshold: below 1% after 1000+ impressions
  • Quality Score: QS 3 or below with $50+ spend

Sub-agent prompt quality

Each sub-agent has a system prompt in src/lib/analysis/sub-agents/. If recommendations are consistently off:

  • Too aggressive — add more conservative guardrails to the system prompt
  • Missing context — check feedback rules, top-performing copy, and competitor data are being passed through
  • Wrong tone in ad copy — check the MM brand context is being injected into Agents 4 and 5

Feedback rules not applying

Check the feedback_rules table in Supabase. Active rules should be filtering out previously-rejected actions. If not:

  • Check is_active = true
  • Check expires_at hasn't passed
  • Check the scope matches (entity vs pattern vs global)
  • For entity-level rules, check the entity_id matches exactly

Quick reference — key URLs

WhatWhere
Vercel dashboardvercel.com/teddi-coder/mm-google-ads-autopilot ↗
Vercel function logs/logs ↗
Supabase dashboardCheck NEXT_PUBLIC_SUPABASE_URL in Vercel env vars
Fly.io MCP serversflyctl status -a mechanic-mcp-server / flyctl status -a hedgehog-ads-writer
Slack app configapi.slack.com/apps ↗ — MM Ads Autopilot app
Google Ads APIconsole.cloud.google.com → APIs & Services → Google Ads API
App URLmm-google-ads-autopilot.vercel.app ↗

Restarting everything from scratch

1
Check Fly.io MCP servers are running: flyctl status -a mechanic-mcp-server and flyctl status -a hedgehog-ads-writer
2
Check all Vercel env vars are set
3
Trigger a manual test run for one client (Ultra Tune is safest)
4
Check Vercel logs — should see MCP calls, data returned, rules engine, sub-agents
5
If the test works, Monday crons will work. If it fails, the logs will tell you exactly where.
ℹ️
Always include the Vercel function logs and the specific error message when escalating to Teddi or Josh.