Agents

List an agent's open incidents (the failure inbox)

Everything currently broken on the monitors this agent owns, newest first, as a JSON array (never null). This is the pull half of failure delivery: an agent polls it at the start of its next run and learns what broke while it was not looking — no webhook, no inbox, no chat integration to configure.

Only open incidents are returned. There is no closed_at field: it would be null on every row this endpoint can emit.

The payload carries what an agent cannot work out from its own run:

  • cause — silence and fail demand opposite responses. A fail means the job ran and reported an error; a silence means it never reported at all, which usually implicates the scheduler or the host rather than the job.
  • body_excerpt — the error text the failing run printed.
  • failed_step — where it died. For a stalled incident this is the whole diagnosis: the run is alive but has not moved past this step.
  • failure_signature — new problem, or the fortieth repeat. The single fact that decides retry versus escalate.
  • duration_vs_normal — a comparison, never a bare number. "40 minutes" is a measurement; "8.3x the typical run" is a diagnosis.

Every enrichment degrades to absent rather than erroring. A brand-new monitor has no fingerprint history and no archived daily stats; an incident opened by silence has no failure body because nothing was reported — that is the complaint itself. The thin payload is still useful and thickens on its own as history accumulates. This endpoint never fails over a missing enrichment.

  • exit_code — the status the run exited with, when it sent one. 137 (SIGKILL, usually the OOM killer) and 1 demand different responses, and only the numeric ping form /ping/{id}/{code} carries one. The field is absent when no code was reported, which is not the same as 0; see the OpenIncident schema.
get/api/v1/agents/{id}/open-incidents

Request

  • Base URL: https://app.lastping.dev
  • URL: https://app.lastping.dev/api/v1/agents/{id}/open-incidents
  • Auth: API key in header X-Api-Key

Response

Array of open incidents (may be empty).

incident_idinteger required

Identifies this incident. Stable for its lifetime.

check_idstring uuid required

The monitor this incident is about.

check_slugstring required
check_namestring required
cause'silence' | 'fail' | 'overrun' | 'never_started' | 'runaway' | 'stalled' | 'blocked' | 'assertion' | 'upstream' required

Why the incident opened. These need different responses, which is the reason this field leads the payload:

  • fail — the job ran and explicitly reported failure.
  • upstream: runs in a row ended on the model provider's API error (server_error, overloaded or rate_limit), not on the agent's own work: 3 of them, or the monitor's failure_threshold when that is higher. detail names the last error type. Fewer are recorded on the run and page no one.
  • assertion — the job reported success, but its output violated criteria the agent itself declared at the start of that run.
  • silence — nothing was reported within the expected window. Suspect the scheduler or the host before the job.
  • never_started — the monitor has never reported at all; the wiring is probably wrong.
  • overrun — the run exceeded its maximum runtime.
  • stalled — the run is alive but has reported no step progress. failed_step is the diagnosis here.
  • runaway — the monitor exceeded a ping-rate ceiling or a metric guard.
  • blocked — a run is waiting on a human.
opened_atstring date-time required

RFC 3339 UTC timestamp when the incident opened.

detailstring

Why it opened, when the opener knew more than the cause code can say — which assertion rejected the output, which metric guard tripped, the last API error type of an upstream incident (Last error: server_error), or a CI job's own failure detail. Omitted when empty.

run_idstring

The rid of the run this incident is about, so the agent can line it up against its own logs. Recorded when the incident opens, which is the only moment it can be: the transition that opens an incident also clears the monitor's in-flight run, so the identity does not survive anywhere else.

Omitted when there was no run to name — a never_started incident, or a monitor that reported without ever opening a run.

body_excerptstring

The failure output the run reported: the body of the ping that opened the incident, or — for an incident opened by a missed deadline, where no ping coincides with opened_at — the latest fail reported while the incident has been open.

That second case matters more than it looks. Incidents open only on the transition into down, so a cron that runs late and then fails keeps its original silence incident: without the fallback the agent would be told "silence" while the error text sat unread.

Omitted only when nothing was reported at all, which for never_started and an ongoing silence is the incident itself.

exit_codeinteger

The status the run exited with, as sent through the numeric ping form POST /ping/{check_id}/{code}. Read from the same ping body_excerpt comes from, so the output and the status always describe one run.

Omitted means no exit code was reported. It never means "exited cleanly". A job reports a status only through the numeric form; the word forms (/fail, /start, …) carry none, an incident opened by a missed deadline has no ping at all, and pings recorded before this field existed did not keep the number and cannot be backfilled. A clean exit is the present value 0 — which does occur on an incident, since an assertion incident opens on a run that reported success and then failed the criteria the agent declared for it.

Two conventions are worth decoding, and are what the console shows in words beside the number:

  • 128 + n is death by signal — 137 is SIGKILL (most often the OOM killer or a container runtime), 143 is SIGTERM (a shutdown the job did not survive), 139 is SIGSEGV.
  • 124 is a timeout(1) kill — the status GNU timeout uses when it kills the command it wrapped.

Everything else is application-defined: 1, 2 and the rest mean whatever the program that exited chose them to mean, and LastPing does not guess.

Example response

[
  {
    "incident_id": 4821,
    "check_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "check_slug": "nightly-etl",
    "check_name": "Nightly ETL",
    "cause": "fail",
    "opened_at": "2026-08-21T03:14:07Z",
    "detail": "assertion contains(\"rows_written\") failed",
    "run_id": "2026-08-21T03-00-00Z-a91f",
    "body_excerpt": "psycopg2.OperationalError: could not connect to server",
    "exit_code": 137,
    "failed_step": {
      "name": "load-warehouse",
      "seq": 4,
      "at": "2026-08-21T03:12:44Z"
    },
    "failure_signature": {
      "fingerprint": "9f2c1ab30de54771",
      "occurrences": 40,
      "first_seen": "2026-06-02T03:11:58Z",
      "last_seen": "2026-08-21T03:14:07Z"
    },
    "duration_vs_normal": {
      "run_ms": 2400000,
      "typical_ms": 288000,
      "ratio": 8.33,
      "days_sampled": 30,
      "summary": "8.3x the typical run (40m0s vs 4m48s), from 30 archived days"
    },
    "ci": {
      "run_url": "https://github.com/acme/etl/actions/runs/1234567890",
      "failing_stage": "integration-tests",
      "outcome": "failure",
      "branch": "main",
      "commit_sha": "9f2c1ab30de547714a0f2c1ab30de547714a0f2c"
    }
  }
]

Changes

No recorded changes to this operation across all 2 revisions of this API.