See delivery fail and recover
Observe durable acceptance, retryable failure, terminal failure, and intentional replay.
Use the reference receiver to see what acknowledgement and recovery mean. The homepage ledger uses illustrative fixtures for this same procurement email; it is not a live dashboard.
The diagram uses the same address and event identity as the homepage. It is illustrative; acceptance is separate from agent completion.
Local receiver experiment
Start a fresh receiver database:
export AGENTOWL_SIGNING_SECRET=local-demo-only
python3 receiver.py serve --db recovery.sqlite3 --fail-firstIn another terminal with the same secret:
python3 send_fixture.py
# 503 rejected evt_procurement_demo
python3 send_fixture.py
# 204 accepted evt_procurement_demo
python3 receiver.py inspect --db recovery.sqlite3
python3 receiver.py worker --once --db recovery.sqlite3The first send fails before acceptance; the second creates one job. Repeated accepted deliveries do not create additional jobs. This manual experiment exercises receiver behavior; it is not an automatic AgentOwl retry.
Observe automatic delivery recovery
With a real signed endpoint configured for this receiver, send a new email while --fail-first is enabled. Inspect the event in Inbox and Webhooks:
| Stage | Expected evidence |
|---|---|
| Received | Event ID and original message stored |
| Attempt 1 | HTTP 503; retryable failure |
| Attempt 2 | HTTP 204; receiver accepted the event |
| Receiver | One durable job, same event and delivery key |
Do not use --fail-first for ordinary traffic. Real delivery uses the configured backoff, timeout, and retry budget. The local integration test accelerates the next-attempt timestamp while exercising the actual consumer and signed HTTP receiver.
Terminal failure and intentional replay
An endpoint returning 404 is terminal; waiting does not repair it. Correct the endpoint URL, publish your configuration, then replay:
agentowl events inspect <event_id>
agentowl config publish <workspace>
agentowl events replay <event_id> --mode re-evaluate-routere-evaluate-route evaluates current routing. In the current source implementation, both replay modes enqueue a new event and the consumer resolves current routes; redrive-dispatch does not restore the original delivery plan. Do not rely on replay to retain an old endpoint URL. Automatic retries also retain their original destination; editing an endpoint does not redirect a pending retry.
Replay creates a new event ID and delivery key. This intentionally creates new application work; the original event history remains available. Expired payloads or retained attachments can prevent replay. simulate returns the source event without queueing or evaluating current routes.
Verification scope
The repository integration check uses local D1 and a real loopback receiver. It verifies 503 → 204, one saved job, worker output, terminal 404, and API replay with a new identity. Run from repository root:
node --test --import tsx examples/receiver/delivery.test.mtsPublic HTTPS, live SMTP/provider provisioning, and current hosted enablement require separate deployment verification. See delivery reference for exact semantics and troubleshooting for missing routes and dead letters.