production-agent-systems 1.0.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. production_agent_systems-1.0.1/LICENSE +21 -0
  2. production_agent_systems-1.0.1/PKG-INFO +365 -0
  3. production_agent_systems-1.0.1/README.md +345 -0
  4. production_agent_systems-1.0.1/pyproject.toml +49 -0
  5. production_agent_systems-1.0.1/setup.cfg +4 -0
  6. production_agent_systems-1.0.1/src/production_agent_systems/__init__.py +90 -0
  7. production_agent_systems-1.0.1/src/production_agent_systems/audit.py +54 -0
  8. production_agent_systems-1.0.1/src/production_agent_systems/effect_cli.py +171 -0
  9. production_agent_systems-1.0.1/src/production_agent_systems/effect_executor.py +612 -0
  10. production_agent_systems-1.0.1/src/production_agent_systems/effect_ledger.py +627 -0
  11. production_agent_systems-1.0.1/src/production_agent_systems/effect_models.py +219 -0
  12. production_agent_systems-1.0.1/src/production_agent_systems/effects.py +37 -0
  13. production_agent_systems-1.0.1/src/production_agent_systems/events.py +73 -0
  14. production_agent_systems-1.0.1/src/production_agent_systems/model.py +16 -0
  15. production_agent_systems-1.0.1/src/production_agent_systems/models.py +205 -0
  16. production_agent_systems-1.0.1/src/production_agent_systems/planner.py +19 -0
  17. production_agent_systems-1.0.1/src/production_agent_systems/policy.py +25 -0
  18. production_agent_systems-1.0.1/src/production_agent_systems/reliability.py +51 -0
  19. production_agent_systems-1.0.1/src/production_agent_systems/replay.py +47 -0
  20. production_agent_systems-1.0.1/src/production_agent_systems/runtime.py +418 -0
  21. production_agent_systems-1.0.1/src/production_agent_systems/state.py +26 -0
  22. production_agent_systems-1.0.1/src/production_agent_systems/testkit.py +170 -0
  23. production_agent_systems-1.0.1/src/production_agent_systems/tools.py +298 -0
  24. production_agent_systems-1.0.1/src/production_agent_systems.egg-info/PKG-INFO +365 -0
  25. production_agent_systems-1.0.1/src/production_agent_systems.egg-info/SOURCES.txt +40 -0
  26. production_agent_systems-1.0.1/src/production_agent_systems.egg-info/dependency_links.txt +1 -0
  27. production_agent_systems-1.0.1/src/production_agent_systems.egg-info/entry_points.txt +3 -0
  28. production_agent_systems-1.0.1/src/production_agent_systems.egg-info/requires.txt +5 -0
  29. production_agent_systems-1.0.1/src/production_agent_systems.egg-info/top_level.txt +1 -0
  30. production_agent_systems-1.0.1/tests/test_effect_assurance_demo.py +12 -0
  31. production_agent_systems-1.0.1/tests/test_effect_cli.py +126 -0
  32. production_agent_systems-1.0.1/tests/test_effects.py +834 -0
  33. production_agent_systems-1.0.1/tests/test_foundation.py +12 -0
  34. production_agent_systems-1.0.1/tests/test_hardening.py +129 -0
  35. production_agent_systems-1.0.1/tests/test_models.py +56 -0
  36. production_agent_systems-1.0.1/tests/test_process_recovery.py +112 -0
  37. production_agent_systems-1.0.1/tests/test_recovery.py +75 -0
  38. production_agent_systems-1.0.1/tests/test_reliability.py +63 -0
  39. production_agent_systems-1.0.1/tests/test_replay.py +32 -0
  40. production_agent_systems-1.0.1/tests/test_runtime.py +197 -0
  41. production_agent_systems-1.0.1/tests/test_runtime_effects.py +97 -0
  42. production_agent_systems-1.0.1/tests/test_tool_validation.py +139 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Peyman Salimi
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,365 @@
1
+ Metadata-Version: 2.4
2
+ Name: production-agent-systems
3
+ Version: 1.0.1
4
+ Summary: Provider-neutral effect assurance and reliability testing for agent tool operations.
5
+ Author: Peyman Salimi
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/peymanpro/Production-Agent-Systems
8
+ Project-URL: Repository, https://github.com/peymanpro/Production-Agent-Systems
9
+ Project-URL: Issues, https://github.com/peymanpro/Production-Agent-Systems/issues
10
+ Project-URL: Changelog, https://github.com/peymanpro/Production-Agent-Systems/blob/main/CHANGELOG.md
11
+ Project-URL: Security, https://github.com/peymanpro/Production-Agent-Systems/blob/main/SECURITY.md
12
+ Requires-Python: >=3.11
13
+ Description-Content-Type: text/markdown
14
+ License-File: LICENSE
15
+ Provides-Extra: dev
16
+ Requires-Dist: pytest>=8; extra == "dev"
17
+ Requires-Dist: ruff>=0.13; extra == "dev"
18
+ Requires-Dist: mypy>=1.18; extra == "dev"
19
+ Dynamic: license-file
20
+
21
+ # Production Agent Systems
22
+
23
+ Production Agent Systems is a provider-neutral Python library for making agent tool effects safer to execute, recover, and test under failure. It records durable operation state, uses explicit provider contracts to reconcile uncertain outcomes, and includes a deterministic fault-injection testkit for verifying external-effect behavior.
24
+
25
+ [![Python 3.11+](https://img.shields.io/badge/python-3.11%2B-3776AB.svg)](https://www.python.org/)
26
+ [![MIT License](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
27
+ [![CI](https://github.com/peymanpro/Production-Agent-Systems/actions/workflows/quality.yml/badge.svg?branch=main)](https://github.com/peymanpro/Production-Agent-Systems/actions/workflows/quality.yml)
28
+ [![Latest release](https://img.shields.io/github/v/release/peymanpro/Production-Agent-Systems)](https://github.com/peymanpro/Production-Agent-Systems/releases)
29
+
30
+ > **The failure this library targets:** an agent sends a write request, the destination commits it, and the acknowledgement is lost. The agent sees a timeout—not proof of failure. Retrying blindly may charge a customer twice; giving up may leave required work unfinished.
31
+
32
+ The library focuses on the boundary between **what an agent believes happened** and **what the external system actually committed**. It is complementary to an agent framework or workflow engine, not a replacement for either.
33
+
34
+ ## Table of contents
35
+
36
+ - [Why this library exists](#why-this-library-exists)
37
+ - [Current capabilities](#current-capabilities)
38
+ - [Installation](#installation)
39
+ - [Quick start](#quick-start)
40
+ - [Effect contracts and recovery](#effect-contracts-and-recovery)
41
+ - [Fault-injection testkit](#fault-injection-testkit)
42
+ - [Persistence and concurrency](#persistence-and-concurrency)
43
+ - [Security model and limits](#security-model-and-limits)
44
+ - [Research behind the design](#research-behind-the-design)
45
+ - [Development](#development)
46
+ - [V1 scope and optional future extensions](#v1-scope-and-optional-future-extensions)
47
+ - [Changelog](CHANGELOG.md)
48
+ - [Security policy](SECURITY.md)
49
+ - [License](#license)
50
+
51
+ ## Why this library exists
52
+
53
+ Agent frameworks can retry tool calls, persist execution state, and resume interrupted runs. Those capabilities do not, by themselves, establish whether an external write took effect.
54
+
55
+ Consider a payment operation:
56
+
57
+ 1. An agent submits a capture request.
58
+ 2. The payment provider records the capture.
59
+ 3. The acknowledgement is lost in transit.
60
+ 4. The agent receives a timeout and retries or resumes.
61
+ 5. Without a stable idempotency contract or reliable reconciliation, a second capture may occur—or the application may incorrectly report failure.
62
+
63
+ The same failure pattern appears in email delivery, ticket creation, resource provisioning, deployment, inventory updates, and other operations with external side effects.
64
+
65
+ Production Agent Systems records an operation before dispatch, uses a stable business identity, tracks whether the result is confirmed or uncertain, and only retries an uncertain write when the provider contract supplies a safe basis for doing so. It never treats a timeout or an LLM's final answer as proof of external success.
66
+
67
+ A local handler deadline is not cancellation: the Python worker thread can continue and send a request after the caller has timed out. In that case, even a provider lookup that currently reports no commit cannot, by itself, prove that retry is safe. The ledger records this possibility and blocks retry unless the provider's stable-key idempotency guarantee makes overlapping dispatch safe or a trusted operator establishes that the previous handler can no longer send the request.
68
+
69
+ ## Current capabilities
70
+
71
+ The current core implementation includes:
72
+
73
+ - **Explicit effect contracts** — define a stable operation ID, provider idempotency key, optional outcome probe, postcondition, and unknown-outcome policy.
74
+ - **Stable operation identity, contract versions, and request fingerprints** — reject reuse of one operation ID for different request arguments, provider keys, or contract versions. Existing SQLite ledgers are migrated to contract version `1`.
75
+ - **Durable SQLite effect ledger** — persist operation state, attempt count, provider result, evidence, and ordered state-change events.
76
+ - **Outcome-aware recovery** — distinguish confirmed success, definitive rejection, active dispatch, unknown outcome, and quarantined operation.
77
+ - **Provider-aware retries** — retry after terminal NOT_COMMITTED evidence only when no earlier local handler can still dispatch; an overlapping retry requires an explicitly declared provider idempotency guarantee.
78
+ - **Conservative ambiguity handling** — quarantine uncertain writes by default when neither a reliable outcome probe nor a provider idempotency guarantee can make retry safe.
79
+ - **Postcondition validation** — require a caller-defined condition before treating a returned or probed result as confirmed.
80
+ - **Operation conflict detection** — detect request-fingerprint mismatches before another handler dispatch.
81
+ - **Operator inspection and audited resolution** — list operations by status, record evidence-backed manual confirmation or rejection, and explicitly authorize a retry after trusted verification.
82
+ - **Fault-injection demo** — reproduce failure before commit and commit followed by a lost acknowledgement, then report the number of committed fake effects.
83
+ - **No model-provider dependency** — the core tests and demo run without API keys or hosted model calls.
84
+
85
+ The effect core integrates with the existing agent runtime: attach an effect contract to a ToolDefinition and supply an EffectExecutor to AgentRuntime. An uncertain or quarantined effect transitions the run to WAITING, so the same logical action can be reconciled on resume rather than being reported as a definitive failure. The existing permission policy still runs before the tool handler.
86
+
87
+ ## Installation
88
+
89
+ Install the published package from PyPI:
90
+
91
+ ~~~bash
92
+ python -m pip install production-agent-systems
93
+ ~~~
94
+
95
+ For development from a source checkout, install the project and its development tools:
96
+
97
+ ~~~bash
98
+ python -m pip install -e ".[dev]"
99
+ ~~~
100
+
101
+ The effect ledger uses the Python standard library and SQLite; no external database or model provider is required for the core example.
102
+
103
+ ## Quick start
104
+
105
+ The handler receives the stable provider idempotency key. The outcome probe uses the same key to ask the destination what happened.
106
+
107
+ ~~~python
108
+ from production_agent_systems import (
109
+ EffectContract,
110
+ EffectExecutor,
111
+ EffectStatus,
112
+ OutcomeProbeResult,
113
+ ProbeStatus,
114
+ SQLiteEffectLedger,
115
+ )
116
+
117
+ # Implement these using your provider's documented API.
118
+ def capture_payment(arguments, *, idempotency_key):
119
+ return payment_provider.capture(
120
+ invoice_id=arguments["invoice_id"],
121
+ idempotency_key=idempotency_key,
122
+ )
123
+
124
+
125
+ def find_payment_outcome(arguments, *, idempotency_key):
126
+ payment = payment_provider.lookup_by_idempotency_key(idempotency_key)
127
+ if payment is not None:
128
+ return OutcomeProbeResult(
129
+ status=ProbeStatus.COMMITTED,
130
+ output=payment,
131
+ provider_operation_id=payment["id"],
132
+ evidence={"source": "provider_lookup"},
133
+ )
134
+
135
+ # Return NOT_COMMITTED only if the provider can prove the earlier request
136
+ # is terminal and cannot commit later. An eventually consistent empty read
137
+ # must instead return PENDING or UNKNOWN.
138
+ return OutcomeProbeResult(
139
+ status=ProbeStatus.UNKNOWN,
140
+ evidence={"source": "provider_lookup"},
141
+ )
142
+
143
+
144
+ contract = EffectContract(
145
+ name="capture_payment",
146
+ operation_id=lambda args: f"invoice:{args['invoice_id']}:capture",
147
+ provider_idempotency_key=lambda args: f"capture:{args['invoice_id']}",
148
+ provider_idempotency_guaranteed=True,
149
+ outcome_probe=find_payment_outcome,
150
+ )
151
+
152
+ executor = EffectExecutor(ledger=SQLiteEffectLedger("agent-effects.sqlite3"))
153
+ result = executor.execute(
154
+ contract=contract,
155
+ arguments={"invoice_id": "INV-1042"},
156
+ handler=capture_payment,
157
+ )
158
+
159
+ if result.status is EffectStatus.CONFIRMED:
160
+ print("Payment capture is confirmed.")
161
+ elif result.status is EffectStatus.OUTCOME_UNKNOWN:
162
+ print("The operation still needs reconciliation.")
163
+ elif result.status is EffectStatus.QUARANTINED:
164
+ print("Automatic execution is blocked until the outcome is resolved.")
165
+ ~~~
166
+
167
+ The example's provider functions are integration points, not a bundled payment SDK. The exact behavior depends on the external provider's documented idempotency and query semantics.
168
+
169
+ ### Two identities matter
170
+
171
+ - **Operation ID** identifies the logical business operation across retries and recovery.
172
+ - **Provider idempotency key** is forwarded to a destination that documents support for idempotency.
173
+
174
+ Do not generate a new key on every retry. Do not reuse one operation ID for different business actions. The request fingerprint also prevents accidental reuse of an operation ID with changed arguments.
175
+
176
+ ## Effect contracts and recovery
177
+
178
+ Every operation is tracked by an explicit state. A handler timeout does not mean the external effect failed.
179
+
180
+ ~~~text
181
+ PREPARED
182
+ |
183
+ v
184
+ DISPATCHED --------------------+
185
+ | |
186
+ | handler returns | timeout, crash, lost response
187
+ v v
188
+ CONFIRMED OUTCOME_UNKNOWN
189
+ |
190
+ v
191
+ RECONCILING
192
+ / | \
193
+ v v v
194
+ CONFIRMED PREPARED QUARANTINED
195
+ (retry) or UNKNOWN
196
+ ~~~
197
+
198
+ ### Contract fields
199
+
200
+ | Field | Purpose |
201
+ | --- | --- |
202
+ | **name** | Stable name for the contract. Changing its semantics should use a new name or versioned name. |
203
+ | **operation_id** | Function mapping business arguments to a stable operation ID. |
204
+ | **provider_idempotency_key** | Optional function deriving the same destination key for every attempt. |
205
+ | **provider_idempotency_guaranteed** | Explicit assertion that the provider's documented key semantics make repeated sends safe. Defaults to false. |
206
+ | **outcome_probe** | Optional function returning COMMITTED, NOT_COMMITTED, PENDING, or UNKNOWN. |
207
+ | **postcondition** | Optional predicate that must hold for a result to be considered confirmed. |
208
+ | **unknown_outcome** | QUARANTINE by default, or KEEP_UNKNOWN when the caller manages quarantine elsewhere. |
209
+
210
+ A probe should return:
211
+
212
+ - **COMMITTED** only with evidence that the effect committed.
213
+ - **NOT_COMMITTED** only with authoritative terminal evidence that the earlier request cannot commit later.
214
+ - **PENDING** when the provider says the operation is still processing or the result is not final.
215
+ - **UNKNOWN** when available evidence cannot settle the outcome.
216
+
217
+ An empty lookup is not necessarily proof of non-execution. A provider may process a request asynchronously or expose an eventually consistent read path. If the probe cannot establish the outcome, the executor preserves uncertainty by default. It may dispatch a retry with the same provider key only when the caller explicitly asserts the provider's documented idempotency guarantee; that assertion must be grounded in the provider's actual contract, not merely in the presence of a key parameter.
218
+
219
+ ### Definitive rejections
220
+
221
+ A handler can raise **EffectRejected** only when it has reliable evidence that the provider rejected the operation without applying the effect. Do not raise it for timeouts, connection resets, or generic server errors where the commit state may be unknown.
222
+
223
+ ### What happens on recovery?
224
+
225
+ - **Confirmed operation:** return the recorded result for the same operation and request.
226
+ - **Active dispatch lease:** report that another worker is still handling the operation; do not start a competing dispatch.
227
+ - **Confirmed non-execution:** make the operation eligible for retry only when the probe's contract makes that result terminal.
228
+ - **Unknown outcome:** run the configured probe, use the provider's documented idempotency behavior, or quarantine.
229
+ - **Conflicting operation ID:** raise OperationConflictError before another external dispatch.
230
+ - **Result that cannot be stored as JSON:** preserve an unknown outcome rather than claiming a durable replay result that was not stored.
231
+
232
+ Operations can be inspected with **SQLiteEffectLedger.list_operations(status=EffectStatus.QUARANTINED)**; transitions are available through **SQLiteEffectLedger.events(operation_id)**. The separate `agent-effect-ops` CLI can list operation summaries, inspect event history, and record auditable manual confirmation, rejection, or retry authorization. These operations require an actor, reason, and evidence reference, but the CLI does not authenticate the actor; restrict access to the ledger and enforce operator authorization at the environment boundary. See [Effect Contracts and Recovery](docs/effect-contracts.md).
233
+
234
+ ## Fault-injection testkit
235
+
236
+ The demo runs a fake payment provider and asserts on the count of committed effects—not only on the agent's reported status.
237
+
238
+ ~~~bash
239
+ # Provider commits, but the acknowledgement is lost.
240
+ agent-effect --scenario after-commit-before-ack
241
+
242
+ # The request fails before the provider commits, so a safe retry is possible.
243
+ agent-effect --scenario before-commit
244
+
245
+ # Save the JSON report as a CI artifact.
246
+ agent-effect --scenario after-commit-before-ack --output artifacts/effect-report.json
247
+ ~~~
248
+
249
+ Inspect an existing ledger and its quarantined operations:
250
+
251
+ ~~~bash
252
+ agent-effect-ops --db agent-effects.sqlite3 list --status quarantined
253
+ agent-effect-ops --db agent-effects.sqlite3 events invoice:INV-1042:capture
254
+ ~~~
255
+
256
+ After independently verifying the provider outcome, record a manual resolution with an auditable operator identity and evidence reference:
257
+
258
+ ~~~bash
259
+ agent-effect-ops --db agent-effects.sqlite3 confirm invoice:INV-1042:capture \
260
+ --output-json '{"payment_id":"pay-123","status":"captured"}' \
261
+ --provider-operation-id pay-123 \
262
+ --actor on-call-operator \
263
+ --reason "Verified provider capture record" \
264
+ --evidence-reference INC-1042/provider-event-123
265
+
266
+ # Only after establishing terminal non-execution:
267
+ agent-effect-ops --db agent-effects.sqlite3 authorize-retry invoice:INV-1042:capture \
268
+ --actor on-call-operator \
269
+ --reason "Provider confirms request cannot still commit" \
270
+ --evidence-reference INC-1042/provider-terminal-query
271
+ ~~~
272
+
273
+ The JSON report includes the scenario, operation ID, final status, attempt count, committed-effect count, duplicate detection, and event types. The built-in fake provider is deterministic and does not call a real payment service. For a complete example using `AgentRuntime`, a contracted `ToolDefinition`, the SQLite ledger, and lost-ack reconciliation, run `python examples/effect_assurance_demo.py`. The example exits with an error if the runtime does not complete with exactly one committed fake payment.
274
+
275
+ The test suite covers:
276
+
277
+ | Scenario | Expected behavior |
278
+ | --- | --- |
279
+ | Destination commits, acknowledgement is dropped | Probe finds the committed effect; the library confirms it without another dispatch. |
280
+ | Failure before commit | An authoritative negative probe allows one retry; one effect is committed. |
281
+ | Timeout without probe or idempotency guarantee | The operation is quarantined and the handler is not automatically run again. |
282
+ | Same operation ID, different arguments | The request fingerprint conflict is rejected. |
283
+ | Repeated invocation after confirmation | The stored result is replayed after reopening the SQLite ledger. |
284
+ | Provider reports pending | The operation remains unknown and is not retried blindly. |
285
+
286
+ This initial testkit exercises local contracts and a deterministic fake provider. A production-grade library should add more adapters and chaos scenarios only with the same independent effect-count assertions.
287
+
288
+ ## Persistence and concurrency
289
+
290
+ SQLiteEffectLedger stores operation records and their event history in a file-backed SQLite database. Claims and state changes use database transactions; an active dispatch receives a time-limited ownership token so immediate concurrent invocations do not both start the same operation.
291
+
292
+ SQLite is intended for local and single-host workflows. A durable SQLite database does not make an external provider transactional, and it is not a substitute for a shared coordination backend in a multi-host deployment. A PostgreSQL ledger and its cross-host concurrency contract are not included in the current implementation.
293
+
294
+ Lease expiry also does not prove that a slow handler or remote request stopped. The effect executor can bound how long it waits for a handler, but a running Python thread cannot be forcibly terminated. Provider-native network timeouts are still required. After a handler timeout or lease expiry, a negative provider probe alone does not authorize retry while the old handler may still dispatch; use provider idempotency or an evidence-backed operator resolution.
295
+
296
+ ## Security model and limits
297
+
298
+ Production Agent Systems treats model output and tool arguments as untrusted. It records business-operation identity separately from the model's reasoning and does not let model text turn an unknown outcome into a confirmed success.
299
+
300
+ The integrating application remains responsible for:
301
+
302
+ - authenticating users and authorizing access to the specific resource named by a tool;
303
+ - protecting credentials and using least-privilege provider permissions;
304
+ - collecting real human approval through a trusted channel;
305
+ - providing correct operation identities and truthful provider contracts;
306
+ - preventing sensitive customer payloads or secrets from being copied into logs or evidence.
307
+
308
+ This package is not a payment processor, an authentication service, a host/container sandbox, or a universal guarantee of exactly-once execution.
309
+
310
+ ### Guarantees and non-guarantees
311
+
312
+ Subject to the configured ledger and destination contract, the effect core provides durable operation records, request-conflict detection, recorded-result replay, conservative handling of ambiguous writes, and a reproducible way to test selected failure modes.
313
+
314
+ It cannot guarantee that every outside system changes exactly once when that system offers neither a reliable idempotency mechanism nor authoritative outcome evidence. When the state cannot be established, the correct result may be a quarantined operation requiring human or application-level reconciliation.
315
+
316
+ ## Research behind the design
317
+
318
+ These studies motivate the failure models and testing approach. They are not evidence that this library itself has achieved the same benchmark results.
319
+
320
+ 1. **Li, J. (September 2026). _Where Does Exactly-Once Live? Model, Harness, and Tool-Contract Effects on Duplicate Side Effects in LLM Agents._** [arXiv:2609.29095](https://arxiv.org/abs/2609.29095). The LIMBO study evaluates 25,930 episodes across nine models and multiple tool contracts and fault conditions. It finds that late commits and missing or weak tool contracts make verification-only strategies insufficient; stable provider idempotency keys reduced duplicates in the tested conditions.
321
+ 2. **Tan et al. (August 2026). _AgentChaos: Chaos Engineering for Agent Systems via Programmatic Fault Injection._** [arXiv:2608.06790](https://arxiv.org/abs/2608.06790). This work injects faults at the LLM API boundary and reports that pass@1 fell by up to 50 percentage points across the tested fault configurations, supporting the use of repeatable fault injection rather than happy-path-only evaluation.
322
+ 3. **Mazumder and Lia (July 2026). _AgentCheck: A Reproduce-Intervene-Mitigate Workbench for LLM Agents over MCP._** [arXiv:2607.11098](https://arxiv.org/abs/2607.11098). AgentCheck replays tool interactions with injected faults so developers can compare a mitigation under the same failure conditions before deployment.
323
+ 4. **Zhang et al. (August 2026). _When Agentic Executions Fail: Detecting and Localizing Runtime Faults from Telemetry._** [arXiv:2608.14680](https://arxiv.org/abs/2608.14680). AGENTCHAOSBENCH studies runtime-fault diagnosis from execution telemetry and shows why the final task answer alone is insufficient to determine where an execution failed.
324
+ 5. **Temporal documentation: _Error handling and idempotent Activities._** [Official guide](https://docs.temporal.io/develop/python/best-practices/error-handling). Temporal recommends idempotent activities and stable provider idempotency keys because activities can be retried after a worker fails.
325
+ 6. **LangGraph documentation: _Persistence._** [Official guide](https://docs.langchain.com/oss/python/langgraph/persistence). LangGraph checkpoints make graph state resumable; they do not independently make a separate external write atomic with the checkpoint.
326
+
327
+ Related work includes [swarmproof/exactly-once](https://github.com/swarmproof/exactly-once), a focused idempotency middleware for agent side effects, as well as workflow systems such as Temporal and stateful orchestration frameworks such as LangGraph. These tools overlap in places and should be compared by their documented guarantees, supported stores, and integration boundaries—not by the claim of “exactly once” alone.
328
+
329
+ ## Development
330
+
331
+ ~~~bash
332
+ python -m venv .venv
333
+ # Activate the environment using your platform's command.
334
+ python -m pip install -e ".[dev]"
335
+ python -m pytest -q
336
+ ruff check src tests examples
337
+ mypy src
338
+ ~~~
339
+
340
+ Run the deterministic fault scenarios without a model API key:
341
+
342
+ ~~~bash
343
+ agent-effect --scenario after-commit-before-ack
344
+ agent-effect --scenario before-commit
345
+ ~~~
346
+
347
+ The default tests must never contact production payment, messaging, or infrastructure services.
348
+
349
+ ## V1 scope and optional future extensions
350
+
351
+ **The single-host V1 scope is implemented.** It includes the standalone effect contract, versioned operation identity, file-backed SQLite ledger, effect-aware AgentRuntime integration, provider-aware recovery, operator inspection and manual-resolution CLI, deterministic fault injection, an end-to-end lost-acknowledgement example, and a subprocess crash-recovery regression test. The quality workflow passes tests, Ruff, and mypy on `main`.
352
+
353
+ The implementation deliberately makes bounded guarantees rather than claiming universal exactly-once execution. Use this version for a single-host application when its provider contract offers an appropriate idempotency guarantee or outcome probe, and treat unresolved outcomes as operational incidents requiring reconciliation.
354
+
355
+ The following are deployment-specific extensions, not prerequisites for the implemented single-host V1:
356
+
357
+ - **PostgreSQL ledger:** needed before claiming shared multi-host coordination.
358
+ - **Framework adapters:** useful when a project needs first-class integration beyond the generic `ToolDefinition` and `AgentRuntime` boundary.
359
+ - **Additional fault matrices and benchmarking:** useful for validating a particular provider integration against its own baseline.
360
+
361
+ Generic agent checkpoints, trace, and audit sinks remain in-memory reference implementations. The durable effect ledger is SQLite-only; the local operations CLI records operator-supplied identity and evidence but does not authenticate the operator. These boundaries are intentional and documented in [docs/security-boundaries.md](docs/security-boundaries.md) and [SECURITY.md](SECURITY.md).
362
+
363
+ ## License
364
+
365
+ Production Agent Systems is distributed under the [MIT License](LICENSE).