Synthetic Monitoring skill for Codex

Prove login and checkout work, every five minutes. Codex turns a handful of revenue-critical journeys into short Playwright browser checks and API checks, defined as code with Checkly or run by a self-hosted scheduler. It uses tagged synthetic accounts and test payment modes, stable role-based selectors, retries in another region before alerting, and asks before deploying monitors that change the team's alerting.

  • Observability & SRE
  • $synthetic-monitoring
  • 167 lines
  • 2 files
  • ~1,750 tokens
  • MIT
  • Updated

Install

curl -fsSL codexskills.dev/install.sh \  | sh -s -- synthetic-monitoring

Installs to ~/.agents/skills/synthetic-monitoring/ for every project on this machine.

104-line POSIX script. No sudo, no telemetry. Read install.sh

Use it in Codex

Start a prompt with $synthetic-monitoring, or pick it from /skills. You can also just describe the task: Codex reads the description below and loads the playbook when your request matches.

What Codex reads before loading it

Builds synthetic monitors that exercise critical user journeys in production - Playwright browser checks and multi-step API checks run on a schedule from several regions with Checkly monitoring as code or a self-hosted Playwright runner - with dedicated test accounts, stable selectors, flake control, alert thresholds and cleanup of created data. Use when asked to monitor login, signup, checkout or search flows end to end, to turn Playwright tests into production monitors, or to fix flaky synthetic checks that page on-call.

Use it when

  • Critical journeys like login or checkout need monitoring from outside
  • Existing Playwright tests should double as production monitors
  • Synthetic checks are flaky and noisy
  • You need API checks with assertions on response bodies and timings

Use something else when

  • A simple up/down HTTP check and status page is enough: use uptime-monitoring
  • You are writing pre-release end-to-end tests rather than production monitors: use playwright-e2e

How to check the result

Each check passes against production, fails at the right step with a screenshot when deliberately broken, and runs a week below about 1% false failures before it may page.

The mistake it prevents

Running synthetic journeys with real customer accounts or payment methods, or never cleaning up the orders and data the checks create.

~/.agents/skills/synthetic-monitoring/SKILL.md

--- name: synthetic-monitoring description: Builds synthetic monitors that exercise critical user journeys in production - Playwright browser checks and multi-step API checks run on a schedule… license: MIT ---

Done well means: the few journeys that make money or lock users out are exercised every few minutes from outside, a failure means the journey is really broken (not that a selector moved), each run leaves production data clean, and an alert includes the screenshot, trace and step that failed.

Inspect first

  1. Read AGENTS.md; look for existing Playwright tests (playwright.config.*, tests/e2e/), a checkly.config.ts, or other synthetic tooling (Datadog Synthetics, Grafana synthetic monitoring with k6 browser).
  2. List candidate journeys with the product owner: login, signup, search, add to cart, checkout with a test payment method, core API write and read. Pick three to six.
  3. Ask how test accounts and test payments work in production (feature flag, test tenant, payment provider test mode on a separate key). Never use real customer accounts or real payment methods.

Design rules

RuleWhy
One journey per check, short (under 60 s)A failure points to one flow; long scripts flake
Dedicated synthetic accounts, tagged ([email protected])Excludable from analytics and billing; safe to reset
Stable selectors: roles, labels, data-testidCSS classes and text change with design work
Assert outcomes users care about“Order confirmation number visible”, not “spinner disappeared”
Clean up what the check creates, or use an idempotent pathProduction fills with junk orders otherwise
Secrets from the platform’s environment variablesNever committed in the check file
Exclude synthetic traffic from SLIs and product analytics, or tag itAvoid skewing both

Checkly as code

Initialise with npm create checkly@latest (network required). Layout:

// checkly.config.ts
import { defineConfig } from 'checkly';
import { Frequency } from 'checkly/constructs';

export default defineConfig({
  projectName: 'Shop production monitors',
  logicalId: 'shop-prod-monitors',
  checks: {
    frequency: Frequency.EVERY_5M,
    locations: ['us-east-1', 'eu-west-1', 'ap-southeast-1'],
    tags: ['prod'],
    checkMatch: '**/__checks__/**/*.check.ts',
    browserChecks: { testMatch: '**/__checks__/**/*.spec.ts' },
  },
  cli: { runLocation: 'eu-west-1' },
});

Browser check (plain Playwright Test):

// __checks__/login.spec.ts
import { test, expect } from '@playwright/test';

test('user can log in and see dashboard', async ({ page }) => {
  await page.goto(process.env.APP_URL ?? 'https://app.example.com/login');
  await page.getByLabel('Email').fill(process.env.SYNTH_USER!);
  await page.getByLabel('Password').fill(process.env.SYNTH_PASSWORD!);
  await page.getByRole('button', { name: 'Sign in' }).click();
  await expect(page.getByRole('heading', { name: 'Dashboard' })).toBeVisible({ timeout: 15_000 });
});

API check:

// __checks__/orders-api.check.ts
import { ApiCheck, AssertionBuilder } from 'checkly/constructs';

new ApiCheck('orders-api-read', {
  name: 'Orders API read',
  degradedResponseTime: 1000,
  maxResponseTime: 3000,
  request: {
    method: 'GET',
    url: 'https://api.example.com/v1/orders?limit=1',
    headers: [{ key: 'Authorization', value: 'Bearer {{SYNTH_API_TOKEN}}' }],
    assertions: [
      AssertionBuilder.statusCode().equals(200),
      AssertionBuilder.jsonBody('$.items').isNotNull(),
    ],
  },
});

Commands:

npx checkly test            # runs checks once in Checkly's cloud from runLocation, deploys nothing
npx checkly test --record   # same, with results stored for review
npx checkly deploy          # creates or updates production monitors

npx checkly deploy changes live monitoring and alerting for the team; show the user the diff of checks and get confirmation first, or run it from CI after review. Store SYNTH_USER, SYNTH_PASSWORD and tokens as Checkly environment variables (or secrets), not in the repo.

Self-hosted alternative

When a SaaS is not an option, run Playwright on a schedule and export results:

  • Kubernetes CronJob or a CI scheduled workflow per region running npx playwright test --project=synthetic.
  • Push synthetic_check_success{journey="login",region="eu"} and duration to Prometheus Pushgateway or via OTLP, and alert with quorum (two regions failing).
  • Keep traces and screenshots (trace: 'retain-on-failure', screenshot: 'only-on-failure') in object storage and link them from the alert.

Scheduled CI runners are often not reliable enough to page on (queue delays, 5-minute minimum schedules); use them for tickets, not pages, unless the runner is dedicated.

Alerting

  • Retry once in a different location before declaring failure (Checkly retry strategy, or a second run) to remove single-run network flakes.
  • Page when the journey fails from two or more locations for two consecutive runs; ticket for a single location or degraded response time.
  • Alert payload must include journey name, failing step, screenshot or trace link, and the runbook.
  • Route to the team that owns the journey, not to a central platform team.

Flake control workflow

  • Find the failing step from traces of the last 20 failures
  • Replace brittle selectors with roles, labels or data-testid
  • Replace sleeps with web-first assertions (await expect(...).toBeVisible())
  • Block third-party scripts that are not part of the journey (page.route for analytics and chat widgets)
  • Raise timeouts only for steps with a known slow backend, never globally
  • If a flow is inherently slow or nondeterministic, split it or move it to a ticket-level check

Verification

  • Run each check locally or with npx checkly test against production and staging.
  • Break it on purpose: point at a staging build with the login button renamed, or use an invalid password, and confirm the check fails at the right step with a screenshot.
  • Confirm cleanup: after a day of runs, synthetic accounts have no accumulated orders or data beyond what you expect.
  • Check the failure rate over the first week; anything above roughly 1% failed runs without a real incident needs flake work before it is allowed to page.

Output

A table of checks: journey, type (browser/API), frequency, locations, assertions, account used, cleanup method, alert route. Include the config files and the deploy command run (or the CI job that runs it).

Gotchas

  • Bot protection, CAPTCHAs and WAF rules block synthetic traffic; ask the owner to allowlist the monitor’s IPs or headers rather than trying to bypass them.
  • MFA on synthetic accounts needs a supported method (TOTP secret held as a monitor secret) agreed with the security team.
  • Checks that create orders can trigger real emails, fulfilment or invoices; use flagged test tenants and confirm the downstream behaviour first.
  • Reusing full e2e test suites as monitors makes them slow and flaky; extract only the critical path.

What the zip contains

SKILL.md plus the interface file below. Nothing runs on install.

agents/openai.yamlgenerated from this page

Gives the Codex app a display name, a one-line description and a starter prompt for this skill.

interface:
  display_name: "Synthetic Monitoring"
  short_description: "Prove login and checkout work, every five minutes"
  default_prompt: "$synthetic-monitoring Create Checkly browser checks for login and checkout from three regions"

About this skill

Written and maintained by the Codex Skills editors to the same editorial standard as every skill here: a selective description, a real workflow, known pitfalls and a way to verify the work. First published , last updated . MIT licensed. Something wrong or out of date? Tell us.

esc