Does your agent survive a lost response?
An API call can succeed while the answer never reaches your agent. The agent retries, and the customer gets a second refund or a second email. The chaos tester causes exactly that failure on purpose, before production does, and lists every action that ran twice.
pip install agentraas
agentraas chaos --mock -- python my_agent.py
How it works
Your command gets AGENTRAAS_CHAOS_URL to use as its API base URL. --mock answers every call itself; --upstream forwards to a real API with test keys.
The first time each distinct write (POST, PUT, PATCH, DELETE) arrives, it is executed and then the connection is cut.
If your code retries without a stable idempotency key, the same action executes again. The report lists each one, and the exit code is 1.
What you get
Real output for a small agent that retries every failed call, and sends an Idempotency-Key only for the charge:
agentraas-chaos: 6 write requests, 3 responses dropped after execution
DUPLICATES: 2 action(s) executed more than once
2x POST /v1/refunds (body sha256 632185d99062)
2x POST /v1/emails (body sha256 553c24128024)
Fix: send an Idempotency-Key header that stays the same across retries, for
providers that honor one. With agentraas.local.exactly_once, give the function an
`idempotency_key` parameter and send it as that header; for providers without
idempotency support, route the call through an AgentRaaS server.
Protected by an idempotency key: 1 retry
Run it on every pull request
The GitHub Action fails the build when a change makes any action run twice.
- uses: actions/setup-python@v5
with: { python-version: "3.12" }
- uses: sumedhchatse/agentraas/src/chaos-action@main
with:
run: python my_agent.py # optional: upstream, fault
Show that your project passes, in your README:
[](https://agentraas.io/chaos)
Options
| Flag | What it does | Default |
|---|---|---|
--mock | Answer every call with a fake 200. Nothing real is called. | |
--upstream URL | Forward to a real API base URL. Use test-mode keys. | |
--fault | lost-response cuts the connection, error-after-commit returns a 502 instead, none only records. | lost-response |
--port | Local port. | 8787 |
Without a command it runs until Ctrl-C, so you can point an n8n workflow or any other tool at it by hand. Works with any language: it is an HTTP server, your code only needs a configurable base URL.
Fix what it found
In Python, @exactly_once from the same package runs a function once across retries, backed by SQLite or your own Redis (TypeScript: exactlyOnce on npm). For providers with no idempotency support, or to add approvals and an audit trail, run the calls through an AgentRaaS server. The Community edition is free to self-host.