The public, versioned JSON file of detection checks and thresholds that the monitoring prompts load at the start of every run, and how to override it.
The monitoring prompts do not carry thresholds themselves. They load them from a public JSON file at the start of every run, so a fix to a check reaches every agent without changing your prompts.
https://stitchdb.com/agent/checks/v1.jsonv1.jsonkeeps its format: new checks and tuned thresholds are added in place and raiseversion(1.1.0, 1.2.0, …) andupdated. A change that breaks the format gets a new file,v2.json.https://stitchdb.com/agent/checks/latest.jsonalways has the newest file; pinv1.jsonin scheduled prompts.- Reports end with the version they used, so you can tell which thresholds applied.
#Format
{
"version": "1.0.0",
"updated": "2026-10-26",
"checks": [
{
"id": "health.rest_errors",
"area": "health",
"title": "REST API error rate",
"source": {
"tool": "query_logs",
"logs": "api",
"filter": "path starts with /rest/v1/",
"fallback": {
"tool": "get_logs",
"args": {
"service": "api",
"status": "5xx",
"search": "/rest/v1/",
"minutes": 60
}
}
},
"metric": "Share of /rest/v1 requests with status >= 500, and the number of such errors",
"threshold": {
"rate_pct": 5,
"critical_pct": 20,
"spike_ratio": 2,
"min_requests": 20
},
"window": "60m",
"compare": "previous_window",
"rule": "rate_pct >= 5 with at least 20 requests, and either >= 2 x the previous hour or >= 20 (critical at >= 20)",
"severity": "high",
"next_step": "Group the 5xx requests by path and read the postgres logs of the same minutes (get_logs service=postgres level=error) to find the failing query or function."
}
]
}| Field | Meaning |
|---|---|
id | Stable id, <area>.<name>. Used in alert state and overrides. |
area | health, security, performance or resources: which prompt runs it. |
title | Short name used in reports. |
source | The read-only MCP tool that measures it (tool), with arguments, a filter, the exact SQL for execute_sql, or a fallback tool when the first is not available. |
metric | What is measured. |
threshold | The numbers the rule uses, for example rate_pct, min_errors, spike_ratio, used_pct. |
window | Time measured: 60m, 24h, 1d, 7d, now (a snapshot) or since_reset (cumulative statistics). |
compare | absolute, previous_window (the window before, for spikes), baseline_7d, plan_limit or state (the value saved at the last run). |
rule | The rule in words, combining threshold and compare. |
severity | critical, high, medium or low. |
next_step | The one next step a report suggests. |
#Checks
#Health
| Check | Metric | Default rule | Window | Measured with | Severity |
|---|---|---|---|---|---|
health.rest_errorsREST API error rate | Share of /rest/v1 requests with status >= 500, and the number of such errors | rate_pct >= 5 with at least 20 requests, and either >= 2 x the previous hour or >= 20 (critical at >= 20) | 60m | query_logs (or get_logs) | high |
health.auth_errorsAuth error rate | Share of /auth/v1 requests with status >= 500, and the number of such errors | rate_pct >= 5 with at least 20 requests, and either >= 2 x the previous hour or >= 20 (critical at >= 20) | 60m | query_logs (or get_logs) | high |
health.auth_failed_sign_insFailed sign-ins above normal | Share of POST /auth/v1/token requests answered 4xx (not 429) | rate_pct >= 30 with at least 20 requests, and either >= 2 x the previous hour or >= 60 | 60m | query_logs (or get_logs) | medium |
health.storage_errorsStorage error rate | Share of /storage/v1 requests with status >= 500, and the number of such errors | rate_pct >= 5 with at least 20 requests, and either >= 2 x the previous hour or >= 20 (critical at >= 20) | 60m | query_logs (or get_logs) | medium |
health.functions_errorsEdge Functions error rate | Share of /functions/v1 requests with status >= 500 per function (third path segment), and the number of such errors | per function: rate_pct >= 5 with at least 20 requests, and either >= 2 x the previous hour or >= 20 (critical at >= 20) | 60m | query_logs (or get_edge_function_logs) | medium |
health.api_latencySlow API responses | 95th percentile of response time (ms) per service over the window | p95_ms >= 1500 with at least 50 requests, and p95 >= 2 x the previous hour | 60m | query_logs | medium |
health.postgres_errorsDatabase errors | Number of postgres log lines at error level or above in the window, grouped by message without literals | errors >= 20 and errors >= 3 x the previous hour | 60m | get_logs | medium |
health.connectionsConnection pressure | Connections of your database role in use as a share of your plan's connection limit | used_pct >= 80 (critical at >= 95) | now | execute_sql | high |
health.pooler_waitingClients waiting for a pooled connection | Average number of clients waiting for a free pooled connection over 5 minutes | clients >= 1 (critical at >= 10) | 5m | get_advisors | medium |
#Security
| Check | Metric | Default rule | Window | Measured with | Severity |
|---|---|---|---|---|---|
security.advisor_findingsSecurity advisor findings | Security findings by id and level (error, warn) | any finding with level error or warn whose id is not in the alert state | now | get_advisors | high |
security.exposureData readable or writable by anyone | Critical exposure findings: tables an anonymous visitor or any signed-in user can read or change | one or more critical findings that are not in the alert state | now | check_exposure | critical |
security.auth_failuresFailed sign-ins | Failed sign-in attempts in the window, total and per client IP | failures >= 100 and >= 3 x the previous 24 hours, or one IP with >= 30 failures | 24h | query_logs (or get_logs) | high |
security.authorization_failuresRequests refused (401/403) | 401 and 403 responses per service and path, as a share of all requests | count >= 50 and (rate_pct >= 5 or count >= 3 x the previous 24 hours) | 24h | query_logs (or get_logs) | medium |
security.permission_deniedPermission denied in the database | postgres errors with SQLSTATE 42501 (permission denied, row-level security violation) in the window, by table | count >= 20 and >= 3 x the previous 24 hours | 24h | get_logs | medium |
security.storage_denialsStorage access refused | Refused storage requests per bucket | count >= 50 and >= 3 x the previous 24 hours | 24h | query_logs | low |
#Performance
| Check | Metric | Default rule | Window | Measured with | Severity |
|---|---|---|---|---|---|
performance.slow_queriesSlow queries | Mean execution time per normalized query (pg_stat_statements; counters since the last reset) | mean_ms >= 500 with at least 20 calls, for a queryid not in state or with mean_ms >= 1.5 x the saved value | since_reset | execute_sql | medium |
performance.lock_waitsSessions waiting on locks | Sessions waiting on a lock for more than 30 seconds, with the blocking session | one or more sessions waiting >= 30 s (high when >= 5 sessions) | now | execute_sql | medium |
performance.long_runningLong-running queries | Active queries running longer than 5 minutes | one or more active queries running >= 5 minutes | now | execute_sql | medium |
performance.idle_in_transactionIdle in transaction | Sessions idle inside an open transaction for more than 5 minutes (they hold locks and connections) | one or more sessions idle in transaction >= 5 minutes | now | execute_sql | medium |
performance.advisor_findingsPerformance advisor findings | Performance findings by id (missing primary keys, unindexed foreign keys, ...) | any finding with level error or warn whose id is not in the alert state | now | get_advisors | low |
performance.cache_hitLow cache hit rate | Share of table and index reads answered from memory | hit_pct < 95 with at least 100000 block reads | since_reset | execute_sql | low |
#Resources
| Check | Metric | Default rule | Window | Measured with | Severity |
|---|---|---|---|---|---|
resources.requests_growthAPI requests growth | API requests of the last full day against the daily average of the 7 days before | requests >= 10000 and >= 2 x the 7-day average | 1d | get_usage | low |
resources.errors_growthServer errors growth | 5xx errors of the last full day against the daily average of the 7 days before | errors >= 100 and >= 2 x the 7-day average | 1d | get_usage | medium |
resources.database_sizeDatabase size | Database size as a share of the plan's included size, and growth over the last 7 days | used_pct >= 80, or size grew >= 25% in 7 days | 7d | get_project | medium |
resources.storage_sizeFile storage size | File storage as a share of the plan's included storage | used_pct >= 80, or storage grew >= 25% in 7 days | 7d | get_project | low |
resources.table_growthFast-growing tables | Size and rows of the 20 largest tables, compared with the values saved at the last run | table >= 100 MB that grew >= 50% since the last run, or dead_rows >= 30% of rows | 1d | execute_sql | low |
resources.connections_peakConnections close to the limit | Client connections now against max_connections, and the highest value saved in state over the last 7 runs | used_pct >= 70 now or in any of the last 7 saved runs | 1d | execute_sql | low |
The health checks match the Health advisor in Studio, so the agent and Studio agree on what counts as above normal.
#Override thresholds
A few values: edit the OVERRIDES line at the end of the prompt. Keys are check ids; threshold values replace the defaults one by one, severity changes the level and disabled skips the check.
OVERRIDES: {"security.auth_failures": {"threshold": {"min_failures": 300}}, "resources.requests_growth": {"severity": "medium"}, "performance.cache_hit": {"disabled": true}}Your own file: download v1.json, change it (add your own checks with any read-only SQL), host it where your agent can read it, or keep it in the agent's working folder, and set CHECKS_URL in the prompt. Keep version so reports show which file ran.
CHECKS_URL: https://example.com/ops/stitchdb-checks.json
# or a file next to the state:
CHECKS_URL: .stitchdb/checks.json