Skip to main content
Glama

MIT Go Terraform Free


Most monitoring watches a thing and tells you when it looks wrong. LastPing waits for a thing to check in and tells you when it doesn't. That inversion is the whole product: a job that breaks can't send you an error, but it can fail to send you anything — and absence is the one signal a broken process can still produce.

This repository holds the open-source pieces: the lastping CLI and the MCP server. The hosted service they talk to is at lastping.dev, free for individuals.

Install

curl -fsSL https://raw.githubusercontent.com/tp322d/lastping-app/main/install.sh | sh

No Go toolchain needed — that pulls a prebuilt binary for macOS and Linux, on amd64 and arm64, and verifies its checksum. Windows builds are on the releases page.

If you do have Go:

go install github.com/tp322d/lastping-app/cmd/lastping@latest

Related MCP server: UNITARES

lastping run — reporting you can't forget

Put it in front of whatever you already run:

lastping run --monitor <monitor-id> -- python nightly_etl.py
lastping run --monitor <monitor-id> -- ./backup.sh
lastping run --monitor <monitor-id> -- claude

It sends a start ping, runs your command untouched, and reports the exit code when it finishes — success on 0, failure on anything else, with the tail of stderr attached so the alert says why.

Three properties worth knowing, because they are the difference between a monitoring wrapper you can trust in production and one you remove after a bad night:

  • Your exit code always propagates. The wrapper exits with whatever your command exited with, so CI behaves exactly as it did before you added it.

  • A failed ping never touches your command. If LastPing is unreachable, your job still runs, still writes its output, still exits normally.

  • Interactive stays interactive. stdin and stdout are handed over as file descriptors, so wrapping a REPL or an agent session works.

Why a wrapper rather than an instruction? Because anything advisory decays. An AI agent told to report on every task will stop doing it, and a cron line you meant to add a curl to never gets it. A wrapper reports from the process lifecycle, so nothing depends on anybody remembering.

MCP server — let an agent set up its own monitoring

// claude_desktop_config.json, .mcp.json, or your client's equivalent
{
  "mcpServers": {
    "lastping": {
      "command": "npx",
      "args": ["-y", "mcp-remote", "https://mcp.lastping.dev/mcp",
               "--header", "Authorization: Bearer ${LASTPING_API_KEY}"],
      "env": { "LASTPING_API_KEY": "lp__your_key_here" }
    }
  }
}

The hosted server is the recommended path — nothing to install, and it always carries the current tool set.

A stdio binary is also here if you would rather run it yourself:

go install github.com/tp322d/lastping-app/cmd/lastping-mcp@latest

Monitors: create_monitor · get_monitor · list_monitors · update_monitor · delete_monitor · pause_monitor · resume_monitor · snooze_monitor

Discovery: discover_monitors_reconcile

Reporting: get_ping_instructions · declare_run_expectations

Incidents & runs: list_incidents · get_run_history

The failure loop: list_open_incidents · add_incident_note

Alert routing: set_route

Destinations: list_destinations · create_destination · update_destination · test_destination · delete_destination

Alert templates: get_alert_templates · set_alert_template

Agent registry: register_agent · list_agents · get_agent · update_agent · delete_agent

Status pages: list_status_pages · create_status_page · update_status_page · delete_status_page

API keys: create_api_key · list_api_keys · revoke_api_key

Terraform: export_terraform

This binary carries the same tool set as the hosted server at mcp.lastping.dev. It is a thin REST client throughout: every tool is a direct HTTP call to the management API, so it stays free to run yourself with no lag behind the hosted surface beyond a new release.

The one that matters most is get_ping_instructions: an agent calls create_monitor, then asks for its own ping commands, and wires them into its own work — in one conversation, without a human opening a dashboard.

Ping API

Every monitor gets a URL. There is nothing to install and no library to keep current; anything that can make an HTTP request can report.

What happened

Request

finished successfully

POST <ping-url>

started a run

POST <ping-url>/start

failed

POST <ping-url>/fail with the error as the body

exited with a code

POST <ping-url>/<exit-code>

waiting on a human

POST <ping-url>/blocked

progress worth recording

POST <ping-url>/note

Add ?rid=<id> to pair a run's start with its result, so LastPing can group a run's pings and time it.

# The classic one-liner, at the end of a cron job:
curl -fsS -m 10 --retry 3 https://ping.lastping.dev/<monitor-id>

Monitoring as code

resource "lastping_monitor" "nightly_etl" {
  name          = "nightly-etl"
  slug          = "nightly-etl"
  schedule_kind = "cron"
  cron_expr     = "0 3 * * *"
  tz            = "Europe/Berlin"
  grace_s       = 900
}

The provider is on the Terraform Registry as lastping-dev/lastping, with source at lastping-dev/terraform-provider-lastping.

License

MIT. See LICENSE.

Available Tools

36 tools
add_incident_noteAInspect

Write back, in your own words, what you found out about an incident — so the person who gets paged reads a diagnosis instead of a timestamp: 'failed because the upstream API returned 503; same failure as the last three nights; I retried twice and stopped' instead of 'check failed at 03:04'. The note appears on the incident's page in the dashboard, attributed to its author, in the order it was written. Take incident_id from list_open_incidents. SEND A NOTE WHETHER OR NOT YOU COULD FIX THE PROBLEM. The person reading the alert cannot see what you saw. With no note, an incident is indistinguishable from one nobody has looked at yet, so an agent that writes back only its successes leaves a record worse than none: every unexplained incident then reads as 'not looked at yet' when it may equally mean 'looked at and gave up'. 'Could not reproduce; gave up after two attempts' IS a finding and is worth writing. NOTES ARE APPEND-ONLY. There is no way to edit a note and no way to delete one — not merely unexposed: no route and no query exists for either, and an edit is refused by the database itself. A correction is a new note, never an edit, because a diagnosis whose history a reader cannot trust is not evidence. This is NOT a write-once resource: a second, third or tenth note on the same incident is normal and expected, and there is no conflict for writing one. The only conflict this tool has is the cap of 50 notes per incident, and reaching it means something is looping rather than diagnosing. A CLOSED incident still accepts notes, on purpose: the run that finally succeeded is usually the one that understood why the previous one did not, so refusing the note would lose the explanation exactly when it became available. Authorship is not yours to choose — every note written through this tool is stored as author 'agent', because this is the API-key surface; there is no author argument and supplying one is not possible.

ParametersJSON Schema
NameRequiredDescriptionDefault
bodyYesThe diagnosis, in plain words and one or two sentences: what actually failed, whether it is the same failure as before (compare failure_signature.occurrences from list_open_incidents), and what you did about it. Must not be empty or whitespace-only, and must be at most 8192 bytes. An oversized body is REJECTED, never truncated — a truncated diagnosis reads as a complete one that trails off, and the reader cannot tell that the sentence naming the cause was the one cut — so shorten it and call again. A pasted stack trace is a note nobody reads: the full failure output already lives on the run that produced it.
incident_idYesThe incident's numeric id, taken straight from an entry's incident_id in list_open_incidents. An integer, not a UUID.

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description goes far beyond annotations by disclosing append-only behavior, the impossibility of editing or deleting notes, forced author attribution as 'agent', acceptance of notes on closed incidents, the 50-note cap, and the non-idempotent nature of the operation. This richly covers behavioral traits annotations alone do not express. There is no contradiction with the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is long, but it is front-loaded with the core purpose and every paragraph addresses a distinct behavioral or usage concern. It is justifiably detailed given the append-only and attribution requirements, though it could be tightened without losing value.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool with this level of behavioral complexity and no output schema, the description is remarkably complete. It covers success expectations, conflict behavior, closed-incident handling, author attribution, content requirements, and failure handling for oversized bodies, leaving no major ambiguity for an agent deciding whether and how to call it.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already fully documents body and incident_id. The tool description does reinforce the source of incident_id and the preferred note style, but it does not add meaning beyond the schema's own parameter descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb ('write back'), a specific resource (incident notes), and the core action: recording findings on an incident's page. It clearly differentiates this from sibling tools like list_open_incidents and list_incidents by focusing on adding a note rather than reading incident data.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description is explicit about when to use this tool: after investigating an incident, using incident_id from list_open_incidents, and sending a note whether or not the problem was fixed. It also gives strong guidance about what not to do, such as omitting notes or pasting stack traces, and clarifies that multiple notes on the same incident are expected and valid.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

create_api_keyAInspect

Create a new LastPing API key. The plaintext key is returned ONCE and cannot be retrieved again — store it immediately in a secret manager. Set expires_at for a short-lived key.

ParametersJSON Schema
NameRequiredDescriptionDefault
nameYesLabel for the key, e.g. "github-actions".
expires_atNoOptional RFC 3339 expiry, e.g. "2026-12-31T00:00:00Z". Omit for a key that never expires.

TDQS

A3.9/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description discloses a critical behavioral trait beyond the annotations: the plaintext key is returned only once and cannot be retrieved again, requiring immediate storage. It also suggests the use of expires_at for short-lived keys. This adds real operational awareness.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is brief and well-structured: it states the purpose, gives a critical security warning, and provides parameter guidance. Every sentence earns its place with no filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple two-parameter creation tool with no output schema, the description covers what matters most: what is created, the one-time return of the plaintext key, the storage imperative, and optional expiry guidance. An agent has enough to invoke it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already explains both name and expires_at. The description reinforces expires_at as a short-lived-key option but adds little new semantic detail beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the action and resource: 'Create a new LastPing API key.' This distinguishes it from the sibling list_api_keys and revoke_api_key at a basic level, though it does not explicitly call out those alternatives.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The usage is implied: use this to create a new API key. It gives helpful security context about storing the key and short-lived keys, but it does not explicitly say when not to use it or point to alternatives like revoke_api_key.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

create_destinationAInspect

Create a notification destination (channel) that monitors can route alerts to. Provide the fields for the chosen kind; unrelated fields are ignored. Non-email kinds are usable immediately; email kinds are created unverified and send a confirmation link that must be clicked before they can be attached to a route. Returns the new channel id — pass it to set_route.

ParametersJSON Schema
NameRequiredDescriptionDefault
urlNowebhook: the POST target URL.
kindYesOne of: webhook, email, slack, discord, telegram, ntfy, pushover, msteams, googlechat.
nameYesHuman-readable destination name, e.g. 'On-call Slack'.
tokenNopushover: the application API token.
secretNowebhook: shared secret used to sign the HMAC-SHA256 payload.
addressNoemail: the destination email address (a confirmation link is sent).
chat_idNotelegram: the target chat id.
user_keyNopushover: the user or group key.
bot_tokenNotelegram: the bot token from @BotFather.
topic_urlNontfy: the full topic URL, e.g. 'https://ntfy.sh/my-topic'.
webhook_urlNoslack / discord / msteams / googlechat: the incoming-webhook URL.

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the annotations, the description discloses important behavioral nuances: unrelated fields are ignored, non-email kinds are immediately usable, email kinds start unverified and require a confirmation click before route attachment, and the tool returns the new channel id. These are exactly the side effects and preconditions an agent needs to know.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Four sentences, each earning its place: purpose, field-selection rule, email caveat, and return-value usage. The most important scoping instruction is front-loaded, and there is no redundant wording.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool with 11 kind-dependent parameters and no output schema, the description covers the essential operational details: return value, email verification prerequisite, and how the result connects to set_route. It could have added a brief example or noted potential errors, but it is sufficient for correct selection and invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3. The description adds meaningful parameter-level guidance by stating that fields must match the chosen kind and that unrelated fields are ignored, which helps agents avoid sending the wrong fields. It also explains the email-specific confirmation behavior for the address field.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description names a specific verb-resource pair ('Create a notification destination') and states what it is for ('monitors can route alerts to'), plus what it returns. It clearly distinguishes creation from sibling tools like update_destination, delete_destination, and list_destinations.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives clear context for when to use this tool: when creating a new destination, and it differentiates the email flow from non-email flows. It doesn't explicitly say 'use update_destination instead for existing channels,' but the create-focused wording and return-id guidance make the intended use clear enough.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

create_monitorA
DestructiveIdempotent
Inspect

Create a new LastPing monitor (or update an existing one if slug matches — returns 'updated' note on upsert). For heartbeat/ci monitors supply schedule_kind ('simple' requires period_s, 'cron' requires cron_expr, 'on_demand' requires neither). For http monitors supply probe_url and probe_interval_s instead — and set probe_expected_status/probe_expected_body too, because those are what define 'healthy'; a probe with neither only proves something answered. For a monitor fed by CI rather than by its own pings, set ci_provider here: it is the ONLY place it can be set, and the secret it returns is shown exactly once.

ParametersJSON Schema
NameRequiredDescriptionDefault
tzNoIANA timezone for cron evaluation. Defaults to UTC.
nameYesHuman-readable monitor name, e.g. 'Daily backup job'.
slugNoOptional stable ID. If a monitor with this slug exists, it will be updated (upsert). Trimmed and lowercased automatically. Must match ^[a-z0-9][a-z0-9-]{1,48}[a-z0-9]$ (3-50 chars, lowercase alphanumeric and hyphens, starting and ending alphanumeric) after normalisation. UUID-shaped slugs are rejected — they would be ambiguous with a monitor id when importing into Terraform. Omit entirely for no slug.
tagsNoComma-separated labels for namespace scoping, e.g. 'agent:claude,env:prod'. Max 20 tags, each max 50 chars.
grace_sNoGrace period in seconds after a ping is due before alerting.
agent_idNoAttach this monitor to an agent from the registry, by the agent's id OR its slug (both are returned by register_agent). Omit for a monitor with no owning agent. Naming an agent that does not exist is an error — 400 UNKNOWN_AGENT — it is NEVER created implicitly; call register_agent first to get a valid agent_id. On an upsert (existing slug), omitting this leaves the monitor's current attachment (or lack of one) unchanged; supplying it re-applies the attachment, so an agent re-running its own registration converges to 'attached' every time rather than silently no-opping after the first call.
period_sNoPing interval in seconds. Required when schedule_kind='simple'.
ci_branchNoCI filter: only count runs on this branch, e.g. 'main'. Requires ci_provider. WITHOUT IT a run on ANY branch — a feature branch, a fork's pull request — reports to this monitor, so somebody else's broken branch marks your monitor down. Set it to the branch whose health you actually care about, which is almost always the default branch.
cron_exprNo5-field cron expression, e.g. '0 3 * * *'. Required when schedule_kind='cron'.
probe_urlNohttp monitors only: the absolute http/https URL to probe. Required when monitor_type='http'. The host is resolved at write time and rejected if it resolves only to private/link-local addresses.
ci_providerNoBind this monitor to a CI system, so the CI system itself reports every run by webhook and the job needs NO ping code at all. One of: 'github', 'gitlab', 'jenkins'. SET-ONCE: ci_provider can only be chosen when the monitor is created — update_monitor cannot change or remove it, so a monitor bound to the wrong provider must be deleted and recreated. Setting it generates a webhook secret that is returned exactly ONCE, in THIS call's response, together with the webhook URL. It is never retrievable afterwards — no MCP tool and no API read returns it again — so copy both out of the response and configure the CI webhook before doing anything else. Omit for a monitor that pings for itself. Also set ci_workflow and ci_branch unless the repository really has exactly one workflow on one branch.
ci_workflowNoCI filter: only count runs of the workflow / pipeline / job with this exact name. Requires ci_provider. WITHOUT IT, EVERY workflow in the repository reports to this monitor — so one unrelated failing workflow opens an incident against a job that is perfectly healthy, and a green run of a different workflow clears an incident the real job never recovered from. Set it whenever the repository has more than one workflow.
monitor_fromNoDORMANT UNTIL: an RFC 3339 timestamp before which no deadline is computed and no incident can open — the monitor is fully configured but not yet armed. Use it when you provision ahead of the work: a monitor for a job that does not start running until next Monday is otherwise 'late' from the moment you create it, which is a false alert on day one. The first-run deadline is seeded as monitor_from + grace_s. Default: unset, meaning deadlines start immediately. Example: '2026-01-01T00:00:00Z'. On an upsert (existing slug), omitting this clears the monitor's monitor_from and arms it immediately — pass the current value to keep it.
monitor_typeNo'heartbeat' (default), 'ci', or 'http'.
probe_methodNohttp monitors only: the HTTP method the probe sends. One of 'GET', 'HEAD', 'POST'. Default 'GET'. Use 'HEAD' for a cheap liveness check when the body does not matter — but note it returns no body, so probe_expected_body cannot match anything.
max_runtime_sNoMaximum seconds a single run may take before it is reported overdue (the 'overrun' rule), measured from the run's start ping. Omit to fall back to grace_s. This is how a long job avoids being flagged overdue while still being detected quickly if it goes silent: e.g. grace_s=600 with max_runtime_s=14400 alerts 10 minutes after a missed ping but tolerates a 4-hour run. It replaces grace_s for the overrun deadline ONLY — the silence rule and the first-run deadline still use grace_s. Range 60-31536000. Not supported on http monitors: a probe has no start/success pair, so the overrun rule can never fire and the API returns 400 MAX_RUNTIME_NOT_SUPPORTED (use probe_timeout_s to bound a single probe). On an upsert (existing slug), omitting this clears the monitor's max_runtime_s — pass the current value to keep it.
schedule_kindNo'simple' (requires period_s), 'cron' (requires cron_expr), or 'on_demand' (requires neither). Required for heartbeat/ci monitors. 'on_demand' means no cadence at all: no period_s, no cron_expr — the API returns 400 if either is supplied — and, by default, NO ABSENCE DEADLINES ARE ARMED BETWEEN RUNS. What this trades away: nothing tells you if the agent is never invoked again; silence between runs is invisible unless you opt in to expect_every_s. What it buys: a healthy agent that nobody happens to invoke for a week never generates a false 'late' or 'down' for simply not having been asked to run. Only run-scoped detection still applies once a run starts — max_runtime_s (overrun), step_timeout_s (stall), blocked_timeout_s (stuck on a human) — because those are anchored to a run's own start ping, not to a cadence. IMPORTANT: if you would be alarmed to find this agent silent for hours, set expect_every_s as well — it is the silence floor, and it is the only thing that makes an on_demand monitor detect absence at all. Choose 'simple'/'cron' when the agent is supposed to run on a cadence; choose 'on_demand' when invocation is inherently irregular and a quiet stretch between runs is expected, not a symptom.
expect_every_sNoSILENCE FLOOR in seconds: open a 'silence' incident if NO ping of any kind — success, start, fail, step — has arrived within this window, regardless of the schedule. It is anchored on the monitor's last activity, not on a cadence, which is what makes it the ONLY absence rule an 'on_demand' monitor can have: that schedule_kind arms nothing between runs, so without this field an on_demand monitor reads 'up' forever no matter how long the agent stays dark. Set it on any on_demand agent monitor you would be alarmed to find silent — that is what it is for. It does NOT fire mid-run: while a run is in flight (a start ping is outstanding) the floor stands down entirely and the run clock owns detection (max_runtime_s, step_timeout_s), so a legitimate 4-hour run that reports nothing is still not an incident. A 'blocked' ping also pauses it, bounded by blocked_timeout_s. On 'simple'/'cron' monitors it is a backstop rather than the main rule: it joins the existing deadline as whichever is SOONER, so it can tighten detection under a long cadence (a daily cron has a ~25-hour blind window) but can never loosen it. Default: unset, which means no floor and is exactly how every monitor behaved before this field existed. Range 60-31536000. Accepted on every monitor_type and every schedule_kind. On an upsert (existing slug), omitting this clears the monitor's expect_every_s and turns the silence floor back off — pass the current value to keep it.
step_timeout_sNoProgress budget in seconds: how long an armed run may go without reporting a step before a 'stalled' incident opens (the stall rule). The clock is anchored on the LATER of the run's start ping and its most recent step, so a run that wedges before its first step is caught too. Reach for this when 'still running' and 'still making progress' are different things — a long agent loop, a multi-stage pipeline, a migration. max_runtime_s alone tells you nothing until the whole budget expires; step_timeout_s=300 on a 4-hour budget tells you within five minutes, and names the last step that reported. To use it the run must report steps: call get_ping_instructions and use curl_step (POST <ping_url>/step?rid=<run-id>&step=<name>). A monitor with step_timeout_s set whose job never reports a step will open a stalled incident on EVERY run — set the field and instrument the job in the same change. Default: unset, which disables stall detection entirely; a monitor that sets nothing behaves exactly as it did before this field existed. Range 10-86400. Two constraints. (1) It must be strictly LESS than the effective run budget, COALESCE(max_runtime_s, grace_s), or the API returns 400 STEP_TIMEOUT_EXCEEDS_BUDGET — at or above the budget the run overruns first, so the stall rule could never fire. (2) Not supported on http monitors: a probe never arms a run and has no /step endpoint to call, so the API returns 400 STEP_TIMEOUT_NOT_SUPPORTED. A step resets the stall clock ONLY — it never extends max_runtime_s, so an agent that reports progress forever still overruns. On an upsert (existing slug), omitting this clears the monitor's step_timeout_s and turns stall detection back off — pass the current value to keep it.
probe_timeout_sNohttp monitors only: how many seconds a single probe may take before it counts as a failure. Range 1-30, default 10. This is the http equivalent of max_runtime_s, which http monitors reject: it is the only way to say 'answering, but far too slowly to be healthy'.
runaway_ceilingNoPING-RATE CEILING: the maximum number of pings this monitor may receive in a rolling one-hour window. Exceeding it opens a 'runaway' incident. This is the rule that catches a job or agent stuck in a LOOP — the failure every other rule misses, because a looping agent is pinging enthusiastically and therefore reads 'up' the whole time it is burning tokens or money. Set it a little above the monitor's real cadence: a job that runs every 15 minutes sends about 4 pings/hour, so 20 absorbs retries and still catches a loop. It is RATE-based, so failure_threshold does not gate it and neither does any run budget. Default: unset, which disables the runaway rule entirely. On an upsert (existing slug), omitting this clears the monitor's ceiling and turns the runaway rule back off — pass the current value to keep it.
notify_min_run_sNoNOTIFICATION DURATION FLOOR in seconds: a run SHORTER than this does not produce an INFO-CLASS notification (success, started, every-run, note). This exists for exactly one problem: on an agent monitor, one run is one task you asked for, so asking the agent 'what's 2+2' produces a start and a success notification exactly like a 56-minute deploy does. If you have routed success/started/every-run/note to a destination, you WILL be paged for trivial runs unless you set this. IT NEVER SUPPRESSES A FAILURE. down, fail, recovery and blocked are alert-class and are never affected by this field, however short the run — a run that failed in two seconds is exactly what you need to hear about, and this field cannot silence that, structurally, no matter how it is set. It also never suppresses 'started': a run's duration does not exist yet the moment it begins, so started is always reported regardless of this floor. And it never suppresses an event whose duration could not be measured at all (e.g. a bare success with no preceding start ping) — an unknown duration always means 'notify', never 'suppress'. Default: unset, which means no floor and is exactly how every monitor behaved before this field existed. Range 60-31536000. Not supported on http monitors: an http probe has no start/success pair, so its run duration is never measured and the floor could never apply (the API returns 400 NOTIFY_MIN_RUN_NOT_SUPPORTED). On an upsert (existing slug), omitting this clears the monitor's notify_min_run_s and turns the notification duration floor back off — pass the current value to keep it.
probe_interval_sNohttp monitors only: how often to probe, in seconds. Required when monitor_type='http'. Range 30-86400.
blocked_timeout_sNoMaximum seconds a run may sit in the 'blocked' state (an agent reported it is waiting on a human) before a 'blocked' incident opens. UNSET DOES NOT MEAN WAIT FOREVER: omitting this does not disable the timeout, it falls back to the default, which is 24 HOURS — an agent still blocked 24 hours after reporting so, with this field never set, gets a 'blocked' incident regardless. Lower it to be paged sooner when a stuck approval is urgent; raise it for work that legitimately waits on a human for longer than a day. This is distinct from the immediate, non-incident 'blocked' notification a route on the 'blocked' event type delivers the moment the agent reports it (see set_route) — that fires right away; this field governs the separate incident that opens only if the wait outlives the timeout. Accepted on every monitor_type: unlike max_runtime_s/step_timeout_s it has no run-scoped precondition an http monitor could fail, so there is nothing to reject. On an upsert (existing slug), omitting this clears the monitor's blocked_timeout_s and falls back to the 24h default — pass the current value to keep it.
failure_thresholdNoNumber of consecutive failures required before an incident opens. Default 1 (open on the very first failure). This is how you stop a single transient blip from paging someone: set 2-5 on a job that fails occasionally for reasons that resolve themselves, and no incident opens until that many runs in a row have failed. Any success resets the count to zero. It gates the 'fail' cause ONLY — silence (a missed ping), overrun, never_started and runaway are time- or rate-based, so a consecutive count means nothing for them and they are never delayed by it. Range 1-100. On an upsert (existing slug), omitting this resets the monitor's threshold to 1 — pass the current value to keep it.
probe_expected_bodyNohttp monitors only: a substring that MUST appear in the response body for the probe to count as healthy. THIS IS THE DIFFERENCE BETWEEN 'the server answered' AND 'the app works': a broken app that renders an error page still returns 200, passes a status-only check, and leaves the monitor green. Match on something only a healthy response contains, e.g. '"status":"ok"'. Substring match, not a regex, and case-sensitive. Default: empty, meaning the body is not inspected at all.
probe_expected_statusNohttp monitors only: the EXACT HTTP status code that counts as healthy. Default 200; any other code fails the probe. Set it when the healthy answer is not 200 — 204 for a no-content health endpoint, or 301 when what you are checking is that a redirect still exists (pair that with probe_follow_redirects=false, or the probe will follow it and see the destination's status instead).
probe_follow_redirectsNohttp monitors only: whether the probe follows 3xx redirects. Default false. Leaving it false is usually what you want: the redirect itself is then compared against probe_expected_status like any other response, so a site that starts redirecting to a login wall, a parking page or an outage notice is CAUGHT rather than silently followed to a healthy-looking 200. Set true only when the URL you are checking is legitimately a redirect to the thing you actually care about.

TDQS

A4.5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare the safety profile (readOnlyHint=false, destructiveHint=true, idempotentHint=true), and the description adds substantial context beyond them: the upsert overwrite semantics, the set-once ci_provider constraint, and the critical disclosure that the CI webhook secret 'is shown exactly once' and is never retrievable afterwards. The described upsert behavior is consistent with both idempotentHint (same slug converges) and destructiveHint (existing config can be overwritten), so there is no contradiction.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Four sentences pack the core verb, the upsert caveat, the three archetype routings, and the one-time-secret warning with zero filler — every sentence earns its place, and the most decision-relevant facts (upsert, type routing, set-once) are front-loaded. It loses a point only because it is a single dense wall of text with no scannable structure; light bolding or bullets would improve it given the breadth it covers.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 28-parameter create tool with no output schema and low annotation richness, the description covers the major decision branches an agent needs: which parameters to supply per monitor type, the upsert pathway, and the one-time return of the CI secret. The only notable gap is that it never states the general success return shape (e.g., the new monitor's id), mentioning only the 'updated' note and the secret; since no output schema exists, a sentence on the primary return value would round it out.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, and every one of the 28 parameters already carries a rich schema-level description, so the baseline is 3. The tool description adds value on top by grouping parameters into the three usage scenarios (schedule_kind clusters, probe_url/probe_interval_s/probe_expected_* clusters, ci_provider/ci_workflow/ci_branch clusters) and by explaining why probe_expected_status/probe_expected_body matter ('a probe with neither only proves something answered'), which the schema states per-parameter but the description synthesizes.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource — 'Create a new LastPing monitor' — and immediately qualifies the scope with the upsert behavior ('or update an existing one if slug matches — returns 'updated' note on upsert'), which distinguishes it from the sibling update_monitor. It then names the three monitor archetypes (heartbeat/ci, http, CI-fed), leaving no ambiguity about what the tool produces.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives strong when-to-use routing: which parameter groups apply to heartbeat/ci vs http monitors, and the explicit statement that ci_provider 'is the ONLY place it can be set' — a direct exclusion that routes the agent to create_monitor rather than update_monitor for CI binding. It does not, however, explicitly name update_monitor as the alternative for editing a slugless existing monitor's fields, and it says nothing about when to prefer delete_monitor/pause_monitor/resume_monitor, so the when-not guidance is partial.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

create_status_pageAInspect

Create a status page — a single page showing the current status and recent history of a chosen set of monitors. Reach for this when the health of a monitor needs to be visible to someone who cannot log in to the project. Pages are PRIVATE unless you ask for otherwise; read the visibility parameter before making one public.

ParametersJSON Schema
NameRequiredDescriptionDefault
slugNoOptional URL slug, which is what appears in the public link (/status/<slug>). Must match ^[a-z0-9][a-z0-9-]{1,48}[a-z0-9]$ (3-50 chars, lowercase alphanumeric and hyphens, starting and ending alphanumeric). Slugs are GLOBALLY unique across all projects, not just yours, so a desirable one may be taken — that returns 409. OMIT IT unless the user asked for a specific URL: a random unguessable slug is then generated, which is also the safer default for a public page.
titleYesHuman-readable page title, e.g. 'Acme API Status'. Shown at the top of the page, and to anyone the page is shared with.
check_idsNoComma-separated monitor UUIDs to show on the page, in no particular order. Get them from list_monitors. Every id must belong to this project — an unknown or cross-project id returns 400 and nothing is saved. An empty value is legal and produces a page with no monitors on it.
visibilityNo'private' (default) or 'public'. 'public' means the page is served at a guessable-free but UNAUTHENTICATED URL: anyone with the link sees the title, the name of every monitor on it, and its up/down history. Monitor names are frequently internal ('billing-reconciler', 'acme-corp-nightly-sync'), so treat this as publishing them. Choose 'private' unless the user has actually asked for a page other people can see. The free tier allows exactly ONE public page per project; a second returns 403.

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations are all false, so the description carries the behavioral burden. It excellently discloses that pages are private by default, that public pages are served at unauthenticated URLs and expose monitor names, that slug conflicts return 409, that invalid check_ids return 400 with nothing saved, and that the free tier allows only one public page. This goes well beyond the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three dense sentences with no filler. The purpose is stated first, followed by the primary use case and then the most critical behavioral caveat about privacy. Every sentence earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a create tool with four parameters and no output schema, the description covers the key context: when to use it, the privacy implications, failure modes (400, 403, 409), and how to handle the optional slug safely. An agent has enough information to invoke it correctly and avoid the most common mistakes.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds meaningful decision guidance: omit slug unless a specific URL is requested, random slugs are safer, private is the safer default for visibility, and monitor names may be sensitive. These are important operational semantics not fully captured in the schema alone.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb ('Create') and resource ('status page') and immediately defines what a status page is: a single page showing current status and recent history of chosen monitors. This clearly separates it from sibling tools like update_status_page, delete_status_page, and list_status_pages.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly states when to use the tool: when monitor health needs to be visible to someone who cannot log in to the project. It gives strong contextual guidance about privacy and visibility but does not explicitly name alternatives or state when not to use it, so it falls just short of a 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

declare_run_expectationsA
Idempotent
Inspect

Commit, at the START of a run, to the criteria by which THAT RUN will be judged when it closes — before you can see how it turns out. This is how a run stops grading itself: once declared, a success ping whose body does not satisfy every declared criterion is recorded as a FAILED run with cause 'assertion', regardless of the exit code or what the ping claims. Call this right after your run's /start ping, before doing any work — see the assertions argument for the full, immutable contract, and get_ping_instructions' expectations_how_to for a worked example.

ParametersJSON Schema
NameRequiredDescriptionDefault
ridYesThe run id exactly as sent on this run's /start ping — the same rid used on every step and the terminal ping.
check_idYesMonitor UUID (from create_monitor or list_monitors).
assertionsYesThe run's complete set of expectations, declared ONCE at the start of the run -- criteria the ping BODY of THIS run's eventual success ping must satisfy when the run closes, checked instead of letting the run grade itself. IMMUTABLE: a second call for the same rid is rejected with a conflict error and the first declaration stands unchanged -- there is no way to edit, add to, or replace it once made, so decide the whole set before you start work. Declaring nothing is allowed and always has been: simply never call this tool for a run, and the monitor's own check-level assertions (if any) stay in force unchanged. INCLUDE AT LEAST ONE POSITIVE CRITERION -- a 'contains', 'matches' or 'json_path' entry -- in every declaration. A declaration made ENTIRELY of 'not_contains' entries is self-satisfying on empty output: a run that produces nothing at all still passes, because there is nothing for the pattern to find. That is precisely the evasion this feature exists to close, so a purely negative declaration defeats its own purpose. A 'matches' entry only counts as positive if its pattern REJECTS an empty body: '.*', '(?s).*' and '^$' all accept one and are validated as perfectly legal patterns, so a declaration resting on one of those is no better than a purely negative declaration. Supply a JSON ARRAY as a string, e.g. '[{"kind":"json_path","path":"result.rows_processed","op":"gt","value":"0"}]'. Fields per entry: kind (required), value, path, op -- no name; a run's declared criteria have none, unlike a monitor's own output assertions. kind is one of 'contains' (body contains value as a substring), 'not_contains' (body does not contain it), 'matches' (body matches value as a Go RE2 regexp, max 1000 bytes), or 'json_path' (parse the body as JSON, read the value at path, compare it against value with op). contains/not_contains/matches require value; json_path requires path and op. path is a DOTTED path only ('a.b.c') -- the query syntax of a real JSONPath library ('[', '*', '$') is rejected. op is one of 'eq', 'ne', 'gt', 'gte', 'lt', 'lte'. At most 20 assertions per run. A malformed entry (uncompilable regexp, a path carrying query syntax, an unknown kind or op) is rejected before anything is written, and nothing is stored if any entry fails.

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The annotations carry only coarse hints (idempotentHint=true, readOnlyHint=false), but the description and the assertions contract disclose the full behavioral profile: grading is taken over from the monitor, failures are recorded as cause 'assertion' regardless of exit code, declarations are immutable with a conflict error on second call, malformed entries are rejected before anything is written, and purely negative declarations are flagged as self-defeating. The second-call conflict behavior refines rather than contradicts the idempotentHint — it specifies precisely what idempotency means here, so the agent gets accurate expectations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The main description is three sentences with zero waste: the commitment semantics in the first, the grading effect in the second, and call timing plus pointers to the contract and worked example in the third. It is front-loaded with the most decision-relevant facts before any deferral to the schema or sibling documentation.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a high-complexity commit tool with no output schema, the definition covers when to call, what it does, the failure consequence, immutability, validation-before-write, and the evasion edge cases, while deferring the parameter contract to the schema and the worked example to get_ping_instructions. The only real gap is that a successful call's return value is never described, which is minor for a side-effect commit operation whose behavior is otherwise fully specified.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%: rid and check_id are self-explanatory, and the assertions parameter is exhaustively documented with kinds, ops, dotted-path restrictions, the 20-entry cap, the positive-criterion requirement, and a concrete JSON-array-as-string example. The main description adds only routing context ('see the assertions argument for the full, immutable contract') plus the grading consequence, which is useful framing but not new parameter-level meaning — so the high-coverage baseline of 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb ('Commit') and a precise resource (the criteria by which the run will be judged), immediately followed by the observable consequence: the run stops grading itself and unsatisfied criteria produce a FAILED run with cause 'assertion'. It is unmistakably distinct from every sibling tool, none of which declare run expectations, and the '/start ping' timing frames it within a specific lifecycle.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicit timing guidance is given ('Call this right after your run's /start ping, before doing any work') and an explicit when-not-to-use is stated: 'simply never call this tool for a run, and the monitor's own check-level assertions (if any) stay in force unchanged' — naming the built-in alternative of doing nothing. It also routes the agent to get_ping_instructions' expectations_how_to for a worked example, leaving no ambiguity about when or how to invoke it.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

delete_agentA
DestructiveIdempotent
Inspect

Permanently delete a LastPing agent from the registry by UUID. THIS DOES NOT DELETE ITS MONITORS: the agent_id foreign key on a monitor is ON DELETE SET NULL, so every monitor this agent owned survives the delete with its ping history and incidents completely intact — it just becomes unowned (agent_id cleared to null) and keeps running on its existing schedule, no longer attributed to any agent. list_monitors/get_monitor will still show it afterwards. To reattach a survivor, call update_monitor with agent_id set to a different agent's id or slug. To also remove a monitor, call delete_monitor on it separately — deleting the agent alone never does that. This action on the agent row itself cannot be undone.

ParametersJSON Schema
NameRequiredDescriptionDefault
idYesAgent UUID (from register_agent or list_agents).

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description goes far beyond the annotations by disclosing the ON DELETE SET NULL foreign-key behavior, explaining that monitors survive with 'ping history and incidents completely intact,' keep running 'on its existing schedule, no longer attributed to any agent,' and remain visible via list_monitors/get_monitor. It also flags that the action 'cannot be undone.' This complements the destructiveHint=true and idempotentHint=true annotations without contradicting them — no annotation contradiction.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Every sentence earns its place: the core action leads, followed by the critical side-effect warning, visibility consequences, the two alternative operations, and the irreversibility note. There is no filler or redundant restatement; the length is justified by the non-obvious cascade behavior that genuinely needs explanation.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a destructive tool with no output schema, the description covers all decision-relevant context: what gets destroyed (the agent row only), what survives (monitors, ping history, incidents), what survivors look like afterward (unowned, still scheduled, still listed), and how to accomplish reattachment or full removal via update_monitor/delete_monitor. The only omitted details are edge cases like repeated-call behavior, but the idempotentHint annotation already communicates that expectation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, with the id parameter already described as 'Agent UUID (from register_agent or list_agents),' so the schema carries the full semantic load. The description reinforces that the UUID targets the agent being permanently deleted, but adds no new format, source, or syntax details beyond what the schema already provides.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb+resource+scope: 'Permanently delete a LastPing agent from the registry by UUID,' which unambiguously defines the action. It also distinguishes itself from the closely related sibling delete_monitor by explicitly stating 'deleting the agent alone never does that' when referring to removing monitors, so an agent can tell the two apart immediately.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives explicit alternative routing: 'To reattach a survivor, call update_monitor with agent_id set to a different agent's id or slug' and 'To also remove a monitor, call delete_monitor on it separately.' It also states a clear when-not condition — this tool never removes monitors — so an agent knows exactly when a sibling tool is required instead.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

delete_destinationA
DestructiveIdempotent
Inspect

Permanently delete a notification destination (channel). This cannot be undone. It also removes the destination from every monitor's routing — any event type routed ONLY to this destination stops notifying anyone, silently and with no incident to show for it. Before deleting a destination that is in use, check which monitors route to it (get_monitor returns a monitor's routes) and give those event types another destination first. To stop using a destination temporarily, prefer editing the routes with set_route and leaving the destination in place.

ParametersJSON Schema
NameRequiredDescriptionDefault
idYesDestination (channel) UUID. Get it from list_destinations.

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the destructiveHint annotation, the description discloses critical cascade behavior: deletion removes the destination from every monitor's routing, and event types routed only to this destination silently stop notifying anyone. It also states irreversibility ('This cannot be undone'), adding meaningful context beyond the schema and annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is front-loaded with the core destructive action, then covers consequences, pre-deletion checks, and the temporary alternative. Every sentence contributes essential guidance for a destructive operation, with no filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's destructive and cascading nature, the description covers permanence, routing impact, silent notification loss, prerequisite checks, and alternative behavior. The absence of an output schema does not create a meaningful gap because the key context an agent needs before invoking deletion is thoroughly explained.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema already fully describes the single id parameter with 100% coverage, including how to obtain it via list_destinations. The description does not add further parameter-level detail, so the baseline score of 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb and resource: 'Permanently delete a notification destination (channel).' It clearly differentiates from sibling tools like delete_monitor, delete_agent, and set_route by focusing on notification destinations and their routing side effects.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It explicitly instructs when to avoid deletion: check which monitors route to the destination via get_monitor and reassign those event types first. It also provides the alternative for temporary changes: edit routes with set_route and keep the destination in place.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

delete_monitorA
DestructiveIdempotent
Inspect

Permanently delete a LastPing monitor by UUID. This cannot be undone.

ParametersJSON Schema
NameRequiredDescriptionDefault
idYesMonitor UUID.

TDQS

A4.1/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already indicate destructive behavior, and the description goes further by adding 'cannot be undone,' which conveys irreversibility beyond the plain destructiveHint flag. It also clarifies the exact target by UUID, adding useful behavioral context.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short sentences with no filler. The action and resource are front-loaded, and the irreversibility warning follows naturally. Every word earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a one-parameter destructive tool with strong annotations and no output schema, this description is complete. It states what is deleted, how it is identified, and that the action is irreversible—enough for an agent to invoke it safely and correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema already covers the single parameter fully: id is a string described as 'Monitor UUID.' The description repeats 'by UUID' but adds no additional semantic detail beyond the schema, so the baseline score of 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific action ('delete'), a specific resource ('LastPing monitor'), and a specific identifier ('UUID'). It clearly distinguishes this from other deletion tools like delete_destination and delete_status_page.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies use for permanently removing a monitor and warns it cannot be undone, but it does not explicitly contrast this with non-destructive alternatives like pause_monitor or snooze_monitor. Usage context is clear but exclusions and alternatives are not stated.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

delete_status_pageA
DestructiveIdempotent
Inspect

Permanently delete a status page. This cannot be undone, and any public URL it had stops working immediately. The monitors on the page are NOT affected — they keep running and alerting exactly as before; only the shared view of them is removed. To stop sharing without losing the page, set visibility to 'private' with update_status_page instead.

ParametersJSON Schema
NameRequiredDescriptionDefault
idYesStatus page UUID, from list_status_pages.

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already signal destructiveHint=true, and the description goes beyond that by disclosing irreversible consequences, immediate URL invalidation, and the precise non-effect on monitors. This is exactly the kind of behavioral context that helps an agent understand side effects.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences, each earning its place: the core action, the irreversible consequences, and the alternative for a non-destructive use case. The most important information is front-loaded, and there is no filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple single-parameter destructive operation, the description fully covers what happens on deletion, what does not happen, and what to use instead. Combined with the schema and annotations, nothing essential is missing for an agent to invoke the tool correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, with the id parameter fully described as 'Status page UUID, from list_status_pages.' The description adds no additional parameter-level meaning, but the schema already carries the burden, so a baseline score of 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource: 'Permanently delete a status page.' It also distinguishes the action from the related update_status_page tool by clarifying that this removes the shared view while leaving monitors unaffected, so an agent can confidently select the right tool.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly states when not to use the tool: 'To stop sharing without losing the page, set visibility to 'private' with update_status_page instead.' This provides clear routing to the alternative and gives a concrete condition that should trigger the alternative choice.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

discover_monitors_reconcileA
Idempotent
Inspect

Turn a scan of a repository or a host into monitors: send every scheduled job you found, get back a diff of what was created, what already existed and what has gone missing. This is how a user gets monitored without filling in a form. PROPOSE, THEN ASK. Show the user what you found and get their agreement BEFORE calling this — it CREATES monitors. Eleven monitors created on a repository you were asked to look at are eleven things that can page a person at 03:00 and that they never agreed to, and this endpoint has no delete path to undo them with. WHAT TO SEND: a JSON array as a string in sources, one entry per job. Each entry needs source_kind and source_ref — that pair is the key this call diffs against, so source_ref must be STABLE between scans; a ref whose shape changes makes every monitor look new and duplicates the whole fleet on the next run. Kinds: 'crontab' (crontab -l, /etc/cron.d/, /etc/crontab), 'github-actions' (.github/workflows/.yml, an on.schedule.cron entry), 'k8s-cronjob' (a manifest or Helm template with kind: CronJob and a spec.schedule), 'systemd-timer' (/etc/systemd/system/*.timer, an OnCalendar= line). Send schedule_cron only when you actually read a cron expression; a workflow triggered on push has no cadence to be late against, and an invented one pages the user every quiet afternoon. Without it the monitor is created on-demand instead. READ THE TIMEZONE, DO NOT ASSUME ONE. crontab and systemd-timer fire in the HOST's local time; github-actions and k8s-cronjob evaluate their schedules in UTC. A 'crontab' or 'systemd-timer' entry carrying a schedule_cron MUST state its tz, and the zone must be READ from the host — timedatectl show -p Timezone --value, or readlink /etc/localtime where that is unavailable — not filled in as a default. A host at UTC+4 running '0 3 * * *' pings at 23:00 UTC, so a monitor recorded as tz=UTC arms its deadline about twenty hours before the job is due and opens a false incident every single day. The API cannot catch this for you: it requires that a zone be STATED, and a stated 'UTC' from a scanner that read the host is indistinguishable on the wire from a stated 'UTC' a client filled in. Send 'UTC' only when you read the host and it really is UTC. Scanning a REPOSITORY, where there is no host to read, ASK THE USER which zone those machines run in — not knowing is a question to put to them, never a reason to reach for a default. WHAT COMES BACK is a three-way diff: created (sources that had no monitor and now have one), existing (sources already monitored, returned COMPLETELY UNMODIFIED — not the name, not the schedule, not the thresholds, so an expect_every_s the user tuned by hand survives every scan), and orphaned (monitors whose source this scan did NOT report). RECONCILE NEVER DELETES, NEVER PAUSES AND NEVER EDITS ANYTHING. There is no delete path and no update path in this endpoint at all, so an orphaned monitor is still running and still alerting; treat that list as a question for the user ('this job is gone, should its monitor go too?'), never as something to act on yourself. BECAUSE OF THAT IT IS SAFE TO RE-RUN, and re-running is the point: run it nightly, on every CI build, after every deploy, and the second run creates only what has appeared since the first while orphaned becomes your drift report. A scan that runs once is a setup wizard; a scan that is safe on a schedule is drift detection. Existing monitors already carry source_kind and source_ref in list_monitors, so you can see what is already discovered without calling this.

ParametersJSON Schema
NameRequiredDescriptionDefault
sourcesYesThe complete scan result: a JSON ARRAY supplied as a string, one entry per scheduled job, e.g. '[{"source_kind":"crontab","source_ref":"/etc/cron.d/backup:/usr/local/bin/backup.sh","name":"nightly backup","schedule_cron":"0 3 * * *","tz":"Europe/Berlin"}]'. Fields per entry: source_kind and source_ref (both REQUIRED — an entry missing either cannot be matched against an existing monitor and would be re-created on every scan), name (optional display name; falls back to source_ref), schedule_cron (optional 5-field cron expression, sent only when you actually read one), tz (the IANA zone that cron fires in — REQUIRED for a crontab or systemd-timer entry carrying a schedule_cron, read from the host, never guessed), and suggested_expect_every_s (optional; state the silence floor outright when you know the real cadence better than the cron expression does — it WINS over the value derived from the cron). Send the WHOLE scan in one call: this is a diff, so a source you leave out is reported as orphaned rather than ignored. Send '[]' to report that the scan found nothing — every discovered monitor is then listed as orphaned, and none of them is deleted. At most 1000 entries per call, each source_kind/source_ref pair at most once (a duplicate is rejected outright, not merged), and the project's 100-monitor cap is applied to the whole batch at once — if the batch would exceed it, NOTHING is created. Nothing is written unless every entry validates: one bad entry rejects the entire payload and leaves no monitors behind.

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description goes far beyond the annotations, which only state idempotentHint=true and destructiveHint=false. It explicitly discloses that the endpoint CREATES monitors, has no delete or update path, never pauses or edits, returns a three-way diff, leaves existing monitors completely unmodified, rejects the entire payload if any entry is invalid, and applies a 100-monitor cap atomically. This gives the agent a precise behavioral model well beyond the structured hints.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is long, but the tool is complex and dangerous (it creates monitors with no delete path), so the length is largely justified. It is front-loaded with purpose and structured into clearly captioned sections (PROPOSE, THEN ASK; WHAT TO SEND; READ THE TIMEZONE; WHAT COMES BACK). A little repetition of the 'no delete' point exists, but it serves as emphasis rather than fluff.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Despite having no output schema, the description fully explains the return shape (created/existing/orphaned) and all calling constraints: required source_kind/source_ref, supported kinds, timezone handling, size caps, duplicate rejection, batch atomicity, and the ability to send '[]'. It even tells the agent where to see already-discovered monitors (list_monitors). Nothing needed to call this correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Although the schema already covers 100% of the single parameter, the description adds crucial semantic meaning: source_ref must be stable between scans or every monitor looks new, schedule_cron must only be sent when a real cron expression is read, tz must be read from the host or asked of the user, and omitting a source reports it as orphaned rather than ignored. These are meaning-bearing details the schema alone does not convey.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource: "Turn a scan of a repository or a host into monitors: send every scheduled job you found, get back a diff of what was created, what already existed and what has gone missing." This clearly distinguishes the tool from siblings like create_monitor by framing it as reconciliation/diff discovery rather than one-off creation. The later contrast with list_monitors further sharpens its identity.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives strong usage context: run it nightly, on every CI build, after every deploy, and only after proposing the change to the user ("PROPOSE, THEN ASK"). It also points to list_monitors as a way to see existing discovered monitors without calling this. However, it does not explicitly name create_monitor as the alternative for manual one-off creation, so the when-not-to-use guidance is implied rather than fully explicit.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

export_terraformA
Read-onlyIdempotent
Inspect

Export existing LastPing monitors, destinations, routes, alert templates and status pages as Terraform HCL, including import blocks so they are adopted rather than recreated. Secrets are NOT exported — the output references Terraform variables you must fill in.

ParametersJSON Schema
NameRequiredDescriptionDefault
tagNoOptional tag to filter monitors by, e.g. 'agent:claude'. Only monitors carrying this tag (and their routes/templates) are exported.
includeNoOptional comma-separated subset of monitors,destinations,routes,templates,status_pages. Omit to export everything.
monitor_slugNoOptional slug to export a single monitor by. Combines with tag if both are given.

TDQS

A4.5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already mark the tool readOnly, idempotent, and non-destructive. The description adds valuable behavioral detail: secrets are not exported, and placeholders become Terraform variables the user must fill in. This goes beyond annotation coverage without contradicting it.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences front-load the resource scope and output format, then state the key secrets caveat. Every sentence adds meaningful, non-redundant information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For an export tool with three optional, fully documented parameters and no output schema, the description covers what is exported, the output format, adoption behavior, and the secrets handling. Nothing critical is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema already documents all three optional parameters with 100% coverage, so the description does not need to repeat them. It adds no extra parameter-level detail, but none is needed given the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Description names the exact action and scope: export existing LastPing monitors, destinations, routes, alert templates, and status pages as Terraform HCL. It is clearly distinct from the sibling CRUD and monitoring tools.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description makes clear this is for exporting existing resources into Terraform and adopting them via import blocks rather than recreating them. It does not explicitly discuss when not to use the tool, but the use case is well implied.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_agentA
Read-onlyIdempotent
Inspect

Get a single LastPing agent by UUID. Returns the same fields as list_agents, including its live status rollup. Use list_agents to find valid IDs, or register_agent to create one.

ParametersJSON Schema
NameRequiredDescriptionDefault
idYesAgent UUID (from register_agent or list_agents).

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, idempotentHint, and destructiveHint, so safety behavior is covered. The description adds useful behavioral context by stating the return shape matches list_agents and includes the live status rollup, which is not inferable from annotations or the minimal schema.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two focused sentences with no filler. The primary behavior is stated immediately, and the usage hints are concise and actionable.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a single-parameter read-only tool, the description plus annotations and schema fully cover operation semantics, valid ID sources, and return-shape expectations. No output schema exists, but referencing list_agents' fields is sufficient context for an agent to understand the response.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%; the id parameter is already described as 'Agent UUID (from register_agent or list_agents).' The description mostly repeats this in prose ('by UUID') without adding new format, validation, or default information, so a baseline score of 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the specific action ('Get a single LastPing agent by UUID') and distinguishes it from list_agents by emphasizing 'single' and from mutation tools like update_agent/delete_agent. It also specifies the resource type and return-scope detail (same fields as list_agents, including live status rollup).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly directs the agent to use list_agents to find valid IDs and register_agent to create one, making the typical read flow clear. It does not explicitly contrast with update_agent/delete_agent, but sibling names plus the read-only annotation make the intended use clear.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_alert_templatesA
Read-onlyIdempotent
Inspect

Get all custom alert message templates for a LastPing monitor. Returns a map of event-type (or event-type/cause) keys to template strings. Keys: 'down', 'recovery', 'fail', 'every-run', 'success', 'started', 'blocked', 'note', or 'event_type/cause' (e.g. 'down/silence'). An empty result means all alerts use the built-in plain-language defaults.

ParametersJSON Schema
NameRequiredDescriptionDefault
idYesMonitor UUID.

TDQS

A4.1/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare the operation read-only, idempotent, and non-destructive. The description adds meaningful behavioral context beyond that by specifying the return shape (a map), enumerating the possible keys, and explaining the semantic of an empty result. This helps the agent interpret the response correctly.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is compact and front-loaded: the operation is stated first, followed by the return format and key details, ending with an important edge-case interpretation. Every sentence adds distinct value and there is no redundant filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple read-only tool with one documented parameter and no output schema, the description fully covers what an agent needs: what the tool returns, the allowed keys, and the meaning of an empty result. Nothing critical is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The only parameter, 'id', is already fully described in the schema as 'Monitor UUID' with 100% coverage. The tool description does not need to repeat this and does not add additional parameter semantics, so the baseline score of 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource: 'Get all custom alert message templates for a LastPing monitor.' It clearly identifies the product scope and the operation, and the mention of a map keyed by event-type distinguishes it from related mutation tools like set_alert_template.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies this is the tool to inspect existing custom templates, especially with its note about empty results meaning built-in defaults. However, it never explicitly names the alternative set_alert_template or states when to use one vs. the other, so the guidance is only implied rather than explicit.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_monitorA
Read-onlyIdempotent
Inspect

Get a single LastPing monitor by UUID. Returns the monitor's full configuration including its output assertions (the assertions field: conditions a successful run's ping body must satisfy; absent when the monitor has none) and its metric guards (the guards field: ceilings on a number the job reports about itself; absent when the monitor has none) and its alert ROUTING (the routes field: which destinations receive which event type; absent when the monitor has none). Read this before calling update_monitor with assertions or guards, and before calling set_route — every one of those three writes REPLACES a whole set, so an agent that did not read the current one first will silently drop assertions, guards or destinations somebody else configured.

ParametersJSON Schema
NameRequiredDescriptionDefault
idYesMonitor UUID.

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already mark this as read-only and idempotent, and the description adds critical behavioral context: assertions, guards, and routes are absent when not configured, and the related write tools replace entire sets. This warning goes well beyond the structured annotations and prevents silent data loss.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Although the description is longer than typical, every sentence earns its place: it states the core function, explains the three significant return fields and their absence semantics, and delivers a crucial pre-write warning. The key action is front-loaded and the warning is clearly structured.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a read tool with no output schema, the description sufficiently covers what is returned, when fields may be absent, and why reading before writing is necessary. The single parameter is fully documented in the schema, so nothing essential is missing for correct invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema already provides full documentation for the single `id` parameter ("Monitor UUID"), so the description does not need to add parameter details. It reinforces that the lookup is by UUID, but this is a minor addition beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource: "Get a single LastPing monitor by UUID," and clarifies it returns the full configuration including assertions, guards, and routes. This distinguishes it clearly from list_monitors and other monitor-related tools.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides explicit when-to-use guidance: read this before update_monitor with assertions or guards, and before set_route. It also explains the consequence of not doing so, making the routing decision unambiguous and actionable.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_ping_instructionsA
Read-onlyIdempotent
Inspect

Get everything needed to make a monitor actually report: the ping URL, copy-paste check-in snippets, and the three MECHANISMS for reporting, returned together. Call this right after create_monitor. CHOOSE BY WHAT THE MONITORED THING IS — read reporting_options first and pick by that, rather than defaulting to the raw curl list: how_to — the manual protocol — is the UNIVERSAL path: it works in any agent, any language, any tool, with no prerequisite, so it is the default choice for any agent this applies to. Pair it with expect_every_s (the silence floor, set via update_monitor) so an agent that quietly stops reporting opens a detected incident instead of leaving its monitor reading healthy. If you ARE Claude Code specifically, hook_install is available as an OPTIONAL SHORTCUT, not a better tier: a one-time install that binds reporting to Claude Code's own hooks (UserPromptSubmit, Stop, StopFailure), automating how_to's exact same protocol so reporting becomes a property of your event loop instead of something you must remember — and it is the only mechanism that can send every state this product models, including blocked and note. hook_install is Claude Code specific: if you are a DIFFERENT AI agent — even one with its own hook or event system, Cursor, Windsurf, Codex, a custom framework — do NOT translate its steps into your own hooks; the event semantics differ and a translated install can pass its own verification while never reporting, so use how_to instead. If what you are monitoring is launched as a command instead — a cron job, a CI step, a script, or an agent started from a shell — use run_wrapper: wrap the command with lastping run and a separate process reports for you, so nothing has to be remembered; the tradeoff is that it reports the process's own lifecycle (start, success, fail, cancel) and has no way to send blocked or note. Whichever you choose, the underlying protocol is the same: the success ping at the END of the work, the fail URL if it failed, the start ping first for long or possibly-hung runs (this enables overrun / never-finished detection), and a step (curl_step) as each stage completes so a run that wedges mid-way is caught by name rather than only when its whole budget expires. Also read expectations_how_to: before you start work, use declare_run_expectations to say how THIS run should be judged when it closes — a one-time, unchangeable commitment that replaces the run grading itself. And discovery_how_to, which is about the OTHER jobs on this host or in this repo: how to find the scheduled work nobody is watching yet and propose it, rather than monitoring only the one thing you were asked about.

ParametersJSON Schema
NameRequiredDescriptionDefault
idYesMonitor UUID (from create_monitor or list_monitors).

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, so the description does not need to reassert safety. It adds meaningful behavioral context by explaining that the tool returns all mechanisms together, describes the universal protocol, and discloses the limitations of each mechanism (e.g., run_wrapper cannot send blocked or note). No contradiction with annotations exists.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is front-loaded with the core purpose, and it has logical sections for choosing among mechanisms. However, it is very long and dense for a one-parameter getter, mixing returned-field descriptions, decision routing, protocol details, and follow-on tool guidance into continuous prose. Every sentence contributes useful content, but the structure could be tighter.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Because there is no output schema, the description carries the full burden of explaining what the tool returns and how to act on it. It covers all major return fields, names alternatives, gives prerequisites, warns about misuse, and connects to related tools like update_monitor and declare_run_expectations. An agent has enough context to select and invoke this tool correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

There is only one parameter, id, and the schema already fully describes it as 'Monitor UUID (from create_monitor or list_monitors)'. The description adds no new parameter-specific semantics beyond implicitly reinforcing that the tool should be called after create_monitor, so the baseline of 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource: 'Get everything needed to make a monitor actually report' and lists the concrete return contents: ping URL, copy-paste snippets, and three reporting mechanisms. It clearly differentiates this from siblings by framing it as the post-create_monitor retrieval of reporting setup material.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives explicit when-to-use guidance ('Call this right after create_monitor'), names the three internal options, and provides strong exclusion rules: Claude Code may use hook_install, other agents must not translate it, and command-launched processes should use run_wrapper. It also tells the agent to read expectations_how_to and discovery_how_to, so the usage context is fully specified.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_run_historyA
Read-onlyIdempotent
Inspect

Get structured run history for a monitor — both CI/CD runs and agent/heartbeat runs. Each run carries its run id (rid), kind, received_at, the progress steps reported under it (steps: seq, name, at), and the correlated incident log excerpt (incident_detail) with resolution status. A run that stalled tells you which step it reached and when it stopped moving — no need to follow links to the CI provider. steps is absent for a run that reported none — steps are matched on rid, so they appear only when the job or agent posted /step?rid= with the same run id it started with. CI-specific fields — failing step (failing_stage), triggering actor, commit SHA, run URL, branch, duration_s, outcome — are present only on runs that carried ci_meta; they are simply absent on agent/heartbeat runs. A ping with neither ci_meta nor a rid is excluded entirely. duration_ms is a SEPARATE measurement, present on ANY run (CI or agent/heartbeat) whose success ping paired with its preceding start — this is how to answer 'how long does this job normally take?' for a non-CI monitor. It is computed by LastPing from the /start->success timing, not self-reported by a provider like duration_s is; the two must not be confused as confirming each other, and either can be present without the other.

ParametersJSON Schema
NameRequiredDescriptionDefault
idYesMonitor UUID.
limitNoMax runs to return (default 20, max 100).

TDQS

A4.2/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With readOnlyHint and idempotentHint already covering safety, the description goes far beyond annotations to explain field-presence semantics: ci_meta-only fields, steps matching on rid, exclusion of pings lacking both ci_meta and rid, and the critical provenance distinction between duration_ms (computed by LastPing) and duration_s (provider-reported). This is exactly the behavioral nuance an agent needs to interpret data correctly.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is long (~180 words) but nearly every clause earns its place by preventing a real misinterpretation, such as conflating duration_s with duration_ms. The core scope is front-loaded, and the conditional-field detail follows logically. It is dense rather than bloated, though it could be tightened.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

There is no output schema, so the description carries the full burden of explaining return values — and it does so exhaustively: run fields, conditional presence rules, exclusion criteria, and cross-field relationships. For a tool with this much conditional complexity, nothing an agent needs to interpret the response is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% for both parameters (id as Monitor UUID, limit with default/max), so the schema carries the full burden. The description adds context about what a run contains but not about the parameters themselves, landing at the baseline.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description names a specific verb ('Get') and resource ('structured run history for a monitor') and immediately distinguishes the two run kinds it covers: CI/CD runs and agent/heartbeat runs. This is precise enough to separate it from sibling list/get tools without opening schemas.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage context well — it explicitly teaches the agent how to answer 'how long does this job normally take?' for a non-CI monitor via duration_ms. However, it never names an alternative or states when NOT to use this tool, so routing guidance is left to inference rather than stated.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_agentsA
Read-onlyIdempotent
Inspect

List all agents registered in the project. Returns id, slug, name, status, monitor_count and last_seen for each. status is rolled up live from the monitors the agent owns, worst first: down (a monitor is down), blocked (a monitor's run needs a human right now), late (a monitor is late), running (a monitor's run is in flight), up (healthy), pending (a monitor exists but has never reported) or idle (no monitors, or all of them paused/in maintenance). Use register_agent to create one.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already establish readOnly, idempotent, and non-destructive behavior, so the description does not need to restate safety. It adds valuable behavioral detail beyond annotations: status is a live roll-up from the agent's monitors, ordered worst-first, with each possible value explained. This is essential context for interpreting results, especially given the absence of an output schema.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The purpose is front-loaded in the first sentence, return fields are listed, and the status semantics are explained compactly but thoroughly. The final sentence routes to register_agent without adding noise. Every sentence earns its place, and the status enumeration is necessary because the status field has custom domain meaning.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

This is a zero-parameter read-only list operation with annotations covering safety. The description supplies the return fields and the complete semantics of the status field, which compensates for the missing output schema. An agent has everything needed to invoke the tool and interpret its response correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool has zero parameters and 100% schema description coverage, so there is no parameter burden for the description to carry. The phrase 'registered in the project' adds scope context but no parameter-specific documentation is needed.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb ('List'), the resource ('agents registered in the project'), and the exact fields returned, including the nuanced status field. This makes it clearly distinguishable from siblings like get_agent (single lookup) and register_agent (creation).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly names register_agent as the alternative when the goal is to create an agent. It does not explicitly contrast with get_agent for single-agent retrieval, but the phrase 'List all agents' makes the usage context clear without requiring an exclusion statement.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_api_keysA
Read-onlyIdempotent
Inspect

List all API keys in the project. Never returns plaintext key values — only the non-secret prefix, which is enough to identify a key for revoke_api_key. Each key includes last_used_at and last_used_surface (which client — "mcp", "terraform", or "api" — most recently authenticated with it), both absent if the key has never been used. last_used_surface is best-effort client self-identification from a caller-controlled, spoofable User-Agent header: useful for answering "did my client ever successfully authenticate?", never a basis for trust or authorization decisions.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already mark the operation as read-only and idempotent, but the description adds substantial behavioral detail: it never returns plaintext values, includes last_used_at and last_used_surface, omits those fields for unused keys, and explicitly warns that last_used_surface is spoofable and not a trust boundary. This is exactly the kind of context an agent needs beyond structured annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Every sentence earns its place: the core action, the security boundary, the field semantics, and the spoofability caveat. The most important information is front-loaded, and the length is justified by the nuanced security warning about caller-controlled User-Agent data.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a zero-parameter list operation, the description covers the key return values, their absence behavior, and a security caveat. No output schema exists, so this descriptive coverage is sufficient for an agent to call the tool correctly and interpret results appropriately. The annotations cover safety, and the description covers behavior.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema has zero parameters, so there is nothing for the description to explain about parameter usage. The description appropriately clarifies that the call lists all keys in the project without filtering, and it documents the meaning of fields returned. With no parameters, this is effectively complete.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource: 'List all API keys in the project.' It goes beyond a generic listing by clarifying the security-relevant behavior of returning only non-secret prefixes, which also distinguishes it from create_api_key and revoke_api_key. This is unambiguous and clearly scoped.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description makes it clear this is the read-only listing tool and explains that the returned prefix is sufficient for a subsequent revoke_api_key call. It does not explicitly enumerate when not to use it, but the context strongly implies this is the appropriate tool for identifying existing keys without exposing secrets.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_destinationsA
Read-onlyIdempotent
Inspect

List all notification destinations (channels) in the project: email, webhook, Slack, Discord, Telegram. Use channel IDs to configure routing rules for monitors.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.2/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already assert readOnlyHint, idempotentHint, and destructiveHint=false, so the read-only safety profile is known. The description adds the project scope and channel type enumeration, and claims 'all', but offers no detail on response structure, pagination, or ordering. This is useful but not rich behavioral context.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences with no filler. The main action and scope are front-loaded, followed by a purpose statement. Every word earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a parameterless list tool, the description covers what is listed, the project scope, and the downstream use of channel IDs. Since no output schema exists, an explicit return-format note would strengthen it, but the description is largely sufficient.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool accepts zero parameters, so the input schema is fully descriptive. Baseline 4 applies; the description adds no parameter detail because none is needed.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb ('List') and resource ('notification destinations (channels)'), scopes to 'in the project', and enumerates channel types. The final clause ties the output to routing rules, clearly distinguishing it from sibling tools like create_destination or delete_destination.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The sentence 'Use channel IDs to configure routing rules for monitors' gives a concrete usage context. However, it does not explicitly state exclusions or alternative tools, so it stops short of the fullest guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_incidentsA
Read-onlyIdempotent
Inspect

List recent incidents (downtime events) for a monitor. Returns newest first. An open incident has closed_at=null.

ParametersJSON Schema
NameRequiredDescriptionDefault
idYesMonitor UUID.
limitNoMax incidents to return (default 50, max 200).

TDQS

A3.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already cover read-only, idempotent, non-destructive behavior, so the safety profile is accounted for. The description adds useful behavioral context beyond annotations: results are returned newest first, and open incidents are identifiable by closed_at=null. This is meaningful operational information for an agent interpreting the output.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is three short sentences with no filler. It front-loads the core purpose, then the ordering behavior, then the open-incident convention, so every sentence earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple read-only list operation, the description covers the essential behavior: what is listed, for which resource, in what order, and how open incidents are represented. Pagination or time-window details are not mentioned, but the limit parameter is already in the schema and annotations cover safety, so the gaps are minor.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema documents all parameters with 100% coverage: id is a Monitor UUID and limit has a default of 50 and max of 200. The description adds no parameter-specific details beyond the schema, so it meets the baseline without adding extra semantic value.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description names a specific verb ('List'), a specific resource ('incidents'), and scopes it to a monitor, while clarifying that incidents are downtime events. It also notes that open incidents have closed_at=null, which helps distinguish from the sibling list_open_incidents, though it never explicitly names that alternative.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies this is the general incident listing tool that includes both open and closed incidents, and it is clearly tied to a monitor context. However, it does not explicitly state when to prefer list_open_incidents or provide any exclusions or conditions, leaving the usage guidance largely inferable.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_monitorsA
Read-onlyIdempotent
Inspect

List all monitors in the authenticated LastPing project. Returns id, name, slug, status, ping_url for each. Use the tag param to filter by a single tag.

ParametersJSON Schema
NameRequiredDescriptionDefault
tagNoOptional tag to filter by, e.g. 'agent:claude'. Returns only monitors that have this tag.

TDQS

A4.1/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already provide readOnlyHint, idempotentHint, and destructiveHint, so the safety profile is covered. The description adds valuable behavioral context beyond annotations: it specifies the project scope, the exact return fields, and the tag-filtering behavior. No pagination or ordering details are given, but this is minor for a simple list tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two concise sentences with no filler. The main action is front-loaded, the return payload is stated immediately, and the parameter guidance is included without redundancy. Every sentence earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a read-only list tool with one optional parameter and no output schema, the description is complete: it names the scope, lists the returned fields, and explains filtering. The annotations cover safety, and the missing details like pagination are not critical given the tool's simplicity.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, and the schema already documents the optional tag parameter with an example and expected effect. The description repeats this in slightly different words ('filter by a single tag') but adds no meaningful meaning beyond the schema, so the baseline of 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb ('List'), a clear resource ('monitors'), and the scope ('in the authenticated LastPing project'). It also enumerates the returned fields (id, name, slug, status, ping_url), making the tool's purpose unmistakable and distinguishable from sibling monitor tools like get_monitor or update_monitor.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description clearly implies the tool is the list/filter operation and explains how to use the tag parameter, but it never explicitly contrasts it with alternatives such as get_monitor for a single monitor or mentions when not to use this tool. Usage context is present but relies on inference from sibling names.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_open_incidentsA
Read-onlyIdempotent
Inspect

Read this agent's failure inbox: every incident currently OPEN on the monitors it owns, newest first. Call it at the START of a run, before doing the work — this is how an agent finds out what broke while it was not running, with no webhook, chat integration or mailbox to wire up. What makes the payload worth reading is NOT 'your check failed' — the run that failed already knows that. It is the context that no single failure body can contain:

  • failure_signature.occurrences — how many times THIS EXACT failure has been seen on this monitor (with first_seen/last_seen, and a fingerprint you can use to correlate incidents yourself). First occurrence or fortieth repeat is the fact that decides retry versus escalate, and no amount of reasoning over one failure body can recover it.

  • failed_step — the last step the run reported before it stopped. For a 'stalled' incident this is the entire diagnosis: the run is still alive and has not moved past this step.

  • exit_code — the status the run exited with. 137 (SIGKILL, usually the OOM killer) and 1 are both the word 'fail' and are completely different problems.

  • duration_vs_normal — a COMPARISON, not a measurement: '8.2x the typical run (41m vs 5m), from 30 archived days'. run_ms, typical_ms, ratio and days_sampled are carried too, so you can apply your own threshold and tell a 30-day norm from a 2-day one.

  • cause — 'silence' and 'fail' demand opposite responses. 'fail' means the job ran and reported an error; 'silence' means it never reported at all, which usually implicates the scheduler or the host rather than the job.

  • body_excerpt (the error text the failing run actually printed), run_id (line the incident up against your own logs), and ci.run_url (where the full log is, when the failure came from a CI provider). ABSENCE MEANS NO EVIDENCE — NEVER GOOD NEWS. Every enrichment degrades to ABSENT rather than erroring, so a missing field is the ordinary case, not an error. A missing duration_vs_normal means the run's duration or the monitor's baseline is unknown; it does NOT mean the run took a normal amount of time. A missing exit_code means no numeric code was reported (the ping used a word form such as /fail, or a detector opened the incident with no ping at all); it does NOT mean the job exited cleanly — and exit_code 0 is a real value this field does report, on a run that claimed success and then failed its declared expectations. A missing failure_signature or failed_step reads the same way: not known, never 'none'. Then WRITE BACK what you found with add_incident_note, passing the incident_id from the entry you acted on. Reading the inbox and saying nothing leaves the human exactly where they were.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMax incidents to return (default 50, max 200). Newest first, so a small limit drops the oldest open incidents, not the newest.
agent_idYesAgent UUID (from register_agent or list_agents). The inbox covers every monitor this agent owns.

TDQS

A4.4/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly, idempotent, and non-destructive behavior, and the description adds substantial extra context: it explains the meaning of missing fields, that absence is evidence of absence rather than success, the difference between 'fail' and 'silence', and the semantics of exit_code 0. This goes far beyond what annotations provide.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is long but well-structured: it front-loads the core purpose, then uses a bulleted list to explain why each payload field matters. Some rhetorical framing is present, but nearly every sentence adds signal, and the organization makes the detail digestible.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

There is no output schema, so the description carries the full burden of explaining return semantics, and it does so thoroughly: it names the key fields, explains what they mean, clarifies absence behavior, and even describes the recommended follow-up action. For a read-only tool with fully documented parameters, nothing essential is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the input schema already documents agent_id and limit, including defaults, max, and newest-first ordering. The description reinforces the 'newest first' behavior and the agent-owned scope, but it does not add much new parameter-specific meaning beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a precise verb and resource: 'Read this agent's failure inbox' and further scopes it to incidents that are currently OPEN on monitors the agent owns, newest first. This clearly distinguishes the tool from broader list_incidents and other siblings.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly says to call this tool at the START of a run, before doing work, and explains its role as the way an agent discovers what broke while it was not running. It also instructs to follow up with add_incident_note, though it does not explicitly state when not to use the tool or name list_incidents as an alternative.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_status_pagesA
Read-onlyIdempotent
Inspect

List the project's status pages: id, slug, title, the monitors on each, visibility, and the public URL of any public page. A status page is how a monitor's health is shown to people who are not in the project — customers, or another team. This is also the read you need before update_status_page, because its check_ids REPLACE the page's monitor set.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already mark it read-only, idempotent, and non-destructive. The description adds meaningful behavioral context beyond that: the returned fields, the public-URL caveat, and the replacement semantics relevant to update_status_page. No contradictions with annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences with each earning its place: output fields, conceptual definition, and critical interaction with update_status_page. The most actionable information is front-loaded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a no-parameter, read-only list tool with no output schema, the description covers purpose, returned fields, the domain concept, and the key usage caution. Nothing essential is missing for an agent to call it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool has zero parameters, so the schema fully covers parameters and the description has no burden to explain them. The baseline of 4 applies because no parameter information could improve the description.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource ('List the project's status pages') and enumerates the exact fields returned: id, slug, title, monitors, visibility, and public URL. This makes the tool's purpose immediately distinguishable from list_monitors and list_incidents.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives a concrete usage scenario: this is the read to perform before update_status_page, because update's check_ids replace the monitor set. It does not explicitly mention when not to use it or name alternative list tools, so it is not a full 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

pause_monitorA
Idempotent
Inspect

Pause a LastPing monitor so it stops alerting (paused=true). The monitor still receives pings but does not alert.

ParametersJSON Schema
NameRequiredDescriptionDefault
idYesMonitor UUID.

TDQS

A3.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already state readOnly=false, idempotent=true, and destructive=false. The description adds valuable behavioral context by explaining the paused=true state, that pings continue to be received, and that alerting ceases—useful beyond the annotations and no contradiction.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short sentences with the key action and effect front-loaded. Every clause earns its place; no filler or redundant restatement of the tool name.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a single-parameter, no-output-schema tool with annotations covering safety and idempotence, the description is largely complete. The only notable gap is not placing pause in relation to the sibling snooze/resume tools, but an agent can still invoke it correctly with the given information.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and the only parameter, id, is already documented as a Monitor UUID. The description does not add extra param detail, so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly identifies the action (pause a LastPing monitor) and the intended effect (stops alerting, paused=true). It distinguishes from destructive actions like delete_monitor, though it doesn't explicitly contrast with snooze_monitor, so it falls just short of full sibling differentiation.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The usage context is implied: use when you want the monitor to keep receiving pings but stop alerting. However, no alternative tools are named, and there is no explicit when-not-to-use guidance such as comparing with snooze_monitor or resume_monitor.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

register_agentAInspect

Register a new autonomous agent in the project's agent registry, returning its id, slug and wire-up instructions in one call — so an agent can go from nothing to reporting in a single conversation. Call this ONCE per autonomous worker, not once per monitor. ATTACHMENT RULE: after registering, attach monitors to this agent by passing the returned agent_id (its id OR its slug) to create_monitor's agent_id parameter. Naming an agent that does not exist is an error (400 UNKNOWN_AGENT) — it is NEVER an implicit create, so re-running this tool with the same name is the only way to get a new agent_id to attach to. Re-registering with the same name is safe: the API derives a stable slug from name and rejects a duplicate slug rather than creating a second row.

ParametersJSON Schema
NameRequiredDescriptionDefault
nameYesHuman-readable agent name, e.g. 'Deploy Bot'. Used to derive the agent's slug.
descriptionNoOptional free-text description of what this agent does. Omit for none.

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations are all false, so the description carries the full burden. It goes beyond basic 'register' semantics by disclosing return values (id, slug, wire-up instructions), duplicate-slug rejection behavior, the 400 UNKNOWN_AGENT error, and the safety of re-registering with the same name. No annotation contradiction exists.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is longer but every sentence earns its place. It front-loads the core purpose and return value, then adds the one-time usage rule, attachment rule, and error semantics in a clear labeled structure. No filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

There is no output schema, so the description explicitly names what is returned (id, slug, wire-up instructions). It also covers the critical workflow context: how to attach monitors, re-registration behavior, and error cases, making it complete for an agent to call this tool correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, providing baseline 3. The description adds valuable extra semantics for the name parameter: it derives a stable slug, duplicate slugs are rejected, and re-registering with the same name is safe. The description parameter is adequately covered by the schema's own description.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states a specific verb and resource: 'Register a new autonomous agent in the project's agent registry, returning its id, slug and wire-up instructions'. It also distinguishes itself from related tools by explicitly noting it is not an implicit create and by providing an attachment rule tied to create_monitor.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides explicit when-to-use guidance: 'Call this ONCE per autonomous worker, not once per monitor.' It also explains the exact relationship with create_monitor: pass the returned agent_id (id or slug) to create_monitor's agent_id parameter, and warns that naming a non-existent agent is an error and never an implicit create.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

resume_monitorA
Idempotent
Inspect

Resume a paused LastPing monitor (paused=false). Alerting resumes on the next missed ping.

ParametersJSON Schema
NameRequiredDescriptionDefault
idYesMonitor UUID.

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already indicate this is a non-read-only, idempotent, non-destructive action. The description adds useful behavioral context by specifying the state transition ('paused=false') and the timing of alerting resumption.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two concise sentences carry the full meaning: the action, the target state, and the behavioral consequence. No filler or redundant detail.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

This is a simple one-parameter mutation with annotations covering safety and idempotency. The description covers the state change and future alerting behavior, so an agent has everything needed to call it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and the only parameter, id, is already documented as 'Monitor UUID.' The description does not need to add parameter meaning and does not add anything beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb ('Resume'), a specific resource ('a paused LastPing monitor'), and the resulting state ('paused=false'). This clearly distinguishes it from siblings like pause_monitor and snooze_monitor.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description makes clear that the tool applies to paused monitors and that alerting resumes on the next missed ping. It does not explicitly discuss alternatives or exclusions, but the usage context is unambiguous.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

revoke_api_keyA
DestructiveIdempotent
Inspect

Permanently revoke an API key. The key stops authenticating immediately. This cannot be undone — a new key must be created to replace it.

ParametersJSON Schema
NameRequiredDescriptionDefault
api_key_idYesUUID of the key to revoke. Get it from list_api_keys.

TDQS

A4.3/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description adds meaningful behavioral detail beyond the annotations: revocation is permanent, takes effect immediately, and cannot be undone. It does not contradict the destructiveHint or idempotentHint annotations, and it clarifies the real-world consequence for the agent.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two crisp sentences with no filler. It front-loads the action and permanence, then immediately covers the behavioral consequence and replacement need.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a single-parameter destructive tool, the description and schema together cover what the tool does, what the argument means, where to find it, and what happens after execution. No output schema is needed to make the call behavior understandable.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, with the schema already explaining that api_key_id is a UUID and where to obtain it. The tool description adds no additional parameter-specific meaning, so the baseline of 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb ('revoke') and resource ('API key'), and clearly conveys the permanent, immediate effect. This distinguishes it from sibling tools like create_api_key and list_api_keys without requiring schema inspection.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is implied: if a key must be permanently invalidated, use this tool. The description notes that a replacement key must be created, which hints at the create_api_key sibling, but it does not explicitly name that alternative or state when not to use this tool.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

set_alert_templateA
DestructiveIdempotent
Inspect

Set or clear a single alert message template on a monitor. The template is validated for allowed variables before saving. Pass an empty string for template to reset that entry to the built-in default. All other existing templates are preserved (read-modify-write). Available variables: {check_name}, {event}, {status}, {cause}, {last_ping}, {schedule}, {incident_url}, {run_url}, {branch}, {commit}, {actor}, {failing_stage}, {duration}, {latency}, {status_code}, {url}, {last_step}, {step_count}, {run_duration}, {body}, {detail}. {failing_stage} is CI-only and provider-dependent: always populated on GitLab; on GitHub only if the repository webhook also subscribes to the workflow_job event; never on Jenkins, whose Notification Plugin payload carries no step detail. {body} is the triggering ping's own text (pings.body_excerpt) — it is how a 'blocked' or 'note' event's reason reaches the alert, and a custom template is the only way to control where in the message it appears.

ParametersJSON Schema
NameRequiredDescriptionDefault
idYesMonitor UUID.
causeNoOptional cause for a per-cause override (e.g. 'silence', 'overrun', 'never_started', 'stalled', 'runaway'). Omit or leave empty for an event-type-wide template.
templateYesTemplate text with {variable} placeholders. Empty string resets to the built-in default.
event_typeYesEvent type: 'down', 'recovery', 'fail', 'every-run', 'success', 'started', 'blocked', 'note'.

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description goes far beyond the annotations. It discloses validation against allowed variables, the reset-to-default behavior for empty strings, the read-modify-write merge behavior that preserves other templates, and detailed provider-dependent caveats for {failing_stage} and {body}. Annotations already include destructiveHint=true and idempotentHint=true, and the description is fully consistent with those traits rather than contradicting them.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is long, but nearly every sentence earns its place by explaining validation, reset semantics, read-modify-write behavior, variable availability, and provider caveats. The main sentence is front-loaded with the core purpose before diving into details. The variable list could arguably be shortened, but it is immediately useful and not redundant.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a mutating tool with no output schema and a moderately complex template parameter, the description covers side effects, concurrency behavior, validation requirements, reset semantics, and important environment-specific variable limitations. There are no significant gaps that would prevent an agent from using the tool correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds substantial value beyond the schema: it enumerates all allowed template variables, explains the semantic meaning of {body} via pings.body_excerpt, and details CI-provider behavior for {failing_stage}. This materially improves the agent's ability to construct a valid template parameter.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb-plus-resource statement: 'Set or clear a single alert message template on a monitor.' It clearly distinguishes this from the read-only sibling get_alert_templates by emphasizing 'set or clear' and 'single' template, so an agent can immediately identify the operation.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives clear operational context: when to pass an empty string, that this is a read-modify-write preserving other templates, and that a custom template is the only way to control where {body} appears. It does not explicitly name an alternative tool such as get_alert_templates for reading, but the contrast is strongly implied and the context is sufficient for selection.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

set_routeA
DestructiveIdempotent
Inspect

Route a monitor's alerts for one event type to a set of destinations (channels). THIS REPLACES THE WHOLE SET for that event type — every destination you leave out stops receiving that event, including ones somebody else configured. CALL get_monitor FIRST and read its routes field: that is the monitor's current routing, and adding a destination means passing the existing ids PLUS the new one. Pass an empty channel_ids to remove all routing for the event. Destinations must be verified and enabled (email destinations must be confirmed first). Use list_destinations for IDs.

ParametersJSON Schema
NameRequiredDescriptionDefault
event_typeYesOne of eight: down (alert opened), recovery (alert cleared), fail (explicit failure ping), every-run (one notification per completed run, success or failure), success (fires only when a run completes successfully), started (fires when a run begins), blocked (an agent reported it is waiting on a human — fires immediately, the moment the ping arrives; this is separate from the 'blocked' INCIDENT that opens later only if the wait outlives blocked_timeout_s, see create_monitor/update_monitor), note (a free-form annotation ping — never itself opens or clears an incident). Prefer down/recovery/fail: they fire only on a state change. every-run, success, started, and note are not state changes and are bounded only by how often the monitor runs (or how often the agent chooses to send them), so they can be very chatty, and none of them is flap-damped. started is the chattiest of the bunch for CI-fed monitors: GitHub maps both the workflow_run 'requested' and 'in_progress' webhook events to a start signal, so a single CI run can emit more than one started event — this was observed in production, where a real run logged two starts seconds apart. every-run, success, started, and note share one separate per-channel rate cap (60/hour by default), so together they can no longer use up the budget that down/fail/recovery/blocked need — but a chatty route on any one of the four can silently suppress its own notifications, and its sibling informational types' notifications, once it exceeds that shared cap. blocked is deliberately NOT in that shared group even though it is agent-reported rather than system-derived: a blocked agent needs a human, so it draws on the protected down/fail/recovery budget instead, precisely so it cannot be starved by chatty every-run/success/started/note traffic. Route informational types to a low-stakes destination, not to the one that pages someone.
monitor_idYesMonitor (check) UUID.
channel_idsNoComma-separated destination (channel) UUIDs to notify. Empty string clears the route.

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare destructiveHint=true and idempotentHint=true, and the description amplifies them with concrete context: the whole set is replaced, destinations configured by others are silently dropped, empty channel_ids clears routing. It even discloses downstream behavioral nuances (rate caps, blocked's protected budget, GitHub double-starts), far exceeding what annotations convey. No contradiction with annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The main description is tightly front-loaded with the most critical fact (whole-set replacement) in caps, followed by prerequisites and edge cases. The event_type parameter text is long (~380 words), but nearly every sentence carries operational knowledge an agent needs to route safely; a small deduction for verbosity in the rate-cap explanation.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a destructive 3-parameter tool with no output schema, the description covers the action, the destructive semantics, preconditions (verified/enabled destinations, email confirmation), how to obtain IDs and current routing, clearing behavior, and deep guidance on event-type selection. Nothing an agent needs to invoke this correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, setting a baseline of 3, but the description adds substantial operational meaning beyond the schema: the event_type parameter is enriched with state-change vs. informational categorization, chatty-event rate-cap grouping, and the blocked-event budget rationale, which materially changes how an agent selects event types. The channel_ids semantics (pass existing IDs plus new one; empty string clears) are also spelled out beyond the schema's literal text.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource: 'Route a monitor's alerts for one event type to a set of destinations (channels).' This distinguishes it from siblings like get_monitor (reads routes), list_destinations (enumerates destinations), and update_monitor (monitor settings), by making the exact scope — one event type, full destination set — explicit.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives explicit workflow directives: 'CALL get_monitor FIRST and read its routes field' and 'Use list_destinations for IDs.' It also warns against the partial-update mental model ('adding a destination means passing the existing ids PLUS the new one'), which functions as when-not-to-use guidance for a destructive replace operation.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

snooze_monitorA
Idempotent
Inspect

Set or clear a maintenance window on a monitor. During the window the monitor will not alert. Provide exactly one of: duration (e.g. '1h', '24h'), until (RFC 3339 timestamp), or clear=true to remove the window.

ParametersJSON Schema
NameRequiredDescriptionDefault
idYesMonitor UUID.
clearNoSet true to remove the active maintenance window.
untilNoRFC 3339 end timestamp. Use this OR duration OR clear.
durationNoGo duration string, e.g. '1h' or '24h'. Use this OR until OR clear.

TDQS

A3.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations indicate this is a mutating, idempotent, non-destructive operation. The description adds useful behavioral context beyond the annotations: during the window, alerts are suppressed, and clear=true removes the window. It does not contradict any annotation.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two concise sentences lead with the primary action, then give the required exclusivity rule and examples. Every sentence adds value, and the structure is easy to parse quickly.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 4-parameter mutation tool with full schema coverage, no output schema, and annotations covering safety and idempotency, the description is essentially complete. The main missing piece is return behavior, but that is not required to invoke the tool correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and each parameter already has a descriptive schema comment. The description reinforces the 'exactly one of' relationship and provides examples for duration, but does not add meaning beyond what the input schema already states.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific action ('Set or clear a maintenance window') on a specific resource ('a monitor') and explains the observable effect ('the monitor will not alert'). It is clear even among siblings like pause_monitor and resume_monitor, though it does not explicitly differentiate itself from those alternatives.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives clear operational constraints: 'Provide exactly one of' duration, until, or clear=true. However, it does not explain when to choose snooze_monitor over related sibling tools such as pause_monitor or resume_monitor, leaving the selection context mostly implied.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

test_destinationAInspect

Send something through a destination right now, to move it from 'created' to 'known to work'. By default it delivers a synthetic 'LastPing test alert' immediately — use that after create_destination to confirm the credentials are right. For an EMAIL destination that is still unverified, a test alert is not what you need: an unverified email cannot be attached to a route at all, and no amount of testing changes that. Pass resend_verification=true instead to re-send the confirmation link a human must click. That is the tool to reach for when create_destination reported UNVERIFIED and the confirmation email never arrived or has expired.

ParametersJSON Schema
NameRequiredDescriptionDefault
idYesDestination (channel) UUID. Get it from list_destinations or create_destination.
resend_verificationNoSet true to re-send the email confirmation link INSTEAD of a test alert. Email destinations only — any other kind returns 400. Safe to repeat, and idempotent: on an already-verified destination it reports verified and sends nothing rather than mailing the user again.

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the annotations, the description discloses the default synthetic LastPing alert behavior, the 400 error for non-email destinations with resend_verification, and the idempotent verified-state behavior. The idempotentHint=false annotation is not contradicted because the default test-alert path is not idempotent, while the description specifically limits idempotency to resend_verification on verified destinations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is dense but every sentence carries decision-relevant information, and the core action is front-loaded in the first sentence. The length is justified by the two-mode behavior (test alert vs. resend verification) that the agent must distinguish.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool with two modes, no output schema, and a closely related create_destination sibling, the description covers invocation, mode selection, error conditions, and repeat safety. An agent can decide whether to call this tool and with which flag without needing additional context.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% and the schema already documents both parameters, including id source, the instead-of-test-alert behavior, email-only restriction, 400 error, and idempotency. The description repeats this semantic context but does not add new parameter-level meaning beyond the schema, so the baseline score of 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific action and resource ('send something through a destination') and the intended outcome ('move it from created to known to work'). It distinguishes this from create_destination and other destination siblings by positioning it as the post-creation verification step.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It explicitly tells when to use the default test alert ('after create_destination to confirm the credentials are right') and when to use resend_verification instead (when create_destination reported UNVERIFIED and the confirmation email never arrived or expired). It also warns that a test alert is useless for unverified email destinations, giving a clear exclusion.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

update_agentA
DestructiveIdempotent
Inspect

Update an existing LastPing agent's name/description by UUID using merge-patch semantics: only the fields you supply are changed, and any field you omit keeps its current stored value. slug is derived from name at creation and is immutable — this can rename the agent's display name, but never its slug, so anything that already references it by slug (including monitors attached via agent_id) keeps working.

ParametersJSON Schema
NameRequiredDescriptionDefault
idYesAgent UUID (from register_agent or list_agents).
nameYesHuman-readable agent name, e.g. 'Deploy Bot'.
descriptionNoFree-text description of what this agent does. Omit to leave the agent's current description unchanged — THIS IS THE DEFAULT AND SAFE CHOICE for a name-only rename. Pass an explicit empty string to clear an existing description back to none.

TDQS

A4.5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description goes well beyond the annotations, explaining exactly what merge-patch semantics mean, that omitted fields retain their current value, and that the slug is immutable so existing references (including monitors attached via agent_id) keep working. This meaningfully enriches the idempotentHint and destructiveHint annotations and sets accurate expectations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two well-structured sentences with no filler. The core operation is front-loaded, and the second sentence adds critical behavioral nuance about slug immutability. Every word contributes to correct invocation.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a small 3-parameter update operation with no output schema, the description covers the important caveats: merge-patch semantics, the safe default for name-only renames, how to clear description, and why the slug remains stable. Nothing critical is missing for an agent to call this correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents id, name, and description with helpful examples. The description reinforces the merge-patch behavior but does not add much new per-parameter meaning beyond what the schema provides. Baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description names a specific verb ('Update'), a specific resource ('existing LastPing agent'), and the target fields ('name/description by UUID'). It is immediately distinguishable from sibling tools like register_agent, delete_agent, and get_agent.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description clearly establishes when to use this tool: to modify an existing agent's name or description. It also gives practical usage guidance on merge-patch behavior (omit to keep, empty string to clear) and notes slug immutability. It does not explicitly name alternatives like register_agent for creation, but the context is clear enough.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

update_destinationA
DestructiveIdempotent
Inspect

Update a notification destination's name and/or config in place. Only the fields you pass are changed. The destination kind cannot be changed — delete and recreate instead. Changing an email destination's address resets verification and sends a new confirmation email.

ParametersJSON Schema
NameRequiredDescriptionDefault
nameNoNew human-readable label. Omit to leave unchanged.
configNoReplacement config for the destination's existing kind — one of webhook, telegram, discord, slack, ntfy, pushover, msteams, googlechat, email. Shape must match the kind: {"url":…,"secret":…} for webhook, {"bot_token":…,"chat_id":…} for telegram, {"webhook_url":…} for slack/discord/msteams/googlechat, {"topic_url":…} for ntfy, {"token":…,"user_key":…} for pushover, {"address":…} for email. Omit to leave unchanged.
destination_idYesUUID of the destination to update. Get it from list_destinations.

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the annotations, the description discloses important behavioral details: the operation is in-place and partial, the kind is immutable, and changing an email address resets verification and triggers a new confirmation email. This adds meaningful side-effect context that the annotations alone do not provide.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three concise sentences deliver the core action, the key limitation, and the most important side effect. Every sentence earns its place and the most critical information is front-loaded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a mutating tool with a nested config object and no output schema, the description plus the detailed schema provides all necessary information for an agent to call it correctly: what updates, what cannot change, how to handle config, and the email-specific consequence.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema already documents all parameters with high coverage, including detailed config shapes, so the baseline is 3. The description adds value by explaining that only passed fields are changed and by highlighting the email verification reset, which affects the config parameter's semantics.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the verb and resource: 'Update a notification destination's name and/or config in place.' It also explicitly distinguishes itself from create/delete operations by noting that the destination kind cannot be changed and must be deleted and recreated instead.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly explains when this tool should not be used: changing the destination kind requires 'delete and recreate instead.' It also clarifies partial-update semantics with 'Only the fields you pass are changed,' which guides an agent on how to construct a correct call.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

update_monitorA
DestructiveIdempotent
Inspect

Update an existing LastPing monitor's schedule/config by UUID using merge-patch semantics: only the fields you supply are changed, and any field you omit keeps its current stored value. If supplied, tags replaces the full tag set on the monitor (not merged). slug is immutable and cannot be changed. This is also the tool that sets a monitor's OUTPUT ASSERTIONS (the assertions argument) — conditions the ping body of a successful run must satisfy, which is how a job that exits zero having done nothing gets caught — and its METRIC GUARDS (the guards argument) — ceilings on a number the job reports, which is how an agent that loops and burns money gets caught. Like tags, assertions and guards each REPLACE the full set. ci_provider is NOT patchable — it is immutable once set, so only its ci_workflow/ci_branch filters can be changed here; rebinding a monitor to a different CI system means deleting and recreating it.

ParametersJSON Schema
NameRequiredDescriptionDefault
idYesMonitor UUID.
tzNoIANA timezone for cron evaluation.
nameYesHuman-readable monitor name.
tagsNoComma-separated labels to set on this monitor, e.g. 'agent:claude,env:prod'. Replaces existing tags. Max 20 tags, each max 50 chars.
guardsNoMetric guards: CEILINGS on a number the job reports about itself, checked on every ping. An assertion catches a run that did nothing; a guard catches the opposite — an agent that loops, retries and burns money. Each guard reads one number out of the ping body at a dotted path, rolls it up across a trailing window, and opens an incident with cause 'runaway' when the total EXCEEDS the ceiling (equal does not trip). Supply a JSON ARRAY as a string, e.g. '[{"name":"daily spend","path":"cost.usd","window_s":86400,"ceiling":50,"aggregation":"sum"}]'. REPLACE-THE-SET: the array you send becomes the monitor's complete guard set — it is NOT merged with what is already there. Omit the argument entirely to leave the current guards untouched; pass '[]' to remove all of them. Fields per entry, all required: name (appears on the incident, and is the only thing that tells a tripped guard apart from the fixed pings-per-hour runaway ceiling), path (DOTTED path into the ping body parsed as JSON — 'cost.usd'; the query syntax of a real JSONPath library ('[', '*', '$') is rejected, exactly as for an assertion's path), window_s (trailing window in seconds), ceiling (number), aggregation (one of 'sum', 'max', 'avg'). Pings whose body is missing, is not JSON, or carries nothing numeric at that path are SKIPPED, not counted as zero — so a `start` ping never drags an average down. At most 5 guards per monitor, and window_s at most 604800 seconds (7 days). Both caps are cost, not policy: a guard re-aggregates every ping body in its window on every ping, so the per-ping work is linear in BOTH the window and the number of guards (measured: 4.2 ms/ping at a 1-hour window, 390 ms/ping at 30 days). A window longer than the 90-day ping retention would also aggregate over already-pruned rows and quietly under-report. A malformed entry is rejected before anything is written and names the offending guard.
grace_sNoGrace period in seconds.
agent_idNoAttach this monitor to an agent from the registry, by the agent's id OR its slug (both are returned by register_agent). Omit for a monitor with no owning agent. Naming an agent that does not exist is an error — 400 UNKNOWN_AGENT — it is NEVER created implicitly; call register_agent first to get a valid agent_id. Omit to leave the monitor's current attachment (or lack of one) unchanged.
period_sNoPing interval in seconds (for schedule_kind='simple').
ci_branchNoCI filter: only count runs on this branch, e.g. 'main'. Requires ci_provider. WITHOUT IT a run on ANY branch — a feature branch, a fork's pull request — reports to this monitor, so somebody else's broken branch marks your monitor down. Set it to the branch whose health you actually care about, which is almost always the default branch. Omit to leave the current filter unchanged; pass an explicit JSON null to remove it. An EMPTY STRING also leaves it unchanged — that is a deliberate API compatibility rule, not a bug, so an empty string cannot be used to clear the filter.
cron_exprNo5-field cron expression (for schedule_kind='cron').
probe_urlNohttp monitors only: the absolute http/https URL to probe. Required when monitor_type='http'. The host is resolved at write time and rejected if it resolves only to private/link-local addresses. Omit to leave unchanged.
assertionsNoOutput assertions: conditions the ping BODY of a successful run must satisfy, checked on every success ping. This is how you catch the job that exits zero having done nothing — a backup that wrote no rows, an export that produced an empty file. When an assertion fails, the success ping opens an incident with cause 'assertion' naming the assertion that did not hold, exactly as a real failure would. Supply a JSON ARRAY as a string, e.g. '[{"name":"rows written","kind":"json_path","path":"result.rows_processed","op":"gt","value":"0"}]'. REPLACE-THE-SET: the array you send becomes the monitor's complete assertion set — it is NOT merged with what is already there. Omit the argument entirely to leave the current assertions untouched; pass '[]' to remove all of them. Fields per entry: name (required, appears in the alert), kind (required), value, path, op. kind is one of 'contains' (body contains value as a substring), 'not_contains' (body does not contain it), 'matches' (body matches value as a Go RE2 regexp, max 1000 bytes), or 'json_path' (parse the body as JSON, read the value at path, compare it against value with op). contains/not_contains/matches require value; json_path requires path and op and ignores them otherwise. path is a DOTTED path only ('a.b.c') — the query syntax of a real JSONPath library ('[', '*', '$') is rejected. op is one of 'eq', 'ne', 'gt', 'gte', 'lt', 'lte'. Comparison rule for json_path: when BOTH the value read from the body and the value you supplied parse as numbers the comparison is numeric, otherwise both sides are compared as strings — so with op 'gt', value '3' beats '12.5' lexically but loses numerically, and 'rows_processed gt 0' means what it looks like it means. At most 20 assertions per monitor. A malformed entry (uncompilable regexp, a path carrying query syntax, an unknown kind or op) is rejected before anything is written and names the offending assertion.
ci_workflowNoCI filter: only count runs of the workflow / pipeline / job with this exact name. Requires ci_provider. WITHOUT IT, EVERY workflow in the repository reports to this monitor — so one unrelated failing workflow opens an incident against a job that is perfectly healthy, and a green run of a different workflow clears an incident the real job never recovered from. Set it whenever the repository has more than one workflow. Omit to leave the current filter unchanged; pass an explicit JSON null to remove it. An EMPTY STRING also leaves it unchanged — that is a deliberate API compatibility rule, not a bug, so an empty string cannot be used to clear the filter.
monitor_fromNoDORMANT UNTIL: an RFC 3339 timestamp before which no deadline is computed and no incident can open — the monitor is fully configured but not yet armed. Use it when you provision ahead of the work: a monitor for a job that does not start running until next Monday is otherwise 'late' from the moment you create it, which is a false alert on day one. The first-run deadline is seeded as monitor_from + grace_s. Default: unset, meaning deadlines start immediately. Example: '2026-01-01T00:00:00Z'. Omit to leave the monitor's current value unchanged.
probe_methodNohttp monitors only: the HTTP method the probe sends. One of 'GET', 'HEAD', 'POST'. Default 'GET'. Use 'HEAD' for a cheap liveness check when the body does not matter — but note it returns no body, so probe_expected_body cannot match anything. Omit to leave unchanged.
max_runtime_sNoMaximum seconds a single run may take before it is reported overdue (the 'overrun' rule), measured from the run's start ping. Omit to fall back to grace_s. This is how a long job avoids being flagged overdue while still being detected quickly if it goes silent: e.g. grace_s=600 with max_runtime_s=14400 alerts 10 minutes after a missed ping but tolerates a 4-hour run. It replaces grace_s for the overrun deadline ONLY — the silence rule and the first-run deadline still use grace_s. Range 60-31536000. Not supported on http monitors: a probe has no start/success pair, so the overrun rule can never fire and the API returns 400 MAX_RUNTIME_NOT_SUPPORTED (use probe_timeout_s to bound a single probe). Omit to leave the monitor's current value unchanged; pass 0 to clear it and fall back to grace_s.
schedule_kindNo'simple', 'cron', or 'on_demand'. 'on_demand' means no cadence at all: no period_s, no cron_expr — the API returns 400 if either is supplied — and, by default, NO ABSENCE DEADLINES ARE ARMED BETWEEN RUNS. What this trades away: nothing tells you if the agent is never invoked again; silence between runs is invisible unless you opt in to expect_every_s. What it buys: a healthy agent that nobody happens to invoke for a week never generates a false 'late' or 'down' for simply not having been asked to run. Only run-scoped detection still applies once a run starts — max_runtime_s (overrun), step_timeout_s (stall), blocked_timeout_s (stuck on a human) — because those are anchored to a run's own start ping, not to a cadence. IMPORTANT: if you would be alarmed to find this agent silent for hours, set expect_every_s as well — it is the silence floor, and it is the only thing that makes an on_demand monitor detect absence at all. Choose 'simple'/'cron' when the agent is supposed to run on a cadence; choose 'on_demand' when invocation is inherently irregular and a quiet stretch between runs is expected, not a symptom.
expect_every_sNoSILENCE FLOOR in seconds: open a 'silence' incident if NO ping of any kind — success, start, fail, step — has arrived within this window, regardless of the schedule. It is anchored on the monitor's last activity, not on a cadence, which is what makes it the ONLY absence rule an 'on_demand' monitor can have: that schedule_kind arms nothing between runs, so without this field an on_demand monitor reads 'up' forever no matter how long the agent stays dark. Set it on any on_demand agent monitor you would be alarmed to find silent — that is what it is for. It does NOT fire mid-run: while a run is in flight (a start ping is outstanding) the floor stands down entirely and the run clock owns detection (max_runtime_s, step_timeout_s), so a legitimate 4-hour run that reports nothing is still not an incident. A 'blocked' ping also pauses it, bounded by blocked_timeout_s. On 'simple'/'cron' monitors it is a backstop rather than the main rule: it joins the existing deadline as whichever is SOONER, so it can tighten detection under a long cadence (a daily cron has a ~25-hour blind window) but can never loosen it. Default: unset, which means no floor and is exactly how every monitor behaved before this field existed. Range 60-31536000. Accepted on every monitor_type and every schedule_kind. Omit to leave the monitor's current value unchanged; pass 0 to clear it and turn the silence floor off.
step_timeout_sNoProgress budget in seconds: how long an armed run may go without reporting a step before a 'stalled' incident opens (the stall rule). The clock is anchored on the LATER of the run's start ping and its most recent step, so a run that wedges before its first step is caught too. Reach for this when 'still running' and 'still making progress' are different things — a long agent loop, a multi-stage pipeline, a migration. max_runtime_s alone tells you nothing until the whole budget expires; step_timeout_s=300 on a 4-hour budget tells you within five minutes, and names the last step that reported. To use it the run must report steps: call get_ping_instructions and use curl_step (POST <ping_url>/step?rid=<run-id>&step=<name>). A monitor with step_timeout_s set whose job never reports a step will open a stalled incident on EVERY run — set the field and instrument the job in the same change. Default: unset, which disables stall detection entirely; a monitor that sets nothing behaves exactly as it did before this field existed. Range 10-86400. Two constraints. (1) It must be strictly LESS than the effective run budget, COALESCE(max_runtime_s, grace_s), or the API returns 400 STEP_TIMEOUT_EXCEEDS_BUDGET — at or above the budget the run overruns first, so the stall rule could never fire. (2) Not supported on http monitors: a probe never arms a run and has no /step endpoint to call, so the API returns 400 STEP_TIMEOUT_NOT_SUPPORTED. A step resets the stall clock ONLY — it never extends max_runtime_s, so an agent that reports progress forever still overruns. Omit to leave the monitor's current value unchanged; pass 0 to clear it and disable stall detection.
probe_timeout_sNohttp monitors only: how many seconds a single probe may take before it counts as a failure. Range 1-30, default 10. This is the http equivalent of max_runtime_s, which http monitors reject: it is the only way to say 'answering, but far too slowly to be healthy'. Omit to leave unchanged.
runaway_ceilingNoPING-RATE CEILING: the maximum number of pings this monitor may receive in a rolling one-hour window. Exceeding it opens a 'runaway' incident. This is the rule that catches a job or agent stuck in a LOOP — the failure every other rule misses, because a looping agent is pinging enthusiastically and therefore reads 'up' the whole time it is burning tokens or money. Set it a little above the monitor's real cadence: a job that runs every 15 minutes sends about 4 pings/hour, so 20 absorbs retries and still catches a loop. It is RATE-based, so failure_threshold does not gate it and neither does any run budget. Default: unset, which disables the runaway rule entirely. Omit to leave the monitor's current value unchanged; pass 0 to clear it and turn the runaway rule off.
notify_min_run_sNoNOTIFICATION DURATION FLOOR in seconds: a run SHORTER than this does not produce an INFO-CLASS notification (success, started, every-run, note). This exists for exactly one problem: on an agent monitor, one run is one task you asked for, so asking the agent 'what's 2+2' produces a start and a success notification exactly like a 56-minute deploy does. If you have routed success/started/every-run/note to a destination, you WILL be paged for trivial runs unless you set this. IT NEVER SUPPRESSES A FAILURE. down, fail, recovery and blocked are alert-class and are never affected by this field, however short the run — a run that failed in two seconds is exactly what you need to hear about, and this field cannot silence that, structurally, no matter how it is set. It also never suppresses 'started': a run's duration does not exist yet the moment it begins, so started is always reported regardless of this floor. And it never suppresses an event whose duration could not be measured at all (e.g. a bare success with no preceding start ping) — an unknown duration always means 'notify', never 'suppress'. Default: unset, which means no floor and is exactly how every monitor behaved before this field existed. Range 60-31536000. Not supported on http monitors: an http probe has no start/success pair, so its run duration is never measured and the floor could never apply (the API returns 400 NOTIFY_MIN_RUN_NOT_SUPPORTED). Omit to leave the monitor's current value unchanged; pass 0 to clear it and turn the notification duration floor off.
probe_interval_sNohttp monitors only: how often to probe, in seconds. Required when monitor_type='http'. Range 30-86400. Omit to leave unchanged.
blocked_timeout_sNoMaximum seconds a run may sit in the 'blocked' state (an agent reported it is waiting on a human) before a 'blocked' incident opens. UNSET DOES NOT MEAN WAIT FOREVER: omitting this does not disable the timeout, it falls back to the default, which is 24 HOURS — an agent still blocked 24 hours after reporting so, with this field never set, gets a 'blocked' incident regardless. Lower it to be paged sooner when a stuck approval is urgent; raise it for work that legitimately waits on a human for longer than a day. This is distinct from the immediate, non-incident 'blocked' notification a route on the 'blocked' event type delivers the moment the agent reports it (see set_route) — that fires right away; this field governs the separate incident that opens only if the wait outlives the timeout. Accepted on every monitor_type: unlike max_runtime_s/step_timeout_s it has no run-scoped precondition an http monitor could fail, so there is nothing to reject. Omit to leave the monitor's current value unchanged; pass 0 to clear it and fall back to the 24h default.
failure_thresholdNoNumber of consecutive failures required before an incident opens. Default 1 (open on the very first failure). This is how you stop a single transient blip from paging someone: set 2-5 on a job that fails occasionally for reasons that resolve themselves, and no incident opens until that many runs in a row have failed. Any success resets the count to zero. It gates the 'fail' cause ONLY — silence (a missed ping), overrun, never_started and runaway are time- or rate-based, so a consecutive count means nothing for them and they are never delayed by it. Range 1-100. Omit to leave the monitor's current threshold unchanged.
probe_expected_bodyNohttp monitors only: a substring that MUST appear in the response body for the probe to count as healthy. THIS IS THE DIFFERENCE BETWEEN 'the server answered' AND 'the app works': a broken app that renders an error page still returns 200, passes a status-only check, and leaves the monitor green. Match on something only a healthy response contains, e.g. '"status":"ok"'. Substring match, not a regex, and case-sensitive. Default: empty, meaning the body is not inspected at all. Omit to leave unchanged; pass an explicit JSON null to stop inspecting the body. An empty string leaves it unchanged, so it cannot be cleared that way.
probe_expected_statusNohttp monitors only: the EXACT HTTP status code that counts as healthy. Default 200; any other code fails the probe. Set it when the healthy answer is not 200 — 204 for a no-content health endpoint, or 301 when what you are checking is that a redirect still exists (pair that with probe_follow_redirects=false, or the probe will follow it and see the destination's status instead). Omit to leave unchanged.
probe_follow_redirectsNohttp monitors only: whether the probe follows 3xx redirects. Default false. Leaving it false is usually what you want: the redirect itself is then compared against probe_expected_status like any other response, so a site that starts redirecting to a login wall, a parking page or an outage notice is CAUGHT rather than silently followed to a healthy-looking 200. Set true only when the URL you are checking is legitimately a redirect to the thing you actually care about. Omit to leave unchanged; pass false to turn following back off.

TDQS

A4.5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The annotations (readOnlyHint=false, idempotentHint=true, destructiveHint=true) already frame this as a read-write, idempotent, potentially destructive update. The description goes well beyond them: merge-patch semantics, replace-the-set behavior for tags/assertions/guards, slug and ci_provider immutability, and the delete/recreate consequence. It even explains WHY the destructive capability exists (guards catch looping agents burning money), which is exactly the behavioral context that changes how an agent exercises the tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single ~170-word paragraph with no wasted sentences: every clause (merge-patch, tags replacement, slug immutability, assertions/guards role, ci_provider immutability) is load-bearing for a 28-parameter tool, and the core semantics are front-loaded. It loses the top score only because it is one dense unbroken block of text with no bullets or paragraph breaks, which taxes scannability.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 28-parameter mutation tool with no output schema and no auth/rate-limit annotations, the description covers the operation's semantics thoroughly: what changes, what replaces wholesale, what is immutable, and what the delete/recreate fallback is. The main gap is that it never states the return value or any permission/rate-limit expectations — with no output schema present, one line on what the call returns would make it fully self-sufficient.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the per-parameter burden is already carried by the schema — baseline 3 applies. The description adds a layer the schema cannot express as a whole: global merge-patch semantics ('any field you omit keeps its current stored value'), the replace-the-set rule spanning tags/assertions/guards, and the immutability of slug and ci_provider — facts about fields that do not even appear as parameters in the schema. That is meaningful additive value, while per-parameter details are correctly left to the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource — 'Update an existing LastPing monitor's schedule/config by UUID' — and layers on the defining semantic (merge-patch) that separates it from siblings like create_monitor, delete_monitor, pause_monitor, and resume_monitor. It also advertises two responsibilities an agent would not guess from the name alone: this is the tool that sets output assertions and metric guards, with explicit 'how a job that exits zero... gets caught' motivation.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides clear operational context plus an explicit when-not: 'rebinding a monitor to a different CI system means deleting and recreating it' because ci_provider is immutable, which routes the agent to the delete/create sibling pair. It also scopes what CAN be changed here ('only its ci_workflow/ci_branch filters can be changed'), but it never systematically enumerates when to prefer create, pause, resume, or snooze over this tool, so it stops short of a 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

update_status_pageA
DestructiveIdempotent
Inspect

Update a status page's title, slug, visibility, or the set of monitors on it. Only the arguments you pass are changed; anything you omit keeps its current value (this tool reads the page first and merges, so omitting check_ids can never blank the page). check_ids, when you DO pass it, REPLACES the whole monitor set — to add one monitor, pass the existing ids plus the new one, which list_status_pages gives you. Changing the slug changes the public URL and BREAKS any link already shared.

ParametersJSON Schema
NameRequiredDescriptionDefault
idYesStatus page UUID, from list_status_pages.
slugNoNew URL slug. Omit to leave unchanged — which is almost always right, because changing it breaks every link already handed out. Same format rules and same global uniqueness as on create; a taken slug returns 409.
titleNoNew page title. Omit to leave unchanged.
check_idsNoComma-separated monitor UUIDs to show on the page, in no particular order. Get them from list_monitors. Every id must belong to this project — an unknown or cross-project id returns 400 and nothing is saved. An empty value is legal and produces a page with no monitors on it. REPLACES the page's whole monitor set. Omit to leave the current set alone.
visibilityNo'private' (default) or 'public'. 'public' means the page is served at a guessable-free but UNAUTHENTICATED URL: anyone with the link sees the title, the name of every monitor on it, and its up/down history. Monitor names are frequently internal ('billing-reconciler', 'acme-corp-nightly-sync'), so treat this as publishing them. Choose 'private' unless the user has actually asked for a page other people can see. The free tier allows exactly ONE public page per project; a second returns 403. Omit to leave unchanged. Switching a page from private to public publishes every monitor name already on it.

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Discloses merge behavior ('reads the page first and merges'), replace semantics for check_ids, destructive slug changes that break public links, and privacy consequences of visibility='public'. This adds substantial context beyond the annotations and aligns with destructiveHint=true.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is front-loaded with the core update behavior, and every sentence contributes a distinct rule or warning: partial updates, replacement semantics, link breakage, and public visibility risks. It is appropriately detailed for the tool's complexity.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a five-parameter tool with destructive effects and no output schema, the description covers merge behavior, replacement, error conditions, data sources, and privacy caveats. An agent has enough context to select and invoke this tool correctly without additional documentation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3. The description adds cross-parameter insight: how to add one monitor by combining existing ids from list_status_pages with the new id, and that omitting check_ids can never blank the page. This meaningfully increases utility beyond the schema field descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States the operation explicitly: update a status page's title, slug, visibility, or monitor set. Names the resource and specific fields, and is clearly distinct from create_status_page, delete_status_page, and update_monitor.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides strong usage context: only pass fields you want to change, omit to preserve current values, and pass existing ids plus a new monitor to avoid blanking the page. It does not explicitly name create/delete alternatives, but the partial-update and replacement semantics make when to use this tool clear.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.

  1. 36 tool updates
    • First observedadd_incident_note
    • First observedcreate_api_key
    • First observedcreate_destination
    • First observedcreate_monitor
    • First observedcreate_status_page
    • First observeddeclare_run_expectations
    • First observeddelete_agent
    • First observeddelete_destination
    • First observeddelete_monitor
    • First observeddelete_status_page
    • First observeddiscover_monitors_reconcile
    • First observedexport_terraform
    • First observedget_agent
    • First observedget_alert_templates
    • First observedget_monitor
    • First observedget_ping_instructions
    • First observedget_run_history
    • First observedlist_agents
    • First observedlist_api_keys
    • First observedlist_destinations
    • First observedlist_incidents
    • First observedlist_monitors
    • First observedlist_open_incidents
    • First observedlist_status_pages
    • First observedpause_monitor
    • First observedregister_agent
    • First observedresume_monitor
    • First observedrevoke_api_key
    • First observedset_alert_template
    • First observedset_route
    • First observedsnooze_monitor
    • First observedtest_destination
    • First observedupdate_agent
    • First observedupdate_destination
    • First observedupdate_monitor
    • First observedupdate_status_page

TDQS

A4/5.0
Disambiguation4/5

Most tools map cleanly to a distinct resource+action, so an agent can usually pick the right one. A few boundaries invite confusion: create_monitor also updates by slug, pause_monitor and snooze_monitor both suppress alerting, and list_incidents/list_open_incidents are easy to mix.

Naming Consistency4/5

The overwhelming pattern is verb_noun snake_case (create_monitor, update_monitor, delete_monitor, list_agents), which is highly predictable. The main outlier is discover_monitors_reconcile, which inverts the expected verb-object order and adds a trailing verb, plus minor singular/plural asymmetries like set_alert_template vs get_alert_templates.

Tool Count2/5

36 tools is well beyond the practical surface for a monitoring server; even with eight resource families, the count falls into the 'too many' range and makes tool selection harder. A leaner set of roughly 15-20 tools covering the same domain would be more coherent.

Completeness4/5

The set covers full CRUD for monitors, agents, destinations, status pages, and API keys, plus routing, alert templates, run history, incident notes, Terraform export, and discovery reconciliation. Minor gaps remain—no direct read for incident notes, no manual incident close/acknowledge, and no singular get for every resource—but agents can work around these with existing read tools.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    A
    maintenance
    Runtime governance for AI-agent fleets that continuously monitors agent health, confidence, and behavior through check-ins, and returns verdicts to enable self-correction before failures occur.
    4
    Apache 2.0
  • F
    license
    Not graded
    quality
    A
    maintenance
    Provides real-time monitoring of AI agents, context, usage limits, workflows, files, Git, tests, builds, errors, secrets, and model-economy advice for tools like Claude Code, Codex, and Cursor, with 30 MCP tools for comprehensive observability.
    1
    -

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/tp322d/lastping-app'

If you have feedback or need assistance with the MCP directory API, please join our Discord server