The dead man's switch for everything that runs without you —
including your AI agents.
An autonomous agent is the new cron job. It runs unattended, on a schedule or a loop, and its worst failures are silent — the process is alive, the work has stopped. LastPing is the first monitor your agent can set up itself, via MCP, in one conversation.
Agents fail silently. For the same reasons cron jobs do.
The failure class that makes cron monitoring necessary — silent absence of a signal that should have arrived — applies to AI agents word for word. Five modes, zero notifications.
Silent death
The agent process exits — crash, OOM, unhandled exception — and nothing in your stack notices. The operator assumes it's running. It has been dead for hours.
The hung run
The agent started. It hasn't finished. The process is alive by every health check — event loop not frozen, memory stable — but it has been waiting on a tool call, a token, or an external API for 90 minutes. Nobody gets paged.
The stalled run
The agent started, worked through three stages, and then stopped making progress. It is not finished, not failed, and not yet over its runtime budget — so nothing fires for another three hours. You find out at the end, and you still don't know which stage it died in.
The runaway loop
The agent is alive and running — but it has looped far beyond what any successful run should take, burning tokens and compute indefinitely. Too many pings is also a signal.
Scheduled runs that stop
Your nightly agent ran reliably for three weeks, then silently stopped. The scheduler is fine; the trigger condition stopped being met; no one noticed. Absence detection is the fix.
LLM-observability tools (LangSmith, Langfuse, AgentOps) instrument
inside the agent — traces, tokens, evals — and answer "is
the output good?" LastPing is outside-in: it answers "did the agent
run at all, finish in time, and not loop forever?" That question is
unowned. LastPing's dead-man's-switch primitive handles it without
any SDK or language dependency — the same
curl -fsS https://ping.lastping.dev/<id>
that works in crontab works in an agent's tool call.
The flagship: the agent that monitors itself
Via the MCP server, an agent in Claude Code, Cursor, or any MCP-enabled client can create its own dead-man's-switch and wire in the pings — in one conversation, without opening a dashboard.
And then it becomes code. A monitor created
mid-conversation is real, but the repo does not know about it. The
export_terraform
tool renders what exists as HCL — with an
import
block per resource, so the first plan adopts it rather than recreating it — and
the agent commits it. Working the other way round, an agent adding a scheduled
job can declare the monitor that watches it in the
same pull request, so the job can never ship
unmonitored. That is monitoring as code, and it
matters more when the agent is the one writing the job.
Connect your agent in about a minute
Hosted and remote — add a URL and your API key, nothing to install. Works with Claude Desktop, Claude Code, Cursor, and any client that supports the Model Context Protocol. Prefer local? Self-host the stdio binary instead.
Get a LastPing API key
Sign in at app.lastping.dev, then go to Settings → API Keys and create a key. Copy it — you'll need it in the next step.
Add to your MCP client config
Point your client at the hosted server — nothing to install, no
local process. For Claude Desktop add to
claude_desktop_config.json; for Claude Code
or a project, add to .mcp.json:
Prefer to self-host? Run the stdio binary locally with
go install github.com/tp322d/lastping-app/cmd/lastping-mcp@latest,
then use "command": "lastping-mcp" and
"env": { "LASTPING_API_KEY": "lp_…" } instead of the URL.
Ask the agent to instrument itself
Restart the client. The agent now has access to
create_monitor, get_ping_instructions,
and the full tool set. In a conversation:
get_ping_instructions is the key tool — it returns
reporting_options, a decision rule for how to
report (chosen by what the agent is, not ranked), plus all
three mechanisms: the manual curl_success /
curl_start / curl_fail /
curl_step snippets (the universal default — works
in any agent, any language, any tool), run_wrapper
(wrap a command with lastping run so a separate
process reports), and hook_install (an optional
shortcut for Claude Code specifically — a one-time hook
install, and the only mechanism that can send every state,
including blocked and note). From
that point on, any silent failure opens a LastPing incident
and alerts you.
Pair the manual path with expect_every_s, the
silence floor, and an agent that quietly stops reporting opens
a silence incident rather than leaving its monitor
reading healthy — which is why reporting it yourself is the
default rather than a compromise. Monitors created through the
agent wizard get a 24-hour floor already set.
What LastPing catches for agents
The same durable detection engine as LastPing's cron and CI/CD monitoring — deadlines in the database, never in-memory timers.
- Silent death — the agent crashes or exits without sending a success or fail ping. No signal in the expected window → incident.
- Hung runs — the agent sent a start ping but never sent success or fail within the grace window. Silence after start → incident.
- Stalled runs — the agent kept reporting progress steps and then stopped. Opt-in: set
step_timeout_sand report a step as each stage finishes. The incident names the last step that reported, so you learn where it wedged minutes in rather than when the whole run budget expires. Leave it unset and the monitor behaves exactly as before. - Explicit failures — the agent POSTs to
/failwith the error body. Incident opens immediately with the failure detail attached. - A success that did nothing — the run finishes, exits zero, and reports nothing useful. Assert on the ping body it already sends: a substring, a regex, or a JSON path compared against a value. A failing assertion turns that success into a failure, and the incident quotes what it got against what it expected —
got "3", expected gte "10". Up to 20 per monitor. A malformed pattern is rejected when you save it, not when the job runs. - A success the agent did not earn — the same check, with the criteria set by the agent instead of by you. At the start of a run it calls
declare_run_expectationsand commits to what its own output must contain, before it can see how the run turns out. A success ping that does not meet them is recorded as a failed run whatever the exit code says. The declaration is immutable — a second attempt for the same run is refused — because an agent that could revise its criteria once it saw the outcome coming would just be grading itself again. Declaring nothing is allowed and leaves your own assertions in force. - Runaway spend — the agent loops and burns money while every ping still says success. Report a number in the body —
cost_usd, tokens, rows — and set a ceiling over a trailing window:sum,maxoravg. Exceed it and an incident opens. Windows up to seven days, five guards per monitor. - Scheduled runs that stop — expected on a cron or interval; if no run signal arrives in the window, LastPing opens an incident. The scheduler being "up" is not enough.
- Recovery — the next successful ping closes the incident and sends a recovery notice automatically.
The full ping API: GET /<id> (success) ·
/<id>/start (run began — arms overrun detection) ·
/<id>/fail (POST failure body as text/plain) ·
/<id>/<exit-code> (0 = success, non-zero = fail) ·
/<id>/step?rid=<run-id>&step=<name> (a
progress marker inside a started run — arms stall detection) ·
?rid=<run-id> (pair start with its later result and
record duration). See the full reference at
app.lastping.dev/docs/api/
or in agents.md.
The agent registry
Register an agent once and every monitor it owns rolls up into one live state — worst first. The one that matters most: blocked means a run stopped to ask you something and is still waiting. One run is one task you asked for; before the registry, nothing told you a person was needed.
down— a monitor this agent owns is down.blocked— a run is waiting on you. It stopped to ask a question and needs an answer to continue.late— a monitor is overdue.running— a run is in flight.up— healthy.pending— a monitor exists but has never reported.idle— no monitors, or all of them paused or in maintenance.
Every agent and its current state live in one list — see the five registry tools below.
Why on_demand
An agent's tasks don't run on a schedule, so "did it check in on
time?" is the wrong question for it. An on_demand
monitor does no absence detection between runs — it only bounds a
run once one has started.
- No interval to invent — nothing pages for the gap between one task and the next, because there isn't supposed to be a regular one.
- A run budget instead —
max_runtime_sbounds how long a started run is allowed to take before it's reported as stuck. - Four hours by default — set a run budget and you get a real one. Leave it unset and it falls back to the monitor's grace, which is a silence tolerance rather than a run-duration budget — a task running longer than that gets reported as stuck while the agent is still legitimately working. Generous, but still bounded: a run nobody ever closes has to alert eventually. That is the point.
The onboarding wizard sets both automatically: a new agent's first
monitor defaults to on_demand with the run budget
pre-filled at four hours, editable before you save it.
What the MCP server exposes
Verified against cmd/lastping-mcp — every tool listed here
is implemented and ships in the binary.
-
Monitors —
create_monitor(upsert-by-slug, safe to retry) ·list_monitors·get_monitor·update_monitor·delete_monitor·pause_monitor·resume_monitor·snooze_monitor -
Incidents —
list_incidents(includes CI failure detail — the "why it failed") ·get_run_history(each run's id and the progress steps reported under it — the last step is where a stalled run wedged) -
The failure loop —
list_open_incidentsis the agent's inbox: what broke on its monitors while it was not running, read at the start of its next run. The entry carries what the agent could not work out for itself —failure_signature.occurrences(first time or fortieth repeat, the fact that decides retry versus escalate), the step it died on, the exit code, and how the run's duration compared with its own normal. A missing field means no evidence, never "normal" and never "exited cleanly".add_incident_noteis the write-back: the agent's own diagnosis, on the incident a human reads, sent whether or not it could fix the problem. Notes are append-only — a correction is a new note, never an edit. -
Destinations —
list_destinations·create_destination(email, Slack, Discord, Telegram, webhook, ntfy, Pushover, Teams, Google Chat) ·update_destination·test_destination -
Agent registry —
register_agent(name an agent once; returns its monitor and ping URL) ·list_agents(every agent and its current state) ·get_agent·update_agent·delete_agent -
Routing —
set_routesends a monitor'sdown/recovery/fail/every-run/success/started/blocked/notealerts to one or more destinations (replaces the set; empty clears it) -
Self-instrumentation —
get_ping_instructionsreturnsreporting_options(a decision rule, not a ranking, for choosing among the manualcurl_success/curl_start/curl_fail/curl_stepsnippets,run_wrapper, andhook_install), and tells the agent whether stall detection is armed on that monitor. This is the tool that makes one-conversation self-instrumentation possible. -
Discovery —
discover_monitors_reconciletakes a scan the agent ran itself (LastPing never reads your repository) and turns it into monitors:crontablines,github-actionsschedules,k8s-cronjobmanifests andsystemd-timerunits. What comes back is a diff — created, existing, orphaned. Existing monitors are returned completely unmodified, so a threshold somebody tuned by hand survives the scan, and orphaned ones are reported and left running: the call has no delete path. That is what makes it safe to re-run nightly, which turns a one-off setup step into drift detection. The agent proposes what it found and waits for a yes before creating anything. -
Monitoring as code —
export_terraformrenders existing monitors, destinations, routes, templates and status pages as Terraform HCL, with animportblock per resource. How work created over MCP becomes code in a repo — see the Terraform provider.
Questions
Front-loaded answers — the most important fact first.
-
What AI agent failures does LastPing detect?
LastPing detects eight classes of agent failure: silent death (process exits without a ping), hangs (start ping sent, no success/fail within the grace window), stalled runs (start ping sent, progress steps reported and then stopped — opt-in via
step_timeout_s), explicit failures (agent posts to/failwith the error body), a run blocked on a human (the agent reports it needs an answer; if nobody responds before the blocked timeout — 24 hours by default — an incident opens), scheduled runs that stop (no signal in the expected cron window), a success that did nothing (the run exits zero but its output fails an assertion on the ping body), and runaway spend (a reported number, such as cost or tokens, exceeds a ceiling over a trailing window). The last two evaluate the ping body against a rule; the rest are explicit signals or outside-in liveness checks — no SDK or language binding required. -
How does an AI agent set up its own monitor?
Install the
lastping-mcpserver (hosted at mcp.lastping.dev, or self-host the Go binary — no npm). In one conversation, tell the agent to create a monitor for itself: it callscreate_monitor, thenget_ping_instructions, which returnsreporting_optionsand three ways to report, chosen by what the agent is, not ranked — the manual curl snippets (the universal default: any agent, any language, any tool), thelastping runwrapper if it's launched as a command, or a one-time hook install as an optional shortcut if it IS Claude Code specifically — and wires in whichever fits. The whole loop — create, instrument, verify — takes one conversation and zero dashboards. -
Do I need an SDK or library inside the agent?
No. The ping API is plain HTTP — a
curlGET or POST from any language or shell. The MCP server is for creating and managing monitors, not for pinging them. Once a monitor exists, the agent pings by making a plain HTTP request — no dependency, no import. -
Is LastPing free for monitoring AI agents?
Yes. LastPing is free for individuals — no monitor cap, no feature gate. Every monitor type is available at no cost. A paid team tier may be introduced later for teams running fleets of agents.
-
How is this different from LLM-observability tools like LangSmith?
LLM-observability tools (LangSmith, Langfuse, AgentOps, Coralogix AI Center) instrument inside the agent — traces, token counts, evals, guardrails — and answer "is the output good?" LastPing is outside-in and answers "did the agent run at all, finish in time, and not loop forever?" Those are different questions. LastPing requires no SDK; any agent that can make an HTTP request can use it.
-
Which MCP clients does lastping-mcp support?
Any client that speaks the Model Context Protocol over stdio: Claude Desktop, Claude Code, Cursor, Windsurf, and others. Configure it in
claude_desktop_config.json(for Claude Desktop) or a project-level.mcp.json(for Claude Code and Cursor).
The first monitor your agent can set up itself.
Install lastping-mcp,
ask the agent to create its own monitor, and you'll know the moment
it goes silent — without opening a dashboard.