fettle-mcp
fettle-mcp is an MCP server that lets an AI assistant drive Fettle uptime monitoring — managing monitors, heartbeats, incidents, maintenance windows, tags, and status pages, and reading uptime/response-time data — through 49 tools over stdio or remote HTTP.
Monitors — list/filter and inspect them, probe a target before creating one, create (single or bulk up to 100), update settings (single or bulk), pause/resume (single or bulk), soft-delete, force a check now, and fetch the exposed-ports preset.
Results & uptime — uptime summary over 24h/7d/30d, per-day uptime, average response time by region, and individual check results (region, status code, error).
Incidents — list and read incidents (cause, alert attempts), and acknowledge an open one to stop repeat notifications.
Heartbeats — list, read, create, update, pause, resume, and delete cron/dead-man's-switch monitors, including their ping URLs.
Maintenance windows — list windows or those active now, read one with upcoming occurrences, preview a schedule, and create/update/delete one-time or recurring (iCal RRULE) windows scoped to the org or specific monitors.
Tags — list tags with usage counts, add/remove tags across up to 300 monitors at once, and rename or delete a tag everywhere.
Status pages — list and read pages and their incidents, post a new incident or an update (emails subscribers), rename an incident, or delete one.
Organization & platform — read plan limits and usage, list notification channels, and list available check regions.
Access model — read-scope keys can call read tools; write-scope keys are needed for any change (and for the read-only
preview_maintenance_window/check_target); only the fivedelete_*tools are destructive, and calls share the org's REST API rate budget.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@fettle-mcpadd an HTTP monitor for https://api.acme.dev, check every minute"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
fettle-mcp
Website: fettle.sh · MCP docs: fettle.sh/docs/mcp · Dashboard: dashboard.fettle.sh · Support: support@fettle.sh
MCP server for Fettle — uptime monitoring you can drive from Claude Code, Codex, Claude Desktop, Cursor, Windsurf or anything else that speaks the Model Context Protocol.
Ask your assistant to create a monitor, look up why one went down, acknowledge an incident or pause checks before a deploy — it calls the same public API you would.
"Add an HTTP monitor for https://api.acme.dev, check it every 5 minutes from Europe."
"Which of my monitors had incidents this week?"
"Pause the checkout monitor — we're deploying for the next 20 minutes."In the official MCP registry this
server is sh.fettle/mcp — one entry covering both channels, for clients that
install from the registry rather than from a hand-edited config file.
Requirements
Node.js 20 or newer
A Fettle account and an API key (Settings → API Keys at https://fettle.sh)
An API key belongs to one organization and carries either read or write scope. Read-scope keys can list and inspect; the write tools below need a write-scope key.
Related MCP server: IonHour MCP Server
Install
There is nothing to install — MCP clients run the package with npx on demand.
Add one entry to your client's config and restart it.
Claude Code
claude mcp add fettle --env FETTLE_API_KEY=fettle_your_key_here -- npx -y fettle-mcpCodex
codex mcp add fettle --env FETTLE_API_KEY=fettle_your_key_here -- npx -y fettle-mcpOr by hand in ~/.codex/config.toml (.codex/config.toml for one trusted
project):
[mcp_servers.fettle]
command = "npx"
args = ["-y", "fettle-mcp"]
[mcp_servers.fettle.env]
FETTLE_API_KEY = "fettle_your_key_here"Claude Desktop
~/Library/Application Support/Claude/claude_desktop_config.json on macOS,
%APPDATA%\Claude\claude_desktop_config.json on Windows:
{
"mcpServers": {
"fettle": {
"command": "npx",
"args": ["-y", "fettle-mcp"],
"env": { "FETTLE_API_KEY": "fettle_your_key_here" }
}
}
}Cursor
~/.cursor/mcp.json (global) or .cursor/mcp.json (per project):
{
"mcpServers": {
"fettle": {
"command": "npx",
"args": ["-y", "fettle-mcp"],
"env": { "FETTLE_API_KEY": "fettle_your_key_here" }
}
}
}Windsurf
~/.codeium/windsurf/mcp_config.json:
{
"mcpServers": {
"fettle": {
"command": "npx",
"args": ["-y", "fettle-mcp"],
"env": { "FETTLE_API_KEY": "fettle_your_key_here" }
}
}
}Configuration
Variable | Required | Default | What it does |
| yes | — | Your API key. The server refuses to start without it. |
| no |
| Point the server at a different API. You will not normally set this. |
| no |
| How long one tool call may take before it is abandoned. |
Tools
49 tools, grouped by what they work on. Read-scope keys can call the read ones; everything marked write needs a write-scope key.
Every tool carries the MCP hints readOnlyHint, destructiveHint, idempotentHint and openWorldHint, so a client can tell reads from changes without parsing names and ask for confirmation only where it matters. Only the five delete_* tools are destructive. preview_maintenance_window and check_target are marked read-only although they need a write-scope key: they change nothing. check_now and check_target reach the target host, so they are open-world.
Every tool whose result is a JSON object declares an outputSchema and returns the result as structuredContent as well as text, so a client can read typed fields instead of parsing the text. The four exceptions return the text only: list_monitors (its compact rows) and the three tools whose result is a list — list_active_maintenance, preview_maintenance_window and list_channels.
Monitors
Tool | Scope | What it does |
| read | List monitors compactly (status, target, tags, SSL expiry), filtered by type, status, tags. |
| read | Read one monitor's full configuration and current status by id. |
| write | Probe a target once from one region before creating a monitor for it. |
| write | Create a monitor that checks a URL, host or port on a schedule. |
| write | Create up to 100 monitors in one call — all of them or none. |
| write | Change an existing monitor's settings. |
| write | Set the same interval, regions, channels or thresholds on up to 100 monitors, all or nothing. |
| write | Stop checking a monitor without deleting it — use before planned downtime. |
| write | Pause up to 100 monitors in one call, all or nothing. |
| write | Resume checks on a paused monitor. |
| write | Resume up to 100 paused monitors in one call, all or nothing. |
| write | Soft-delete a monitor: it stops being checked and leaves the monitor list. |
| write | Re-arm a monitor to run on the next scheduler tick instead of waiting out its interval. |
| read | Database and admin ports that should not be reachable from the internet. |
Results and uptime
Tool | Scope | What it does |
| read | Uptime, average response time and incident counts over 24h / 7d / 30d at once. |
| read | A monitor's uptime for each UTC day, oldest first. |
| read | A monitor's average response time over 24h, 7d or 30d, one series per region. |
| read | Individual check results of a monitor, newest first, filtered by region, status or period. |
Incidents
Tool | Scope | What it does |
| read | List incidents, optionally filtered by monitor, status, cause or period. |
| read | Read one incident with its cause and every alert attempt. |
| write | Acknowledge an open incident so repeat notifications stop. |
Heartbeats
Tool | Scope | What it does |
| read | List heartbeat (cron / dead-man's-switch) monitors and when each was last pinged. |
| read | Read one heartbeat, including its ping URL and when it will be reported late. |
| write | Create a heartbeat monitor and get the URL a scheduled job should ping. |
| write | Change a heartbeat's name, period, grace, channels or tags. |
| write | Pause a heartbeat: it is not reported late and its pings are ignored. |
| write | Resume a paused heartbeat. |
| write | Delete a heartbeat for good; its ping URL stops working. |
Maintenance windows
Tool | Scope | What it does |
| read | List maintenance windows (one-time or recurring, organization-wide or per monitor). |
| read | The maintenance windows in effect right now. |
| read | Read one maintenance window with its next three occurrences. |
| write | Show the next three occurrences a schedule would produce, without saving it. |
| write | Create a window that silences alerts, once or on an iCal RRULE schedule. |
| write | Change a maintenance window. |
| write | Delete a maintenance window; alerts resume at once. |
Tags
Tool | Scope | What it does |
| read | List every tag in the organization with how many monitors and heartbeats carry it. |
| write | Add and/or remove tags across up to 300 monitors in one call. |
| write | Rename a tag on every monitor and heartbeat that carries it. |
| write | Remove a tag from every monitor and heartbeat that carries it. |
Status pages
Tool | Scope | What it does |
| read | List status pages, with each page's slug and whether it is published. |
| read | Read one status page with its groups and components. |
| read | List a status page's incidents, posted by a person or opened by Fettle, with their timelines. |
| write | Open an incident on a status page with a first message. |
| write | Add a message to a status page incident and set its status; RESOLVED closes it. |
| write | Rename a status page incident; subscribers are not notified. |
| write | Remove an incident and its timeline from a status page. |
Organization and platform
Tool | Scope | What it does |
| read | The organization's plan, its limits, and how much of each is used. |
| read | List notification channels (id, type, label, verified) to bind to monitors. |
| read | List the check regions and the codes the regions argument takes. |
The list is not written by hand. It is generated in the Fettle backend from one
registry and served at
/public-api/mcp-tools.json;
this package vendors that file and builds its tools from it at startup, so the
two MCP channels can never offer different tools.
Agent guide
The server sends this guide to the client in initialize (instructions), so an
agent connected through either channel already has it. It is reproduced here for
humans and for clients that do not surface server instructions.
Fettle is an uptime monitoring service. The tools see only the API key's organization: monitors, heartbeats, maintenance windows, incidents, status page incidents, tags, channels (read), regions. Channels, status pages, members, API keys and billing are managed only in the dashboard (https://dashboard.fettle.sh). Read a tool's description (arguments, limits, errors) before its first call.
FINDING THINGS
- list_monitors gives one short row per monitor; use it to find ids. Filters are JSON arrays. Broken now: status ["DOWN", "DEGRADED"]. Certificates expiring first: type ["SSL"], sort "ssl_expiry".
- tag filters lists; tag_match "all" (default) needs every tag, "any" one of them.
- Lists are paginated: page from 1, size 1..100 (default 25).
PLAN LIMITS
Call get_plan_usage before creating anything: limits (null means none) and usage. A broken limit or an unknown region is a 403 naming it: change the request or tell the user; never retry it unchanged.
CREATING MONITORS
- check_target probes a target once before create_monitor. list_regions names the region codes.
- bulk_create_monitors creates up to 100, all or nothing.
- type and target never change after create.
- channel_ids: ids from list_channels. Empty or omitted on create alerts every verified, active channel. Email is not a channel: every alert also goes to the account email of whoever created the monitor or heartbeat.
- update tools change only the fields you pass. Never send null; omit a field to keep it. A monitor's config is replaced whole: send every config field you want to keep.
- Exposed ports on a server: follow get_exposed_ports_preset.
MANY MONITORS AT ONCE
Find ids with list_monitors, then bulk_pause_monitors, bulk_resume_monitors or bulk_update_monitors (interval, timeout, regions, channels, threshold, cooldown) for up to 100 ids, all or nothing. bulk_update_monitor_tags adds or removes tags on up to 300. There is no bulk delete.
TAGS
Call list_tags first and reuse names. Tags are flat labels such as env:prod, trimmed, lowercased and deduplicated; at most 10 per item. rename_tag and delete_tag act on every monitor and heartbeat.
HEARTBEATS
A job calls ping_url when it succeeds. Job every N seconds, alert after T seconds of silence: period_seconds = N, grace_seconds = T - N. Never late before its first success ping. ping_url + "/start" restarts the clock, ping_url + "/fail" marks it DOWN at once.
MAINTENANCE
Before a deploy or reboot, create_maintenance_window (scope ORG or MONITOR) instead of pausing monitors: checks keep running, but no incident opens and no alert goes out. Not for heartbeats. preview_maintenance_window shows a schedule's next occurrences; list_active_maintenance shows what is silenced now.
OUTAGES
list_monitors status ["DOWN"] -> list_check_results (status code, error, region per check) -> get_incident. acknowledge_incident stops repeat alerts; the recovery alert still goes out. create_status_page_incident and post_status_page_update can email the page's subscribers: confirm the text with the user first.
ERRORS (start of a failed call's text)
- "Authentication failed": the key is missing, revoked or expired, the address is not allowed, or its creator lost access. Do not retry; tell the user.
- "This tool requires/needs an API key with write scope": the key is read-only; tell the user.
- "Invalid argument(s)": names each failing field. "Invalid request:": the rule broken. Fix, retry.
- "Forbidden:": a plan limit, an unknown region, or the key's user lacks the permission; the reason says which.
- "Not found:": no such id in this organization.
- "Rate limited": wait the seconds given, then retry. All API key calls share the organization's per-minute budget.
- "Tool '<name>' failed: the API returned 5xx": server fault, retry once later.
- "Tool '<name>' does not accept argument(s)": drop the ones named.
- "Request failed with status N": read the reason, do not retry unchanged.
The other channel: remote MCP
If your client supports remote MCP servers over HTTP, you do not need this
package at all — point it at https://api.fettle.sh/mcp with the same API key
as a Bearer token. Same tools, same behaviour, nothing to install or update.
Claude Code adds the remote channel from the command line — a different flag set from the stdio one above, with the key as a header rather than an environment variable:
claude mcp add fettle --transport http https://api.fettle.sh/mcp \
--header "Authorization: Bearer fettle_your_key_here"Clients configured through a JSON file take the same two fields:
{
"mcpServers": {
"fettle": {
"url": "https://api.fettle.sh/mcp",
"headers": { "Authorization": "Bearer fettle_your_key_here" }
}
}
}Codex takes the remote channel in ~/.codex/config.toml and reads the key from
an environment variable, so it never sits in the file:
[mcp_servers.fettle]
url = "https://api.fettle.sh/mcp"
bearer_token_env_var = "FETTLE_API_KEY"Use this package when your client speaks only stdio, or when you would rather the credential stayed in a local config file than in a client's cloud configuration.
There is no OAuth on either channel yet; both authenticate with an API key.
Rate limits and plans
Tool calls spend the same per-organization request budget as the REST API — the
plan's limit, not a separate one. A rate-limited call comes back saying how many
seconds to wait. check_now also has its own cap of 10 calls per minute per
calling address. get_plan_usage shows the organization's request budget as
limits.api_rate_limit_per_minute. Plan limits are listed at
https://fettle.sh/pricing.
Troubleshooting
FETTLE_API_KEY is not set — the client started the server without the
variable. Check the env block of the config above, then fully restart the
client: most clients read MCP config only at launch.
Authentication failed — the key is wrong, revoked, or from a deleted
organization. Create a fresh one in Settings → API Keys.
This tool requires an API key with write scope — the key is read-only. Create
a write-scoped key; there is no way to widen an existing key's scope.
The assistant does not see the tools — restart the client, then confirm
Node.js 20+ with node -v. Run npx -y fettle-mcp in a terminal: it should
print the missing-key message and exit, which proves the package itself runs.
Development
pnpm install
pnpm run typecheck
pnpm test
pnpm run build
pnpm run contract:check # vendored contract vs. productionAdding a tool is a change in the backend's registry, not here: regenerate
the contract there, then re-vendor it with
pnpm run contract:check -- --write and commit the result. No source file in
this package describes a tool.
server.json is the entry the official MCP registry
serves, and it repeats the version — a test fails if it stops matching
package.json, so bump both together.
A release is a version tag: pushing vX.Y.Z runs .github/workflows/publish.yml,
which tests, builds and publishes the package to npm with provenance.
License
MIT © Fettle
Available Tools
49 toolsacknowledge_incidentAcknowledge an incidentAIdempotentInspect
Mark an open incident as being handled so its repeat alerts stop; the recovery alert still goes out when it resolves. Use it when someone is working on the outage. It does not close the incident (that happens when the monitor recovers) and it is not for status page incidents (post_status_page_update). Requires a key with the write scope. Acknowledging twice keeps the first acknowledgement; on a resolved incident it succeeds without effect on alerts. Returns the incident in the get_incident shape.
| Name | Required | Description | Default |
|---|---|---|---|
| incident_id | Yes | The incident's uuid from list_incidents. An id that is not an incident of this organization is a 404. |
Output Schema
| Name | Required | Description |
|---|---|---|
| id | Yes | |
| cause | Yes | Known values: TIMEOUT, DNS_FAILURE, CONNECTION_REFUSED, TLS_INVALID, HTTP_4XX, HTTP_5XX, HTTP_UNEXPECTED_STATUS, KEYWORD_MISSING, TOO_MANY_REDIRECTS, TARGET_BLOCKED, PORT_STATE_MISMATCH, INVALID_TARGET, HEARTBEAT_MISSED, HEARTBEAT_FAILED, UNKNOWN. |
| created_at | Yes | |
| monitor_id | No | |
| started_at | Yes | |
| updated_at | Yes | |
| resolved_at | Yes | |
| cause_detail | Yes | |
| heartbeat_id | No | |
| renotify_count | Yes | |
| acknowledged_at | Yes | |
| acknowledged_by | Yes | |
| last_notified_at | Yes | |
| notification_logs | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the annotations: explains that only repeat alerts are suppressed while the recovery alert still sends, that the incident is closed by monitor recovery rather than by this call, that a write-scoped key is required, and the exact semantics of double-acknowledgement and acknowledging a resolved incident. These are non-obvious behaviors an agent could not derive from idempotentHint/destructiveHint alone.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core effect and then layers constraints, auth, and edge-case semantics in four tight sentences. Dense but nearly every clause earns its place; only the trailing return-shape note is arguably redundant given the output schema.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With rich annotations, a fully documented single parameter, and an output schema (the description just points at the get_incident shape), the description covers everything an agent needs: effect, exclusions, auth scope, idempotency, and error behavior.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and the single parameter's uuid origin and 404 failure mode are fully documented in the schema, so the description adds no parameter detail. Baseline 3 is appropriate when the schema carries the parameter burden.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource ('Mark an open incident as being handled') plus the precise effect (repeat alerts stop, recovery alert still fires). It explicitly disambiguates from the sibling that handles status page incidents, so an agent can route correctly 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.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit when-to-use ('when someone is working on the outage'), when-not ('it does not close the incident'), and names the alternative for the adjacent case ('post_status_page_update'). Nothing is left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
bulk_create_monitorsCreate several monitorsAInspect
Create 1 to 100 monitors in one call, all or nothing; for a single monitor use create_monitor. Requires a key with the write scope. An invalid item, or a batch that would exceed the plan, rejects the whole call and creates nothing: call get_plan_usage first to check the batch fits. Errors name the failing item. A field that fails validation is named by its path, such as monitors.3.target (index 3 is the fourth item; all such errors are reported at once). Any other item error keeps the status create_monitor would give (403 when its interval or regions break the plan or name an unknown region, 404 for an unknown channel id, 422 for its config or its type's region rules) and its reason starts with monitors[3] (""): — only the first such item is reported. Read the index only from that leading monitors[N] (the pattern ^monitors[(\d+)] after any lead-in such as "Forbidden: " or "Invalid request: "), never from the name, which may itself contain quotes or brackets. A plan-limit 403 without that prefix is about the batch as a whole: together the items would exceed the plan's monitor count or its quota of monitors below 60 seconds. Fix the item or shrink the batch and send the whole call again. Returns monitors: one list_monitors row per created monitor, in request order. Example: {"monitors": [{"name": "db.example.com exposed ports", "type": "TCP", "target": "db.example.com", "interval_seconds": 3600, "timeout_seconds": 10, "regions": ["eu-central"], "config": {"ports": [5432, 6379, 27017], "expected_state": "closed"}}]}
| Name | Required | Description | Default |
|---|---|---|---|
| monitors | Yes | 1 to 100 monitors, each taking the same fields and rules as create_monitor's arguments. Items with is_active false are created paused and still count toward the plan. |
Output Schema
| Name | Required | Description |
|---|---|---|
| monitors | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the annotations: atomicity (nothing is created on any failure), plan-limit behavior, per-item vs batch error discrimination, the exact status codes inherited from create_monitor (403/404/422), and the monitors[N] prefix contract for locating the offending item. This is exactly the kind of operational detail annotations cannot carry.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Purpose and the create_monitor alternative are front-loaded, but the long middle paragraph about regex-parsing the monitors[N] prefix ('only the first such item is reported', quoting several lead-in variants) is verbose and could be tightened without losing meaning. It is information-dense rather than padded, but not as lean as it could be.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, yet the description still adds the ordering guarantee ('one list_monitors row per created monitor, in request order'), which the schema alone may not convey. Combined with atomicity, prerequisite checks, and error semantics, an agent has everything needed for a 100-item batch call.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
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 the field set and rules. The description adds value with a complete worked example payload (TCP monitor with ports config) and clarifies error-path semantics like monitors.3.target, but does not restate field-level constraints, keeping it modestly above the baseline.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Create 1 to 100 monitors in one call') plus the batch cardinality and all-or-nothing semantics, and explicitly distinguishes from the sibling create_monitor for the single-item case. An agent can identify the tool without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit routing ('for a single monitor use create_monitor') and an actionable prerequisite ('call get_plan_usage first to check the batch fits'). The failure-and-retry guidance ('Fix the item or shrink the batch and send the whole call again') tells the agent how to recover, which is rare and genuinely useful.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
bulk_pause_monitorsPause many monitorsAIdempotentInspect
Pause up to 100 monitors in one call, all or nothing: no checks run and each open incident closes without an alert. Use it to stop monitoring a whole project or group found with list_monitors; for one monitor use pause_monitor, and to silence alerts around a deploy while checks keep running use create_maintenance_window instead. Requires a key with the write scope. Pausing a paused monitor is not an error. Returns monitors: the list_monitors rows after the change, in request order. Example: {"monitor_ids": ["", ""]}
| Name | Required | Description | Default |
|---|---|---|---|
| monitor_ids | Yes | 1 to 100 distinct monitor uuids from list_monitors. A repeated id is a 422; an id that is not a monitor of this organization is a 404 naming it, and then nothing changes. |
Output Schema
| Name | Required | Description |
|---|---|---|
| monitors | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Adds substantial context beyond the annotations: all-or-nothing atomicity, that no checks run and open incidents close without alert, the write-scope requirement, and that re-pausing is not an error. These are behavioral facts the idempotent/destructive hints alone would not convey.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loads the action and scope, then routes to alternatives, then states prerequisites and return shape. Dense but every sentence carries distinct information; no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, yet the description still names the return ('list_monitors rows after the change, in request order'), and the auth requirement plus atomicity behavior are covered. Nothing needed to invoke it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and the schema already documents the 422 duplicate-id and 404 unknown-id behavior, so the baseline is 3. The description's inline example clarifies invocation format and reinforces the atomic failure semantics ('all or nothing'), adding modest value over the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource with scope: 'Pause up to 100 monitors in one call'. It also explicitly distinguishes itself from pause_monitor (single) and create_maintenance_window (silence while checks run), so the sibling boundary is unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit when-to-use ('stop monitoring a whole project or group found with list_monitors') plus two named alternatives with the condition that selects each. No inference required.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
bulk_resume_monitorsResume many monitorsAIdempotentInspect
Resume up to 100 paused monitors in one call, all or nothing; each goes back to PENDING and is checked on the next tick. For one monitor use resume_monitor; to run a check right away on a monitor that is already running, use check_now. Requires a key with the write scope. Resuming more monitors than the plan's active limit allows is a 403 and nothing changes (see get_plan_usage). A monitor already running is left as it is. Returns monitors: the list_monitors rows after the change, in request order. Example: {"monitor_ids": ["", ""]}
| Name | Required | Description | Default |
|---|---|---|---|
| monitor_ids | Yes | 1 to 100 distinct monitor uuids from list_monitors. A repeated id is a 422; an id that is not a monitor of this organization is a 404 naming it, and then nothing changes. |
Output Schema
| Name | Required | Description |
|---|---|---|
| monitors | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations cover safety (idempotent=true, destructive=false), and the description adds substantial context beyond them: transactionality ('all or nothing'), resulting state (PENDING, checked next tick), the 403 plan-limit behavior with no partial change, and the no-op on already-running monitors. No contradiction with idempotentHint or destructiveHint.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loads the batch semantics, then routing, then auth/preconditions, then return shape, then example. Every sentence carries distinct information; no filler or restatement of the title.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a single-parameter bulk mutation, the description covers scope, alternatives, permissions, failure modes, no-op behavior, and return format — everything an agent needs. An output schema exists, and the description's brief return note is complementary rather than redundant.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and already documents the 1-100 distinct-uuid constraint plus 422/404 handling, so baseline is 3. The description adds a concrete invocation example and states the return order is the request order, giving slightly more than the schema alone.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Specific verb (resume) plus resource (monitors), with scope stated (up to 100 paused monitors, all-or-nothing). It explicitly distinguishes itself from resume_monitor and check_now, so an agent can route without opening sibling schemas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Names two alternatives with their selecting conditions: resume_monitor for a single monitor, check_now for an immediate check on an already-running monitor. Also states the auth prerequisite (write scope) and the plan-limit failure path with a pointer to get_plan_usage.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
bulk_update_monitorsChange settings of many monitorsAIdempotentInspect
Set the same interval, timeout, regions, channels, threshold or cooldown on up to 100 monitors in one call, all or nothing. For example, move twenty PING monitors to other regions. Not for config or name (use update_monitor, one monitor at a time) or tags (use bulk_update_monitor_tags). Requires a key with the write scope. The plan's rules apply to the result: an interval below the plan minimum, too many fast monitors, too many regions or an unknown region is a 403. A value one monitor cannot take (several regions on an SSL, DNS or port-list TCP monitor, or an interval under 300 on a port-list one) is a 422 that starts with monitors[] (""). Returns monitors: list_monitors rows, which show the interval but not the other settings; read those with get_monitor. Example: {"monitor_ids": ["", ""], "changes": {"regions": ["eu-central", "us-east"], "interval_seconds": 300}}
| Name | Required | Description | Default |
|---|---|---|---|
| changes | Yes | The values to set, at least one of: interval_seconds (30 to 86400), timeout_seconds (1 to 120), regions (region codes from limits.allowed_regions in get_plan_usage), channel_ids (channel uuids from list_channels; replaces each binding, [] clears it, an unknown channel is a 404), confirmation_threshold (1 to 10) and notification_cooldown_seconds (60 to 86400). Omit a field to keep it; never send null. | |
| monitor_ids | Yes | 1 to 100 distinct monitor uuids from list_monitors. A repeated id is a 422; an id that is not a monitor of this organization is a 404 naming it, and then nothing changes. |
Output Schema
| Name | Required | Description |
|---|---|---|
| monitors | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations cover safety (readOnlyHint=false, idempotentHint=true, destructiveHint=false), and the description adds real behavior beyond them: atomic all-or-nothing semantics, 403 plan-rule failures, 422 per-monitor errors with the monitors[<i>] ("<name>") format, and the caveat that returned list_monitors rows omit most settings so get_monitor is needed.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Purpose and exclusions are front-loaded, and every sentence carries distinct information (scope, alternatives, auth, limits, error shapes, return caveat, example). It is dense and long, but no sentence is filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given a 2-param tool with a nested changes object and an output schema, the description covers invocation, gating rules, partial-failure behavior, and result interpretation. 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.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and the nested changes object is fully documented in the schema, so baseline is 3. The description goes further with a concrete example payload and the semantics of channel_ids replacement/clearing and monitor_ids uniqueness/404 behavior, adding meaning beyond the raw schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Opens with a specific verb and resource ("Set the same interval, timeout, regions...") and bounds scope (up to 100 monitors, all-or-nothing). Explicitly names the siblings it is not (update_monitor, bulk_update_monitor_tags), so an agent can route correctly 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.
Does the description explain when to use this tool, when not to, or what alternatives exist?
States when-not to use it: not for config or name (use update_monitor) and not for tags (use bulk_update_monitor_tags). Also names the prerequisite (a key with write scope), which is the condition that gates invocation.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
bulk_update_monitor_tagsRetag several monitors at onceAIdempotentInspect
Add and/or remove tags across up to 300 monitors in one call, all or nothing: each monitor ends with (its tags | add) - remove. Use it to retag a fleet; to replace one monitor's whole tag list use update_monitor, to rename or drop a tag everywhere (heartbeats too) use rename_tag or delete_tag. Requires a key with the write scope. At least one of add or remove is required, and they must not share a tag (422). A monitor that would end with more than 10 tags rejects the whole call (422). Each tag is trimmed, lowercased and deduplicated on write, at most 50 characters of a-z, 0-9 and : _ . / -, starting with a letter or digit. Reuse names from list_tags rather than inventing near-duplicates. Returns monitors_updated. Example: {"monitor_ids": ["", ""], "add": ["env:prod"], "remove": ["env:staging"]}
| Name | Required | Description | Default |
|---|---|---|---|
| add | No | Tags to add to every listed monitor, up to 10. | |
| remove | No | Tags to remove from every listed monitor, up to 10. | |
| monitor_ids | Yes | 1 to 300 distinct monitor uuids from list_monitors. A repeated id is a 422; an unknown id rejects the whole call with a 404 naming every id not found. |
Output Schema
| Name | Required | Description |
|---|---|---|
| monitors_updated | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations (readOnlyHint=false, idempotentHint=true, destructiveHint=false), the description discloses real behavior: all-or-nothing atomicity, write-scope key requirement, the exact 422 failure conditions (shared tag, >10 tags, duplicate id), tag normalization on write, and the return field monitors_updated. This is far more than the 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.
Is the description appropriately sized, front-loaded, and free of redundancy?
It is dense but front-loaded with the core contract, then alternatives, then requirements, then an example. Every sentence carries usable information, though the packed constraint list and example make it longer than strictly necessary.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema plus rich annotations already present, the description still covers scope, prerequisites, failure modes, normalization rules and return value, leaving nothing an agent needs to invoke it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
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 constraints the schema omits: at least one of add/remove is required and the two must not share a tag (422), plus a concrete example payload. It adds meaningful semantics beyond the documented fields.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb pair and resource ('Add and/or remove tags across up to 300 monitors in one call'), states the all-or-nothing scope, and names exactly which siblings handle the adjacent cases (update_monitor, rename_tag, delete_tag). An agent can distinguish this from every bulk_* and tag sibling without opening a schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives explicit routing: 'Use it to retag a fleet; to replace one monitor's whole tag list use update_monitor, to rename or drop a tag everywhere (heartbeats too) use rename_tag or delete_tag.' When-to-use and when-to-use-something-else are both spelled out with the selecting condition.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
check_nowCheck a monitor nowAInspect
Queue one existing monitor to run on the scheduler's next tick instead of waiting out its interval, for example to confirm a fix. It returns the monitor record, not a check result: call get_monitor or list_check_results a moment later for the outcome. To probe a target that has no monitor yet use check_target; to restart a paused monitor use resume_monitor. Requires a key with the write scope. A repeat call for the same monitor within 30 seconds, or a call on a paused monitor, is a silent no-op that returns it unchanged. Calls are limited to 10 per minute per calling address (not per key or organization); past that it is a 429 with the seconds to wait, so pace a run over many monitors.
| Name | Required | Description | Default |
|---|---|---|---|
| monitor_id | Yes | The monitor's uuid from list_monitors. An id that is not a monitor of this organization, or a deleted one, is a 404. |
Output Schema
| Name | Required | Description |
|---|---|---|
| id | Yes | |
| name | Yes | |
| tags | No | |
| type | Yes | Known values: HTTP, PING, SSL, TCP, DNS. |
| config | Yes | |
| status | Yes | Known values: PENDING, UP, DEGRADED, DOWN, PAUSED. |
| target | Yes | |
| regions | Yes | |
| user_id | Yes | |
| is_active | Yes | |
| created_at | Yes | |
| updated_at | Yes | |
| channel_ids | No | |
| next_run_at | Yes | |
| badge_enabled | No | |
| ssl_cert_info | No | |
| ssl_expires_at | Yes | |
| last_checked_at | Yes | |
| region_statuses | Yes | Per-region latest status, sorted by region name. Built from ``region_snapshots``; ``job_id`` is dropped (internal dedup key) and malformed/partial snapshot rows are skipped rather than failing the read. |
| timeout_seconds | Yes | |
| interval_seconds | Yes | |
| confirmation_threshold | Yes | |
| notification_cooldown_seconds | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare the safety profile, but the description adds substantial non-structured context: it returns the monitor record rather than a check result, the 30-second and paused-monitor no-op semantics, the write scope requirement, and a per-address rate limit with 429 behavior and a pacing recommendation. This is exactly the operational detail an agent needs before calling.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core action and effect, then layered: return-value caveat, sibling routing, auth requirement, no-op conditions, rate limit. Every sentence carries actionable information with no padding.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Covers the gaps an output schema cannot: latency of the result, silent no-op conditions, auth scope, and rate limiting with pacing guidance. The explicit note that the return is the monitor record, not a check result, is the key clarification for correct agent follow-up.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and the single parameter is fully documented there (uuid source from list_monitors, 404 conditions). The description adds no additional parameter-level syntax or format 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.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Queue one existing monitor to run on the scheduler's next tick instead of waiting out its interval') and explicitly distinguishes itself from check_target and resume_monitor. The purpose and scope are unambiguous without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives an explicit use case ('to confirm a fix'), names two sibling alternatives with the condition that selects each (check_target for no monitor yet, resume_monitor for a paused monitor), and flags the silent no-op cases that make the call pointless. Nothing is left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
check_targetProbe a target before creating a monitorARead-onlyIdempotentInspect
Run one real check of a target from one region chosen by Fettle, without creating anything. It reports status (up, down, error or unknown), region, response_time_ms, status_code, error and failure_kind. unknown means no definite answer came back, not a failure. Use it before create_monitor to catch a typo or an unreachable host; a down result does not stop you creating the monitor. For a monitor that already exists use check_now. Requires a key with the write scope. It is rate limited per calling address: a 429 whose retry_after says how many seconds to wait. Example: {"type": "HTTP", "target": "https://api.example.com/health"}
| Name | Required | Description | Default |
|---|---|---|---|
| type | Yes | HTTP (a URL answers with an expected status), PING (a host answers ICMP), SSL (a certificate is valid and not about to expire), TCP (a port is open, or a list of ports is closed) or DNS (a record resolves, optionally to an expected value). | |
| config | No | As in create_monitor; TCP and DNS need it. The region, interval and update rules there do not apply to a one-off probe. An object whose fields depend on type, all optional unless stated. HTTP: method (GET, HEAD, POST, PUT, PATCH or DELETE, any case; default GET); expected_status_codes (non-empty list of codes 100 to 599, default [200]); keyword (case-sensitive substring the body must contain, at most 1024 characters, not with HEAD); follow_redirects (default true); verify_ssl (default true; false skips TLS verification, so the monitor can never report TLS_INVALID); request_headers (object of name to value: at most 20, a name at most 128 characters of letters, digits and ! # $ % & ' * + - . ^ _ ` | ~, a value at most 1024 bytes of printable ASCII, space or tab, the whole object at most 8192 bytes as JSON; names differing only in case, and Host, Content-Length, Transfer-Encoding, Connection, Upgrade, TE, Trailer, Keep-Alive, CF-Connecting-IP or any Proxy-* name, are a 422); request_body (string, at most 8192 bytes as UTF-8, needs POST, PUT, PATCH or DELETE). Reads return every request_headers value as the literal __FETTLE_UNCHANGED__; writing that literal back in an update keeps the stored value (on create it is a 422). PING: packet_count (1 to 20, default 4). SSL: warn_before_days (1 to 365, default 14) and port (1 to 65535, default 443). TCP: either port (1 to 65535) with expected_state "open" (default) or "closed", or ports (1 to 20 distinct ports that must all be closed, which needs expected_state "closed", exactly one region and interval_seconds of at least 300; a check fails when any of them accepts a connection, and the monitor goes DOWN once confirmation_threshold failures confirm it). Both port and ports, or neither, is a 422; expected_state values are lowercase. DNS: record_type (A, AAAA, CNAME, MX, TXT or NS; required) and expected_value (at most 2048 characters). With expected_value one answer must equal it (case-insensitive, ignoring surrounding spaces and a trailing dot; exact for TXT); without it any answer passes. MX answers are the mail host names without priority (mail.example.com, not 10 mail.example.com). A and AAAA look up every address of the host, IPv4 and IPv6 alike, and any one may match; write an IPv6 address in its shortest form. | |
| target | Yes | What to check, up to 2048 characters. HTTP: an http:// or https:// URL (https:// is added when the scheme is missing; port, path and query are kept). PING, SSL, TCP and DNS: a bare public hostname or IP address with no :port and no path (the port goes in config): host:port is a 422, and a full URL is cut down to its host, losing its port. Hostnames are ASCII (punycode for internationalized domains). localhost, *.localhost and addresses that are not public (private, loopback, link-local, CGNAT 100.64.0.0/10, reserved, unspecified) are a 422. |
Output Schema
| Name | Required | Description |
|---|---|---|
| error | No | |
| region | Yes | |
| status | Yes | Known values: up, down, error, unknown. |
| status_code | No | |
| failure_kind | No | |
| response_time_ms | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations cover safety (readOnly, idempotent, non-destructive), and the description still adds real operational context: the write-scope auth requirement, per-address rate limiting with a 429/retry_after contract, and the semantic that 'unknown' means no definite answer rather than a failure. That last point is behavior an agent cannot infer from schema or annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Well front-loaded: purpose, then outputs, then the confusing 'unknown' semantics, then usage, then auth/rate limits, then the example. Slightly dinged because enumerating the returned fields (region, response_time_ms, status_code, error, failure_kind) duplicates what the output schema already provides.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a probe tool with an output schema in place, the description covers everything an agent needs: auth scope, rate-limit failure mode, the meaning of each status value, and how this call relates to create_monitor and check_now. No gaps remain for correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and the enum values and config sub-fields are thoroughly documented in the schema itself, so the baseline is 3. The description only adds a single worked example ({"type": "HTTP", "target": "https://api.example.com/health"}) and a note that TCP/DNS need config; it does not meaningfully extend parameter semantics beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Specific verb+resource ('Run one real check of a target') with an explicit scope qualifier ('without creating anything'), and it enumerates the result fields. It also distinguishes itself from both siblings it could be confused with: create_monitor and check_now.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit when-to-use ('Use it before create_monitor to catch a typo or an unreachable host'), an explicit non-blocking caveat ('a down result does not stop you creating the monitor'), and the alternative for the other case ('For a monitor that already exists use check_now'). Nothing is left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_heartbeatCreate a heartbeat monitorAInspect
Create a heartbeat: Fettle alerts when a scheduled job stops calling its ping_url. Use it for cron jobs, backups and workers that should report in; to probe a URL, host or port from outside use create_monitor. The job calls ping_url (GET or POST) on success, ping_url + "/start" when it begins (restarts the clock) and ping_url + "/fail" to go DOWN at once. It is never late before its first success ping (a /fail call still marks it DOWN); after that an alert fires period_seconds + grace_seconds after the last ping. Requires a key with the write scope. The plan caps how many heartbeats exist (403 past it; see get_plan_usage). An invalid argument is a 422 naming it. Returns the heartbeat, with ping_url. Example: {"name": "nightly backup", "period_seconds": 86400, "grace_seconds": 3600}
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | Display name, 1 to 255 characters. | |
| tags | No | Flat labels for grouping and filtering, for example env:prod or service:api, at most 10. Each tag is trimmed, lowercased and deduplicated on write, at most 50 characters of a-z, 0-9 and : _ . / -, starting with a letter or digit. Reuse names from list_tags rather than inventing near-duplicates. | |
| channel_ids | No | Notification channel uuids from list_channels. Omit it or pass [] to alert every verified, active channel of the organization. An id that is not an active channel of this organization is a 404. | |
| grace_seconds | Yes | Extra seconds of silence tolerated after the period before the heartbeat is reported late, 0 to 2592000; it may exceed the period. | |
| period_seconds | Yes | How often the job runs, 60 to 2592000 seconds. To ping every N seconds and be alerted after T seconds of silence, set period_seconds = N and grace_seconds = T - N (T at least N). | |
| notification_cooldown_seconds | No | 60 to 86400 seconds; 1800 when not set on create. Only holds back a duplicate first alert for the same incident within that window. Repeat reminders while an incident stays open and unacknowledged follow the plan's renotify_interval_seconds and renotify_max_count (get_plan_usage; 0 means no reminders) instead, and the recovery alert is never held back. |
Output Schema
| Name | Required | Description |
|---|---|---|
| id | Yes | |
| name | Yes | |
| tags | No | |
| state | Yes | Known values: PENDING, UP, DOWN, PAUSED. |
| ping_url | Yes | |
| is_active | Yes | |
| created_at | Yes | |
| overdue_at | Yes | |
| updated_at | Yes | |
| channel_ids | No | |
| last_ping_at | Yes | |
| grace_seconds | Yes | |
| last_start_at | Yes | |
| period_seconds | Yes | |
| last_success_at | Yes | |
| last_duration_ms | Yes | |
| notification_cooldown_seconds | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only declare the mutation safety profile (readOnlyHint=false, destructiveHint=false, idempotentHint=false). The description adds substantial behavior: the ping_url contract (/start restarts the clock, /fail goes DOWN immediately), the never-late-before-first-ping rule, the period_seconds + grace_seconds alert timing, the write-scope requirement, the plan cap returning 403, and invalid args returning 422. This is exactly the context annotations cannot carry.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
It is a single dense paragraph, but it is front-loaded with the purpose and then the ping_url contract, error behavior, and example in a logical order. Every sentence carries distinct information, though the run-on density slightly taxes readability compared to a cleaner separation.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 6-parameter mutation tool with an output schema, the description covers the gaps an agent actually needs: purpose, alternative tool, ping contract, auth scope, plan limits, and error codes. Return values are summarized ('returns the heartbeat, with ping_url') without redundantly re-specifying the output schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the baseline is 3. The description adds value on top: a worked example tying name/period_seconds/grace_seconds together and the timing rule (alert fires period_seconds + grace_seconds after the last ping), which explains how the two numeric params interact. It does not add detail for tags, channel_ids, or notification_cooldown_seconds beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (Create) and resource (a heartbeat), then immediately defines what a heartbeat is: 'Fettle alerts when a scheduled job stops calling its ping_url.' It explicitly distinguishes itself from the sibling create_monitor ('to probe a URL, host or port from outside use create_monitor'), so an agent can route correctly without opening either schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives concrete when-to-use cases (cron jobs, backups, workers that report in) and an explicit alternative with its condition (use create_monitor to probe a URL/host/port from outside). It also routes to get_plan_usage for quota and names the write scope requirement. Nothing about selection is left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_maintenance_windowCreate a maintenance windowAInspect
Create a one-time or recurring maintenance window that silences alerts for some or all monitors. While a window is in effect its monitors keep being checked, but no incident opens and no alert goes out. Use it around a deploy or reboot instead of pause_monitor; it does not cover heartbeats (use pause_heartbeat). For a recurring schedule run preview_maintenance_window first. Requires a key with the write scope. The plan caps how many windows exist (403 past it or when the plan has none; see max_maintenance_windows in get_plan_usage). An invalid argument or schedule is a 422 naming it. Returns the window. Example: {"name": "Deploy", "scope": "MONITOR", "monitor_ids": [""], "dtstart": "2026-10-14T22:00:00", "duration_minutes": 30}
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | Display name, 1 to 255 characters. | |
| rrule | No | Repeats the window: one iCal RRULE without the RRULE: prefix, at most 1024 characters, for example FREQ=WEEKLY;BYDAY=SU;BYHOUR=3. Hourly, minutely and secondly frequencies are refused. Omit it for a one-time window. | |
| scope | Yes | ORG covers every monitor of the organization and ignores monitor_ids; MONITOR covers only monitor_ids. | |
| dtstart | Yes | The first start, an ISO 8601 date-time in the wall-clock time of timezone, for example 2026-10-14T22:00:00. A UTC offset or Z is a 422. | |
| enabled | No | Default true; false stores the window without effect. | |
| timezone | No | IANA zone name such as Europe/Berlin, at most 64 characters. The schedule repeats in it, so a weekly 03:00 stays 03:00 across daylight-saving changes. Defaults to the organization's timezone. | |
| monitor_ids | No | Monitor uuids from list_monitors, at least one when scope is MONITOR. An id that is not a monitor of this organization is a 404. | |
| duration_minutes | Yes | How long each occurrence lasts, 1 to 40320 minutes. |
Output Schema
| Name | Required | Description |
|---|---|---|
| id | Yes | |
| name | Yes | |
| rrule | Yes | |
| scope | Yes | Known values: MONITOR, ORG. |
| dtstart | Yes | |
| enabled | Yes | |
| timezone | Yes | |
| created_at | Yes | |
| monitor_ids | No | |
| duration_minutes | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only cover the safety profile (readOnly=false, idempotent=false, destructive=false), and the description adds substantial behavior beyond that: monitors keep being checked but no incident/alert fires, write-scope auth is required, plan caps produce a 403, and invalid args produce a 422 naming the field. Return value is only named, but an output schema exists. Slight gap is that idempotency/duplicate-creation behavior is not discussed, though the annotation hints it.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the purpose in sentence one, then behavior, alternatives, auth, error modes, and a worked example in descending priority. Dense but every sentence carries distinct operational information; nothing is redundant with the name or schema.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For an 8-param write tool with annotations and an output schema, the description supplies the missing pieces an agent needs: effect on monitoring, sibling routing, auth scope, quota failure mode, validation failure mode, and a concrete call. Nothing material is absent.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
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 goes modestly beyond by giving a complete example call that demonstrates the MONITOR-scope + monitor_ids + dtstart + duration_minutes combination and pointing at list_monitors as the id source, which helps the agent assemble a valid request rather than just read field docs.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource ('Create a ... maintenance window') and immediately qualifies scope ('one-time or recurring', 'some or all monitors') and effect ('silences alerts'). It also distinguishes itself from pause_monitor and pause_heartbeat, so an agent can route correctly without opening a schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit when-to-use ('around a deploy or reboot'), explicit alternative ('instead of pause_monitor'), explicit exclusion ('does not cover heartbeats (use pause_heartbeat)'), and a precondition for the recurring case ('run preview_maintenance_window first'). Nothing is left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_monitorCreate a monitorAInspect
Create one monitor that checks a URL, host or port on a schedule from one or more regions, and return it in the get_monitor shape. Use check_target first to catch a typo or an unreachable host; use bulk_create_monitors for several monitors, and create_heartbeat for a job that should report in rather than be probed. Requires a key with the write scope. Plan limits apply (monitor count, minimum interval, monitors faster than 60 seconds, regions per monitor): breaking one is a 403 naming it, so call get_plan_usage first. A paused monitor still counts toward them. An invalid argument is a 422 naming it. Example: {"name": "API", "type": "HTTP", "target": "https://api.example.com/health", "interval_seconds": 300, "timeout_seconds": 10, "regions": ["eu-central"], "config": {"expected_status_codes": [200]}, "tags": ["env:prod"]}
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | Display name, 1 to 255 characters. | |
| tags | No | Flat labels for grouping and filtering, for example env:prod or service:api, at most 10. Each tag is trimmed, lowercased and deduplicated on write, at most 50 characters of a-z, 0-9 and : _ . / -, starting with a letter or digit. Reuse names from list_tags rather than inventing near-duplicates. | |
| type | Yes | HTTP (a URL answers with an expected status), PING (a host answers ICMP), SSL (a certificate is valid and not about to expire), TCP (a port is open, or a list of ports is closed) or DNS (a record resolves, optionally to an expected value). Cannot be changed after create. | |
| config | No | An object whose fields depend on type, all optional unless stated. HTTP: method (GET, HEAD, POST, PUT, PATCH or DELETE, any case; default GET); expected_status_codes (non-empty list of codes 100 to 599, default [200]); keyword (case-sensitive substring the body must contain, at most 1024 characters, not with HEAD); follow_redirects (default true); verify_ssl (default true; false skips TLS verification, so the monitor can never report TLS_INVALID); request_headers (object of name to value: at most 20, a name at most 128 characters of letters, digits and ! # $ % & ' * + - . ^ _ ` | ~, a value at most 1024 bytes of printable ASCII, space or tab, the whole object at most 8192 bytes as JSON; names differing only in case, and Host, Content-Length, Transfer-Encoding, Connection, Upgrade, TE, Trailer, Keep-Alive, CF-Connecting-IP or any Proxy-* name, are a 422); request_body (string, at most 8192 bytes as UTF-8, needs POST, PUT, PATCH or DELETE). Reads return every request_headers value as the literal __FETTLE_UNCHANGED__; writing that literal back in an update keeps the stored value (on create it is a 422). PING: packet_count (1 to 20, default 4). SSL: warn_before_days (1 to 365, default 14) and port (1 to 65535, default 443). TCP: either port (1 to 65535) with expected_state "open" (default) or "closed", or ports (1 to 20 distinct ports that must all be closed, which needs expected_state "closed", exactly one region and interval_seconds of at least 300; a check fails when any of them accepts a connection, and the monitor goes DOWN once confirmation_threshold failures confirm it). Both port and ports, or neither, is a 422; expected_state values are lowercase. DNS: record_type (A, AAAA, CNAME, MX, TXT or NS; required) and expected_value (at most 2048 characters). With expected_value one answer must equal it (case-insensitive, ignoring surrounding spaces and a trailing dot; exact for TXT); without it any answer passes. MX answers are the mail host names without priority (mail.example.com, not 10 mail.example.com). A and AAAA look up every address of the host, IPv4 and IPv6 alike, and any one may match; write an IPv6 address in its shortest form. Omit it for HTTP, PING or SSL to take the defaults; a TCP or DNS monitor without it is a 422. | |
| target | Yes | What to check, up to 2048 characters. HTTP: an http:// or https:// URL (https:// is added when the scheme is missing; port, path and query are kept). PING, SSL, TCP and DNS: a bare public hostname or IP address with no :port and no path (the port goes in config): host:port is a 422, and a full URL is cut down to its host, losing its port. Hostnames are ASCII (punycode for internationalized domains). localhost, *.localhost and addresses that are not public (private, loopback, link-local, CGNAT 100.64.0.0/10, reserved, unspecified) are a 422. Cannot be changed after create. | |
| regions | Yes | One or more distinct region codes, for example eu-central: the plan's choices are limits.allowed_regions in get_plan_usage. An unknown code, or more regions than the plan's max_regions, is a 403. SSL and DNS monitors take exactly one region (422 otherwise). | |
| is_active | No | Default true. false creates it paused: no check runs until resume_monitor. | |
| channel_ids | No | Notification channel uuids from list_channels. Omit it or pass [] to alert every verified, active channel of the organization. An id that is not an active channel of this organization is a 404. | |
| timeout_seconds | Yes | Seconds one check may take before it fails, 1 to 120. | |
| interval_seconds | Yes | Seconds between checks, 30 to 86400. The plan sets a minimum (limits.min_interval_seconds) and caps how many monitors may check more often than every 60 seconds (max_fast_monitors); breaking either is a 403 naming the limit. | |
| confirmation_threshold | No | How many checks in a row must fail in every region before the monitor goes DOWN and an incident opens, 1 to 10; 3 when not set on create. | |
| notification_cooldown_seconds | No | 60 to 86400 seconds; 1800 when not set on create. Only holds back a duplicate first alert for the same incident within that window. Repeat reminders while an incident stays open and unacknowledged follow the plan's renotify_interval_seconds and renotify_max_count (get_plan_usage; 0 means no reminders) instead, and the recovery alert is never held back. |
Output Schema
| Name | Required | Description |
|---|---|---|
| id | Yes | |
| name | Yes | |
| tags | No | |
| type | Yes | Known values: HTTP, PING, SSL, TCP, DNS. |
| config | Yes | |
| status | Yes | Known values: PENDING, UP, DEGRADED, DOWN, PAUSED. |
| target | Yes | |
| regions | Yes | |
| user_id | Yes | |
| is_active | Yes | |
| created_at | Yes | |
| updated_at | Yes | |
| channel_ids | No | |
| next_run_at | Yes | |
| badge_enabled | No | |
| ssl_cert_info | No | |
| ssl_expires_at | Yes | |
| last_checked_at | Yes | |
| region_statuses | Yes | Per-region latest status, sorted by region name. Built from ``region_snapshots``; ``job_id`` is dropped (internal dedup key) and malformed/partial snapshot rows are skipped rather than failing the read. |
| timeout_seconds | Yes | |
| interval_seconds | Yes | |
| confirmation_threshold | Yes | |
| notification_cooldown_seconds | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare this is a non-read-only, non-destructive create, and the description adds substantial context beyond them: write scope required, plan limits (count, min interval, fast-monitor cap, regions per monitor) failing as a 403 that names the limit, paused monitors still counting, and 422 behavior for invalid arguments.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Content is front-loaded with purpose, then alternatives, then error/limit semantics, then an example. It is dense but every clause carries useful information; the single-paragraph format is slightly heavy though not wasteful.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 12-parameter create tool with an output schema, the description covers purpose, routing to siblings, required scope, limit/quota failure modes, the get_monitor return shape, and a valid example. Nothing an agent needs to invoke it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the baseline is 3, but the description adds value by including a full worked example that shows how name, type, target, interval_seconds, timeout_seconds, regions, config and tags combine in a valid call. It does not restate individual field semantics, which the schema handles.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource ('Create one monitor'), its scope (checks a URL, host or port on a schedule from one or more regions) and its return shape. It clearly distinguishes itself from bulk_create_monitors and create_heartbeat, which are named explicitly.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It names the alternatives and the condition selecting each: check_target first to catch typos/unreachable hosts, bulk_create_monitors for several, create_heartbeat for report-in jobs, and get_plan_usage before hitting limits. When-to-use routing is fully explicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_status_page_incidentPost an incident on a status pageAInspect
Open a new incident on a status page with its first message, to tell the page's visitors about an outage. It is public and emails the page's confirmed subscribers: confirm the wording with the user before calling. Any status but RESOLVED emails every confirmed subscriber at once; RESOLVED records an already closed incident (a postmortem) and emails nobody. To add to an existing incident use post_status_page_update. Requires a key with the write scope. Returns the incident. Example: {"page_id": "", "title": "API errors", "body": "We are investigating elevated error rates."}
| Name | Required | Description | Default |
|---|---|---|---|
| body | Yes | The first message. The message subscribers read, 1 to 5000 characters. | |
| title | Yes | The incident's headline, 1 to 255 characters. | |
| status | No | INVESTIGATING, IDENTIFIED, MONITORING or RESOLVED; RESOLVED closes the incident on the page. Default INVESTIGATING. | |
| page_id | Yes | The status page's uuid from list_status_pages. An id that is not a status page of this organization is a 404. | |
| component_ids | No | The affected components: uuids from get_status_page. An id that is not a component of this page is a 404. |
Output Schema
| Name | Required | Description |
|---|---|---|
| id | Yes | |
| title | Yes | |
| status | Yes | Known values: INVESTIGATING, IDENTIFIED, MONITORING, RESOLVED. |
| is_auto | Yes | |
| updates | Yes | |
| started_at | Yes | |
| notified_at | Yes | |
| resolved_at | Yes | |
| component_ids | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the annotations: discloses that the incident is public, that it emails confirmed subscribers, the exact divergence between RESOLVED (records a closed incident/postmortem, emails nobody) and any other status (emails everyone at once), and the required write-scope key. The annotations only say it is a non-idempotent, non-destructive write; the description supplies the real blast radius.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Dense but front-loaded: purpose, then notification behavior, then the sibling escape hatch, then auth, then an example. Every sentence carries information, though the example is somewhat redundant given a 100%-covered schema.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a public, notification-triggering mutation with an output schema already present, the description covers purpose, routing, side effects and auth. Nothing material an agent needs to invoke it safely is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% so the baseline is 3, and the description earns an upgrade by explaining the subscriber-notification semantics of the status enum and by showing a concrete call example with page_id, title and body. Component_ids and the length limits are left to the schema, which already documents them.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Open a new incident on a status page with its first message') and explicitly distinguishes itself from the sibling post_status_page_update, which adds to an existing incident. An agent can route between these two without opening either schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives the when (tell visitors about an outage), the when-not (adding to an existing incident → post_status_page_update), and a procedural precondition ('confirm the wording with the user before calling'). No inference required.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
delete_heartbeatDelete a heartbeat monitorADestructiveIdempotentInspect
Delete one heartbeat for good: its ping_url stops working (404) and no tool restores it. Use it only when the user asked for deletion; to stop alerts for a while use pause_heartbeat. Requires a key with the write scope. Returns {"success": true}.
| Name | Required | Description | Default |
|---|---|---|---|
| heartbeat_id | Yes | The heartbeat's uuid from list_heartbeats. An id that is not a heartbeat of this organization, or a deleted one, is a 404. |
Output Schema
| Name | Required | Description |
|---|---|---|
| success | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true and idempotentHint=true, yet the description still adds real behavioral context beyond them: the ping_url returns 404 afterward, no tool can restore it, and a write-scoped key is required. The return shape is restated from the output schema but the irreversibility and auth requirements are genuinely additive.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three compact sentences, each earning its place: what it does, when to use it versus the alternative, and the auth/return facts. The most consequential fact (permanent deletion) is front-loaded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Covers the destructive nature, the irreversibility, the required scope, and the sibling alternative, while the output schema carries the return value and annotations carry the safety profile. Nothing an agent needs 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.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and the single heartbeat_id parameter is fully documented in the schema, including the 404 behavior for foreign or already-deleted ids. The description adds no parameter-level detail beyond that, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Delete one heartbeat') and immediately pins down the scope ('for good'), which distinguishes it from pause/update siblings. An agent can tell this apart from pause_heartbeat or delete_monitor without opening either schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit when-to-use ('only when the user asked for deletion') and names the alternative for the adjacent case ('to stop alerts for a while use pause_heartbeat'). Both the condition and the routing target are given, leaving nothing to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
delete_maintenance_windowDelete a maintenance windowADestructiveIdempotentInspect
Delete one maintenance window; alerts for its monitors resume at once and no tool restores it. To suspend a window but keep it, use update_maintenance_window with enabled false. Requires a key with the write scope. Returns {"success": true}.
| Name | Required | Description | Default |
|---|---|---|---|
| window_id | Yes | The window's uuid from list_maintenance_windows. An id that is not a window of this organization is a 404. |
Output Schema
| Name | Required | Description |
|---|---|---|
| success | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Adds substantial context beyond the annotations: the effect is immediate ('alerts for its monitors resume at once'), it is unrecoverable ('no tool restores it'), and it requires a key with the write scope. The annotations declare destructiveHint=true, but the description tells the agent what is actually destroyed and that recovery is impossible.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three tight clauses covering effect, alternative, and prerequisites, with the destructive consequence front-loaded. No filler sentences.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a destructive single-parameter tool, everything needed is present: irreversibility, side effect on monitors, the safer alternative, auth scope, and return shape. The output schema exists, so restating the return value is a minor redundancy rather than a gap.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Only one parameter with 100% schema description coverage, so the schema already carries the semantics including the uuid format and the 404 condition. The description adds no additional parameter-level detail, which is the baseline 3 for a fully documented schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Delete one maintenance window') and immediately distinguishes it from the sibling update_maintenance_window by contrasting deletion with suspension. An agent can route correctly without opening either schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly names the alternative and the exact condition that selects it: 'To suspend a window but keep it, use update_maintenance_window with enabled false.' This is genuine when-to-use/when-not guidance rather than implied usage.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
delete_monitorDelete a monitorADestructiveIdempotentInspect
Delete one monitor: it stops being checked and disappears from the organization's monitors, and no tool restores it. Use it only when the user explicitly asked for deletion; otherwise prefer pause_monitor, which keeps the monitor and its history. There is no bulk delete. Requires a key with the write scope. Returns {"success": true}.
| Name | Required | Description | Default |
|---|---|---|---|
| monitor_id | Yes | The monitor's uuid from list_monitors. An id that is not a monitor of this organization, or a deleted one, is a 404. |
Output Schema
| Name | Required | Description |
|---|---|---|
| success | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already flag destructiveHint=true and idempotentHint=true, but the description adds the irreversibility guarantee ('no tool restores it'), the side effect on monitoring ('stops being checked'), the authorization prerequisite ('Requires a key with the write scope'), and the 404 semantics on unknown/deleted ids. These go meaningfully beyond the annotation flags.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Dense and well front-loaded: the destructive effect and irreversibility come before the alternative and the prerequisite. The trailing 'Returns {"success": true}' restates what the existing output schema already conveys, a minor redundancy that keeps it short of a perfect score.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a single-parameter destructive tool with full annotation coverage and an output schema, the description supplies exactly the missing pieces: reversibility, authorization, sibling routing, and bulk-delete absence. An agent has everything needed to call it correctly and safely.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and the single monitor_id parameter is fully documented in the schema (uuid format, source from list_monitors, 404 on invalid/deleted id). The description therefore does not need to compensate and adds no parameter-level detail the schema lacks — baseline 3 is correct.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Delete one monitor') and immediately describes the effect: it stops being checked and disappears from the organization's monitors, with no restoration path. It also explicitly contrasts with the closest sibling (pause_monitor) and rules out a bulk variant, so an agent can select it confidently without opening another schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit when-to-use ('only when the user explicitly asked for deletion'), explicit when-not ('otherwise prefer pause_monitor, which keeps the monitor and its history'), and an explicit scope exclusion ('There is no bulk delete'). Nothing is left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
delete_status_page_incidentDelete a status page incidentADestructiveIdempotentInspect
Remove an incident and its timeline from a status page; it stops showing at once, nothing is sent to subscribers, and no tool restores it. Use it for an incident posted by mistake; to close a real one use post_status_page_update with RESOLVED. Requires a key with the write scope. Returns {"success": true}.
| Name | Required | Description | Default |
|---|---|---|---|
| page_id | Yes | The status page's uuid from list_status_pages. An id that is not a status page of this organization is a 404. | |
| incident_id | Yes | The status page incident's uuid from list_status_page_incidents (not from list_incidents). An unknown id is a 404. |
Output Schema
| Name | Required | Description |
|---|---|---|
| success | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true and readOnlyHint=false, but the description goes further: it states the effect is immediate, that subscribers are not notified, that it is irreversible ('no tool restores it'), and that a write-scoped key is required. That is exactly the extra context annotations cannot carry.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loads the destructive outcome and the alternative route in three tight clauses with no filler. The closing 'Returns {"success": true}' is redundant given the output schema exists, a small waste.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a destructive, irreversible mutation the description covers effect, notification behavior, reversibility, auth scope, and the correct alternative tool; return values are already covered by the output schema. An agent has everything needed to call it safely.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and the schema already explains both page_id and incident_id, including the 404 behavior and which list tool supplies each id. The description adds no parameter-level detail, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Specific verb (remove) plus resource (status page incident and its timeline), and it explicitly distinguishes itself from create_status_page_incident and update_status_page_incident by describing the delete-only semantics. An agent can identify the right sibling without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives an explicit when-to-use ('an incident posted by mistake') and an explicit when-not with the named alternative ('to close a real one use post_status_page_update with RESOLVED'). Nothing is left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
delete_tagRemove a tag everywhereADestructiveIdempotentInspect
Remove a tag from every monitor and heartbeat that carries it; the items themselves stay, and no tool restores the tag. Use it to retire a tag across the organization; to take it off chosen monitors only use bulk_update_monitor_tags with remove, and to rename it use rename_tag. Requires a key with the write scope. A tag nothing carries is not an error (both counts are 0). Returns from (the tag), monitors_updated and heartbeats_updated.
| Name | Required | Description | Default |
|---|---|---|---|
| tag | Yes | The tag to remove, exactly as list_tags shows it. |
Output Schema
| Name | Required | Description |
|---|---|---|
| from | Yes | |
| monitors_updated | Yes | |
| heartbeats_updated | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructive=true, idempotent=true, readOnly=false, but the description adds behavior beyond them: the tagged items survive, no tool can restore the tag (irreversibility), a write-scoped key is required, and deleting an unattached tag is not an error (counts 0). These are meaningful operational facts not derivable from 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.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the effect and its scope, then alternatives, then prerequisites, then edge cases and return shape. Every clause carries distinct information with no filler or repetition.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a destructive, single-parameter mutation with an output schema present, the description covers effect, irreversibility, alternatives, auth requirement, and the empty-input edge case. An agent has everything needed to invoke it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With one parameter at 100% schema coverage, the schema already documents the 'tag' argument and its format ('exactly as list_tags shows it'). The description adds little parameter-level meaning beyond restating that the tag is echoed back in the response, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (remove) and resource (tag) plus the exact scope: 'from every monitor and heartbeat that carries it'. It explicitly contrasts itself with the two nearest siblings (bulk_update_monitor_tags for selective removal, rename_tag for renaming), so an agent can distinguish it without opening a schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit when-to-use ('retire a tag across the organization') and two when-not cases with named alternatives and their selecting conditions ('take it off chosen monitors only use bulk_update_monitor_tags with remove'; 'to rename it use rename_tag'). Nothing is left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_exposed_ports_presetGet the exposed-ports presetARead-onlyIdempotentInspect
List the ports that should never be reachable from the internet (databases, queues, admin panels). Returns ports, each a port number and the service that usually listens on it. Use it to pick ports when asked to watch a server for exposed services; it creates nothing. Then create one TCP monitor on the server's public hostname or IP with config {"ports": [...], "expected_state": "closed"} (1 to 20 distinct ports, one region, interval_seconds 300 or more; 3600 is plenty) through create_monitor: it counts as one monitor and fails naming every port that answers.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| ports | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint/idempotentHint/destructiveHint=false, so 'it creates nothing' is largely redundant. The description still adds genuine value by describing what the list contains (port number plus the service that usually listens on it) and by warning how the data is consumed downstream (one monitor counted, fails naming every answering port).
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the purpose in the first clause, then uses. The final sentence is long and packs create_monitor configuration details that arguably belong in that tool's own docs, though they are actionable for completing the workflow.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter preset lookup with rich annotations and an output schema, this is more than sufficient: purpose, return content, safe-to-call status, and the intended downstream workflow are all covered.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, which is the baseline-4 case; nothing in the description is needed to disambiguate arguments. The mention of the 1-20 distinct ports / interval_seconds constraints pertains to create_monitor's payload, not this tool's schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource with scope: 'List the ports that should never be reachable from the internet (databases, queues, admin panels).' It also names the return content, so an agent knows this is a static preset lookup rather than a scan of any particular server, distinguishing it from siblings like check_target or get_monitor.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly says when to use it ('Use it to pick ports when asked to watch a server for exposed services'), what it does not do ('it creates nothing'), and names the follow-up tool with the exact config shape, port/region/interval constraints, and the failure semantics of that call.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_heartbeatGet a heartbeat monitorARead-onlyIdempotentInspect
Read one heartbeat in full, including how long its last run took. It has name, state, period_seconds, grace_seconds, ping_url, last_ping_at, last_success_at, last_start_at, last_duration_ms (how long the last run took, from its /start to its success ping), overdue_at (when it will be reported late), notification_cooldown_seconds, is_active, channel_ids and tags. Use it to answer whether a job ran, how long it took and when it is next due. To find a heartbeat use list_heartbeats; to change it use update_heartbeat; probed monitors are get_monitor.
| Name | Required | Description | Default |
|---|---|---|---|
| heartbeat_id | Yes | The heartbeat's uuid from list_heartbeats. An id that is not a heartbeat of this organization, or a deleted one, is a 404. |
Output Schema
| Name | Required | Description |
|---|---|---|
| id | Yes | |
| name | Yes | |
| tags | No | |
| state | Yes | Known values: PENDING, UP, DOWN, PAUSED. |
| ping_url | Yes | |
| is_active | Yes | |
| created_at | Yes | |
| overdue_at | Yes | |
| updated_at | Yes | |
| channel_ids | No | |
| last_ping_at | Yes | |
| grace_seconds | Yes | |
| last_start_at | Yes | |
| period_seconds | Yes | |
| last_success_at | Yes | |
| last_duration_ms | Yes | |
| notification_cooldown_seconds | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the safety profile (readOnly, idempotent, non-destructive), and the description adds genuinely useful semantic context on returned fields such as last_duration_ms being measured from /start to success ping and overdue_at meaning the late-report time. It stops short of discussing pagination or error behavior beyond the schema's 404 note, so a 4 rather than a 5.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Purpose and routing are front-loaded in the first and last sentences, which is good structure. However, the long enumeration of returned fields is partly redundant given an output schema exists, so it is not maximally economical.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a single-parameter read tool with annotations and a full output schema, the description covers purpose, usage, alternatives, and field interpretation adequately. The field list slightly duplicates the output schema rather than adding new information, leaving a minor gap in efficiency rather than completeness.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Only one parameter and schema description coverage is 100%, with the schema already documenting that heartbeat_id comes from list_heartbeats and that foreign/deleted ids yield 404. The description adds no parameter-specific meaning, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Read one heartbeat in full') and explicitly distinguishes itself from get_monitor ('probed monitors are get_monitor'), so an agent can separate this from the closest sibling without opening either schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives the use case ('answer whether a job ran, how long it took and when it is next due') plus explicit alternatives for the adjacent tasks: list_heartbeats to find one, update_heartbeat to change it, get_monitor for probed monitors. Nothing is left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_incidentGet an incidentARead-onlyIdempotentInspect
Read one incident in full, with every alert sent for it. It has id, monitor_id or heartbeat_id (exactly one is set), started_at, resolved_at, cause, cause_detail, last_notified_at, acknowledged_at, acknowledged_by, renotify_count and notification_logs (each alert attempt: id, channel_type, destination, event TRIGGERED, RESOLVED or SSL_EXPIRY, sent_at, status PENDING, SENT or FAILED, and error). Use it to tell who acknowledged an incident and whether its alerts were delivered. destination is an email address, a Telegram chat id, or only scheme://host/… of a webhook. To find incidents use list_incidents; to stop its reminders use acknowledge_incident.
| Name | Required | Description | Default |
|---|---|---|---|
| incident_id | Yes | The incident's uuid from list_incidents. An id that is not an incident of this organization is a 404. |
Output Schema
| Name | Required | Description |
|---|---|---|
| id | Yes | |
| cause | Yes | Known values: TIMEOUT, DNS_FAILURE, CONNECTION_REFUSED, TLS_INVALID, HTTP_4XX, HTTP_5XX, HTTP_UNEXPECTED_STATUS, KEYWORD_MISSING, TOO_MANY_REDIRECTS, TARGET_BLOCKED, PORT_STATE_MISMATCH, INVALID_TARGET, HEARTBEAT_MISSED, HEARTBEAT_FAILED, UNKNOWN. |
| created_at | Yes | |
| monitor_id | No | |
| started_at | Yes | |
| updated_at | Yes | |
| resolved_at | Yes | |
| cause_detail | Yes | |
| heartbeat_id | No | |
| renotify_count | Yes | |
| acknowledged_at | Yes | |
| acknowledged_by | Yes | |
| last_notified_at | Yes | |
| notification_logs | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, destructiveHint=false, and openWorldHint=false. The description adds valuable context beyond annotations: exactly one of monitor_id or heartbeat_id is set, notification_logs fields with event/status/error semantics, and destination formats. Missing only auth or rate-limit details, which are minor for a read tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with core purpose. The long enumeration of return fields is somewhat redundant with the existing output schema, making the description longer than strictly necessary. Still well-structured and every sentence serves a purpose for an agent.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a single-parameter read tool with an output schema and rich annotations, the description covers purpose, usage, alternatives, return content, and destination formats. Nothing an agent needs to call it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and the single required parameter is fully documented in the schema (uuid from list_incidents, 404 for wrong organization). The description adds no parameter-specific syntax or constraints 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.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb 'Read' and resource 'incident' with scope 'in full, with every alert sent for it'. Explicitly distinguishes from siblings by naming list_incidents and acknowledge_incident, so an agent can tell it apart 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.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly states the use case: 'Use it to tell who acknowledged an incident and whether its alerts were delivered.' Names alternatives: list_incidents to find incidents and acknowledge_incident to stop reminders. Provides both when-to-use and when-to-use-alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_maintenance_windowGet a maintenance windowARead-onlyIdempotentInspect
Read one maintenance window with its schedule and its next three occurrences. It has the list_maintenance_windows fields plus next_occurrences, each with start and end. Use it to confirm when a recurring window fires next. To check a schedule before saving it use preview_maintenance_window; to find a window use list_maintenance_windows.
| Name | Required | Description | Default |
|---|---|---|---|
| window_id | Yes | The window's uuid from list_maintenance_windows. An id that is not a window of this organization is a 404. |
Output Schema
| Name | Required | Description |
|---|---|---|
| id | Yes | |
| name | Yes | |
| rrule | Yes | |
| scope | Yes | Known values: MONITOR, ORG. |
| dtstart | Yes | |
| enabled | Yes | |
| timezone | Yes | |
| created_at | Yes | |
| monitor_ids | No | |
| duration_minutes | Yes | |
| next_occurrences | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, destructiveHint=false and closed-world, so the safety profile is fully covered. The description adds the return payload shape (schedule plus next_occurrences with start/end), but with an output schema present this is largely redundant and it says nothing about permissions or rate limits.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short sentences, front-loaded with the core action, then the usage case, then the sibling routing. Every clause earns its place with no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a one-parameter read with a full output schema and complete annotations, the description covers purpose, usage, and alternatives. Nothing an agent needs 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.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and there is a single required parameter, so the schema already documents window_id fully. The description adds no syntax, format, or sourcing detail beyond what the schema provides, making the baseline 3 correct.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Read one maintenance window') and immediately scopes it against siblings by naming preview_maintenance_window and list_maintenance_windows. An agent can tell it apart from the other maintenance-window tools without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly gives the selecting condition ('Use it to confirm when a recurring window fires next') and routes to the two alternatives with their own conditions ('to check a schedule before saving it', 'to find a window'). Nothing is left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_monitorGet a monitorARead-onlyIdempotentInspect
Read one monitor's full configuration and current state. It has type, target, interval_seconds, timeout_seconds, regions, config, status, is_active, confirmation_threshold, notification_cooldown_seconds, channel_ids (empty means every verified, active channel is alerted), tags, badge_enabled, last_checked_at, next_run_at, and for SSL monitors ssl_expires_at and ssl_cert_info. Use it before update_monitor, since a config you send replaces the stored one whole. Not for finding a monitor (list_monitors), its uptime (get_uptime_summary) or why it fails (list_check_results).
| Name | Required | Description | Default |
|---|---|---|---|
| monitor_id | Yes | The monitor's uuid from list_monitors. An id that is not a monitor of this organization, or a deleted one, is a 404. |
Output Schema
| Name | Required | Description |
|---|---|---|
| id | Yes | |
| name | Yes | |
| tags | No | |
| type | Yes | Known values: HTTP, PING, SSL, TCP, DNS. |
| config | Yes | |
| status | Yes | Known values: PENDING, UP, DEGRADED, DOWN, PAUSED. |
| target | Yes | |
| regions | Yes | |
| user_id | Yes | |
| is_active | Yes | |
| created_at | Yes | |
| updated_at | Yes | |
| channel_ids | No | |
| next_run_at | Yes | |
| badge_enabled | No | |
| ssl_cert_info | No | |
| ssl_expires_at | Yes | |
| last_checked_at | Yes | |
| region_statuses | Yes | Per-region latest status, sorted by region name. Built from ``region_snapshots``; ``job_id`` is dropped (internal dedup key) and malformed/partial snapshot rows are skipped rather than failing the read. |
| timeout_seconds | Yes | |
| interval_seconds | Yes | |
| confirmation_threshold | Yes | |
| notification_cooldown_seconds | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare the tool as read-only, idempotent, and non-destructive, but the description adds important operational context beyond those hints. It explains the whole-config replacement behavior of update_monitor, clarifies that an empty channel_ids means all verified active channels are alerted, and notes SSL-specific fields.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with the core purpose, followed by usage guidance and exclusions in a logical order. The long field list is relevant to understanding what a full configuration includes, though it is somewhat redundant because an output schema exists.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's simplicity, the detailed schema, annotations, and presence of an output schema, the description is complete enough for correct invocation. It covers purpose, pre-update usage, field semantics, and sibling routing without needing to explain return formatting.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, and the monitor_id parameter is already documented as a UUID from list_monitors with 404 semantics for unknown or deleted monitors. The description does not add meaning beyond the schema for this single parameter, so the baseline of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb and resource: read one monitor's full configuration and current state. It enumerates the key fields returned and explicitly distinguishes the tool from list_monitors, get_uptime_summary, and list_check_results, so an agent can identify its role without ambiguity.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It states a concrete usage condition: call it before update_monitor because update configs replace the stored configuration wholesale. It also names when not to use it and routes the agent to the correct alternatives for listing, uptime, and failure investigation.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_plan_usageGet plan usageARead-onlyIdempotentInspect
Show the organization's plan, its limits and current usage, to check that new monitors, heartbeats or regions fit before creating them or to explain a 403 naming a limit. Region codes and their cities come from list_regions; billing changes happen only in the dashboard. Values are current as of the call. Returns plan (one of FREE, PLUS, PRO, MAX, ENTERPRISE), limits and usage. limits: max_monitors, min_interval_seconds, max_fast_monitors (monitors below fast_interval_threshold_seconds, 60), max_regions per monitor, allowed_regions, max_heartbeats, max_maintenance_windows, history_retention_days, api_rate_limit_per_minute (shared by the whole organization), renotify_interval_seconds and renotify_max_count (how often and how many times an open, unacknowledged incident is alerted again; 0 means no reminders); null means no limit. usage: monitors (paused included), fast_monitors and heartbeats.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| plan | Yes | Known values: FREE, PLUS, PRO, MAX, ENTERPRISE. |
| usage | Yes | |
| limits | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description adds substantial context beyond the annotations: values are current as of the call, null means no limit, API rate limits are shared by the whole organization, and renotify fields describe incident alerting behavior. It also clarifies the output categories plan, limits, and usage in enough detail to support interpretation.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with purpose and usage before moving into field-level detail. It is somewhat long and repeats some return-value information that may already be captured by the output schema, but the detail largely earns its place for a tool whose limits and usage values need interpretation.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's breadth and the presence of an output schema, the description provides all the context an agent needs: when to call it, what the values mean, how limits should be interpreted, and where related actions belong. No material behavioral or usage gap remains.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
There are zero parameters, so the baseline is 4. The description does not need to explain parameter meaning, and it does not introduce any parameter-related ambiguity.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: showing the organization's plan, limits, and current usage. It also distinguishes its scope from related operations by naming list_regions for region codes and the dashboard for billing changes, so an agent can identify it without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives explicit when-to-use guidance: before creating monitors, heartbeats, or regions, and when explaining a 403 that names a limit. It also names alternatives for region data and billing changes, making the selection criteria clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_response_time_by_regionGet a monitor's response time by regionARead-onlyIdempotentInspect
Chart one monitor's average response time over time, one series per region, to see where it is slow and since when. Returns monitor_id, window, bucket_seconds and regions, each with region, display_name and points (oldest first, the same buckets in every series: bucket_start, avg_response_time_ms, null when the bucket had no successful check, and sample_count). Every configured region has a series, even an empty one, followed by removed regions that still had checks; points start at the window's start or at the monitor's creation. For uptime use get_uptime_summary; for single checks use list_check_results.
| Name | Required | Description | Default |
|---|---|---|---|
| window | No | 24h (the default; up to 24 hourly buckets), 7d (up to 28 six-hourly buckets) or 30d (up to 30 daily buckets). | |
| monitor_id | Yes | The monitor's uuid from list_monitors. An id that is not a monitor of this organization, or a deleted one, is a 404. |
Output Schema
| Name | Required | Description |
|---|---|---|
| window | Yes | |
| regions | Yes | |
| monitor_id | Yes | |
| bucket_seconds | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description adds substantial behavioral detail beyond the annotations, including the exact return payload shape, bucket alignment across regions, null handling for empty buckets, sample_count, inclusion of empty configured regions, and treatment of removed regions with checks. Annotations already establish read-only safety, but the description goes further by explaining output semantics and data ordering.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with its purpose, then moves efficiently through return structure and alternative tools. Despite its length, every sentence carries useful information about output shape, ordering, region inclusion, or routing.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present, the description need not define return values, but it still provides rich return semantics, region inclusion rules, bucket alignment, and alternative-tool guidance. Given the annotations, complete schema coverage, and output schema, it is fully 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.
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 the window enum and monitor_id UUID semantics. The description does not add parameter-specific syntax or constraints beyond what the schema provides, 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.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: chart one monitor's average response time over time, one series per region. It also names the sibling alternatives get_uptime_summary and list_check_results, so an agent can distinguish this tool from related uptime and check-listing tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The final sentence gives explicit routing guidance: use get_uptime_summary for uptime and list_check_results for single checks. The opening sentence also clarifies the intended analytical use case of seeing where and since when a monitor is slow by region.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_status_pageGet a status pageARead-onlyIdempotentInspect
Read one status page with its components. It has the list_status_pages fields, where each component has id, monitor_id, display_name and position. Use it to get the component ids that create_status_page_incident takes as component_ids. To find a page use list_status_pages; for the incidents posted on it use list_status_page_incidents.
| Name | Required | Description | Default |
|---|---|---|---|
| page_id | Yes | The status page's uuid from list_status_pages. An id that is not a status page of this organization is a 404. |
Output Schema
| Name | Required | Description |
|---|---|---|
| id | Yes | |
| name | Yes | |
| slug | Yes | |
| groups | Yes | |
| created_at | Yes | |
| description | Yes | |
| history_days | Yes | |
| is_published | Yes | |
| ungrouped_components | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, destructiveHint=false, and openWorldHint=false, so safety behavior is covered. The description adds value beyond that by disclosing the shape of the returned components (id, monitor_id, display_name, position) and the downstream consumer of the ids, which annotations cannot convey.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core action, then the routing guidance, with no filler sentences. The middle sentence describing component fields is slightly dense but earns its place by telling the agent what it will get back for the component_ids use case.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present, the return values need not be re-explained, yet the description still summarizes component fields relevant to the chained call. Combined with a fully documented parameter and read-only annotations, 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.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and the single parameter's description already states the UUID source (list_status_pages) and the 404 for foreign ids. The description adds essentially no syntax or format detail beyond the schema, so the baseline 3 for a fully documented single parameter is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Read one status page with its components') and immediately differentiates it from the closely related list_status_pages and list_status_page_incidents. An agent can distinguish this from every sibling without opening a schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly names the alternative for discovery ('To find a page use list_status_pages'), the alternative for the related sub-resource ('for the incidents posted on it use list_status_page_incidents'), and states a concrete downstream use case (feeding component_ids into create_status_page_incident). When-to-use is fully spelled out.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_uptime_dailyGet a monitor's daily uptimeARead-onlyIdempotentInspect
Report one monitor's uptime for each UTC day, oldest first and ending today, to find the day an outage or degradation began. Each day has date, uptime_percentage, total_checks, up_checks, down_checks, degraded_checks and maintenance_checks; a degraded check counts as up, and a day with no checks outside maintenance has a null uptime_percentage, not 100. For 24h, 7d and 30d totals use get_uptime_summary. Returns monitor_id and days.
| Name | Required | Description | Default |
|---|---|---|---|
| days | No | How many days to return, 1 to 365; default 30. Capped at the plan's limits.history_retention_days (get_plan_usage), so fewer days can come back. | |
| monitor_id | Yes | The monitor's uuid from list_monitors. An id that is not a monitor of this organization, or a deleted one, is a 404. |
Output Schema
| Name | Required | Description |
|---|---|---|
| days | Yes | |
| monitor_id | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the read-only/idempotent profile, and the description adds real behavioral semantics beyond them: degraded checks count as up, days with only maintenance checks yield null uptime_percentage rather than 100, ordering is oldest-first, and results are capped at the plan's history retention. These are exactly the non-obvious traits an agent needs.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three tight sentences: purpose and ordering first, then field semantics and the null-edge case, then the sibling hand-off. Dense but every clause carries information; no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 2-param read tool with annotations and an output schema, the description covers purpose, ordering, edge cases, retention behavior, and the alternative tool. Nothing an agent needs to call it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so both parameters are documented, giving a baseline of 3. The description adds value beyond the schema by reinforcing the retention cap and noting that fewer days than requested can be returned, clarifying the effective behavior of 'days'.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Report one monitor's uptime for each UTC day') with explicit scope (oldest first, ending today). It distinguishes itself from get_uptime_summary by naming that sibling as the alternative for aggregate totals.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives a concrete use case ('to find the day an outage or degradation began') and explicitly routes the agent to get_uptime_summary for 24h/7d/30d totals. Both when-to-use and the alternative are spelled out.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_uptime_summaryGet uptime for a monitorARead-onlyIdempotentInspect
Report one monitor's uptime percentage, average response time and incident count over the last 24 hours, 7 days and 30 days at once, to answer how reliable it has been. For a day-by-day series use get_uptime_daily; for response time per region use get_response_time_by_region; for the individual failures use list_check_results. Returns monitor_id and windows keyed 24h, 7d and 30d, each with uptime_percentage (DEGRADED checks count as up; null when there were no checks), total_checks, up_checks, down_checks, degraded_checks, incident_count and avg_response_time_ms.
| Name | Required | Description | Default |
|---|---|---|---|
| monitor_id | Yes | The monitor's uuid from list_monitors. An id that is not a monitor of this organization, or a deleted one, is a 404. |
Output Schema
| Name | Required | Description |
|---|---|---|
| windows | Yes | |
| monitor_id | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly/idempotent/non-destructive, but the description adds real behavioral semantics beyond them: DEGRADED checks count as up, uptime_percentage is null when there were no checks, and incident_count/avg_response_time_ms are surfaced. It omits anything about permissions or rate limits, but the key interpretive caveats are disclosed.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Purpose is front-loaded, followed by routing and then the return shape; every sentence carries information. The long enumeration of return fields is somewhat heavy given an output schema already exists, which is the only reason this isn't a 5.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a single-parameter read tool with full annotations and an output schema present, the description is more than adequate; it even spells out the window keys and metric names. The return-value detail is partly redundant with the output schema, but nothing an agent needs in order to call it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
There is only one parameter and schema coverage is 100%, so the schema already documents monitor_id fully, including the uuid format and the 404 behavior. The description adds no further parameter meaning, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource (uptime percentage, average response time, incident count for one monitor) and scopes it precisely to three fixed windows (24h, 7d, 30d). It also names the sibling tools it is not, so an agent can distinguish it from get_uptime_daily and get_response_time_by_region without opening either schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly routes the agent: 'For a day-by-day series use get_uptime_daily; for response time per region use get_response_time_by_region; for the individual failures use list_check_results.' This is textbook when-to-use/when-not guidance with named alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_active_maintenanceList maintenance windows in effect nowARead-onlyIdempotentInspect
List the enabled maintenance windows in effect at this moment, to tell whether a monitor's alerts are silenced now. An ORG-scope window covers every monitor, a MONITOR-scope one its monitor_ids. For every window, including future and disabled ones, use list_maintenance_windows. Returns a plain array (not a page) of list_maintenance_windows items; empty when nothing is silenced.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent and non-destructive, so the safety profile is covered. The description adds real behavioral context beyond that: the return is a plain array rather than a page, and it is empty when nothing is silenced. It does not mention sort order or item shape, but that is a minor gap given the annotation coverage.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences, zero waste, and the most decision-relevant information (what it lists, and the sibling to use otherwise) is front-loaded. Every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
No output schema exists, so the description carries the burden of describing returns — and it does, stating the array-vs-page shape and the empty result semantics. Combined with the scope explanation and the sibling routing, an agent has everything needed to call this correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so there is no parameter syntax for the description to compensate for. Baseline 4 applies; the description correctly signals the absence of filters by noting the call is unscoped.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('list the enabled maintenance windows in effect at this moment') plus the scope model (ORG covers every monitor, MONITOR covers its monitor_ids). It explicitly distinguishes itself from the sibling list_maintenance_windows, so an agent can pick between them without opening either schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives an explicit when-to-use ('to tell whether a monitor's alerts are silenced now') and an explicit when-not / alternative: 'For every window, including future and disabled ones, use list_maintenance_windows.' Nothing is left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_channelsList notification channelsARead-onlyIdempotentInspect
List the organization's notification channels (up to 100), to get the ids that channel_ids of monitors and heartbeats take. Each has id, type (TELEGRAM, WEBHOOK, SLACK or DISCORD), label, is_verified, is_active and destination_hint (a chat id, a masked address, or a webhook's scheme and host). Only a verified, active channel is alerted; an unverified one can be bound but receives nothing yet, and an inactive or unknown id cannot be bound (404). Email is not a channel: every alert also goes to the account email of whoever created the monitor or heartbeat. Channels are added only in the dashboard.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare read-only/idempotent/non-destructive, and the description adds substantial context beyond them: a 100-item cap, the alerting semantics of verified+active vs. unverified vs. inactive, the 404 on binding an inactive or unknown id, and the clarification that email is not a channel. These are exactly the behavioral facts an agent cannot infer from annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loads what the tool is and why before enumerating fields, and every sentence carries information. The email aside is slightly tangential but it preempts a plausible agent mistake, so it still earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
No output schema exists, so the description must carry the return shape, and it does: id, type (with the full enum), label, is_verified, is_active, destination_hint, plus the meaning of each status flag. Nothing needed to call or interpret this tool is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so there is nothing for the description to disambiguate; per the baseline for parameterless tools this is a 4. The description instead spends its budget on return-value semantics, which is the right trade.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource ('List the organization's notification channels') and immediately explains the reason to call it: to obtain the ids that channel_ids of monitors and heartbeats take. That framing distinguishes it from every sibling list_* tool, which list monitors, incidents, tags, etc.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives a clear purpose-driven context (resolve ids for binding to monitors/heartbeats) and explicitly closes the loop on creation: 'Channels are added only in the dashboard,' telling the agent there is no create tool to reach for. It does not name alternative siblings, but none are genuinely substitutable for this call.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_check_resultsList a monitor's check resultsARead-onlyIdempotentInspect
List one monitor's individual check results, newest first, to find out why it is DOWN: which regions fail and with what status code or error. Each has id, region, checked_at, status, response_time_ms, status_code, error_message, details and maintenance_window_id (set when the check ran inside a window). For totals use get_uptime_summary or get_uptime_daily; for the incident they opened use list_incidents. Returns a page: items plus total (of matching results), page, size and pages.
| Name | Required | Description | Default |
|---|---|---|---|
| page | No | Page number, 1 or more; default 1. | |
| size | No | Rows per page, 1 to 100; default 25. Keep paging until you have seen total rows. | |
| region | No | Keep one region's results: its exact code, up to 64 characters. | |
| status | No | Keep results with this status only. | |
| monitor_id | Yes | The monitor's uuid from list_monitors. An id that is not a monitor of this organization, or a deleted one, is a 404. | |
| period_days | No | Keep results of the last N days, 1 to 365; without it every stored result is eligible. |
Output Schema
| Name | Required | Description |
|---|---|---|
| page | Yes | |
| size | Yes | |
| items | Yes | |
| pages | Yes | |
| total | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations cover the safety profile (readOnly, idempotent, non-destructive), and the description adds ordering (newest first), the semantics of maintenance_window_id (set when the check ran inside a window), and the paging contract. It does not discuss result retention limits or any rate/volume caveats, so it falls short of the richest disclosure but clearly adds context beyond annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the diagnostic purpose, then the returned fields, then routing to alternatives, then the pagination contract — a logical order with near-zero filler. The 'Returns a page: items plus total, page, size and pages' sentence is largely redundant given an output schema exists, which keeps it from a 5.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a six-parameter paginated read tool with full schema coverage, an output schema and read-only annotations, the description supplies everything an agent needs: purpose, the diagnostic use case, sibling routing, field-level meaning for maintenance_window_id, and how to page. No material gap remains.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so page, size, region, status, monitor_id and period_days are already documented, including enum values and the 404 case. The description adds no filter syntax or semantics beyond the field names it enumerates, so the baseline of 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource (list one monitor's individual check results) plus scope (newest first) and diagnostic intent ('to find out why it is DOWN'). An agent can distinguish it from list_monitors, get_uptime_summary and list_incidents without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly frames the when ('to find out why it is DOWN: which regions fail and with what status code or error') and names two alternatives with their selecting conditions: get_uptime_summary/get_uptime_daily for totals, list_incidents for the incident they opened. Nothing is left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_heartbeatsList heartbeat monitorsARead-onlyIdempotentInspect
Find heartbeat (cron / dead-man's-switch) monitors. Each has id, name, state (PENDING until a success ping makes it UP or a /fail ping makes it DOWN; later UP, DOWN or PAUSED), period_seconds, grace_seconds, ping_url, last_ping_at, last_success_at, overdue_at, tags and channel_ids. Use it to get a heartbeat's id or ping_url, or to see which jobs are late (sort status puts DOWN first). Probed URLs and hosts are monitors: use list_monitors for those. For one heartbeat's full record, with its last run's duration, use get_heartbeat. Returns a page: items plus total, page, size and pages.
| Name | Required | Description | Default |
|---|---|---|---|
| q | No | Case-insensitive substring of the name, up to 255 characters. | |
| tag | No | Keep items carrying these tags: a JSON array of up to 10 tags, each up to 50 characters, lowercased before matching. tag_match decides whether all or any of them must match. | |
| page | No | Page number, 1 or more; default 1. | |
| size | No | Rows per page, 1 to 100; default 25. Keep paging until you have seen total rows. | |
| sort | No | status (the default: DOWN, PENDING, UP, PAUSED, newest first within each), name, or created_at (newest first). | |
| tag_match | No | all (the default): an item must carry every tag in tag. any: at least one of them. |
Output Schema
| Name | Required | Description |
|---|---|---|
| page | Yes | |
| size | Yes | |
| items | Yes | |
| pages | Yes | |
| total | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the read-only/idempotent/non-destructive profile, but the description adds real substance beyond them: the PENDING→UP/DOWN/PAUSED state machine, the meaning of last_ping_at/overdue_at, and the paginated return shape ('items plus total, page, size and pages'). It does not discuss rate limits or auth, but for a read-only list tool this is a rich disclosure.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with purpose and usage before field details, and each sentence carries routing or state information. The long field enumeration is mildly redundant given an output schema exists, but it is compact and not padded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Covers filters, sort behavior, sibling disambiguation, and result paging, which is everything an agent needs to call it correctly. Return-value detail slightly overlaps the output schema but does not leave any gap.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so every parameter (q, tag, page, size, sort, tag_match) is already fully documented in the schema, including defaults and enum meanings. The description only echoes the sort ordering already in the schema ('sort status puts DOWN first'), adding no new syntax or semantics.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Opens with a specific verb+resource ('Find heartbeat (cron / dead-man's-switch) monitors') and immediately enumerates the returned fields, so the agent knows exactly what this list yields. It also draws explicit boundaries against the two nearest siblings, list_monitors and get_heartbeat, making selection unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives concrete when-to-use cases ('get a heartbeat's id or ping_url', 'see which jobs are late'), an explicit when-not ('Probed URLs and hosts are monitors: use list_monitors for those'), and names get_heartbeat for the single-record case. All three routing decisions are stated rather than inferred.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_incidentsList incidentsARead-onlyIdempotentInspect
List the organization's monitor and heartbeat incidents, newest first, to see what is or was down and which alerts went out. Each item has id, monitor_id or heartbeat_id (exactly one is set), started_at, resolved_at (null while open), cause, cause_detail (the raw check error), acknowledged_at and notification_logs: the alerts sent, oldest first, each with id, channel_type (EMAIL, TELEGRAM, WEBHOOK, SLACK or DISCORD), destination (may be masked), event (TRIGGERED for the first alert and every reminder, RESOLVED for the recovery), sent_at, status (PENDING while a webhook, Slack or Discord delivery is still being tried, then SENT or FAILED) and error (the last delivery error). For one incident's full record use get_incident; for the checks behind it use list_check_results; incidents posted on a status page are list_status_page_incidents. An incident resolves by itself when its monitor or heartbeat recovers. Returns a page: items plus total, page, size and pages. An invalid value is a 422 naming the argument. Example: {"status": "open", "size": 50}
| Name | Required | Description | Default |
|---|---|---|---|
| page | No | Page number, 1 or more; default 1. | |
| size | No | Rows per page, 1 to 100; default 25. Keep paging until you have seen total rows. | |
| cause | No | Keep one failure cause, such as TIMEOUT, HTTP_5XX or HEARTBEAT_MISSED. | |
| status | No | open or resolved (lowercase); omit it for both. | |
| monitor_id | No | Keep one monitor's incidents: its uuid from list_monitors. | |
| period_days | No | Keep incidents active within the last N days, 1 to 365. An open incident always qualifies, so with status open it changes nothing: use status resolved, or omit status, to see the window take effect. |
Output Schema
| Name | Required | Description |
|---|---|---|
| page | Yes | |
| size | Yes | |
| items | Yes | |
| pages | Yes | |
| total | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover safety (readOnlyHint, idempotentHint, non-destructive, closed-world), yet the description adds substantial context: newest-first ordering, the self-resolving lifecycle, the 422 error shape on invalid values, and the notification delivery state machine (PENDING while a webhook/Slack/Discord delivery is retried, then SENT or FAILED with the last error). This goes well beyond the structured fields.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Purpose and alternatives are front-loaded, but the body is one dense run-on paragraph enumerating return fields (id, started_at, resolved_at, cause, notification_logs, channel_type, destination, event, sent_at, status, error) that an output schema already carries. Much of that inventory does not earn its place against a structured output contract.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only filtered list with 6 optional parameters, the description covers scope, ordering, alternatives, resolution semantics, pagination and error behavior. An agent has everything needed to call it correctly and interpret the result.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the baseline is 3, but the description adds a worked example ({'status': 'open', 'size': 50}) showing a valid filter combination and reinforces pagination intent. It does not add per-parameter syntax beyond the schema, so it does not reach 5.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('List the organization's monitor and heartbeat incidents, newest first') and immediately bounds the scope to what is or was down. It explicitly distinguishes itself from get_incident, list_check_results and list_status_page_incidents, so an agent can route without opening another schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Names the three alternative tools and the condition selecting each ('For one incident's full record use get_incident; for the checks behind it use list_check_results; incidents posted on a status page are list_status_page_incidents'). It also explains the resolution lifecycle, telling the agent an incident clears itself on monitor/heartbeat recovery.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_maintenance_windowsList maintenance windowsARead-onlyIdempotentInspect
List every maintenance window of the organization, enabled or not, in effect or not. Each has id, name, enabled, scope (ORG or MONITOR), dtstart, duration_minutes, rrule, timezone, monitor_ids and created_at. Use it to find a window's id. To learn whether alerts are silenced right now use list_active_maintenance; for a window's upcoming occurrences use get_maintenance_window. Returns a page: items plus total, page, size and pages.
| Name | Required | Description | Default |
|---|---|---|---|
| q | No | Case-insensitive substring of the name, up to 255 characters. | |
| page | No | Page number, 1 or more; default 1. | |
| size | No | Rows per page, 1 to 100; default 25. Keep paging until you have seen total rows. | |
| sort | No | created_at (the default, newest first) or name. |
Output Schema
| Name | Required | Description |
|---|---|---|
| page | Yes | |
| size | Yes | |
| items | Yes | |
| pages | Yes | |
| total | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent, non-destructive, closed-world, so the safety profile is covered. The description goes beyond that by disclosing that results include both enabled and disabled windows and both active and inactive ones, enumerating the returned fields, and describing the paginated envelope (items plus total, page, size, pages). It stops short of rate-limit or auth notes, so not a 5.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three tight sentences with the purpose and scope front-loaded and the sibling routing immediately after. The field enumeration is somewhat redundant given an output schema exists, which keeps it from a 5, but nothing is padded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With annotations covering safety, a 100%-covered input schema, and an output schema present, the description need not restate return structure in detail yet still does enough to orient the agent. Everything needed to call it correctly — scope, use case, alternatives — is present.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, and each parameter (q, page, size, sort) is already documented in the schema, including defaults and paging advice. The description adds nothing about parameter semantics, so the baseline of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (List) and resource (maintenance windows of the organization) with explicit scope: enabled or not, in effect or not. It further separates itself from siblings by naming list_active_maintenance and get_maintenance_window, so an agent can pick it without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives a concrete use case ('Use it to find a window's id') and explicitly routes to alternatives with conditions: list_active_maintenance for current silencing state, get_maintenance_window for upcoming occurrences. This is exactly the when-to-use/when-not guidance the dimension asks for.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_monitorsList monitorsARead-onlyIdempotentInspect
Find monitors in the organization by name, target, type, status or tag. Each row is short: id, name, type, target, status, is_active, tags, interval_seconds, ssl_expires_at and last_checked_at. Use it first to get a monitor's id, or to answer what is broken now (status ["DOWN", "DEGRADED"]) or which certificates expire first (type ["SSL"], sort ssl_expiry). For one monitor's full settings use get_monitor; for heartbeats use list_heartbeats. Returns a page: items plus total, page, size and pages. An invalid value is a 422 naming the argument. Example: {"status": ["DOWN", "DEGRADED"], "size": 100}
| Name | Required | Description | Default |
|---|---|---|---|
| q | No | Case-insensitive substring of the name or the target, up to 255 characters. | |
| tag | No | Keep items carrying these tags: a JSON array of up to 10 tags, each up to 50 characters, lowercased before matching. tag_match decides whether all or any of them must match. | |
| page | No | Page number, 1 or more; default 1. | |
| size | No | Rows per page, 1 to 100; default 25. Keep paging until you have seen total rows. | |
| sort | No | status (the default: PENDING, DOWN, DEGRADED, UP, PAUSED, then by name), up_first (healthy first), name, newest, oldest, or ssl_expiry (soonest-expiring certificates first; monitors with no known expiry, non-SSL types or not checked yet, last). | |
| type | No | Keep monitors of any of these types: a JSON array. | |
| status | No | Keep monitors in any of these states: a JSON array. PENDING means no verdict yet. | |
| tag_match | No | all (the default): an item must carry every tag in tag. any: at least one of them. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly/idempotent/non-destructive, and the description adds real behavioral context on top: the exact row fields returned, the pagination model (items plus total, page, size, pages), and the 422 error behavior naming the bad argument. It stops short of describing rate limits or ordering guarantees beyond sort, so not a 5.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with purpose, then usage, then return shape, error behavior, and an example — each sentence carries information. The bare field-list enumeration is slightly dense but earns its place given there is no output schema.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description compensates by spelling out the returned row fields and the page envelope, and even notes the error shape. For an 8-parameter read tool with rich annotations, nothing an agent needs to call it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is already 100%, so baseline is 3. The description still adds cross-parameter meaning the schema lacks: a worked example combining status and size, and the intent mapping (status ['DOWN','DEGRADED'] for outages, type ['SSL'] + sort ssl_expiry for certificates), which helps agents compose parameters correctly.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource ('Find monitors in the organization') plus the filterable dimensions, and explicitly contrasts itself with siblings get_monitor and list_heartbeats. An agent can select this over get_monitor without opening either schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives concrete when-to-use cases ('use it first to get a monitor's id', 'answer what is broken now', 'which certificates expire first') and names the alternatives plus the condition that selects them (full settings vs. heartbeats). Exclusions are explicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_regionsList check regionsARead-onlyIdempotentInspect
List every check region of the platform, to show the user where checks can run. Returns regions, each with code (what a regions argument takes), display_name, city, country_code, group and group_display_name. The organization may use only some of them: to choose regions for a monitor read limits.allowed_regions and max_regions from get_plan_usage instead. For one monitor's per-region timings use get_response_time_by_region.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| regions | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly/idempotent/non-destructive, so the safety profile is covered. The description adds real context by noting the organization may use only some regions, steering the agent to get_plan_usage for the actual allowed set. It does not add further behavioral traits like rate limits.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three tight sentences, front-loaded with purpose. The enumerated return fields are somewhat redundant against the output schema, though the note on 'code' justifies inclusion.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present, the description needn't explain returns, yet it covers purpose, alternatives, and the allowed-region caveat. Nothing an agent needs 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.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Zero parameters, so the baseline is 4. The description still earns its keep by explaining that the returned 'code' field is what a 'regions' argument elsewhere consumes, linking this tool's output to other tools' inputs.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('List every check region of the platform') plus the intent ('to show the user where checks can run'). It also disambiguates from two siblings, so an agent can identify it without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly routes the agent away: use limits.allowed_regions/max_regions from get_plan_usage to choose a monitor's regions, and get_response_time_by_region for per-region timings. Both the when-to-use and clear alternatives are named.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_status_page_incidentsList a status page's incidentsARead-onlyIdempotentInspect
List the incidents shown on one status page, newest first, both posted by a person and opened by Fettle. Each has id, title, status, is_auto (opened by Fettle from a monitor), started_at, resolved_at, notified_at (when subscribers were first emailed; null if never), component_ids and updates (the timeline, oldest first, each with id, status, body, created_by and created_at). Use it to find the incident_id for post_status_page_update. Monitor outages behind the scenes are list_incidents. Returns a page: items plus total, page, size and pages.
| Name | Required | Description | Default |
|---|---|---|---|
| page | No | Page number, 1 or more; default 1. | |
| size | No | Rows per page, 1 to 100; default 25. Keep paging until you have seen total rows. | |
| page_id | Yes | The status page's uuid from list_status_pages. An id that is not a status page of this organization is a 404. |
Output Schema
| Name | Required | Description |
|---|---|---|
| page | Yes | |
| size | Yes | |
| items | Yes | |
| pages | Yes | |
| total | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the read-only, idempotent, non-destructive profile, so the bar is lower. The description adds ordering behavior ('newest first', updates 'oldest first') and field semantics such as is_auto meaning Fettle-opened from a monitor and notified_at being null if never emailed. It does not discuss filtering or rate limits, but the added behavioral context is substantive.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core verb and scope, then the returned fields, then the sibling routing. It is dense and slightly long, but nearly every clause conveys return shape or routing information rather than filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Combined with a 100%-covered schema, full annotations, and an output schema, the description supplies ordering, field semantics, pagination behavior, and sibling routing. Nothing an agent needs to call it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and all three parameters (page, size, page_id) are fully documented in the schema, including defaults and the 404 case for page_id. The description adds nothing beyond that, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('List the incidents shown on one status page'), scopes it to a single page, and explicitly distinguishes itself from the sibling list_incidents ('Monitor outages behind the scenes are list_incidents'). An agent can route correctly without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives both the when-to-use rationale ('Use it to find the incident_id for post_status_page_update') and the when-not/alternative ('Monitor outages behind the scenes are list_incidents'). This is explicit routing guidance, not inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_status_pagesList status pagesARead-onlyIdempotentInspect
List the organization's public status pages. Each has id, slug, name, description, is_published (publicly visible now), history_days, created_at, groups (each with name, position and its components) and ungrouped_components. Use it to find a page's id before posting an incident on it. For one page use get_status_page; pages are created and edited only in the dashboard. Returns a page of results: items plus total, page, size and pages.
| Name | Required | Description | Default |
|---|---|---|---|
| page | No | Page number, 1 or more; default 1. | |
| size | No | Rows per page, 1 to 100; default 25. Keep paging until you have seen total rows. | |
| sort | No | created_at (the default, newest first) or name. |
Output Schema
| Name | Required | Description |
|---|---|---|
| page | Yes | |
| size | Yes | |
| items | Yes | |
| pages | Yes | |
| total | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare a safe, idempotent, read-only operation, so the description only needs to add context beyond that. It usefully adds that pages are public, lists returned fields, and explains the paginated result shape, though some field detail overlaps with the 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.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded and efficient, with the primary purpose and alternative tool stated early. The returned-field enumeration is somewhat detailed but still relevant to the task.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given an output schema and full annotation coverage, the description supplies enough context for an agent to call the tool correctly. It covers purpose, alternative, pagination behavior, and creation/edit constraints.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, and the parameters page, size, and sort are already documented in the schema. The description does not add syntax or selection guidance beyond the schema, so the baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description gives a specific verb and resource: listing the organization's public status pages. It also distinguishes this list operation from the sibling get_status_page for a single page.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly states the main use case: finding a page's id before posting an incident. It also names get_status_page as the alternative for one page and clarifies that creation and editing happen only in the dashboard.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_tagsList tagsARead-onlyIdempotentInspect
List the tags used in the organization, most-used first, each with monitor_count and heartbeat_count, as items. Call it before tagging anything so you reuse an existing name instead of inventing a near-duplicate. Not a filter: to find the monitors or heartbeats carrying a tag, pass tag to list_monitors or list_heartbeats. Returns every tag at once, not a page.
| Name | Required | Description | Default |
|---|---|---|---|
| kind | No | monitor or heartbeat lists only the tags that kind of item uses; all (the default) lists both. Both counts are reported either way. |
Output Schema
| Name | Required | Description |
|---|---|---|
| items | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover read-only/idempotent/non-destructive, so the bar is lower, yet the description adds real behavior: result ordering (most-used first), the returned counts, and critically that there is no pagination ('Returns every tag at once, not a page'). It stops short of describing anything about auth scope or what happens with very large tag sets, so it is strong but not exhaustive.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four tight sentences, each doing distinct work: purpose, pre-tagging guidance, disambiguation from filtering tools, and pagination behavior. The most decision-relevant information (what it is, when to call it) is front-loaded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present, return values need not be explained, and the description still surfaces the salient ones (counts, ordering, no paging). Combined with full schema coverage and read-only annotations, an agent has everything needed to call this correctly and to avoid misusing it as a filter.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and the enum values for 'kind' are fully documented in the schema, so the baseline is 3. The description adds no additional semantics for 'kind' (e.g., which count corresponds to which kind), instead spending its parameter-adjacent text on sibling routing.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('List the tags used in the organization') and goes further by specifying ordering ('most-used first') and the per-item payload ('monitor_count and heartbeat_count'). It also distinguishes itself from siblings like list_monitors/list_heartbeats by clarifying it is not a filter.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit when-to-use ('Call it before tagging anything so you reuse an existing name') and explicit when-not ('Not a filter'), with the correct alternative named ('pass tag to list_monitors or list_heartbeats'). Nothing about tool selection is left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
pause_heartbeatPause a heartbeat monitorAIdempotentInspect
Pause one heartbeat: it is no longer reported late, pings to its ping_url are accepted but ignored, and its open incident closes without an alert. Use it when the job is stopped on purpose, such as a runner taken out of service; resume_heartbeat undoes it, while delete_heartbeat removes the heartbeat for good. Maintenance windows do not cover heartbeats. Requires a key with the write scope. Pausing a paused heartbeat changes nothing. Returns the heartbeat.
| Name | Required | Description | Default |
|---|---|---|---|
| heartbeat_id | Yes | The heartbeat's uuid from list_heartbeats. An id that is not a heartbeat of this organization, or a deleted one, is a 404. |
Output Schema
| Name | Required | Description |
|---|---|---|
| id | Yes | |
| name | Yes | |
| tags | No | |
| state | Yes | Known values: PENDING, UP, DOWN, PAUSED. |
| ping_url | Yes | |
| is_active | Yes | |
| created_at | Yes | |
| overdue_at | Yes | |
| updated_at | Yes | |
| channel_ids | No | |
| last_ping_at | Yes | |
| grace_seconds | Yes | |
| last_start_at | Yes | |
| period_seconds | Yes | |
| last_success_at | Yes | |
| last_duration_ms | Yes | |
| notification_cooldown_seconds | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the annotations: pings are accepted but ignored, an open incident is closed without an alert, a write-scoped key is required, and pausing an already-paused heartbeat is a no-op. This is exactly the operational context the annotations (idempotentHint, destructiveHint) cannot convey.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four tightly packed sentences, front-loaded with the effect of pausing, then usage, then alternatives and prerequisites. No filler sentences; even the trailing 'Returns the heartbeat' is one short clause.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Mutation tool with an output schema and full annotation coverage, and the description still covers side effects, auth scope, idempotency, and sibling routing. Nothing an agent needs 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.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and the single heartbeat_id parameter is already fully documented in the schema (uuid source, 404 semantics). The description adds no parameter-level detail, so baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Pause one heartbeat') and immediately qualifies scope by naming the sibling alternatives resume_heartbeat and delete_heartbeat. An agent can distinguish this from resume/delete 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.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit when-to-use condition ('when the job is stopped on purpose, such as a runner taken out of service'), plus explicit when-not/alternatives: resume_heartbeat undoes it, delete_heartbeat removes it permanently, and maintenance windows do not cover heartbeats.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
pause_monitorPause a monitorAIdempotentInspect
Stop checking one monitor without deleting it: its status becomes PAUSED and an open incident on it closes without a recovery alert. Use it when the user wants a monitor off for an open-ended time. For a planned deploy or reboot prefer create_maintenance_window, which keeps checking but silences alerts; for many monitors use bulk_pause_monitors; to restart checks use resume_monitor. Requires a key with the write scope. Pausing a paused monitor changes nothing. Returns the monitor in the get_monitor shape.
| Name | Required | Description | Default |
|---|---|---|---|
| monitor_id | Yes | The monitor's uuid from list_monitors. An id that is not a monitor of this organization, or a deleted one, is a 404. |
Output Schema
| Name | Required | Description |
|---|---|---|
| id | Yes | |
| name | Yes | |
| tags | No | |
| type | Yes | Known values: HTTP, PING, SSL, TCP, DNS. |
| config | Yes | |
| status | Yes | Known values: PENDING, UP, DEGRADED, DOWN, PAUSED. |
| target | Yes | |
| regions | Yes | |
| user_id | Yes | |
| is_active | Yes | |
| created_at | Yes | |
| updated_at | Yes | |
| channel_ids | No | |
| next_run_at | Yes | |
| badge_enabled | No | |
| ssl_cert_info | No | |
| ssl_expires_at | Yes | |
| last_checked_at | Yes | |
| region_statuses | Yes | Per-region latest status, sorted by region name. Built from ``region_snapshots``; ``job_id`` is dropped (internal dedup key) and malformed/partial snapshot rows are skipped rather than failing the read. |
| timeout_seconds | Yes | |
| interval_seconds | Yes | |
| confirmation_threshold | Yes | |
| notification_cooldown_seconds | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the annotations: it discloses that an open incident closes without a recovery alert, that write scope is required, that pausing a paused monitor is a no-op (consistent with idempotentHint), and what shape the result takes. These are exactly the mutation side effects an agent cannot infer from readOnlyHint/destructiveHint alone.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The core action and its state change are front-loaded, followed tightly by routing rules and constraints. Every sentence carries distinct, actionable information with no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Annotations cover the safety/idempotency profile, the output schema covers the return value, and the description covers semantics, prerequisites, and alternatives. An agent has everything needed to call this correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and the single monitor_id parameter is fully documented in the schema (uuid source plus 404 behavior), so the baseline is 3. The description adds nothing further about the parameter itself, leaving the schema to do the work.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('stop checking one monitor without deleting it') plus the resulting state (PAUSED) and the side effect on incidents. It explicitly distinguishes itself from create_maintenance_window, bulk_pause_monitors, and resume_monitor by name.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives an explicit when-to-use ('monitor off for an open-ended time') and multiple when-not-to-use conditions with named alternatives: planned deploy/reboot -> create_maintenance_window, many monitors -> bulk_pause_monitors, restart checks -> resume_monitor. Routing is fully determined.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
post_status_page_updatePost an update to a status page incidentAInspect
Add a message to an existing status page incident and set its status; RESOLVED closes it. It is public and emails the page's confirmed subscribers: confirm the wording with the user before calling. Every confirmed subscriber gets the update, except that resolving an incident they were never told about stays silent. To open a new incident use create_status_page_incident; to fix only the title, silently, use update_status_page_incident. Requires a key with the write scope. A resolved incident accepts only further RESOLVED updates; any other status is a 409. Returns the incident. Example: {"page_id": "", "incident_id": "", "status": "RESOLVED", "body": "Fixed; error rates are back to normal."}
| Name | Required | Description | Default |
|---|---|---|---|
| body | Yes | The message subscribers read, 1 to 5000 characters. | |
| status | Yes | INVESTIGATING, IDENTIFIED, MONITORING or RESOLVED; RESOLVED closes the incident on the page. | |
| page_id | Yes | The status page's uuid from list_status_pages. An id that is not a status page of this organization is a 404. | |
| incident_id | Yes | The status page incident's uuid from list_status_page_incidents (not from list_incidents). An unknown id is a 404. |
Output Schema
| Name | Required | Description |
|---|---|---|
| id | Yes | |
| title | Yes | |
| status | Yes | Known values: INVESTIGATING, IDENTIFIED, MONITORING, RESOLVED. |
| is_auto | Yes | |
| updates | Yes | |
| started_at | Yes | |
| notified_at | Yes | |
| resolved_at | Yes | |
| component_ids | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only provide the generic write profile (readOnly=false, idempotent=false), while the description supplies the traits that actually change agent behavior: the update is public, it emails confirmed subscribers, resolving a never-notified incident stays silent, a write-scope key is required, and a resolved incident only accepts further RESOLVED updates (409 otherwise). None of this is inferable from structured fields.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Dense but front-loaded: the public/email warning follows immediately on the purpose statement and outranks the alternatives and error semantics that come after. It is one long multi-clause paragraph plus an inline example, which slightly hurts scannability, but essentially every sentence carries distinct information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 4-param mutation tool with an output schema, the description covers the gaps that matter: side effects, auth scope, conflict behavior, and sibling routing. Return values are covered by the output schema, and no destructive or idempotency surprise is left unexplained.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
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 goes modestly beyond it by binding each id to its provenance tool (page_id from list_status_pages, incident_id from list_status_page_incidents) and by attaching the 409 constraint to the status value. The worked example clarifies required-field combination but largely restates schema-documented fields.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Add a message to an existing status page incident and set its status') with a crucial scope qualifier: RESOLVED closes it. It also explicitly distinguishes itself from create_status_page_incident and update_status_page_incident, so an agent can route correctly without opening sibling schemas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Names both alternatives with the exact condition that selects each ('To open a new incident use create_status_page_incident; to fix only the title, silently, use update_status_page_incident'). It also gives a pre-call obligation — confirm the wording with the user — which is actionable guidance, not just context.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
preview_maintenance_windowPreview a maintenance scheduleARead-onlyIdempotentInspect
Compute the next three occurrences, each with start and end, that a schedule would produce, without saving anything. Use it to check a recurring schedule before create_maintenance_window or update_maintenance_window; for a saved window's occurrences use get_maintenance_window. Requires a key with the write scope. An invalid schedule is a 422 with the reason. Returns an array. Example: {"dtstart": "2026-10-18T03:00:00", "duration_minutes": 60, "rrule": "FREQ=WEEKLY;BYDAY=SU", "timezone": "Europe/Berlin"}
| Name | Required | Description | Default |
|---|---|---|---|
| rrule | No | Repeats the window: one iCal RRULE without the RRULE: prefix, at most 1024 characters, for example FREQ=WEEKLY;BYDAY=SU;BYHOUR=3. Hourly, minutely and secondly frequencies are refused. Omit it for a one-time window. | |
| dtstart | Yes | The first start, an ISO 8601 date-time in the wall-clock time of timezone, for example 2026-10-14T22:00:00. A UTC offset or Z is a 422. | |
| timezone | No | IANA zone name such as Europe/Berlin, at most 64 characters. The schedule repeats in it, so a weekly 03:00 stays 03:00 across daylight-saving changes. Defaults to the organization's timezone. | |
| duration_minutes | Yes | How long each occurrence lasts, 1 to 40320 minutes. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover read-only/idempotent/non-destructive, and the description adds context annotations cannot express: it requires a write-scoped key despite being a read, invalid schedules fail as a 422 carrying the reason, and the result is an array of three occurrences with start and end. Auth, error, and return-shape behavior are all disclosed.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loads the core behavior, then usage, auth, errors, and return shape in tight sentences. The example earns its place by showing a valid combined payload, though the entry is on the dense side.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description carries the return-value burden and does state an array of start/end occurrences, plus error semantics. It is nearly complete, though it could note whether exactly three are always returned or fewer for one-time windows.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
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 dtstart wall-clock semantics, the RRULE format and refused frequencies, the IANA timezone default, and the duration bounds. The description only echoes this via a sample payload, so baseline 3 is correct.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource: computes the next three occurrences a schedule would produce, without saving. It also names the siblings it is not (create_maintenance_window, update_maintenance_window, get_maintenance_window), so an agent can distinguish it from every adjacent tool.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly routes: use this to validate a recurring schedule before create/update, and use get_maintenance_window instead for a saved window's occurrences. Both the when-to-use and the alternative-selection condition are stated outright.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
rename_tagRename a tag everywhereAIdempotentInspect
Rename a tag on every monitor and heartbeat that carries it; an item that already has the new name keeps one copy. Use it to fix a naming scheme across the organization; to change the tags of chosen monitors only use bulk_update_monitor_tags, and to drop a tag use delete_tag. Requires a key with the write scope. A tag nothing carries is not an error (both counts are 0). Returns from, to, monitors_updated and heartbeats_updated. Example: {"from": "prod", "to": "env:prod"}
| Name | Required | Description | Default |
|---|---|---|---|
| to | Yes | The new name. Each tag is trimmed, lowercased and deduplicated on write, at most 50 characters of a-z, 0-9 and : _ . / -, starting with a letter or digit. Reuse names from list_tags rather than inventing near-duplicates. | |
| from | Yes | The existing tag, as list_tags shows it. |
Output Schema
| Name | Required | Description |
|---|---|---|
| to | No | |
| from | Yes | |
| monitors_updated | Yes | |
| heartbeats_updated | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations cover the safety profile (readOnlyHint=false, idempotentHint=true, destructiveHint=false), and the description adds genuinely new context: write-scope auth requirement, the merge behavior ('an item that already has the new name keeps one copy'), and the edge case that a tag nothing carries is not an error (counts are 0).
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loads the core behavior, then routes to alternatives, then auth, edge cases, return fields and an example. Every clause carries distinct information with no padding.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Complete for a two-parameter mutation: scope, auth, idempotent merge behavior, no-op edge case, alternatives, and example are all present. An output schema exists, so the return-field mention is supplementary rather than required.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the schema already documents both parameters including normalization rules, giving a baseline of 3. The description adds a concrete example mapping ('{"from": "prod", "to": "env:prod"}') and clarifies the merge semantics that govern the 'to' behavior, slightly exceeding the baseline.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (rename) plus resource (tag) and exact scope: 'on every monitor and heartbeat that carries it.' It also names the sibling tools it is not (bulk_update_monitor_tags, delete_tag), so an agent can distinguish it without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit when-to-use ('to fix a naming scheme across the organization') and when-not, with named alternatives: bulk_update_monitor_tags for selected monitors only and delete_tag to drop a tag. Nothing is left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
resume_heartbeatResume a heartbeat monitorAIdempotentInspect
Resume one paused heartbeat: it goes back to PENDING with no deadline, so it is not reported late until its next success ping restarts the clock. Use it once the job runs again; to change its timing use update_heartbeat. There is no bulk resume for heartbeats. Requires a key with the write scope. Resuming one that is not paused resets it to PENDING the same way. Returns the heartbeat.
| Name | Required | Description | Default |
|---|---|---|---|
| heartbeat_id | Yes | The heartbeat's uuid from list_heartbeats. An id that is not a heartbeat of this organization, or a deleted one, is a 404. |
Output Schema
| Name | Required | Description |
|---|---|---|
| id | Yes | |
| name | Yes | |
| tags | No | |
| state | Yes | Known values: PENDING, UP, DOWN, PAUSED. |
| ping_url | Yes | |
| is_active | Yes | |
| created_at | Yes | |
| overdue_at | Yes | |
| updated_at | Yes | |
| channel_ids | No | |
| last_ping_at | Yes | |
| grace_seconds | Yes | |
| last_start_at | Yes | |
| period_seconds | Yes | |
| last_success_at | Yes | |
| last_duration_ms | Yes | |
| notification_cooldown_seconds | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the annotations by describing the resulting state (back to PENDING with no deadline), the reporting consequence (not late until the next success ping restarts the clock), the auth requirement (write scope), and the return ("Returns the heartbeat"). The idempotentHint is corroborated by the note that resuming an already-active heartbeat behaves the same way.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Five short sentences, each carrying distinct information: state effect, timing rule, alternative tool, bulk limitation, auth requirement, edge case, return. Front-loaded with the action and its state consequence.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a single-parameter state-changing tool with an output schema, the description covers everything an agent needs: what changes, what it requires, what it returns, and what happens in the non-obvious case. Return-value detail is correctly delegated to the output schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and the single heartbeat_id already documents its uuid format and 404 conditions. The description adds no id-specific syntax or sourcing detail beyond the schema, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb + resource ("Resume one paused heartbeat") and immediately disambiguates from siblings by saying there is no bulk resume for heartbeats, distinguishing it from bulk_resume_monitors and resume_monitor. An agent can route to it without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly says when to use it ("once the job runs again") and names the alternative for a different need ("to change its timing use update_heartbeat"). It also states the negative case (no bulk resume) and the surprising edge case (resuming a non-paused heartbeat still resets it to PENDING).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
resume_monitorResume a monitorAIdempotentInspect
Restart checks on one paused monitor: its status goes back to PENDING and it is checked on the scheduler's next tick. For many monitors use bulk_resume_monitors; to check a running monitor right away use check_now. Requires a key with the write scope. Resuming an active monitor is a no-op success. A 403 means the organization already has as many active monitors as its plan allows: pause or delete another one first. Returns the monitor in the get_monitor shape.
| Name | Required | Description | Default |
|---|---|---|---|
| monitor_id | Yes | The monitor's uuid from list_monitors. An id that is not a monitor of this organization, or a deleted one, is a 404. |
Output Schema
| Name | Required | Description |
|---|---|---|
| id | Yes | |
| name | Yes | |
| tags | No | |
| type | Yes | Known values: HTTP, PING, SSL, TCP, DNS. |
| config | Yes | |
| status | Yes | Known values: PENDING, UP, DEGRADED, DOWN, PAUSED. |
| target | Yes | |
| regions | Yes | |
| user_id | Yes | |
| is_active | Yes | |
| created_at | Yes | |
| updated_at | Yes | |
| channel_ids | No | |
| next_run_at | Yes | |
| badge_enabled | No | |
| ssl_cert_info | No | |
| ssl_expires_at | Yes | |
| last_checked_at | Yes | |
| region_statuses | Yes | Per-region latest status, sorted by region name. Built from ``region_snapshots``; ``job_id`` is dropped (internal dedup key) and malformed/partial snapshot rows are skipped rather than failing the read. |
| timeout_seconds | Yes | |
| interval_seconds | Yes | |
| confirmation_threshold | Yes | |
| notification_cooldown_seconds | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the annotations: discloses the PENDING transition timing ('scheduler's next tick'), the required write scope, that active monitors yield a no-op success (consistent with idempotentHint), and the specific 403 plan-limit cause with a remediation. It does not add much on failure/retry edge cases, but the annotation set plus this text is unusually thorough.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four tight sentences with zero filler, front-loaded with the core action and its state change, then alternatives, then constraints. Every sentence carries distinct operational value.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Covers the mental model (state transition), authorization requirement, idempotent-success case, a specific plan-limit failure with remedy, and the return shape by reference to get_monitor. Nothing an agent needs 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.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and the single monitor_id param is fully documented there, including the 404 case. The description adds no new parameter-level syntax or format detail, so the baseline of 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource with explicit scope: 'Restart checks on one paused monitor.' The singular 'one' immediately distinguishes it from the bulk sibling, and the state transition (back to PENDING) makes the effect unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly routes to alternatives with conditions: 'For many monitors use bulk_resume_monitors; to check a running monitor right away use check_now.' That is textbook when-to-use/when-not guidance naming two concrete siblings.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
update_heartbeatUpdate a heartbeat monitorAIdempotentInspect
Change one heartbeat's name, timing, channels or tags; only the fields you pass change. A new period or grace applies from the next ping: the current deadline (overdue_at) is not recomputed. To stop or restart late alerts use pause_heartbeat or resume_heartbeat instead; ping_url never changes. Requires a key with the write scope. An invalid argument is a 422 naming it; never send null. Returns the heartbeat. Example: {"heartbeat_id": "", "grace_seconds": 7200}
| Name | Required | Description | Default |
|---|---|---|---|
| name | No | Display name, 1 to 255 characters. | |
| tags | No | Replaces the whole tag list when passed, at most 10; [] clears it; omit it to keep the tags. Each tag is trimmed, lowercased and deduplicated on write, at most 50 characters of a-z, 0-9 and : _ . / -, starting with a letter or digit. Reuse names from list_tags rather than inventing near-duplicates. | |
| channel_ids | No | Notification channel uuids from list_channels. When passed it replaces the whole binding; [] clears it, after which every verified, active channel is alerted; omit it to keep the binding. An id that is not an active channel of this organization is a 404. | |
| heartbeat_id | Yes | The heartbeat's uuid from list_heartbeats. An id that is not a heartbeat of this organization, or a deleted one, is a 404. | |
| grace_seconds | No | Extra seconds of silence tolerated after the period before the heartbeat is reported late, 0 to 2592000; it may exceed the period. | |
| period_seconds | No | How often the job runs, 60 to 2592000 seconds. To ping every N seconds and be alerted after T seconds of silence, set period_seconds = N and grace_seconds = T - N (T at least N). | |
| notification_cooldown_seconds | No | 60 to 86400 seconds; 1800 when not set on create. Only holds back a duplicate first alert for the same incident within that window. Repeat reminders while an incident stays open and unacknowledged follow the plan's renotify_interval_seconds and renotify_max_count (get_plan_usage; 0 means no reminders) instead, and the recovery alert is never held back. |
Output Schema
| Name | Required | Description |
|---|---|---|
| id | Yes | |
| name | Yes | |
| tags | No | |
| state | Yes | Known values: PENDING, UP, DOWN, PAUSED. |
| ping_url | Yes | |
| is_active | Yes | |
| created_at | Yes | |
| overdue_at | Yes | |
| updated_at | Yes | |
| channel_ids | No | |
| last_ping_at | Yes | |
| grace_seconds | Yes | |
| last_start_at | Yes | |
| period_seconds | Yes | |
| last_success_at | Yes | |
| last_duration_ms | Yes | |
| notification_cooldown_seconds | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the annotations (which only declare non-read-only, idempotent, non-destructive). It discloses the delayed effect of period/grace ('applies from the next ping: the current deadline (overdue_at) is not recomputed'), the required write scope, the 422-on-invalid-argument contract with the offending field named, and the null prohibition.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core operation and update semantics, then progressively narrower detail (timing caveat, sibling routing, auth, error contract, example). Every sentence carries distinct operational information with no filler or restatement of the name.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Covers everything an agent needs: what changes and what does not, side-effect timing, sibling routing, permission requirements, error shape, and a call example. Return values are handled by the existing output schema, so their omission is correct.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
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 cross-parameter semantics the schema does not state at the tool level: partial-update behavior, the timing interaction (new period/grace only takes effect from the next ping), and a concrete example pairing heartbeat_id with grace_seconds.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (Change) and resource (one heartbeat) with the exact field set it touches (name, timing, channels, tags). It also differentiates from adjacent siblings by naming pause_heartbeat and resume_heartbeat as the tools for a different intent, so an agent can route 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.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit when-to-use and when-not-to-use: 'only the fields you pass change' defines the partial-update contract, and 'To stop or restart late alerts use pause_heartbeat or resume_heartbeat instead' names the alternatives and the condition that selects them. It further warns that ping_url never changes, removing a plausible mis-selection.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
update_maintenance_windowUpdate a maintenance windowAIdempotentInspect
Change one maintenance window's name, schedule, scope or monitors, or switch it off with enabled false; only the fields you pass change. While a window is in effect its monitors keep being checked, but no incident opens and no alert goes out. A recurring window cannot become one-time: delete it with delete_maintenance_window and create a new one. Check a new schedule with preview_maintenance_window first. Requires a key with the write scope. An invalid argument is a 422 and a resulting schedule that is invalid (for example a bad rrule) a 406, each with the reason. Returns the window. Example: {"window_id": "", "enabled": false}
| Name | Required | Description | Default |
|---|---|---|---|
| name | No | Display name, 1 to 255 characters. | |
| rrule | No | Repeats the window: one iCal RRULE without the RRULE: prefix, at most 1024 characters, for example FREQ=WEEKLY;BYDAY=SU;BYHOUR=3. Hourly, minutely and secondly frequencies are refused. | |
| scope | No | ORG covers every monitor of the organization and ignores monitor_ids; MONITOR covers only monitor_ids. | |
| dtstart | No | The first start, an ISO 8601 date-time in the wall-clock time of timezone, for example 2026-10-14T22:00:00. A UTC offset or Z is a 422. | |
| enabled | No | false keeps the window but stops it silencing alerts. | |
| timezone | No | IANA zone name such as Europe/Berlin, at most 64 characters. The schedule repeats in it, so a weekly 03:00 stays 03:00 across daylight-saving changes. | |
| window_id | Yes | The window's uuid from list_maintenance_windows. An id that is not a window of this organization is a 404. | |
| monitor_ids | No | Replaces the list when passed. Monitor uuids from list_monitors, at least one when scope is MONITOR. An id that is not a monitor of this organization is a 404. | |
| duration_minutes | No | How long each occurrence lasts, 1 to 40320 minutes. |
Output Schema
| Name | Required | Description |
|---|---|---|
| id | Yes | |
| name | Yes | |
| rrule | Yes | |
| scope | Yes | Known values: MONITOR, ORG. |
| dtstart | Yes | |
| enabled | Yes | |
| timezone | Yes | |
| created_at | Yes | |
| monitor_ids | No | |
| duration_minutes | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the annotations: reveals auth requirement (write scope), the side effect while a window is in effect (monitors still checked but no incident opens and no alert fires), the recurrence-immutability constraint, and error semantics (422 invalid argument, 406 invalid resulting schedule, each with a reason). None of this is derivable from readOnlyHint/idempotentHint/destructiveHint.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the action, and nearly every clause carries non-obvious information (partial update, silencing behavior, recurrence constraint, preview step, auth scope, error codes, return, example). The middle is a dense semicolon run-on that could be split into bullets, which is the only reason this is not a 5.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 9-parameter mutation tool with an output schema, the description covers everything an agent needs: mutation semantics, side effects, prerequisites, auth, failure modes, and a concrete invocation example. Return-value detail is correctly left light since an output schema exists.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
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 value: it clarifies that every field other than window_id is optional and only supplied fields change, which reframes the 9-property schema as a patch. The worked example {"window_id": ..., "enabled": false} demonstrates that partial-update pattern concretely.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource (change one maintenance window's fields or disable it) and enumerates the editable dimensions (name, schedule, scope, monitors, enabled). An agent can distinguish it from create_maintenance_window, delete_maintenance_window, get/list_maintenance_window and preview_maintenance_window without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit when-to-use and when-not-to-use: recurring windows cannot be converted to one-time, so delete with delete_maintenance_window and recreate; validate a new schedule with preview_maintenance_window first. It also states the partial-update condition (only passed fields change). Alternatives and prerequisites are named outright.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
update_monitorUpdate a monitorAIdempotentInspect
Change one monitor's settings and return it in the get_monitor shape. Only the fields you pass change, and at least one besides monitor_id is required (422 otherwise); type and target never change (create a new monitor instead). Not for pausing or resuming (pause_monitor, resume_monitor), for many monitors at once (bulk_update_monitors) or for tags alone across monitors (bulk_update_monitor_tags). Requires a key with the write scope. Plan limits are checked against the result, as on create_monitor (only moving a monitor below 60 seconds takes a fast slot): breaking one is a 403 naming it. Port-list rules are checked against the result too, so changing only the interval or regions of a port-list TCP monitor can be a 422. Omit a field to keep it; never send null. Example: {"monitor_id": "", "interval_seconds": 600}
| Name | Required | Description | Default |
|---|---|---|---|
| name | No | Display name, 1 to 255 characters. | |
| tags | No | Replaces the whole tag list when passed, at most 10; [] clears it; omit it to keep the tags. Each tag is trimmed, lowercased and deduplicated on write, at most 50 characters of a-z, 0-9 and : _ . / -, starting with a letter or digit. Reuse names from list_tags rather than inventing near-duplicates. | |
| config | No | Replaces the monitor's whole config, not just the keys you send: a field of the type's schema you leave out resets to its default (read the current one with get_monitor first). Sending only port on a TCP monitor whose expected_state is closed resets it to open. A port-list TCP monitor cannot switch to a single port (422). An object whose fields depend on type, all optional unless stated. HTTP: method (GET, HEAD, POST, PUT, PATCH or DELETE, any case; default GET); expected_status_codes (non-empty list of codes 100 to 599, default [200]); keyword (case-sensitive substring the body must contain, at most 1024 characters, not with HEAD); follow_redirects (default true); verify_ssl (default true; false skips TLS verification, so the monitor can never report TLS_INVALID); request_headers (object of name to value: at most 20, a name at most 128 characters of letters, digits and ! # $ % & ' * + - . ^ _ ` | ~, a value at most 1024 bytes of printable ASCII, space or tab, the whole object at most 8192 bytes as JSON; names differing only in case, and Host, Content-Length, Transfer-Encoding, Connection, Upgrade, TE, Trailer, Keep-Alive, CF-Connecting-IP or any Proxy-* name, are a 422); request_body (string, at most 8192 bytes as UTF-8, needs POST, PUT, PATCH or DELETE). Reads return every request_headers value as the literal __FETTLE_UNCHANGED__; writing that literal back in an update keeps the stored value (on create it is a 422). PING: packet_count (1 to 20, default 4). SSL: warn_before_days (1 to 365, default 14) and port (1 to 65535, default 443). TCP: either port (1 to 65535) with expected_state "open" (default) or "closed", or ports (1 to 20 distinct ports that must all be closed, which needs expected_state "closed", exactly one region and interval_seconds of at least 300; a check fails when any of them accepts a connection, and the monitor goes DOWN once confirmation_threshold failures confirm it). Both port and ports, or neither, is a 422; expected_state values are lowercase. DNS: record_type (A, AAAA, CNAME, MX, TXT or NS; required) and expected_value (at most 2048 characters). With expected_value one answer must equal it (case-insensitive, ignoring surrounding spaces and a trailing dot; exact for TXT); without it any answer passes. MX answers are the mail host names without priority (mail.example.com, not 10 mail.example.com). A and AAAA look up every address of the host, IPv4 and IPv6 alike, and any one may match; write an IPv6 address in its shortest form. | |
| regions | No | One or more distinct region codes, for example eu-central: the plan's choices are limits.allowed_regions in get_plan_usage. An unknown code, or more regions than the plan's max_regions, is a 403. SSL and DNS monitors take exactly one region (422 otherwise). | |
| monitor_id | Yes | The monitor's uuid from list_monitors. An id that is not a monitor of this organization, or a deleted one, is a 404. | |
| channel_ids | No | Notification channel uuids from list_channels. When passed it replaces the whole binding; [] clears it, after which every verified, active channel is alerted; omit it to keep the binding. An id that is not an active channel of this organization is a 404. | |
| badge_enabled | No | Turns the monitor's public status badge on or off. A monitor on a published status page has a badge even when it is false. | |
| timeout_seconds | No | Seconds one check may take before it fails, 1 to 120. | |
| interval_seconds | No | Seconds between checks, 30 to 86400. The plan sets a minimum (limits.min_interval_seconds) and caps how many monitors may check more often than every 60 seconds (max_fast_monitors); breaking either is a 403 naming the limit. | |
| confirmation_threshold | No | How many checks in a row must fail in every region before the monitor goes DOWN and an incident opens, 1 to 10; 3 when not set on create. | |
| notification_cooldown_seconds | No | 60 to 86400 seconds; 1800 when not set on create. Only holds back a duplicate first alert for the same incident within that window. Repeat reminders while an incident stays open and unacknowledged follow the plan's renotify_interval_seconds and renotify_max_count (get_plan_usage; 0 means no reminders) instead, and the recovery alert is never held back. |
Output Schema
| Name | Required | Description |
|---|---|---|
| id | Yes | |
| name | Yes | |
| tags | No | |
| type | Yes | Known values: HTTP, PING, SSL, TCP, DNS. |
| config | Yes | |
| status | Yes | Known values: PENDING, UP, DEGRADED, DOWN, PAUSED. |
| target | Yes | |
| regions | Yes | |
| user_id | Yes | |
| is_active | Yes | |
| created_at | Yes | |
| updated_at | Yes | |
| channel_ids | No | |
| next_run_at | Yes | |
| badge_enabled | No | |
| ssl_cert_info | No | |
| ssl_expires_at | Yes | |
| last_checked_at | Yes | |
| region_statuses | Yes | Per-region latest status, sorted by region name. Built from ``region_snapshots``; ``job_id`` is dropped (internal dedup key) and malformed/partial snapshot rows are skipped rather than failing the read. |
| timeout_seconds | Yes | |
| interval_seconds | Yes | |
| confirmation_threshold | Yes | |
| notification_cooldown_seconds | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare idempotency and non-destructiveness; the description goes further with PATCH-like semantics (omitted fields retained, null forbidden), 422/403/404 failure conditions, plan-limit checks against the result, and the config-wholesale-replacement warning. This is substantial behavioral disclosure beyond the structured hints, though it does not restate the safety profile itself.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core mutation semantics, immutability constraint, and routing alternatives before the operational caveats. It is long and dense, but the length is earned by the complexity of an 11-parameter tool with nested config; a few clauses (e.g. the port-list/plan-limit details) could be trimmed.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given an output schema exists, the description needn't explain return values, and it focuses correctly on update semantics, error paths, and plan-limit interactions. For a complex nested-config mutation tool, the coverage of edge cases (null handling, config replacement, region/interval constraints) is thorough.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
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 cross-field meaning the schema cannot: 'omit a field to keep it; never send null', the requires-one-field-beyond-monitor_id rule, and a concrete usage example. These clarify how parameters interact rather than merely restating individual field docs.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Change one monitor's settings') plus the scope (single monitor) and return shape ('get_monitor shape'). It explicitly distinguishes itself from bulk_update_monitors, pause_monitor/resume_monitor, and bulk_update_monitor_tags, so an agent can route correctly without opening a schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Names the excluded use cases and their alternatives explicitly (pause/resume, bulk updates, tag-only bulk edits) and tells the agent to use create_monitor for immutable type/target changes. It also states the write-scope prerequisite and the minimum-field requirement, covering when and when-not to use it.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
update_status_page_incidentRename a status page incidentAIdempotentInspect
Change a status page incident's title without telling anyone: nothing is sent to subscribers. To change its status or add a message use post_status_page_update. Requires a key with the write scope. Returns the incident. Example: {"page_id": "", "incident_id": "", "title": "API errors in eu-central"}
| Name | Required | Description | Default |
|---|---|---|---|
| title | Yes | The new headline, 1 to 255 characters. | |
| page_id | Yes | The status page's uuid from list_status_pages. An id that is not a status page of this organization is a 404. | |
| incident_id | Yes | The status page incident's uuid from list_status_page_incidents (not from list_incidents). An unknown id is a 404. |
Output Schema
| Name | Required | Description |
|---|---|---|
| id | Yes | |
| title | Yes | |
| status | Yes | Known values: INVESTIGATING, IDENTIFIED, MONITORING, RESOLVED. |
| is_auto | Yes | |
| updates | Yes | |
| started_at | Yes | |
| notified_at | Yes | |
| resolved_at | Yes | |
| component_ids | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations cover the safety profile (readOnlyHint=false, idempotentHint=true, destructiveHint=false), but the description adds behavior the annotations cannot express: no subscriber notification is sent, and a key with the write scope is required. It also states the return value. This is meaningful side-effect and auth context beyond structured fields.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four tight sentences: the action and its silent side effect come first, then the alternative tool, then auth, then a compact example. Every sentence carries a distinct fact and none is padding.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a three-parameter, fully-required mutation with an output schema present, the description supplies the missing pieces: silent notification behavior, required write scope, the competing sibling tool, and ID provenance. Nothing an agent needs to call it correctly is absent.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and each parameter already documents its source and error behavior ('from list_status_pages', 404 on unknown id), so the baseline is 3. The example restates the same ID provenance rather than adding new semantics such as title constraints or conflict behavior, so no credit above baseline.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource — renaming a status page incident's title — and immediately clarifies the scope ('without telling anyone: nothing is sent to subscribers'). It explicitly distinguishes itself from the sibling post_status_page_update, which handles status changes and messages, so an agent can route correctly without opening either schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Names the alternative tool (post_status_page_update) and the exact condition that selects it ('to change its status or add a message'). It also states the positive condition for this tool: a silent title-only change. Nothing about when-to-use is left to inference.
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.
47 tool updates
v0.6.1- Changed
acknowledge_incident2 fields changed- added
Input schema / properties / incident_id / descriptionAdded value: +"The incident's uuid from list_incidents. An id that is not an incident of this organization is a 404." - changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "acknowledged_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "acknowledged_by": { + "anyOf": [ + { + "format": "uuid", + "type": "string" + }, + { + "type": "null" + } + ] + }, + "cause": { + "description": "Known values: TIMEOUT, DNS_FAILURE, CONNECTION_REFUSED, TLS_INVALID, HTTP_4XX, HTTP_5XX, HTTP_UNEXPECTED_STATUS, KEYWORD_MISSING, TOO_MANY_REDIRECTS, TARGET_BLOCKED, PORT_STATE_MISMATCH, INVALID_TARGET, HEARTBEAT_MISSED, HEARTBEAT_FAILED, UNKNOWN.", + "type": "string" + }, + "cause_detail": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "created_at": { + "type": "string" + }, + "heartbeat_id": { + "anyOf": [ + { + "format": "uuid", + "type": "string" + }, + { + "type": "null" + } + ] + }, + "id": { + "format": "uuid", + "type": "string" + }, + "last_notified_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "monitor_id": { + "anyOf": [ + { + "format": "uuid", + "type": "string" + }, + { + "type": "null" + } + ] + }, + "notification_logs": { + "items": { + "properties": { + "channel_type": { + "description": "Known values: EMAIL, TELEGRAM, WEBHOOK, SLACK, DISCORD.", + "type": "string" + }, + "destination": { + "type": "string" + }, + "error": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "event": { + "description": "Known values: TRIGGERED, RESOLVED, SSL_EXPIRY.", + "type": "string" + }, + "id": { + "format": "uuid", + "type": "string" + }, + "sent_at": { + "type": "string" + }, + "status": { + "description": "Known values: PENDING, SENT, FAILED.", + "type": "string" + } + }, + "required": [ + "id", + "channel_type", + "destination", + "event", + "sent_at", + "status", + "error" + ], + "type": "object" + }, + "type": "array" + }, + "renotify_count": { + "type": "integer" + }, + "resolved_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "started_at": { + "type": "string" + }, + "updated_at": { + "type": "string" + } + }, + "required": [ + "id", + "started_at", + "resolved_at", + "cause", + "cause_detail", + "last_notified_at", + "acknowledged_at", + "acknowledged_by", + "renotify_count", + "created_at", + "updated_at" + ], + "type": "object" +}
- Changed
bulk_create_monitors2 fields changed- changed
Input schema / properties / monitors / descriptionPrevious value: -"Monitors to create, each shaped like a single create request."New value: +"1 to 100 monitors, each taking the same fields and rules as create_monitor's arguments. Items with is_active false are created paused and still count toward the plan." - changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "monitors": { + "items": { + "properties": { + "id": { + "format": "uuid", + "type": "string" + }, + "interval_seconds": { + "type": "integer" + }, + "is_active": { + "type": "boolean" + }, + "last_checked_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "name": { + "type": "string" + }, + "ssl_expires_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "status": { + "description": "Known values: PENDING, UP, DEGRADED, DOWN, PAUSED.", + "type": "string" + }, + "tags": { + "items": { + "type": "string" + }, + "type": "array" + }, + "target": { + "type": "string" + }, + "type": { + "description": "Known values: HTTP, PING, SSL, TCP, DNS.", + "type": "string" + } + }, + "required": [ + "id", + "name", + "type", + "target", + "status", + "is_active", + "interval_seconds", + "ssl_expires_at", + "last_checked_at" + ], + "type": "object" + }, + "type": "array" + } + }, + "required": [ + "monitors" + ], + "type": "object" +}
- Changed
bulk_pause_monitors2 fields changed- changed
Input schema / properties / monitor_ids / descriptionPrevious value: -"Monitors to act on. Every id must belong to the active organization."New value: +"1 to 100 distinct monitor uuids from list_monitors. A repeated id is a 422; an id that is not a monitor of this organization is a 404 naming it, and then nothing changes." - changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "monitors": { + "items": { + "properties": { + "id": { + "format": "uuid", + "type": "string" + }, + "interval_seconds": { + "type": "integer" + }, + "is_active": { + "type": "boolean" + }, + "last_checked_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "name": { + "type": "string" + }, + "ssl_expires_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "status": { + "description": "Known values: PENDING, UP, DEGRADED, DOWN, PAUSED.", + "type": "string" + }, + "tags": { + "items": { + "type": "string" + }, + "type": "array" + }, + "target": { + "type": "string" + }, + "type": { + "description": "Known values: HTTP, PING, SSL, TCP, DNS.", + "type": "string" + } + }, + "required": [ + "id", + "name", + "type", + "target", + "status", + "is_active", + "interval_seconds", + "ssl_expires_at", + "last_checked_at" + ], + "type": "object" + }, + "type": "array" + } + }, + "required": [ + "monitors" + ], + "type": "object" +}
- Changed
bulk_resume_monitors2 fields changed- changed
Input schema / properties / monitor_ids / descriptionPrevious value: -"Monitors to act on. Every id must belong to the active organization."New value: +"1 to 100 distinct monitor uuids from list_monitors. A repeated id is a 422; an id that is not a monitor of this organization is a 404 naming it, and then nothing changes." - changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "monitors": { + "items": { + "properties": { + "id": { + "format": "uuid", + "type": "string" + }, + "interval_seconds": { + "type": "integer" + }, + "is_active": { + "type": "boolean" + }, + "last_checked_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "name": { + "type": "string" + }, + "ssl_expires_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "status": { + "description": "Known values: PENDING, UP, DEGRADED, DOWN, PAUSED.", + "type": "string" + }, + "tags": { + "items": { + "type": "string" + }, + "type": "array" + }, + "target": { + "type": "string" + }, + "type": { + "description": "Known values: HTTP, PING, SSL, TCP, DNS.", + "type": "string" + } + }, + "required": [ + "id", + "name", + "type", + "target", + "status", + "is_active", + "interval_seconds", + "ssl_expires_at", + "last_checked_at" + ], + "type": "object" + }, + "type": "array" + } + }, + "required": [ + "monitors" + ], + "type": "object" +}
- Changed
bulk_update_monitor_tags4 fields changed- changed
Input schema / properties / add / descriptionPrevious value: -"Tags to add to every listed monitor."New value: +"Tags to add to every listed monitor, up to 10." - changed
Input schema / properties / monitor_ids / descriptionPrevious value: -"Monitors to retag. Every id must belong to the active organization."New value: +"1 to 300 distinct monitor uuids from list_monitors. A repeated id is a 422; an unknown id rejects the whole call with a 404 naming every id not found." - changed
Input schema / properties / remove / descriptionPrevious value: -"Tags to remove from every listed monitor."New value: +"Tags to remove from every listed monitor, up to 10." - changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "monitors_updated": { + "type": "integer" + } + }, + "required": [ + "monitors_updated" + ], + "type": "object" +}
- Changed
bulk_update_monitors3 fields changed- added
Input schema / properties / changes / descriptionAdded value: +"The values to set, at least one of: interval_seconds (30 to 86400), timeout_seconds (1 to 120), regions (region codes from limits.allowed_regions in get_plan_usage), channel_ids (channel uuids from list_channels; replaces each binding, [] clears it, an unknown channel is a 404), confirmation_threshold (1 to 10) and notification_cooldown_seconds (60 to 86400). Omit a field to keep it; never send null." - changed
Input schema / properties / monitor_ids / descriptionPrevious value: -"Monitors to act on. Every id must belong to the active organization."New value: +"1 to 100 distinct monitor uuids from list_monitors. A repeated id is a 422; an id that is not a monitor of this organization is a 404 naming it, and then nothing changes." - changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "monitors": { + "items": { + "properties": { + "id": { + "format": "uuid", + "type": "string" + }, + "interval_seconds": { + "type": "integer" + }, + "is_active": { + "type": "boolean" + }, + "last_checked_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "name": { + "type": "string" + }, + "ssl_expires_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "status": { + "description": "Known values: PENDING, UP, DEGRADED, DOWN, PAUSED.", + "type": "string" + }, + "tags": { + "items": { + "type": "string" + }, + "type": "array" + }, + "target": { + "type": "string" + }, + "type": { + "description": "Known values: HTTP, PING, SSL, TCP, DNS.", + "type": "string" + } + }, + "required": [ + "id", + "name", + "type", + "target", + "status", + "is_active", + "interval_seconds", + "ssl_expires_at", + "last_checked_at" + ], + "type": "object" + }, + "type": "array" + } + }, + "required": [ + "monitors" + ], + "type": "object" +}
- Changed
check_now2 fields changed- added
Input schema / properties / monitor_id / descriptionAdded value: +"The monitor's uuid from list_monitors. An id that is not a monitor of this organization, or a deleted one, is a 404." - changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "badge_enabled": { + "type": "boolean" + }, + "channel_ids": { + "items": { + "format": "uuid", + "type": "string" + }, + "type": "array" + }, + "config": { + "additionalProperties": true, + "type": "object" + }, + "confirmation_threshold": { + "type": "integer" + }, + "created_at": { + "type": "string" + }, + "id": { + "format": "uuid", + "type": "string" + }, + "interval_seconds": { + "type": "integer" + }, + "is_active": { + "type": "boolean" + }, + "last_checked_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "name": { + "type": "string" + }, + "next_run_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "notification_cooldown_seconds": { + "type": "integer" + }, + "region_statuses": { + "description": "Per-region latest status, sorted by region name.\n\nBuilt from ``region_snapshots``; ``job_id`` is dropped (internal\ndedup key) and malformed/partial snapshot rows are skipped rather\nthan failing the read.", + "items": { + "properties": { + "checked_at": { + "type": "string" + }, + "display_name": { + "type": "string" + }, + "region": { + "type": "string" + }, + "status": { + "description": "Known values: UP, DEGRADED, DOWN, ERROR.", + "type": "string" + } + }, + "required": [ + "region", + "status", + "checked_at", + "display_name" + ], + "type": "object" + }, + "type": "array" + }, + "regions": { + "items": { + "type": "string" + }, + "type": "array" + }, + "ssl_cert_info": { + "anyOf": [ + { + "properties": { + "issuer": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "not_after": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "not_before": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "subject": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "valid": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ] + } + }, + "type": "object" + }, + { + "type": "null" + } + ] + }, + "ssl_expires_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "status": { + "description": "Known values: PENDING, UP, DEGRADED, DOWN, PAUSED.", + "type": "string" + }, + "tags": { + "items": { + "type": "string" + }, + "type": "array" + }, + "target": { + "type": "string" + }, + "timeout_seconds": { + "type": "integer" + }, + "type": { + "description": "Known values: HTTP, PING, SSL, TCP, DNS.", + "type": "string" + }, + "updated_at": { + "type": "string" + }, + "user_id": { + "format": "uuid", + "type": "string" + } + }, + "required": [ + "id", + "user_id", + "name", + "type", + "target", + "interval_seconds", + "timeout_seconds", + "regions", + "config", + "status", + "last_checked_at", + "next_run_at", + "confirmation_threshold", + "notification_cooldown_seconds", + "ssl_expires_at", + "is_active", + "created_at", + "updated_at", + "region_statuses" + ], + "type": "object" +}
- Changed
check_target4 fields changed- added
Input schema / properties / config / descriptionAdded value: +"As in create_monitor; TCP and DNS need it. The region, interval and update rules there do not apply to a one-off probe. An object whose fields depend on type, all optional unless stated. HTTP: method (GET, HEAD, POST, PUT, PATCH or DELETE, any case; default GET); expected_status_codes (non-empty list of codes 100 to 599, default [200]); keyword (case-sensitive substring the body must contain, at most 1024 characters, not with HEAD); follow_redirects (default true); verify_ssl (default true; false skips TLS verification, so the monitor can never report TLS_INVALID); request_headers (object of name to value: at most 20, a name at most 128 characters of letters, digits and ! # $ % & ' * + - . ^ _ ` | ~, a value at most 1024 bytes of printable ASCII, space or tab, the whole object at most 8192 bytes as JSON; names differing only in case, and Host, Content-Length, Transfer-Encoding, Connection, Upgrade, TE, Trailer, Keep-Alive, CF-Connecting-IP or any Proxy-* name, are a 422); request_body (string, at most 8192 bytes as UTF-8, needs POST, PUT, PATCH or DELETE). Reads return every request_headers value as the literal __FETTLE_UNCHANGED__; writing that literal back in an update keeps the stored value (on create it is a 422). PING: packet_count (1 to 20, default 4). SSL: warn_before_days (1 to 365, default 14) and port (1 to 65535, default 443). TCP: either port (1 to 65535) with expected_state \"open\" (default) or \"closed\", or ports (1 to 20 distinct ports that must all be closed, which needs expected_state \"closed\", exactly one region and interval_seconds of at least 300; a check fails when any of them accepts a connection, and the monitor goes DOWN once confirmation_threshold failures confirm it). Both port and ports, or neither, is a 422; expected_state values are lowercase. DNS: record_type (A, AAAA, CNAME, MX, TXT or NS; required) and expected_value (at most 2048 characters). With expected_value one answer must equal it (case-insensitive, ignoring surrounding spaces and a trailing dot; exact for TXT); without it any answer passes. MX answers are the mail host names without priority (mail.example.com, not 10 mail.example.com). A and AAAA look up every address of the host, IPv4 and IPv6 alike, and any one may match; write an IPv6 address in its shortest form." - added
Input schema / properties / target / descriptionAdded value: +"What to check, up to 2048 characters. HTTP: an http:// or https:// URL (https:// is added when the scheme is missing; port, path and query are kept). PING, SSL, TCP and DNS: a bare public hostname or IP address with no :port and no path (the port goes in config): host:port is a 422, and a full URL is cut down to its host, losing its port. Hostnames are ASCII (punycode for internationalized domains). localhost, *.localhost and addresses that are not public (private, loopback, link-local, CGNAT 100.64.0.0/10, reserved, unspecified) are a 422." - added
Input schema / properties / type / descriptionAdded value: +"HTTP (a URL answers with an expected status), PING (a host answers ICMP), SSL (a certificate is valid and not about to expire), TCP (a port is open, or a list of ports is closed) or DNS (a record resolves, optionally to an expected value)." - changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "error": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "failure_kind": { + "anyOf": [ + { + "description": "Known values: TIMEOUT, DNS_FAILURE, CONNECTION_REFUSED, TLS_INVALID, HTTP_4XX, HTTP_5XX, HTTP_UNEXPECTED_STATUS, KEYWORD_MISSING, TOO_MANY_REDIRECTS, TARGET_BLOCKED, PORT_STATE_MISMATCH, INVALID_TARGET, UNKNOWN.", + "type": "string" + }, + { + "type": "null" + } + ] + }, + "region": { + "type": "string" + }, + "response_time_ms": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ] + }, + "status": { + "description": "Known values: up, down, error, unknown.", + "type": "string" + }, + "status_code": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "status", + "region" + ], + "type": "object" +}
- Changed
create_heartbeat7 fields changed- added
Input schema / properties / channel_ids / descriptionAdded value: +"Notification channel uuids from list_channels. Omit it or pass [] to alert every verified, active channel of the organization. An id that is not an active channel of this organization is a 404." - added
Input schema / properties / grace_seconds / descriptionAdded value: +"Extra seconds of silence tolerated after the period before the heartbeat is reported late, 0 to 2592000; it may exceed the period." - added
Input schema / properties / name / descriptionAdded value: +"Display name, 1 to 255 characters." - added
Input schema / properties / notification_cooldown_seconds / descriptionAdded value: +"60 to 86400 seconds; 1800 when not set on create. Only holds back a duplicate first alert for the same incident within that window. Repeat reminders while an incident stays open and unacknowledged follow the plan's renotify_interval_seconds and renotify_max_count (get_plan_usage; 0 means no reminders) instead, and the recovery alert is never held back." - added
Input schema / properties / period_seconds / descriptionAdded value: +"How often the job runs, 60 to 2592000 seconds. To ping every N seconds and be alerted after T seconds of silence, set period_seconds = N and grace_seconds = T - N (T at least N)." - added
Input schema / properties / tags / descriptionAdded value: +"Flat labels for grouping and filtering, for example env:prod or service:api, at most 10. Each tag is trimmed, lowercased and deduplicated on write, at most 50 characters of a-z, 0-9 and : _ . / -, starting with a letter or digit. Reuse names from list_tags rather than inventing near-duplicates." - changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "channel_ids": { + "items": { + "format": "uuid", + "type": "string" + }, + "type": "array" + }, + "created_at": { + "type": "string" + }, + "grace_seconds": { + "type": "integer" + }, + "id": { + "format": "uuid", + "type": "string" + }, + "is_active": { + "type": "boolean" + }, + "last_duration_ms": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ] + }, + "last_ping_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "last_start_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "last_success_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "name": { + "type": "string" + }, + "notification_cooldown_seconds": { + "type": "integer" + }, + "overdue_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "period_seconds": { + "type": "integer" + }, + "ping_url": { + "type": "string" + }, + "state": { + "description": "Known values: PENDING, UP, DOWN, PAUSED.", + "type": "string" + }, + "tags": { + "items": { + "type": "string" + }, + "type": "array" + }, + "updated_at": { + "type": "string" + } + }, + "required": [ + "id", + "name", + "state", + "period_seconds", + "grace_seconds", + "ping_url", + "last_ping_at", + "last_success_at", + "last_start_at", + "last_duration_ms", + "overdue_at", + "notification_cooldown_seconds", + "is_active", + "created_at", + "updated_at" + ], + "type": "object" +}
- Changed
create_maintenance_window9 fields changed- added
Input schema / properties / dtstart / descriptionAdded value: +"The first start, an ISO 8601 date-time in the wall-clock time of timezone, for example 2026-10-14T22:00:00. A UTC offset or Z is a 422." - added
Input schema / properties / duration_minutes / descriptionAdded value: +"How long each occurrence lasts, 1 to 40320 minutes." - added
Input schema / properties / enabled / descriptionAdded value: +"Default true; false stores the window without effect." - added
Input schema / properties / monitor_ids / descriptionAdded value: +"Monitor uuids from list_monitors, at least one when scope is MONITOR. An id that is not a monitor of this organization is a 404." - added
Input schema / properties / name / descriptionAdded value: +"Display name, 1 to 255 characters." - added
Input schema / properties / rrule / descriptionAdded value: +"Repeats the window: one iCal RRULE without the RRULE: prefix, at most 1024 characters, for example FREQ=WEEKLY;BYDAY=SU;BYHOUR=3. Hourly, minutely and secondly frequencies are refused. Omit it for a one-time window." - added
Input schema / properties / scope / descriptionAdded value: +"ORG covers every monitor of the organization and ignores monitor_ids; MONITOR covers only monitor_ids." - added
Input schema / properties / timezone / descriptionAdded value: +"IANA zone name such as Europe/Berlin, at most 64 characters. The schedule repeats in it, so a weekly 03:00 stays 03:00 across daylight-saving changes. Defaults to the organization's timezone." - changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "created_at": { + "type": "string" + }, + "dtstart": { + "type": "string" + }, + "duration_minutes": { + "type": "integer" + }, + "enabled": { + "type": "boolean" + }, + "id": { + "format": "uuid", + "type": "string" + }, + "monitor_ids": { + "items": { + "format": "uuid", + "type": "string" + }, + "type": "array" + }, + "name": { + "type": "string" + }, + "rrule": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "scope": { + "description": "Known values: MONITOR, ORG.", + "type": "string" + }, + "timezone": { + "type": "string" + } + }, + "required": [ + "id", + "name", + "enabled", + "scope", + "dtstart", + "duration_minutes", + "rrule", + "timezone", + "created_at" + ], + "type": "object" +}
- Changed
create_monitor13 fields changed- added
Input schema / properties / channel_ids / descriptionAdded value: +"Notification channel uuids from list_channels. Omit it or pass [] to alert every verified, active channel of the organization. An id that is not an active channel of this organization is a 404." - added
Input schema / properties / config / descriptionAdded value: +"An object whose fields depend on type, all optional unless stated. HTTP: method (GET, HEAD, POST, PUT, PATCH or DELETE, any case; default GET); expected_status_codes (non-empty list of codes 100 to 599, default [200]); keyword (case-sensitive substring the body must contain, at most 1024 characters, not with HEAD); follow_redirects (default true); verify_ssl (default true; false skips TLS verification, so the monitor can never report TLS_INVALID); request_headers (object of name to value: at most 20, a name at most 128 characters of letters, digits and ! # $ % & ' * + - . ^ _ ` | ~, a value at most 1024 bytes of printable ASCII, space or tab, the whole object at most 8192 bytes as JSON; names differing only in case, and Host, Content-Length, Transfer-Encoding, Connection, Upgrade, TE, Trailer, Keep-Alive, CF-Connecting-IP or any Proxy-* name, are a 422); request_body (string, at most 8192 bytes as UTF-8, needs POST, PUT, PATCH or DELETE). Reads return every request_headers value as the literal __FETTLE_UNCHANGED__; writing that literal back in an update keeps the stored value (on create it is a 422). PING: packet_count (1 to 20, default 4). SSL: warn_before_days (1 to 365, default 14) and port (1 to 65535, default 443). TCP: either port (1 to 65535) with expected_state \"open\" (default) or \"closed\", or ports (1 to 20 distinct ports that must all be closed, which needs expected_state \"closed\", exactly one region and interval_seconds of at least 300; a check fails when any of them accepts a connection, and the monitor goes DOWN once confirmation_threshold failures confirm it). Both port and ports, or neither, is a 422; expected_state values are lowercase. DNS: record_type (A, AAAA, CNAME, MX, TXT or NS; required) and expected_value (at most 2048 characters). With expected_value one answer must equal it (case-insensitive, ignoring surrounding spaces and a trailing dot; exact for TXT); without it any answer passes. MX answers are the mail host names without priority (mail.example.com, not 10 mail.example.com). A and AAAA look up every address of the host, IPv4 and IPv6 alike, and any one may match; write an IPv6 address in its shortest form. Omit it for HTTP, PING or SSL to take the defaults; a TCP or DNS monitor without it is a 422." - added
Input schema / properties / confirmation_threshold / descriptionAdded value: +"How many checks in a row must fail in every region before the monitor goes DOWN and an incident opens, 1 to 10; 3 when not set on create." - added
Input schema / properties / interval_seconds / descriptionAdded value: +"Seconds between checks, 30 to 86400. The plan sets a minimum (limits.min_interval_seconds) and caps how many monitors may check more often than every 60 seconds (max_fast_monitors); breaking either is a 403 naming the limit." - added
Input schema / properties / is_active / descriptionAdded value: +"Default true. false creates it paused: no check runs until resume_monitor." - added
Input schema / properties / name / descriptionAdded value: +"Display name, 1 to 255 characters." - added
Input schema / properties / notification_cooldown_seconds / descriptionAdded value: +"60 to 86400 seconds; 1800 when not set on create. Only holds back a duplicate first alert for the same incident within that window. Repeat reminders while an incident stays open and unacknowledged follow the plan's renotify_interval_seconds and renotify_max_count (get_plan_usage; 0 means no reminders) instead, and the recovery alert is never held back." - added
Input schema / properties / regions / descriptionAdded value: +"One or more distinct region codes, for example eu-central: the plan's choices are limits.allowed_regions in get_plan_usage. An unknown code, or more regions than the plan's max_regions, is a 403. SSL and DNS monitors take exactly one region (422 otherwise)." - added
Input schema / properties / tags / descriptionAdded value: +"Flat labels for grouping and filtering, for example env:prod or service:api, at most 10. Each tag is trimmed, lowercased and deduplicated on write, at most 50 characters of a-z, 0-9 and : _ . / -, starting with a letter or digit. Reuse names from list_tags rather than inventing near-duplicates." - added
Input schema / properties / target / descriptionAdded value: +"What to check, up to 2048 characters. HTTP: an http:// or https:// URL (https:// is added when the scheme is missing; port, path and query are kept). PING, SSL, TCP and DNS: a bare public hostname or IP address with no :port and no path (the port goes in config): host:port is a 422, and a full URL is cut down to its host, losing its port. Hostnames are ASCII (punycode for internationalized domains). localhost, *.localhost and addresses that are not public (private, loopback, link-local, CGNAT 100.64.0.0/10, reserved, unspecified) are a 422. Cannot be changed after create." - added
Input schema / properties / timeout_seconds / descriptionAdded value: +"Seconds one check may take before it fails, 1 to 120." - added
Input schema / properties / type / descriptionAdded value: +"HTTP (a URL answers with an expected status), PING (a host answers ICMP), SSL (a certificate is valid and not about to expire), TCP (a port is open, or a list of ports is closed) or DNS (a record resolves, optionally to an expected value). Cannot be changed after create." - changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "badge_enabled": { + "type": "boolean" + }, + "channel_ids": { + "items": { + "format": "uuid", + "type": "string" + }, + "type": "array" + }, + "config": { + "additionalProperties": true, + "type": "object" + }, + "confirmation_threshold": { + "type": "integer" + }, + "created_at": { + "type": "string" + }, + "id": { + "format": "uuid", + "type": "string" + }, + "interval_seconds": { + "type": "integer" + }, + "is_active": { + "type": "boolean" + }, + "last_checked_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "name": { + "type": "string" + }, + "next_run_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "notification_cooldown_seconds": { + "type": "integer" + }, + "region_statuses": { + "description": "Per-region latest status, sorted by region name.\n\nBuilt from ``region_snapshots``; ``job_id`` is dropped (internal\ndedup key) and malformed/partial snapshot rows are skipped rather\nthan failing the read.", + "items": { + "properties": { + "checked_at": { + "type": "string" + }, + "display_name": { + "type": "string" + }, + "region": { + "type": "string" + }, + "status": { + "description": "Known values: UP, DEGRADED, DOWN, ERROR.", + "type": "string" + } + }, + "required": [ + "region", + "status", + "checked_at", + "display_name" + ], + "type": "object" + }, + "type": "array" + }, + "regions": { + "items": { + "type": "string" + }, + "type": "array" + }, + "ssl_cert_info": { + "anyOf": [ + { + "properties": { + "issuer": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "not_after": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "not_before": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "subject": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "valid": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ] + } + }, + "type": "object" + }, + { + "type": "null" + } + ] + }, + "ssl_expires_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "status": { + "description": "Known values: PENDING, UP, DEGRADED, DOWN, PAUSED.", + "type": "string" + }, + "tags": { + "items": { + "type": "string" + }, + "type": "array" + }, + "target": { + "type": "string" + }, + "timeout_seconds": { + "type": "integer" + }, + "type": { + "description": "Known values: HTTP, PING, SSL, TCP, DNS.", + "type": "string" + }, + "updated_at": { + "type": "string" + }, + "user_id": { + "format": "uuid", + "type": "string" + } + }, + "required": [ + "id", + "user_id", + "name", + "type", + "target", + "interval_seconds", + "timeout_seconds", + "regions", + "config", + "status", + "last_checked_at", + "next_run_at", + "confirmation_threshold", + "notification_cooldown_seconds", + "ssl_expires_at", + "is_active", + "created_at", + "updated_at", + "region_statuses" + ], + "type": "object" +}
- Changed
create_status_page_incident6 fields changed- added
Input schema / properties / body / descriptionAdded value: +"The first message. The message subscribers read, 1 to 5000 characters." - added
Input schema / properties / component_ids / descriptionAdded value: +"The affected components: uuids from get_status_page. An id that is not a component of this page is a 404." - added
Input schema / properties / page_id / descriptionAdded value: +"The status page's uuid from list_status_pages. An id that is not a status page of this organization is a 404." - added
Input schema / properties / status / descriptionAdded value: +"INVESTIGATING, IDENTIFIED, MONITORING or RESOLVED; RESOLVED closes the incident on the page. Default INVESTIGATING." - added
Input schema / properties / title / descriptionAdded value: +"The incident's headline, 1 to 255 characters." - changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "component_ids": { + "items": { + "format": "uuid", + "type": "string" + }, + "type": "array" + }, + "id": { + "format": "uuid", + "type": "string" + }, + "is_auto": { + "type": "boolean" + }, + "notified_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "resolved_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "started_at": { + "type": "string" + }, + "status": { + "description": "Known values: INVESTIGATING, IDENTIFIED, MONITORING, RESOLVED.", + "type": "string" + }, + "title": { + "type": "string" + }, + "updates": { + "items": { + "properties": { + "body": { + "type": "string" + }, + "created_at": { + "type": "string" + }, + "created_by": { + "anyOf": [ + { + "format": "uuid", + "type": "string" + }, + { + "type": "null" + } + ] + }, + "id": { + "format": "uuid", + "type": "string" + }, + "status": { + "description": "Known values: INVESTIGATING, IDENTIFIED, MONITORING, RESOLVED.", + "type": "string" + } + }, + "required": [ + "id", + "status", + "body", + "created_by", + "created_at" + ], + "type": "object" + }, + "type": "array" + } + }, + "required": [ + "id", + "title", + "status", + "is_auto", + "started_at", + "resolved_at", + "notified_at", + "component_ids", + "updates" + ], + "type": "object" +}
- Changed
delete_heartbeat2 fields changed- added
Input schema / properties / heartbeat_id / descriptionAdded value: +"The heartbeat's uuid from list_heartbeats. An id that is not a heartbeat of this organization, or a deleted one, is a 404." - changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "success": { + "type": "boolean" + } + }, + "required": [ + "success" + ], + "type": "object" +}
- Changed
delete_maintenance_window2 fields changed- added
Input schema / properties / window_id / descriptionAdded value: +"The window's uuid from list_maintenance_windows. An id that is not a window of this organization is a 404." - changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "success": { + "type": "boolean" + } + }, + "required": [ + "success" + ], + "type": "object" +}
- Changed
delete_monitor2 fields changed- added
Input schema / properties / monitor_id / descriptionAdded value: +"The monitor's uuid from list_monitors. An id that is not a monitor of this organization, or a deleted one, is a 404." - changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "success": { + "type": "boolean" + } + }, + "required": [ + "success" + ], + "type": "object" +}
- Changed
delete_status_page_incident3 fields changed- added
Input schema / properties / incident_id / descriptionAdded value: +"The status page incident's uuid from list_status_page_incidents (not from list_incidents). An unknown id is a 404." - added
Input schema / properties / page_id / descriptionAdded value: +"The status page's uuid from list_status_pages. An id that is not a status page of this organization is a 404." - changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "success": { + "type": "boolean" + } + }, + "required": [ + "success" + ], + "type": "object" +}
- Changed
delete_tag2 fields changed- added
Input schema / properties / tag / descriptionAdded value: +"The tag to remove, exactly as list_tags shows it." - changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "from": { + "type": "string" + }, + "heartbeats_updated": { + "type": "integer" + }, + "monitors_updated": { + "type": "integer" + } + }, + "required": [ + "from", + "monitors_updated", + "heartbeats_updated" + ], + "type": "object" +}
- Changed
get_exposed_ports_preset1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "ports": { + "items": { + "properties": { + "port": { + "type": "integer" + }, + "service": { + "type": "string" + } + }, + "required": [ + "port", + "service" + ], + "type": "object" + }, + "type": "array" + } + }, + "required": [ + "ports" + ], + "type": "object" +}
- Changed
get_heartbeat2 fields changed- added
Input schema / properties / heartbeat_id / descriptionAdded value: +"The heartbeat's uuid from list_heartbeats. An id that is not a heartbeat of this organization, or a deleted one, is a 404." - changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "channel_ids": { + "items": { + "format": "uuid", + "type": "string" + }, + "type": "array" + }, + "created_at": { + "type": "string" + }, + "grace_seconds": { + "type": "integer" + }, + "id": { + "format": "uuid", + "type": "string" + }, + "is_active": { + "type": "boolean" + }, + "last_duration_ms": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ] + }, + "last_ping_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "last_start_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "last_success_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "name": { + "type": "string" + }, + "notification_cooldown_seconds": { + "type": "integer" + }, + "overdue_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "period_seconds": { + "type": "integer" + }, + "ping_url": { + "type": "string" + }, + "state": { + "description": "Known values: PENDING, UP, DOWN, PAUSED.", + "type": "string" + }, + "tags": { + "items": { + "type": "string" + }, + "type": "array" + }, + "updated_at": { + "type": "string" + } + }, + "required": [ + "id", + "name", + "state", + "period_seconds", + "grace_seconds", + "ping_url", + "last_ping_at", + "last_success_at", + "last_start_at", + "last_duration_ms", + "overdue_at", + "notification_cooldown_seconds", + "is_active", + "created_at", + "updated_at" + ], + "type": "object" +}
- Changed
get_incident2 fields changed- added
Input schema / properties / incident_id / descriptionAdded value: +"The incident's uuid from list_incidents. An id that is not an incident of this organization is a 404." - changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "acknowledged_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "acknowledged_by": { + "anyOf": [ + { + "format": "uuid", + "type": "string" + }, + { + "type": "null" + } + ] + }, + "cause": { + "description": "Known values: TIMEOUT, DNS_FAILURE, CONNECTION_REFUSED, TLS_INVALID, HTTP_4XX, HTTP_5XX, HTTP_UNEXPECTED_STATUS, KEYWORD_MISSING, TOO_MANY_REDIRECTS, TARGET_BLOCKED, PORT_STATE_MISMATCH, INVALID_TARGET, HEARTBEAT_MISSED, HEARTBEAT_FAILED, UNKNOWN.", + "type": "string" + }, + "cause_detail": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "created_at": { + "type": "string" + }, + "heartbeat_id": { + "anyOf": [ + { + "format": "uuid", + "type": "string" + }, + { + "type": "null" + } + ] + }, + "id": { + "format": "uuid", + "type": "string" + }, + "last_notified_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "monitor_id": { + "anyOf": [ + { + "format": "uuid", + "type": "string" + }, + { + "type": "null" + } + ] + }, + "notification_logs": { + "items": { + "properties": { + "channel_type": { + "description": "Known values: EMAIL, TELEGRAM, WEBHOOK, SLACK, DISCORD.", + "type": "string" + }, + "destination": { + "type": "string" + }, + "error": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "event": { + "description": "Known values: TRIGGERED, RESOLVED, SSL_EXPIRY.", + "type": "string" + }, + "id": { + "format": "uuid", + "type": "string" + }, + "sent_at": { + "type": "string" + }, + "status": { + "description": "Known values: PENDING, SENT, FAILED.", + "type": "string" + } + }, + "required": [ + "id", + "channel_type", + "destination", + "event", + "sent_at", + "status", + "error" + ], + "type": "object" + }, + "type": "array" + }, + "renotify_count": { + "type": "integer" + }, + "resolved_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "started_at": { + "type": "string" + }, + "updated_at": { + "type": "string" + } + }, + "required": [ + "id", + "started_at", + "resolved_at", + "cause", + "cause_detail", + "last_notified_at", + "acknowledged_at", + "acknowledged_by", + "renotify_count", + "created_at", + "updated_at" + ], + "type": "object" +}
- Changed
get_maintenance_window2 fields changed- added
Input schema / properties / window_id / descriptionAdded value: +"The window's uuid from list_maintenance_windows. An id that is not a window of this organization is a 404." - changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "created_at": { + "type": "string" + }, + "dtstart": { + "type": "string" + }, + "duration_minutes": { + "type": "integer" + }, + "enabled": { + "type": "boolean" + }, + "id": { + "format": "uuid", + "type": "string" + }, + "monitor_ids": { + "items": { + "format": "uuid", + "type": "string" + }, + "type": "array" + }, + "name": { + "type": "string" + }, + "next_occurrences": { + "items": { + "properties": { + "end": { + "type": "string" + }, + "start": { + "type": "string" + } + }, + "required": [ + "start", + "end" + ], + "type": "object" + }, + "type": "array" + }, + "rrule": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "scope": { + "description": "Known values: MONITOR, ORG.", + "type": "string" + }, + "timezone": { + "type": "string" + } + }, + "required": [ + "id", + "name", + "enabled", + "scope", + "dtstart", + "duration_minutes", + "rrule", + "timezone", + "created_at" + ], + "type": "object" +}
- Changed
get_monitor2 fields changed- added
Input schema / properties / monitor_id / descriptionAdded value: +"The monitor's uuid from list_monitors. An id that is not a monitor of this organization, or a deleted one, is a 404." - changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "badge_enabled": { + "type": "boolean" + }, + "channel_ids": { + "items": { + "format": "uuid", + "type": "string" + }, + "type": "array" + }, + "config": { + "additionalProperties": true, + "type": "object" + }, + "confirmation_threshold": { + "type": "integer" + }, + "created_at": { + "type": "string" + }, + "id": { + "format": "uuid", + "type": "string" + }, + "interval_seconds": { + "type": "integer" + }, + "is_active": { + "type": "boolean" + }, + "last_checked_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "name": { + "type": "string" + }, + "next_run_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "notification_cooldown_seconds": { + "type": "integer" + }, + "region_statuses": { + "description": "Per-region latest status, sorted by region name.\n\nBuilt from ``region_snapshots``; ``job_id`` is dropped (internal\ndedup key) and malformed/partial snapshot rows are skipped rather\nthan failing the read.", + "items": { + "properties": { + "checked_at": { + "type": "string" + }, + "display_name": { + "type": "string" + }, + "region": { + "type": "string" + }, + "status": { + "description": "Known values: UP, DEGRADED, DOWN, ERROR.", + "type": "string" + } + }, + "required": [ + "region", + "status", + "checked_at", + "display_name" + ], + "type": "object" + }, + "type": "array" + }, + "regions": { + "items": { + "type": "string" + }, + "type": "array" + }, + "ssl_cert_info": { + "anyOf": [ + { + "properties": { + "issuer": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "not_after": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "not_before": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "subject": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "valid": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ] + } + }, + "type": "object" + }, + { + "type": "null" + } + ] + }, + "ssl_expires_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "status": { + "description": "Known values: PENDING, UP, DEGRADED, DOWN, PAUSED.", + "type": "string" + }, + "tags": { + "items": { + "type": "string" + }, + "type": "array" + }, + "target": { + "type": "string" + }, + "timeout_seconds": { + "type": "integer" + }, + "type": { + "description": "Known values: HTTP, PING, SSL, TCP, DNS.", + "type": "string" + }, + "updated_at": { + "type": "string" + }, + "user_id": { + "format": "uuid", + "type": "string" + } + }, + "required": [ + "id", + "user_id", + "name", + "type", + "target", + "interval_seconds", + "timeout_seconds", + "regions", + "config", + "status", + "last_checked_at", + "next_run_at", + "confirmation_threshold", + "notification_cooldown_seconds", + "ssl_expires_at", + "is_active", + "created_at", + "updated_at", + "region_statuses" + ], + "type": "object" +}
- Changed
get_plan_usage1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "limits": { + "properties": { + "allowed_channel_types": { + "items": { + "description": "Known values: EMAIL, TELEGRAM, WEBHOOK, SLACK, DISCORD.", + "type": "string" + }, + "type": "array" + }, + "allowed_regions": { + "items": { + "type": "string" + }, + "type": "array" + }, + "api_rate_limit_per_minute": { + "type": "integer" + }, + "fast_interval_threshold_seconds": { + "type": "integer" + }, + "history_retention_days": { + "type": "integer" + }, + "max_api_keys": { + "type": "integer" + }, + "max_channels": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ] + }, + "max_fast_monitors": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ] + }, + "max_heartbeats": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ] + }, + "max_maintenance_windows": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ] + }, + "max_monitors": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ] + }, + "max_regions": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ] + }, + "max_status_page_subscribers": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ] + }, + "max_status_pages": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ] + }, + "min_interval_seconds": { + "type": "integer" + }, + "renotify_interval_seconds": { + "type": "integer" + }, + "renotify_max_count": { + "type": "integer" + }, + "tier": { + "description": "Known values: FREE, PLUS, PRO, MAX, ENTERPRISE.", + "type": "string" + } + }, + "required": [ + "tier", + "max_monitors", + "min_interval_seconds", + "max_fast_monitors", + "fast_interval_threshold_seconds", + "max_regions", + "history_retention_days", + "allowed_channel_types", + "max_channels", + "max_heartbeats", + "max_maintenance_windows", + "max_status_pages", + "max_status_page_subscribers", + "renotify_interval_seconds", + "renotify_max_count", + "max_api_keys", + "api_rate_limit_per_minute", + "allowed_regions" + ], + "type": "object" + }, + "plan": { + "description": "Known values: FREE, PLUS, PRO, MAX, ENTERPRISE.", + "type": "string" + }, + "usage": { + "properties": { + "fast_monitors": { + "description": "Monitors with an interval below the fast threshold.", + "type": "integer" + }, + "heartbeats": { + "type": "integer" + }, + "monitors": { + "description": "Monitors, paused ones included.", + "type": "integer" + } + }, + "required": [ + "monitors", + "fast_monitors", + "heartbeats" + ], + "type": "object" + } + }, + "required": [ + "plan", + "limits", + "usage" + ], + "type": "object" +}
- Changed
get_response_time_by_region3 fields changed- added
Input schema / properties / monitor_id / descriptionAdded value: +"The monitor's uuid from list_monitors. An id that is not a monitor of this organization, or a deleted one, is a 404." - added
Input schema / properties / window / descriptionAdded value: +"24h (the default; up to 24 hourly buckets), 7d (up to 28 six-hourly buckets) or 30d (up to 30 daily buckets)." - changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "bucket_seconds": { + "type": "integer" + }, + "monitor_id": { + "format": "uuid", + "type": "string" + }, + "regions": { + "items": { + "properties": { + "display_name": { + "type": "string" + }, + "points": { + "items": { + "properties": { + "avg_response_time_ms": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ] + }, + "bucket_start": { + "type": "string" + }, + "sample_count": { + "type": "integer" + } + }, + "required": [ + "bucket_start", + "sample_count" + ], + "type": "object" + }, + "type": "array" + }, + "region": { + "type": "string" + } + }, + "required": [ + "region", + "display_name", + "points" + ], + "type": "object" + }, + "type": "array" + }, + "window": { + "type": "string" + } + }, + "required": [ + "monitor_id", + "window", + "bucket_seconds", + "regions" + ], + "type": "object" +}
- Changed
get_status_page2 fields changed- added
Input schema / properties / page_id / descriptionAdded value: +"The status page's uuid from list_status_pages. An id that is not a status page of this organization is a 404." - changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "created_at": { + "type": "string" + }, + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "groups": { + "items": { + "properties": { + "components": { + "items": { + "properties": { + "display_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "id": { + "format": "uuid", + "type": "string" + }, + "monitor_id": { + "format": "uuid", + "type": "string" + }, + "position": { + "type": "integer" + } + }, + "required": [ + "id", + "monitor_id", + "display_name", + "position" + ], + "type": "object" + }, + "type": "array" + }, + "id": { + "format": "uuid", + "type": "string" + }, + "name": { + "type": "string" + }, + "position": { + "type": "integer" + } + }, + "required": [ + "id", + "name", + "position", + "components" + ], + "type": "object" + }, + "type": "array" + }, + "history_days": { + "type": "integer" + }, + "id": { + "format": "uuid", + "type": "string" + }, + "is_published": { + "type": "boolean" + }, + "name": { + "type": "string" + }, + "slug": { + "type": "string" + }, + "ungrouped_components": { + "items": { + "properties": { + "display_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "id": { + "format": "uuid", + "type": "string" + }, + "monitor_id": { + "format": "uuid", + "type": "string" + }, + "position": { + "type": "integer" + } + }, + "required": [ + "id", + "monitor_id", + "display_name", + "position" + ], + "type": "object" + }, + "type": "array" + } + }, + "required": [ + "id", + "slug", + "name", + "description", + "is_published", + "history_days", + "created_at", + "groups", + "ungrouped_components" + ], + "type": "object" +}
- Changed
get_uptime_daily3 fields changed- added
Input schema / properties / days / descriptionAdded value: +"How many days to return, 1 to 365; default 30. Capped at the plan's limits.history_retention_days (get_plan_usage), so fewer days can come back." - added
Input schema / properties / monitor_id / descriptionAdded value: +"The monitor's uuid from list_monitors. An id that is not a monitor of this organization, or a deleted one, is a 404." - changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "days": { + "items": { + "properties": { + "date": { + "type": "string" + }, + "degraded_checks": { + "type": "integer" + }, + "down_checks": { + "type": "integer" + }, + "maintenance_checks": { + "type": "integer" + }, + "total_checks": { + "type": "integer" + }, + "up_checks": { + "type": "integer" + }, + "uptime_percentage": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "date", + "uptime_percentage", + "total_checks", + "up_checks", + "down_checks" + ], + "type": "object" + }, + "type": "array" + }, + "monitor_id": { + "format": "uuid", + "type": "string" + } + }, + "required": [ + "monitor_id", + "days" + ], + "type": "object" +}
- Changed
get_uptime_summary2 fields changed- added
Input schema / properties / monitor_id / descriptionAdded value: +"The monitor's uuid from list_monitors. An id that is not a monitor of this organization, or a deleted one, is a 404." - changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "monitor_id": { + "format": "uuid", + "type": "string" + }, + "windows": { + "additionalProperties": { + "properties": { + "avg_response_time_ms": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ] + }, + "degraded_checks": { + "type": "integer" + }, + "down_checks": { + "type": "integer" + }, + "incident_count": { + "type": "integer" + }, + "total_checks": { + "type": "integer" + }, + "up_checks": { + "type": "integer" + }, + "uptime_percentage": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "uptime_percentage", + "total_checks", + "up_checks", + "down_checks", + "incident_count", + "avg_response_time_ms" + ], + "type": "object" + }, + "type": "object" + } + }, + "required": [ + "monitor_id", + "windows" + ], + "type": "object" +}
- Changed
list_check_results7 fields changed- added
Input schema / properties / monitor_id / descriptionAdded value: +"The monitor's uuid from list_monitors. An id that is not a monitor of this organization, or a deleted one, is a 404." - added
Input schema / properties / page / descriptionAdded value: +"Page number, 1 or more; default 1." - added
Input schema / properties / period_days / descriptionAdded value: +"Keep results of the last N days, 1 to 365; without it every stored result is eligible." - added
Input schema / properties / region / descriptionAdded value: +"Keep one region's results: its exact code, up to 64 characters." - added
Input schema / properties / size / descriptionAdded value: +"Rows per page, 1 to 100; default 25. Keep paging until you have seen total rows." - added
Input schema / properties / status / descriptionAdded value: +"Keep results with this status only." - changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "items": { + "items": { + "properties": { + "checked_at": { + "type": "string" + }, + "details": { + "anyOf": [ + { + "additionalProperties": true, + "type": "object" + }, + { + "type": "null" + } + ] + }, + "error_message": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "id": { + "format": "uuid", + "type": "string" + }, + "job_id": { + "type": "string" + }, + "maintenance_window_id": { + "anyOf": [ + { + "format": "uuid", + "type": "string" + }, + { + "type": "null" + } + ] + }, + "monitor_id": { + "format": "uuid", + "type": "string" + }, + "region": { + "type": "string" + }, + "response_time_ms": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ] + }, + "status": { + "description": "Known values: UP, DEGRADED, DOWN, ERROR.", + "type": "string" + }, + "status_code": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "id", + "monitor_id", + "region", + "checked_at", + "status", + "response_time_ms", + "status_code", + "error_message", + "details", + "job_id" + ], + "type": "object" + }, + "type": "array" + }, + "page": { + "type": "integer" + }, + "pages": { + "type": "integer" + }, + "size": { + "type": "integer" + }, + "total": { + "type": "integer" + } + }, + "required": [ + "items", + "total", + "page", + "size", + "pages" + ], + "type": "object" +}
- Changed
list_heartbeats7 fields changed- added
Input schema / properties / page / descriptionAdded value: +"Page number, 1 or more; default 1." - added
Input schema / properties / q / descriptionAdded value: +"Case-insensitive substring of the name, up to 255 characters." - added
Input schema / properties / size / descriptionAdded value: +"Rows per page, 1 to 100; default 25. Keep paging until you have seen total rows." - added
Input schema / properties / sort / descriptionAdded value: +"status (the default: DOWN, PENDING, UP, PAUSED, newest first within each), name, or created_at (newest first)." - added
Input schema / properties / tag / descriptionAdded value: +"Keep items carrying these tags: a JSON array of up to 10 tags, each up to 50 characters, lowercased before matching. tag_match decides whether all or any of them must match." - added
Input schema / properties / tag_match / descriptionAdded value: +"all (the default): an item must carry every tag in tag. any: at least one of them." - changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "items": { + "items": { + "properties": { + "channel_ids": { + "items": { + "format": "uuid", + "type": "string" + }, + "type": "array" + }, + "created_at": { + "type": "string" + }, + "grace_seconds": { + "type": "integer" + }, + "id": { + "format": "uuid", + "type": "string" + }, + "is_active": { + "type": "boolean" + }, + "last_duration_ms": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ] + }, + "last_ping_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "last_start_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "last_success_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "name": { + "type": "string" + }, + "notification_cooldown_seconds": { + "type": "integer" + }, + "overdue_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "period_seconds": { + "type": "integer" + }, + "ping_url": { + "type": "string" + }, + "state": { + "description": "Known values: PENDING, UP, DOWN, PAUSED.", + "type": "string" + }, + "tags": { + "items": { + "type": "string" + }, + "type": "array" + }, + "updated_at": { + "type": "string" + } + }, + "required": [ + "id", + "name", + "state", + "period_seconds", + "grace_seconds", + "ping_url", + "last_ping_at", + "last_success_at", + "last_start_at", + "last_duration_ms", + "overdue_at", + "notification_cooldown_seconds", + "is_active", + "created_at", + "updated_at" + ], + "type": "object" + }, + "type": "array" + }, + "page": { + "type": "integer" + }, + "pages": { + "type": "integer" + }, + "size": { + "type": "integer" + }, + "total": { + "type": "integer" + } + }, + "required": [ + "items", + "total", + "page", + "size", + "pages" + ], + "type": "object" +}
- Changed
list_incidents7 fields changed- changed
Input schema / properties / cause / descriptionPrevious value: -"Filter by structured failure cause."New value: +"Keep one failure cause, such as TIMEOUT, HTTP_5XX or HEARTBEAT_MISSED." - added
Input schema / properties / monitor_id / descriptionAdded value: +"Keep one monitor's incidents: its uuid from list_monitors." - added
Input schema / properties / page / descriptionAdded value: +"Page number, 1 or more; default 1." - changed
Input schema / properties / period_days / descriptionPrevious value: -"Only incidents that were active within the last N days. An incident still open is always included, whenever it started. Combined with status=open this makes period_days a no-op, since every open incident already satisfies that arm — use status=resolved or omit status to see the window take effect."New value: +"Keep incidents active within the last N days, 1 to 365. An open incident always qualifies, so with status open it changes nothing: use status resolved, or omit status, to see the window take effect." - added
Input schema / properties / size / descriptionAdded value: +"Rows per page, 1 to 100; default 25. Keep paging until you have seen total rows." - changed
Input schema / properties / status / descriptionPrevious value: -"Filter by open or resolved; omit for both."New value: +"open or resolved (lowercase); omit it for both." - changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "items": { + "items": { + "properties": { + "acknowledged_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "acknowledged_by": { + "anyOf": [ + { + "format": "uuid", + "type": "string" + }, + { + "type": "null" + } + ] + }, + "cause": { + "description": "Known values: TIMEOUT, DNS_FAILURE, CONNECTION_REFUSED, TLS_INVALID, HTTP_4XX, HTTP_5XX, HTTP_UNEXPECTED_STATUS, KEYWORD_MISSING, TOO_MANY_REDIRECTS, TARGET_BLOCKED, PORT_STATE_MISMATCH, INVALID_TARGET, HEARTBEAT_MISSED, HEARTBEAT_FAILED, UNKNOWN.", + "type": "string" + }, + "cause_detail": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "created_at": { + "type": "string" + }, + "heartbeat_id": { + "anyOf": [ + { + "format": "uuid", + "type": "string" + }, + { + "type": "null" + } + ] + }, + "id": { + "format": "uuid", + "type": "string" + }, + "last_notified_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "monitor_id": { + "anyOf": [ + { + "format": "uuid", + "type": "string" + }, + { + "type": "null" + } + ] + }, + "notification_logs": { + "items": { + "properties": { + "channel_type": { + "description": "Known values: EMAIL, TELEGRAM, WEBHOOK, SLACK, DISCORD.", + "type": "string" + }, + "destination": { + "type": "string" + }, + "error": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "event": { + "description": "Known values: TRIGGERED, RESOLVED, SSL_EXPIRY.", + "type": "string" + }, + "id": { + "format": "uuid", + "type": "string" + }, + "sent_at": { + "type": "string" + }, + "status": { + "description": "Known values: PENDING, SENT, FAILED.", + "type": "string" + } + }, + "required": [ + "id", + "channel_type", + "destination", + "event", + "sent_at", + "status", + "error" + ], + "type": "object" + }, + "type": "array" + }, + "renotify_count": { + "type": "integer" + }, + "resolved_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "started_at": { + "type": "string" + }, + "updated_at": { + "type": "string" + } + }, + "required": [ + "id", + "started_at", + "resolved_at", + "cause", + "cause_detail", + "last_notified_at", + "acknowledged_at", + "acknowledged_by", + "renotify_count", + "created_at", + "updated_at" + ], + "type": "object" + }, + "type": "array" + }, + "page": { + "type": "integer" + }, + "pages": { + "type": "integer" + }, + "size": { + "type": "integer" + }, + "total": { + "type": "integer" + } + }, + "required": [ + "items", + "total", + "page", + "size", + "pages" + ], + "type": "object" +}
- Changed
list_maintenance_windows5 fields changed- added
Input schema / properties / page / descriptionAdded value: +"Page number, 1 or more; default 1." - added
Input schema / properties / q / descriptionAdded value: +"Case-insensitive substring of the name, up to 255 characters." - added
Input schema / properties / size / descriptionAdded value: +"Rows per page, 1 to 100; default 25. Keep paging until you have seen total rows." - added
Input schema / properties / sort / descriptionAdded value: +"created_at (the default, newest first) or name." - changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "items": { + "items": { + "properties": { + "created_at": { + "type": "string" + }, + "dtstart": { + "type": "string" + }, + "duration_minutes": { + "type": "integer" + }, + "enabled": { + "type": "boolean" + }, + "id": { + "format": "uuid", + "type": "string" + }, + "monitor_ids": { + "items": { + "format": "uuid", + "type": "string" + }, + "type": "array" + }, + "name": { + "type": "string" + }, + "rrule": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "scope": { + "description": "Known values: MONITOR, ORG.", + "type": "string" + }, + "timezone": { + "type": "string" + } + }, + "required": [ + "id", + "name", + "enabled", + "scope", + "dtstart", + "duration_minutes", + "rrule", + "timezone", + "created_at" + ], + "type": "object" + }, + "type": "array" + }, + "page": { + "type": "integer" + }, + "pages": { + "type": "integer" + }, + "size": { + "type": "integer" + }, + "total": { + "type": "integer" + } + }, + "required": [ + "items", + "total", + "page", + "size", + "pages" + ], + "type": "object" +}
- Changed
list_monitors8 fields changed- added
Input schema / properties / page / descriptionAdded value: +"Page number, 1 or more; default 1." - added
Input schema / properties / q / descriptionAdded value: +"Case-insensitive substring of the name or the target, up to 255 characters." - added
Input schema / properties / size / descriptionAdded value: +"Rows per page, 1 to 100; default 25. Keep paging until you have seen total rows." - added
Input schema / properties / sort / descriptionAdded value: +"status (the default: PENDING, DOWN, DEGRADED, UP, PAUSED, then by name), up_first (healthy first), name, newest, oldest, or ssl_expiry (soonest-expiring certificates first; monitors with no known expiry, non-SSL types or not checked yet, last)." - added
Input schema / properties / status / descriptionAdded value: +"Keep monitors in any of these states: a JSON array. PENDING means no verdict yet." - added
Input schema / properties / tag / descriptionAdded value: +"Keep items carrying these tags: a JSON array of up to 10 tags, each up to 50 characters, lowercased before matching. tag_match decides whether all or any of them must match." - added
Input schema / properties / tag_match / descriptionAdded value: +"all (the default): an item must carry every tag in tag. any: at least one of them." - added
Input schema / properties / type / descriptionAdded value: +"Keep monitors of any of these types: a JSON array."
- Changed
list_regions1 field changed- changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "regions": { + "items": { + "properties": { + "city": { + "type": "string" + }, + "code": { + "type": "string" + }, + "country_code": { + "type": "string" + }, + "display_name": { + "type": "string" + }, + "group": { + "type": "string" + }, + "group_display_name": { + "type": "string" + } + }, + "required": [ + "code", + "display_name", + "city", + "country_code", + "group", + "group_display_name" + ], + "type": "object" + }, + "type": "array" + } + }, + "required": [ + "regions" + ], + "type": "object" +}
- Changed
list_status_page_incidents4 fields changed- added
Input schema / properties / page / descriptionAdded value: +"Page number, 1 or more; default 1." - added
Input schema / properties / page_id / descriptionAdded value: +"The status page's uuid from list_status_pages. An id that is not a status page of this organization is a 404." - added
Input schema / properties / size / descriptionAdded value: +"Rows per page, 1 to 100; default 25. Keep paging until you have seen total rows." - changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "items": { + "items": { + "properties": { + "component_ids": { + "items": { + "format": "uuid", + "type": "string" + }, + "type": "array" + }, + "id": { + "format": "uuid", + "type": "string" + }, + "is_auto": { + "type": "boolean" + }, + "notified_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "resolved_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "started_at": { + "type": "string" + }, + "status": { + "description": "Known values: INVESTIGATING, IDENTIFIED, MONITORING, RESOLVED.", + "type": "string" + }, + "title": { + "type": "string" + }, + "updates": { + "items": { + "properties": { + "body": { + "type": "string" + }, + "created_at": { + "type": "string" + }, + "created_by": { + "anyOf": [ + { + "format": "uuid", + "type": "string" + }, + { + "type": "null" + } + ] + }, + "id": { + "format": "uuid", + "type": "string" + }, + "status": { + "description": "Known values: INVESTIGATING, IDENTIFIED, MONITORING, RESOLVED.", + "type": "string" + } + }, + "required": [ + "id", + "status", + "body", + "created_by", + "created_at" + ], + "type": "object" + }, + "type": "array" + } + }, + "required": [ + "id", + "title", + "status", + "is_auto", + "started_at", + "resolved_at", + "notified_at", + "component_ids", + "updates" + ], + "type": "object" + }, + "type": "array" + }, + "page": { + "type": "integer" + }, + "pages": { + "type": "integer" + }, + "size": { + "type": "integer" + }, + "total": { + "type": "integer" + } + }, + "required": [ + "items", + "total", + "page", + "size", + "pages" + ], + "type": "object" +}
- Changed
list_status_pages4 fields changed- added
Input schema / properties / page / descriptionAdded value: +"Page number, 1 or more; default 1." - added
Input schema / properties / size / descriptionAdded value: +"Rows per page, 1 to 100; default 25. Keep paging until you have seen total rows." - added
Input schema / properties / sort / descriptionAdded value: +"created_at (the default, newest first) or name." - changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "items": { + "items": { + "properties": { + "created_at": { + "type": "string" + }, + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "groups": { + "items": { + "properties": { + "components": { + "items": { + "properties": { + "display_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "id": { + "format": "uuid", + "type": "string" + }, + "monitor_id": { + "format": "uuid", + "type": "string" + }, + "position": { + "type": "integer" + } + }, + "required": [ + "id", + "monitor_id", + "display_name", + "position" + ], + "type": "object" + }, + "type": "array" + }, + "id": { + "format": "uuid", + "type": "string" + }, + "name": { + "type": "string" + }, + "position": { + "type": "integer" + } + }, + "required": [ + "id", + "name", + "position", + "components" + ], + "type": "object" + }, + "type": "array" + }, + "history_days": { + "type": "integer" + }, + "id": { + "format": "uuid", + "type": "string" + }, + "is_published": { + "type": "boolean" + }, + "name": { + "type": "string" + }, + "slug": { + "type": "string" + }, + "ungrouped_components": { + "items": { + "properties": { + "display_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "id": { + "format": "uuid", + "type": "string" + }, + "monitor_id": { + "format": "uuid", + "type": "string" + }, + "position": { + "type": "integer" + } + }, + "required": [ + "id", + "monitor_id", + "display_name", + "position" + ], + "type": "object" + }, + "type": "array" + } + }, + "required": [ + "id", + "slug", + "name", + "description", + "is_published", + "history_days", + "created_at", + "groups", + "ungrouped_components" + ], + "type": "object" + }, + "type": "array" + }, + "page": { + "type": "integer" + }, + "pages": { + "type": "integer" + }, + "size": { + "type": "integer" + }, + "total": { + "type": "integer" + } + }, + "required": [ + "items", + "total", + "page", + "size", + "pages" + ], + "type": "object" +}
- Changed
list_tags2 fields changed- added
Input schema / properties / kind / descriptionAdded value: +"monitor or heartbeat lists only the tags that kind of item uses; all (the default) lists both. Both counts are reported either way." - changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "items": { + "items": { + "properties": { + "heartbeat_count": { + "type": "integer" + }, + "monitor_count": { + "type": "integer" + }, + "tag": { + "type": "string" + } + }, + "required": [ + "tag", + "monitor_count", + "heartbeat_count" + ], + "type": "object" + }, + "type": "array" + } + }, + "required": [ + "items" + ], + "type": "object" +}
- Changed
pause_heartbeat2 fields changed- added
Input schema / properties / heartbeat_id / descriptionAdded value: +"The heartbeat's uuid from list_heartbeats. An id that is not a heartbeat of this organization, or a deleted one, is a 404." - changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "channel_ids": { + "items": { + "format": "uuid", + "type": "string" + }, + "type": "array" + }, + "created_at": { + "type": "string" + }, + "grace_seconds": { + "type": "integer" + }, + "id": { + "format": "uuid", + "type": "string" + }, + "is_active": { + "type": "boolean" + }, + "last_duration_ms": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ] + }, + "last_ping_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "last_start_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "last_success_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "name": { + "type": "string" + }, + "notification_cooldown_seconds": { + "type": "integer" + }, + "overdue_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "period_seconds": { + "type": "integer" + }, + "ping_url": { + "type": "string" + }, + "state": { + "description": "Known values: PENDING, UP, DOWN, PAUSED.", + "type": "string" + }, + "tags": { + "items": { + "type": "string" + }, + "type": "array" + }, + "updated_at": { + "type": "string" + } + }, + "required": [ + "id", + "name", + "state", + "period_seconds", + "grace_seconds", + "ping_url", + "last_ping_at", + "last_success_at", + "last_start_at", + "last_duration_ms", + "overdue_at", + "notification_cooldown_seconds", + "is_active", + "created_at", + "updated_at" + ], + "type": "object" +}
- Changed
pause_monitor2 fields changed- added
Input schema / properties / monitor_id / descriptionAdded value: +"The monitor's uuid from list_monitors. An id that is not a monitor of this organization, or a deleted one, is a 404." - changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "badge_enabled": { + "type": "boolean" + }, + "channel_ids": { + "items": { + "format": "uuid", + "type": "string" + }, + "type": "array" + }, + "config": { + "additionalProperties": true, + "type": "object" + }, + "confirmation_threshold": { + "type": "integer" + }, + "created_at": { + "type": "string" + }, + "id": { + "format": "uuid", + "type": "string" + }, + "interval_seconds": { + "type": "integer" + }, + "is_active": { + "type": "boolean" + }, + "last_checked_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "name": { + "type": "string" + }, + "next_run_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "notification_cooldown_seconds": { + "type": "integer" + }, + "region_statuses": { + "description": "Per-region latest status, sorted by region name.\n\nBuilt from ``region_snapshots``; ``job_id`` is dropped (internal\ndedup key) and malformed/partial snapshot rows are skipped rather\nthan failing the read.", + "items": { + "properties": { + "checked_at": { + "type": "string" + }, + "display_name": { + "type": "string" + }, + "region": { + "type": "string" + }, + "status": { + "description": "Known values: UP, DEGRADED, DOWN, ERROR.", + "type": "string" + } + }, + "required": [ + "region", + "status", + "checked_at", + "display_name" + ], + "type": "object" + }, + "type": "array" + }, + "regions": { + "items": { + "type": "string" + }, + "type": "array" + }, + "ssl_cert_info": { + "anyOf": [ + { + "properties": { + "issuer": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "not_after": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "not_before": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "subject": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "valid": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ] + } + }, + "type": "object" + }, + { + "type": "null" + } + ] + }, + "ssl_expires_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "status": { + "description": "Known values: PENDING, UP, DEGRADED, DOWN, PAUSED.", + "type": "string" + }, + "tags": { + "items": { + "type": "string" + }, + "type": "array" + }, + "target": { + "type": "string" + }, + "timeout_seconds": { + "type": "integer" + }, + "type": { + "description": "Known values: HTTP, PING, SSL, TCP, DNS.", + "type": "string" + }, + "updated_at": { + "type": "string" + }, + "user_id": { + "format": "uuid", + "type": "string" + } + }, + "required": [ + "id", + "user_id", + "name", + "type", + "target", + "interval_seconds", + "timeout_seconds", + "regions", + "config", + "status", + "last_checked_at", + "next_run_at", + "confirmation_threshold", + "notification_cooldown_seconds", + "ssl_expires_at", + "is_active", + "created_at", + "updated_at", + "region_statuses" + ], + "type": "object" +}
- Changed
post_status_page_update5 fields changed- added
Input schema / properties / body / descriptionAdded value: +"The message subscribers read, 1 to 5000 characters." - added
Input schema / properties / incident_id / descriptionAdded value: +"The status page incident's uuid from list_status_page_incidents (not from list_incidents). An unknown id is a 404." - added
Input schema / properties / page_id / descriptionAdded value: +"The status page's uuid from list_status_pages. An id that is not a status page of this organization is a 404." - added
Input schema / properties / status / descriptionAdded value: +"INVESTIGATING, IDENTIFIED, MONITORING or RESOLVED; RESOLVED closes the incident on the page." - changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "component_ids": { + "items": { + "format": "uuid", + "type": "string" + }, + "type": "array" + }, + "id": { + "format": "uuid", + "type": "string" + }, + "is_auto": { + "type": "boolean" + }, + "notified_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "resolved_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "started_at": { + "type": "string" + }, + "status": { + "description": "Known values: INVESTIGATING, IDENTIFIED, MONITORING, RESOLVED.", + "type": "string" + }, + "title": { + "type": "string" + }, + "updates": { + "items": { + "properties": { + "body": { + "type": "string" + }, + "created_at": { + "type": "string" + }, + "created_by": { + "anyOf": [ + { + "format": "uuid", + "type": "string" + }, + { + "type": "null" + } + ] + }, + "id": { + "format": "uuid", + "type": "string" + }, + "status": { + "description": "Known values: INVESTIGATING, IDENTIFIED, MONITORING, RESOLVED.", + "type": "string" + } + }, + "required": [ + "id", + "status", + "body", + "created_by", + "created_at" + ], + "type": "object" + }, + "type": "array" + } + }, + "required": [ + "id", + "title", + "status", + "is_auto", + "started_at", + "resolved_at", + "notified_at", + "component_ids", + "updates" + ], + "type": "object" +}
- Changed
preview_maintenance_window4 fields changed- added
Input schema / properties / dtstart / descriptionAdded value: +"The first start, an ISO 8601 date-time in the wall-clock time of timezone, for example 2026-10-14T22:00:00. A UTC offset or Z is a 422." - added
Input schema / properties / duration_minutes / descriptionAdded value: +"How long each occurrence lasts, 1 to 40320 minutes." - added
Input schema / properties / rrule / descriptionAdded value: +"Repeats the window: one iCal RRULE without the RRULE: prefix, at most 1024 characters, for example FREQ=WEEKLY;BYDAY=SU;BYHOUR=3. Hourly, minutely and secondly frequencies are refused. Omit it for a one-time window." - added
Input schema / properties / timezone / descriptionAdded value: +"IANA zone name such as Europe/Berlin, at most 64 characters. The schedule repeats in it, so a weekly 03:00 stays 03:00 across daylight-saving changes. Defaults to the organization's timezone."
- Changed
rename_tag3 fields changed- added
Input schema / properties / from / descriptionAdded value: +"The existing tag, as list_tags shows it." - added
Input schema / properties / to / descriptionAdded value: +"The new name. Each tag is trimmed, lowercased and deduplicated on write, at most 50 characters of a-z, 0-9 and : _ . / -, starting with a letter or digit. Reuse names from list_tags rather than inventing near-duplicates." - changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "from": { + "type": "string" + }, + "heartbeats_updated": { + "type": "integer" + }, + "monitors_updated": { + "type": "integer" + }, + "to": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + } + }, + "required": [ + "from", + "monitors_updated", + "heartbeats_updated" + ], + "type": "object" +}
- Changed
resume_heartbeat2 fields changed- added
Input schema / properties / heartbeat_id / descriptionAdded value: +"The heartbeat's uuid from list_heartbeats. An id that is not a heartbeat of this organization, or a deleted one, is a 404." - changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "channel_ids": { + "items": { + "format": "uuid", + "type": "string" + }, + "type": "array" + }, + "created_at": { + "type": "string" + }, + "grace_seconds": { + "type": "integer" + }, + "id": { + "format": "uuid", + "type": "string" + }, + "is_active": { + "type": "boolean" + }, + "last_duration_ms": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ] + }, + "last_ping_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "last_start_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "last_success_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "name": { + "type": "string" + }, + "notification_cooldown_seconds": { + "type": "integer" + }, + "overdue_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "period_seconds": { + "type": "integer" + }, + "ping_url": { + "type": "string" + }, + "state": { + "description": "Known values: PENDING, UP, DOWN, PAUSED.", + "type": "string" + }, + "tags": { + "items": { + "type": "string" + }, + "type": "array" + }, + "updated_at": { + "type": "string" + } + }, + "required": [ + "id", + "name", + "state", + "period_seconds", + "grace_seconds", + "ping_url", + "last_ping_at", + "last_success_at", + "last_start_at", + "last_duration_ms", + "overdue_at", + "notification_cooldown_seconds", + "is_active", + "created_at", + "updated_at" + ], + "type": "object" +}
- Changed
resume_monitor2 fields changed- added
Input schema / properties / monitor_id / descriptionAdded value: +"The monitor's uuid from list_monitors. An id that is not a monitor of this organization, or a deleted one, is a 404." - changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "badge_enabled": { + "type": "boolean" + }, + "channel_ids": { + "items": { + "format": "uuid", + "type": "string" + }, + "type": "array" + }, + "config": { + "additionalProperties": true, + "type": "object" + }, + "confirmation_threshold": { + "type": "integer" + }, + "created_at": { + "type": "string" + }, + "id": { + "format": "uuid", + "type": "string" + }, + "interval_seconds": { + "type": "integer" + }, + "is_active": { + "type": "boolean" + }, + "last_checked_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "name": { + "type": "string" + }, + "next_run_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "notification_cooldown_seconds": { + "type": "integer" + }, + "region_statuses": { + "description": "Per-region latest status, sorted by region name.\n\nBuilt from ``region_snapshots``; ``job_id`` is dropped (internal\ndedup key) and malformed/partial snapshot rows are skipped rather\nthan failing the read.", + "items": { + "properties": { + "checked_at": { + "type": "string" + }, + "display_name": { + "type": "string" + }, + "region": { + "type": "string" + }, + "status": { + "description": "Known values: UP, DEGRADED, DOWN, ERROR.", + "type": "string" + } + }, + "required": [ + "region", + "status", + "checked_at", + "display_name" + ], + "type": "object" + }, + "type": "array" + }, + "regions": { + "items": { + "type": "string" + }, + "type": "array" + }, + "ssl_cert_info": { + "anyOf": [ + { + "properties": { + "issuer": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "not_after": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "not_before": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "subject": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "valid": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ] + } + }, + "type": "object" + }, + { + "type": "null" + } + ] + }, + "ssl_expires_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "status": { + "description": "Known values: PENDING, UP, DEGRADED, DOWN, PAUSED.", + "type": "string" + }, + "tags": { + "items": { + "type": "string" + }, + "type": "array" + }, + "target": { + "type": "string" + }, + "timeout_seconds": { + "type": "integer" + }, + "type": { + "description": "Known values: HTTP, PING, SSL, TCP, DNS.", + "type": "string" + }, + "updated_at": { + "type": "string" + }, + "user_id": { + "format": "uuid", + "type": "string" + } + }, + "required": [ + "id", + "user_id", + "name", + "type", + "target", + "interval_seconds", + "timeout_seconds", + "regions", + "config", + "status", + "last_checked_at", + "next_run_at", + "confirmation_threshold", + "notification_cooldown_seconds", + "ssl_expires_at", + "is_active", + "created_at", + "updated_at", + "region_statuses" + ], + "type": "object" +}
- Changed
update_heartbeat8 fields changed- added
Input schema / properties / channel_ids / descriptionAdded value: +"Notification channel uuids from list_channels. When passed it replaces the whole binding; [] clears it, after which every verified, active channel is alerted; omit it to keep the binding. An id that is not an active channel of this organization is a 404." - added
Input schema / properties / grace_seconds / descriptionAdded value: +"Extra seconds of silence tolerated after the period before the heartbeat is reported late, 0 to 2592000; it may exceed the period." - added
Input schema / properties / heartbeat_id / descriptionAdded value: +"The heartbeat's uuid from list_heartbeats. An id that is not a heartbeat of this organization, or a deleted one, is a 404." - added
Input schema / properties / name / descriptionAdded value: +"Display name, 1 to 255 characters." - added
Input schema / properties / notification_cooldown_seconds / descriptionAdded value: +"60 to 86400 seconds; 1800 when not set on create. Only holds back a duplicate first alert for the same incident within that window. Repeat reminders while an incident stays open and unacknowledged follow the plan's renotify_interval_seconds and renotify_max_count (get_plan_usage; 0 means no reminders) instead, and the recovery alert is never held back." - added
Input schema / properties / period_seconds / descriptionAdded value: +"How often the job runs, 60 to 2592000 seconds. To ping every N seconds and be alerted after T seconds of silence, set period_seconds = N and grace_seconds = T - N (T at least N)." - added
Input schema / properties / tags / descriptionAdded value: +"Replaces the whole tag list when passed, at most 10; [] clears it; omit it to keep the tags. Each tag is trimmed, lowercased and deduplicated on write, at most 50 characters of a-z, 0-9 and : _ . / -, starting with a letter or digit. Reuse names from list_tags rather than inventing near-duplicates." - changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "channel_ids": { + "items": { + "format": "uuid", + "type": "string" + }, + "type": "array" + }, + "created_at": { + "type": "string" + }, + "grace_seconds": { + "type": "integer" + }, + "id": { + "format": "uuid", + "type": "string" + }, + "is_active": { + "type": "boolean" + }, + "last_duration_ms": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ] + }, + "last_ping_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "last_start_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "last_success_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "name": { + "type": "string" + }, + "notification_cooldown_seconds": { + "type": "integer" + }, + "overdue_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "period_seconds": { + "type": "integer" + }, + "ping_url": { + "type": "string" + }, + "state": { + "description": "Known values: PENDING, UP, DOWN, PAUSED.", + "type": "string" + }, + "tags": { + "items": { + "type": "string" + }, + "type": "array" + }, + "updated_at": { + "type": "string" + } + }, + "required": [ + "id", + "name", + "state", + "period_seconds", + "grace_seconds", + "ping_url", + "last_ping_at", + "last_success_at", + "last_start_at", + "last_duration_ms", + "overdue_at", + "notification_cooldown_seconds", + "is_active", + "created_at", + "updated_at" + ], + "type": "object" +}
- Changed
update_maintenance_window10 fields changed- added
Input schema / properties / dtstart / descriptionAdded value: +"The first start, an ISO 8601 date-time in the wall-clock time of timezone, for example 2026-10-14T22:00:00. A UTC offset or Z is a 422." - added
Input schema / properties / duration_minutes / descriptionAdded value: +"How long each occurrence lasts, 1 to 40320 minutes." - added
Input schema / properties / enabled / descriptionAdded value: +"false keeps the window but stops it silencing alerts." - added
Input schema / properties / monitor_ids / descriptionAdded value: +"Replaces the list when passed. Monitor uuids from list_monitors, at least one when scope is MONITOR. An id that is not a monitor of this organization is a 404." - added
Input schema / properties / name / descriptionAdded value: +"Display name, 1 to 255 characters." - added
Input schema / properties / rrule / descriptionAdded value: +"Repeats the window: one iCal RRULE without the RRULE: prefix, at most 1024 characters, for example FREQ=WEEKLY;BYDAY=SU;BYHOUR=3. Hourly, minutely and secondly frequencies are refused." - added
Input schema / properties / scope / descriptionAdded value: +"ORG covers every monitor of the organization and ignores monitor_ids; MONITOR covers only monitor_ids." - added
Input schema / properties / timezone / descriptionAdded value: +"IANA zone name such as Europe/Berlin, at most 64 characters. The schedule repeats in it, so a weekly 03:00 stays 03:00 across daylight-saving changes." - added
Input schema / properties / window_id / descriptionAdded value: +"The window's uuid from list_maintenance_windows. An id that is not a window of this organization is a 404." - changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "created_at": { + "type": "string" + }, + "dtstart": { + "type": "string" + }, + "duration_minutes": { + "type": "integer" + }, + "enabled": { + "type": "boolean" + }, + "id": { + "format": "uuid", + "type": "string" + }, + "monitor_ids": { + "items": { + "format": "uuid", + "type": "string" + }, + "type": "array" + }, + "name": { + "type": "string" + }, + "rrule": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "scope": { + "description": "Known values: MONITOR, ORG.", + "type": "string" + }, + "timezone": { + "type": "string" + } + }, + "required": [ + "id", + "name", + "enabled", + "scope", + "dtstart", + "duration_minutes", + "rrule", + "timezone", + "created_at" + ], + "type": "object" +}
- Changed
update_monitor12 fields changed- added
Input schema / properties / badge_enabled / descriptionAdded value: +"Turns the monitor's public status badge on or off. A monitor on a published status page has a badge even when it is false." - added
Input schema / properties / channel_ids / descriptionAdded value: +"Notification channel uuids from list_channels. When passed it replaces the whole binding; [] clears it, after which every verified, active channel is alerted; omit it to keep the binding. An id that is not an active channel of this organization is a 404." - added
Input schema / properties / config / descriptionAdded value: +"Replaces the monitor's whole config, not just the keys you send: a field of the type's schema you leave out resets to its default (read the current one with get_monitor first). Sending only port on a TCP monitor whose expected_state is closed resets it to open. A port-list TCP monitor cannot switch to a single port (422). An object whose fields depend on type, all optional unless stated. HTTP: method (GET, HEAD, POST, PUT, PATCH or DELETE, any case; default GET); expected_status_codes (non-empty list of codes 100 to 599, default [200]); keyword (case-sensitive substring the body must contain, at most 1024 characters, not with HEAD); follow_redirects (default true); verify_ssl (default true; false skips TLS verification, so the monitor can never report TLS_INVALID); request_headers (object of name to value: at most 20, a name at most 128 characters of letters, digits and ! # $ % & ' * + - . ^ _ ` | ~, a value at most 1024 bytes of printable ASCII, space or tab, the whole object at most 8192 bytes as JSON; names differing only in case, and Host, Content-Length, Transfer-Encoding, Connection, Upgrade, TE, Trailer, Keep-Alive, CF-Connecting-IP or any Proxy-* name, are a 422); request_body (string, at most 8192 bytes as UTF-8, needs POST, PUT, PATCH or DELETE). Reads return every request_headers value as the literal __FETTLE_UNCHANGED__; writing that literal back in an update keeps the stored value (on create it is a 422). PING: packet_count (1 to 20, default 4). SSL: warn_before_days (1 to 365, default 14) and port (1 to 65535, default 443). TCP: either port (1 to 65535) with expected_state \"open\" (default) or \"closed\", or ports (1 to 20 distinct ports that must all be closed, which needs expected_state \"closed\", exactly one region and interval_seconds of at least 300; a check fails when any of them accepts a connection, and the monitor goes DOWN once confirmation_threshold failures confirm it). Both port and ports, or neither, is a 422; expected_state values are lowercase. DNS: record_type (A, AAAA, CNAME, MX, TXT or NS; required) and expected_value (at most 2048 characters). With expected_value one answer must equal it (case-insensitive, ignoring surrounding spaces and a trailing dot; exact for TXT); without it any answer passes. MX answers are the mail host names without priority (mail.example.com, not 10 mail.example.com). A and AAAA look up every address of the host, IPv4 and IPv6 alike, and any one may match; write an IPv6 address in its shortest form." - added
Input schema / properties / confirmation_threshold / descriptionAdded value: +"How many checks in a row must fail in every region before the monitor goes DOWN and an incident opens, 1 to 10; 3 when not set on create." - added
Input schema / properties / interval_seconds / descriptionAdded value: +"Seconds between checks, 30 to 86400. The plan sets a minimum (limits.min_interval_seconds) and caps how many monitors may check more often than every 60 seconds (max_fast_monitors); breaking either is a 403 naming the limit." - added
Input schema / properties / monitor_id / descriptionAdded value: +"The monitor's uuid from list_monitors. An id that is not a monitor of this organization, or a deleted one, is a 404." - added
Input schema / properties / name / descriptionAdded value: +"Display name, 1 to 255 characters." - added
Input schema / properties / notification_cooldown_seconds / descriptionAdded value: +"60 to 86400 seconds; 1800 when not set on create. Only holds back a duplicate first alert for the same incident within that window. Repeat reminders while an incident stays open and unacknowledged follow the plan's renotify_interval_seconds and renotify_max_count (get_plan_usage; 0 means no reminders) instead, and the recovery alert is never held back." - added
Input schema / properties / regions / descriptionAdded value: +"One or more distinct region codes, for example eu-central: the plan's choices are limits.allowed_regions in get_plan_usage. An unknown code, or more regions than the plan's max_regions, is a 403. SSL and DNS monitors take exactly one region (422 otherwise)." - added
Input schema / properties / tags / descriptionAdded value: +"Replaces the whole tag list when passed, at most 10; [] clears it; omit it to keep the tags. Each tag is trimmed, lowercased and deduplicated on write, at most 50 characters of a-z, 0-9 and : _ . / -, starting with a letter or digit. Reuse names from list_tags rather than inventing near-duplicates." - added
Input schema / properties / timeout_seconds / descriptionAdded value: +"Seconds one check may take before it fails, 1 to 120." - changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "badge_enabled": { + "type": "boolean" + }, + "channel_ids": { + "items": { + "format": "uuid", + "type": "string" + }, + "type": "array" + }, + "config": { + "additionalProperties": true, + "type": "object" + }, + "confirmation_threshold": { + "type": "integer" + }, + "created_at": { + "type": "string" + }, + "id": { + "format": "uuid", + "type": "string" + }, + "interval_seconds": { + "type": "integer" + }, + "is_active": { + "type": "boolean" + }, + "last_checked_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "name": { + "type": "string" + }, + "next_run_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "notification_cooldown_seconds": { + "type": "integer" + }, + "region_statuses": { + "description": "Per-region latest status, sorted by region name.\n\nBuilt from ``region_snapshots``; ``job_id`` is dropped (internal\ndedup key) and malformed/partial snapshot rows are skipped rather\nthan failing the read.", + "items": { + "properties": { + "checked_at": { + "type": "string" + }, + "display_name": { + "type": "string" + }, + "region": { + "type": "string" + }, + "status": { + "description": "Known values: UP, DEGRADED, DOWN, ERROR.", + "type": "string" + } + }, + "required": [ + "region", + "status", + "checked_at", + "display_name" + ], + "type": "object" + }, + "type": "array" + }, + "regions": { + "items": { + "type": "string" + }, + "type": "array" + }, + "ssl_cert_info": { + "anyOf": [ + { + "properties": { + "issuer": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "not_after": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "not_before": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "subject": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "valid": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ] + } + }, + "type": "object" + }, + { + "type": "null" + } + ] + }, + "ssl_expires_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "status": { + "description": "Known values: PENDING, UP, DEGRADED, DOWN, PAUSED.", + "type": "string" + }, + "tags": { + "items": { + "type": "string" + }, + "type": "array" + }, + "target": { + "type": "string" + }, + "timeout_seconds": { + "type": "integer" + }, + "type": { + "description": "Known values: HTTP, PING, SSL, TCP, DNS.", + "type": "string" + }, + "updated_at": { + "type": "string" + }, + "user_id": { + "format": "uuid", + "type": "string" + } + }, + "required": [ + "id", + "user_id", + "name", + "type", + "target", + "interval_seconds", + "timeout_seconds", + "regions", + "config", + "status", + "last_checked_at", + "next_run_at", + "confirmation_threshold", + "notification_cooldown_seconds", + "ssl_expires_at", + "is_active", + "created_at", + "updated_at", + "region_statuses" + ], + "type": "object" +}
- Changed
update_status_page_incident4 fields changed- added
Input schema / properties / incident_id / descriptionAdded value: +"The status page incident's uuid from list_status_page_incidents (not from list_incidents). An unknown id is a 404." - added
Input schema / properties / page_id / descriptionAdded value: +"The status page's uuid from list_status_pages. An id that is not a status page of this organization is a 404." - added
Input schema / properties / title / descriptionAdded value: +"The new headline, 1 to 255 characters." - changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "component_ids": { + "items": { + "format": "uuid", + "type": "string" + }, + "type": "array" + }, + "id": { + "format": "uuid", + "type": "string" + }, + "is_auto": { + "type": "boolean" + }, + "notified_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "resolved_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ] + }, + "started_at": { + "type": "string" + }, + "status": { + "description": "Known values: INVESTIGATING, IDENTIFIED, MONITORING, RESOLVED.", + "type": "string" + }, + "title": { + "type": "string" + }, + "updates": { + "items": { + "properties": { + "body": { + "type": "string" + }, + "created_at": { + "type": "string" + }, + "created_by": { + "anyOf": [ + { + "format": "uuid", + "type": "string" + }, + { + "type": "null" + } + ] + }, + "id": { + "format": "uuid", + "type": "string" + }, + "status": { + "description": "Known values: INVESTIGATING, IDENTIFIED, MONITORING, RESOLVED.", + "type": "string" + } + }, + "required": [ + "id", + "status", + "body", + "created_by", + "created_at" + ], + "type": "object" + }, + "type": "array" + } + }, + "required": [ + "id", + "title", + "status", + "is_auto", + "started_at", + "resolved_at", + "notified_at", + "component_ids", + "updates" + ], + "type": "object" +}
49 tool updates
v0.5.4- First observed
acknowledge_incident - First observed
bulk_create_monitors - First observed
bulk_pause_monitors - First observed
bulk_resume_monitors - First observed
bulk_update_monitor_tags - First observed
bulk_update_monitors - First observed
check_now - First observed
check_target - First observed
create_heartbeat - First observed
create_maintenance_window - First observed
create_monitor - First observed
create_status_page_incident - First observed
delete_heartbeat - First observed
delete_maintenance_window - First observed
delete_monitor - First observed
delete_status_page_incident - First observed
delete_tag - First observed
get_exposed_ports_preset - First observed
get_heartbeat - First observed
get_incident - First observed
get_maintenance_window - First observed
get_monitor - First observed
get_plan_usage - First observed
get_response_time_by_region - First observed
get_status_page - First observed
get_uptime_daily - First observed
get_uptime_summary - First observed
list_active_maintenance - First observed
list_channels - First observed
list_check_results - First observed
list_heartbeats - First observed
list_incidents - First observed
list_maintenance_windows - First observed
list_monitors - First observed
list_regions - First observed
list_status_page_incidents - First observed
list_status_pages - First observed
list_tags - First observed
pause_heartbeat - First observed
pause_monitor - First observed
post_status_page_update - First observed
preview_maintenance_window - First observed
rename_tag - First observed
resume_heartbeat - First observed
resume_monitor - First observed
update_heartbeat - First observed
update_maintenance_window - First observed
update_monitor - First observed
update_status_page_incident
TDQS
Scored across 49 tools
Despite the large number of tools, each has a clearly distinct resource and action, and descriptions explicitly contrast similar operations (e.g., list_active_maintenance vs list_maintenance_windows, check_target vs check_now, list_incidents vs list_status_page_incidents). Overlap is minimal, so an agent can reliably select the right tool.
All tool names use snake_case with a predictable verb_noun pattern (list_, get_, create_, update_, delete_, bulk_, pause_, resume_, check_, post_, preview_). Minor variations like bulk_ and post_ are consistent within their families and do not break the pattern.
49 tools is far beyond the typical well-scoped range and places a heavy cognitive load on agents, even though many tools are logically grouped. The server covers a broad domain, but the surface could be consolidated with fewer, more general tools.
The surface covers full lifecycle operations for monitors, heartbeats, maintenance windows, incidents, status pages, tags, channels, regions, and check actions, including bulk operations and plan/usage introspection. Missing pieces (e.g., channel/status-page creation) are explicitly delegated to the dashboard, so no critical dead ends remain.
Maintenance
Related MCP Connectors
Manage uptime monitors and incidents and search logs, metrics and traces from an AI assistant.
Monitor websites, APIs, and servers: create monitors, triage incidents, and query uptime stats.
Uptime monitoring: monitors, incidents, alerts, maintenance, on-call, status pages and telemetry.
Uptime monitoring, status pages and on-call in one place. Create and tune monitors for HTTP, TCP, DNS, ping, TLS certificates, domain expiry, heartbeats and scripted browser logins. Run a check on demand, read uptime and response-time history, acknowledge and resolve incidents, post incident updates, schedule maintenance windows and edit public status pages. Read-only until you grant write access.
Related MCP Servers
- AlicenseBqualityDmaintenanceEnables AI assistants to interact with Uptime Agent monitoring system to check uptime status, manage incidents, create new monitors, and analyze downtime through natural conversation.71MIT
- AlicenseNot gradedqualityDmaintenanceConnects AI assistants to IonHour uptime monitoring workspaces to manage projects, monitoring checks, and incident responses. It enables users to view reliability metrics, send heartbeats, and manage status pages through natural language.8 npmMIT

GetMonitor MCP Serverofficial
AlicenseCqualityBmaintenanceConnects AI assistants to GetMonitor status pages, monitors, incidents, and maintenance schedules via read-only tools.10018 npmApache 2.0- AlicenseNot gradedqualityCmaintenanceEnables AI agents to query and monitor service status, latency, and performance through configurable checks (HTTP, TCP, SSL, keyword, JSON-path) and exposes tools for listing services, retrieving metrics, and running on-demand checks.Apache 2.0