agentic-exception-sdk 1.1.3__py3-none-any.whl
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.
- agentic_exception_sdk/__init__.py +308 -0
- agentic_exception_sdk/__init__.pyi +38 -0
- agentic_exception_sdk/budget/__init__.py +14 -0
- agentic_exception_sdk/budget/__init__.pyi +5 -0
- agentic_exception_sdk/budget/models.py +48 -0
- agentic_exception_sdk/budget/models.pyi +14 -0
- agentic_exception_sdk/budget/streaming.py +144 -0
- agentic_exception_sdk/budget/streaming.pyi +27 -0
- agentic_exception_sdk/budget/watchdog.py +285 -0
- agentic_exception_sdk/budget/watchdog.pyi +24 -0
- agentic_exception_sdk/bundle.py +102 -0
- agentic_exception_sdk/bundle.pyi +37 -0
- agentic_exception_sdk/config/__init__.py +10 -0
- agentic_exception_sdk/config/__init__.pyi +3 -0
- agentic_exception_sdk/config/validate.py +74 -0
- agentic_exception_sdk/config/validate.pyi +11 -0
- agentic_exception_sdk/escalation/__init__.py +22 -0
- agentic_exception_sdk/escalation/__init__.pyi +5 -0
- agentic_exception_sdk/escalation/checkpoint.py +116 -0
- agentic_exception_sdk/escalation/checkpoint.pyi +13 -0
- agentic_exception_sdk/escalation/handlers.py +27 -0
- agentic_exception_sdk/escalation/handlers.pyi +7 -0
- agentic_exception_sdk/escalation/router.py +137 -0
- agentic_exception_sdk/escalation/router.pyi +22 -0
- agentic_exception_sdk/multi_agent/__init__.py +32 -0
- agentic_exception_sdk/multi_agent/__init__.pyi +6 -0
- agentic_exception_sdk/multi_agent/consensus.py +139 -0
- agentic_exception_sdk/multi_agent/consensus.pyi +18 -0
- agentic_exception_sdk/multi_agent/parallel.py +204 -0
- agentic_exception_sdk/multi_agent/parallel.pyi +35 -0
- agentic_exception_sdk/multi_agent/router.py +131 -0
- agentic_exception_sdk/multi_agent/router.pyi +14 -0
- agentic_exception_sdk/multi_agent/sla.py +63 -0
- agentic_exception_sdk/multi_agent/sla.pyi +10 -0
- agentic_exception_sdk/noop.py +27 -0
- agentic_exception_sdk/noop.pyi +5 -0
- agentic_exception_sdk/observability/__init__.py +24 -0
- agentic_exception_sdk/observability/__init__.pyi +6 -0
- agentic_exception_sdk/observability/metrics.py +189 -0
- agentic_exception_sdk/observability/metrics.pyi +36 -0
- agentic_exception_sdk/observability/otel.py +211 -0
- agentic_exception_sdk/observability/otel.pyi +9 -0
- agentic_exception_sdk/observability/sink.py +68 -0
- agentic_exception_sdk/observability/sink.pyi +12 -0
- agentic_exception_sdk/observability/structured_log.py +110 -0
- agentic_exception_sdk/observability/structured_log.pyi +8 -0
- agentic_exception_sdk/persistence/__init__.py +27 -0
- agentic_exception_sdk/persistence/__init__.pyi +35 -0
- agentic_exception_sdk/persistence/attestation.py +36 -0
- agentic_exception_sdk/persistence/attestation.pyi +8 -0
- agentic_exception_sdk/persistence/availability.py +14 -0
- agentic_exception_sdk/persistence/availability.pyi +7 -0
- agentic_exception_sdk/persistence/null_provider.py +71 -0
- agentic_exception_sdk/persistence/null_provider.pyi +19 -0
- agentic_exception_sdk/persistence/provider.py +70 -0
- agentic_exception_sdk/persistence/provider.pyi +33 -0
- agentic_exception_sdk/propagation/__init__.py +39 -0
- agentic_exception_sdk/propagation/__init__.pyi +5 -0
- agentic_exception_sdk/propagation/bus.py +162 -0
- agentic_exception_sdk/propagation/bus.pyi +30 -0
- agentic_exception_sdk/propagation/dlq.py +173 -0
- agentic_exception_sdk/propagation/dlq.pyi +28 -0
- agentic_exception_sdk/propagation/protocol.py +129 -0
- agentic_exception_sdk/propagation/protocol.pyi +10 -0
- agentic_exception_sdk/py.typed +0 -0
- agentic_exception_sdk/resilience/__init__.py +59 -0
- agentic_exception_sdk/resilience/__init__.pyi +7 -0
- agentic_exception_sdk/resilience/circuit_breaker.py +650 -0
- agentic_exception_sdk/resilience/circuit_breaker.pyi +58 -0
- agentic_exception_sdk/resilience/compensating.py +97 -0
- agentic_exception_sdk/resilience/compensating.pyi +9 -0
- agentic_exception_sdk/resilience/fallback.py +88 -0
- agentic_exception_sdk/resilience/fallback.pyi +16 -0
- agentic_exception_sdk/resilience/recovery.py +50 -0
- agentic_exception_sdk/resilience/recovery.pyi +11 -0
- agentic_exception_sdk/resilience/retry.py +455 -0
- agentic_exception_sdk/resilience/retry.pyi +62 -0
- agentic_exception_sdk/resilience/wrap.py +1073 -0
- agentic_exception_sdk/resilience/wrap.pyi +28 -0
- agentic_exception_sdk/taxonomy/__init__.py +56 -0
- agentic_exception_sdk/taxonomy/__init__.pyi +7 -0
- agentic_exception_sdk/taxonomy/classifier.py +216 -0
- agentic_exception_sdk/taxonomy/classifier.pyi +8 -0
- agentic_exception_sdk/taxonomy/enums.py +77 -0
- agentic_exception_sdk/taxonomy/enums.pyi +22 -0
- agentic_exception_sdk/taxonomy/envelope.py +223 -0
- agentic_exception_sdk/taxonomy/envelope.pyi +29 -0
- agentic_exception_sdk/taxonomy/errors.py +173 -0
- agentic_exception_sdk/taxonomy/errors.pyi +34 -0
- agentic_exception_sdk/taxonomy/owasp.py +55 -0
- agentic_exception_sdk/taxonomy/owasp.pyi +19 -0
- agentic_exception_sdk/validation/__init__.py +27 -0
- agentic_exception_sdk/validation/__init__.pyi +6 -0
- agentic_exception_sdk/validation/gates.py +93 -0
- agentic_exception_sdk/validation/gates.pyi +16 -0
- agentic_exception_sdk/validation/guard_rails.py +114 -0
- agentic_exception_sdk/validation/guard_rails.pyi +18 -0
- agentic_exception_sdk/validation/rules_version.py +5 -0
- agentic_exception_sdk/validation/rules_version.pyi +3 -0
- agentic_exception_sdk/validation/trust_boundary.py +420 -0
- agentic_exception_sdk/validation/trust_boundary.pyi +18 -0
- agentic_exception_sdk-1.1.3.dist-info/METADATA +291 -0
- agentic_exception_sdk-1.1.3.dist-info/RECORD +106 -0
- agentic_exception_sdk-1.1.3.dist-info/WHEEL +5 -0
- agentic_exception_sdk-1.1.3.dist-info/licenses/LICENSE +21 -0
- agentic_exception_sdk-1.1.3.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
"""Agentic Exception Management SDK.
|
|
2
|
+
|
|
3
|
+
A protocol-first, zero-host-import SDK for structured exception handling,
|
|
4
|
+
classification, retry, circuit breaking, propagation, and observability in
|
|
5
|
+
agentic AI systems.
|
|
6
|
+
|
|
7
|
+
Quick start:
|
|
8
|
+
|
|
9
|
+
from agentic_exception_sdk import (
|
|
10
|
+
NoOpResilienceBundle,
|
|
11
|
+
ResilienceBundle,
|
|
12
|
+
async_resilient,
|
|
13
|
+
resilient,
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
bundle = NoOpResilienceBundle()
|
|
17
|
+
|
|
18
|
+
@resilient(bundle, tool_name="search_flights", agent_id="travel-agent")
|
|
19
|
+
def search_flights(query: str) -> list[dict]:
|
|
20
|
+
...
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
from __future__ import annotations
|
|
24
|
+
|
|
25
|
+
from importlib.metadata import version as _metadata_version
|
|
26
|
+
|
|
27
|
+
__version__ = _metadata_version("agentic-exception-sdk")
|
|
28
|
+
|
|
29
|
+
# Budget
|
|
30
|
+
from agentic_exception_sdk.budget.models import AgentBudget, UnlimitedBudget
|
|
31
|
+
from agentic_exception_sdk.budget.watchdog import BudgetWatchdog
|
|
32
|
+
|
|
33
|
+
# Bundle and factory
|
|
34
|
+
from agentic_exception_sdk.bundle import ResilienceBundle
|
|
35
|
+
from agentic_exception_sdk.config.validate import BundleValidationError, validate_bundle
|
|
36
|
+
|
|
37
|
+
# Escalation
|
|
38
|
+
from agentic_exception_sdk.escalation.checkpoint import (
|
|
39
|
+
CheckpointStore,
|
|
40
|
+
InMemoryCheckpointStore,
|
|
41
|
+
)
|
|
42
|
+
from agentic_exception_sdk.escalation.handlers import NoOpHandler
|
|
43
|
+
from agentic_exception_sdk.escalation.router import (
|
|
44
|
+
EscalationHandlerLike,
|
|
45
|
+
EscalationRouter,
|
|
46
|
+
NoOpEscalationRouter,
|
|
47
|
+
RecoveryDirective,
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
# Multi-agent
|
|
51
|
+
from agentic_exception_sdk.multi_agent.consensus import (
|
|
52
|
+
ConsensusGate,
|
|
53
|
+
ConsensusNotReachedError,
|
|
54
|
+
)
|
|
55
|
+
from agentic_exception_sdk.multi_agent.parallel import (
|
|
56
|
+
AgentOutcome,
|
|
57
|
+
FanOutOutcomeEnvelope,
|
|
58
|
+
call_parallel,
|
|
59
|
+
)
|
|
60
|
+
from agentic_exception_sdk.multi_agent.router import (
|
|
61
|
+
OrchestratorExceptionRouter,
|
|
62
|
+
WorkerHandler,
|
|
63
|
+
fan_out,
|
|
64
|
+
)
|
|
65
|
+
from agentic_exception_sdk.multi_agent.sla import AgentSLAPolicy
|
|
66
|
+
from agentic_exception_sdk.noop import NoOpResilienceBundle
|
|
67
|
+
from agentic_exception_sdk.observability.metrics import (
|
|
68
|
+
InMemoryMetricsCollector,
|
|
69
|
+
MetricsCollector,
|
|
70
|
+
NoOpMetricsCollector,
|
|
71
|
+
PrometheusMetricsCollector,
|
|
72
|
+
)
|
|
73
|
+
from agentic_exception_sdk.observability.otel import OTelExceptionAdapter
|
|
74
|
+
|
|
75
|
+
# Observability
|
|
76
|
+
from agentic_exception_sdk.observability.sink import ExceptionEventSink, NoOpSink
|
|
77
|
+
from agentic_exception_sdk.observability.structured_log import StructuredLogEmitter
|
|
78
|
+
from agentic_exception_sdk.persistence import (
|
|
79
|
+
AvailabilityMode,
|
|
80
|
+
Checkpoint,
|
|
81
|
+
NullProvider,
|
|
82
|
+
PersistedEnvelope,
|
|
83
|
+
PersistenceProvider,
|
|
84
|
+
ProviderCapabilities,
|
|
85
|
+
attestation,
|
|
86
|
+
get_active_provider,
|
|
87
|
+
set_active_provider,
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
# Propagation
|
|
91
|
+
from agentic_exception_sdk.propagation.bus import (
|
|
92
|
+
AsyncExceptionPropagationBus,
|
|
93
|
+
AsyncInMemoryBus,
|
|
94
|
+
ExceptionPropagationBus,
|
|
95
|
+
InMemoryBus,
|
|
96
|
+
PropagationBufferFullError,
|
|
97
|
+
)
|
|
98
|
+
from agentic_exception_sdk.propagation.dlq import (
|
|
99
|
+
AsyncInMemoryDLQ,
|
|
100
|
+
DeadLetterQueue,
|
|
101
|
+
InMemoryDLQ,
|
|
102
|
+
)
|
|
103
|
+
from agentic_exception_sdk.propagation.protocol import (
|
|
104
|
+
envelope_canonical_bytes,
|
|
105
|
+
envelope_canonical_sha256,
|
|
106
|
+
envelope_debug_repr,
|
|
107
|
+
envelope_from_json,
|
|
108
|
+
envelope_leaf_hash,
|
|
109
|
+
envelope_to_json,
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
# Resilience components
|
|
113
|
+
from agentic_exception_sdk.resilience.circuit_breaker import (
|
|
114
|
+
AsyncInMemoryCircuitBreaker,
|
|
115
|
+
CircuitState,
|
|
116
|
+
InMemoryCircuitBreaker,
|
|
117
|
+
NoOpAsyncCircuitBreaker,
|
|
118
|
+
NoOpCircuitBreaker,
|
|
119
|
+
)
|
|
120
|
+
from agentic_exception_sdk.resilience.compensating import (
|
|
121
|
+
CompensatingTransactionRegistry,
|
|
122
|
+
)
|
|
123
|
+
from agentic_exception_sdk.resilience.fallback import (
|
|
124
|
+
FallbackChain,
|
|
125
|
+
NoOpFallback,
|
|
126
|
+
OrderedFallbackChain,
|
|
127
|
+
)
|
|
128
|
+
from agentic_exception_sdk.resilience.retry import (
|
|
129
|
+
ExponentialBackoffRetry,
|
|
130
|
+
InMemoryRetryInFlightTracker,
|
|
131
|
+
NoOpRetry,
|
|
132
|
+
RetryContext,
|
|
133
|
+
RetryInFlightEntry,
|
|
134
|
+
RetryInFlightTracker,
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
# Primary resilience entry points
|
|
138
|
+
from agentic_exception_sdk.resilience.wrap import (
|
|
139
|
+
MISSING,
|
|
140
|
+
ResilientCallConfig,
|
|
141
|
+
async_resilient,
|
|
142
|
+
extend_lineage,
|
|
143
|
+
force_flush_exception_telemetry,
|
|
144
|
+
resilient,
|
|
145
|
+
)
|
|
146
|
+
from agentic_exception_sdk.taxonomy.classifier import ExceptionClassifier
|
|
147
|
+
|
|
148
|
+
# Core taxonomy — enums, errors, envelope, classifier
|
|
149
|
+
from agentic_exception_sdk.taxonomy.enums import (
|
|
150
|
+
AgentExceptionClass,
|
|
151
|
+
EscalationLevel,
|
|
152
|
+
ExceptionSource,
|
|
153
|
+
)
|
|
154
|
+
from agentic_exception_sdk.taxonomy.envelope import (
|
|
155
|
+
AgentExceptionEnvelope,
|
|
156
|
+
SafeContextSnapshot,
|
|
157
|
+
SafeContextValue,
|
|
158
|
+
)
|
|
159
|
+
from agentic_exception_sdk.taxonomy.errors import (
|
|
160
|
+
AgentHardKillError,
|
|
161
|
+
BudgetExhaustedError,
|
|
162
|
+
BudgetWarningError,
|
|
163
|
+
CircuitBreakerStateUnavailableError,
|
|
164
|
+
CompensationPartialFailureError,
|
|
165
|
+
FallbackCapableError,
|
|
166
|
+
GuardRailViolationError,
|
|
167
|
+
PromptInjectionError,
|
|
168
|
+
SecurityViolationError,
|
|
169
|
+
SLAViolationError,
|
|
170
|
+
StateCorruptionError,
|
|
171
|
+
ToolKindMismatchError,
|
|
172
|
+
ValidationGateError,
|
|
173
|
+
)
|
|
174
|
+
|
|
175
|
+
# Validation
|
|
176
|
+
from agentic_exception_sdk.validation.gates import (
|
|
177
|
+
NoOpGate,
|
|
178
|
+
OutputValidationGate,
|
|
179
|
+
PydanticValidationGate,
|
|
180
|
+
)
|
|
181
|
+
from agentic_exception_sdk.validation.guard_rails import (
|
|
182
|
+
AllowlistedOperations,
|
|
183
|
+
GuardRailPolicy,
|
|
184
|
+
NoOpGuardRails,
|
|
185
|
+
)
|
|
186
|
+
from agentic_exception_sdk.validation.rules_version import RULES_VERSION
|
|
187
|
+
from agentic_exception_sdk.validation.trust_boundary import TrustBoundaryValidator
|
|
188
|
+
|
|
189
|
+
__all__ = [
|
|
190
|
+
"__version__",
|
|
191
|
+
# Taxonomy
|
|
192
|
+
"AgentExceptionClass",
|
|
193
|
+
"AgentExceptionEnvelope",
|
|
194
|
+
"AgentHardKillError",
|
|
195
|
+
"BudgetExhaustedError",
|
|
196
|
+
"BudgetWarningError",
|
|
197
|
+
"CircuitBreakerStateUnavailableError",
|
|
198
|
+
"CompensationPartialFailureError",
|
|
199
|
+
"EscalationLevel",
|
|
200
|
+
"ExceptionClassifier",
|
|
201
|
+
"ExceptionSource",
|
|
202
|
+
"FallbackCapableError",
|
|
203
|
+
"GuardRailViolationError",
|
|
204
|
+
"PromptInjectionError",
|
|
205
|
+
"SafeContextSnapshot",
|
|
206
|
+
"SafeContextValue",
|
|
207
|
+
"SecurityViolationError",
|
|
208
|
+
"SLAViolationError",
|
|
209
|
+
"StateCorruptionError",
|
|
210
|
+
"ToolKindMismatchError",
|
|
211
|
+
"ValidationGateError",
|
|
212
|
+
# Bundle
|
|
213
|
+
"BundleValidationError",
|
|
214
|
+
"NoOpResilienceBundle",
|
|
215
|
+
"ResilienceBundle",
|
|
216
|
+
"validate_bundle",
|
|
217
|
+
# Resilience wrappers
|
|
218
|
+
"MISSING",
|
|
219
|
+
"ResilientCallConfig",
|
|
220
|
+
"async_resilient",
|
|
221
|
+
"extend_lineage",
|
|
222
|
+
"force_flush_exception_telemetry",
|
|
223
|
+
"resilient",
|
|
224
|
+
# Circuit breakers
|
|
225
|
+
"AsyncInMemoryCircuitBreaker",
|
|
226
|
+
"CircuitState",
|
|
227
|
+
"InMemoryCircuitBreaker",
|
|
228
|
+
"NoOpAsyncCircuitBreaker",
|
|
229
|
+
"NoOpCircuitBreaker",
|
|
230
|
+
# Retry
|
|
231
|
+
"ExponentialBackoffRetry",
|
|
232
|
+
"InMemoryRetryInFlightTracker",
|
|
233
|
+
"NoOpRetry",
|
|
234
|
+
"RetryContext",
|
|
235
|
+
"RetryInFlightEntry",
|
|
236
|
+
"RetryInFlightTracker",
|
|
237
|
+
# Fallback
|
|
238
|
+
"FallbackChain",
|
|
239
|
+
"NoOpFallback",
|
|
240
|
+
"OrderedFallbackChain",
|
|
241
|
+
# Compensating transactions
|
|
242
|
+
"CompensatingTransactionRegistry",
|
|
243
|
+
# Validation
|
|
244
|
+
"AllowlistedOperations",
|
|
245
|
+
"GuardRailPolicy",
|
|
246
|
+
"NoOpGate",
|
|
247
|
+
"NoOpGuardRails",
|
|
248
|
+
"OutputValidationGate",
|
|
249
|
+
"PydanticValidationGate",
|
|
250
|
+
"RULES_VERSION",
|
|
251
|
+
"TrustBoundaryValidator",
|
|
252
|
+
# Budget
|
|
253
|
+
"AgentBudget",
|
|
254
|
+
"BudgetWatchdog",
|
|
255
|
+
"UnlimitedBudget",
|
|
256
|
+
# Escalation
|
|
257
|
+
"CheckpointStore",
|
|
258
|
+
"EscalationHandlerLike",
|
|
259
|
+
"EscalationRouter",
|
|
260
|
+
"InMemoryCheckpointStore",
|
|
261
|
+
"NoOpEscalationRouter",
|
|
262
|
+
"NoOpHandler",
|
|
263
|
+
"RecoveryDirective",
|
|
264
|
+
# Persistence
|
|
265
|
+
"AvailabilityMode",
|
|
266
|
+
"Checkpoint",
|
|
267
|
+
"NullProvider",
|
|
268
|
+
"PersistedEnvelope",
|
|
269
|
+
"PersistenceProvider",
|
|
270
|
+
"ProviderCapabilities",
|
|
271
|
+
"attestation",
|
|
272
|
+
"get_active_provider",
|
|
273
|
+
"set_active_provider",
|
|
274
|
+
# Propagation
|
|
275
|
+
"AsyncExceptionPropagationBus",
|
|
276
|
+
"AsyncInMemoryBus",
|
|
277
|
+
"AsyncInMemoryDLQ",
|
|
278
|
+
"DeadLetterQueue",
|
|
279
|
+
"ExceptionPropagationBus",
|
|
280
|
+
"InMemoryBus",
|
|
281
|
+
"InMemoryDLQ",
|
|
282
|
+
"PropagationBufferFullError",
|
|
283
|
+
"envelope_canonical_bytes",
|
|
284
|
+
"envelope_canonical_sha256",
|
|
285
|
+
"envelope_debug_repr",
|
|
286
|
+
"envelope_from_json",
|
|
287
|
+
"envelope_leaf_hash",
|
|
288
|
+
"envelope_to_json",
|
|
289
|
+
# Observability
|
|
290
|
+
"ExceptionEventSink",
|
|
291
|
+
"InMemoryMetricsCollector",
|
|
292
|
+
"MetricsCollector",
|
|
293
|
+
"NoOpMetricsCollector",
|
|
294
|
+
"NoOpSink",
|
|
295
|
+
"OTelExceptionAdapter",
|
|
296
|
+
"PrometheusMetricsCollector",
|
|
297
|
+
"StructuredLogEmitter",
|
|
298
|
+
# Multi-agent
|
|
299
|
+
"AgentSLAPolicy",
|
|
300
|
+
"AgentOutcome",
|
|
301
|
+
"ConsensusGate",
|
|
302
|
+
"ConsensusNotReachedError",
|
|
303
|
+
"FanOutOutcomeEnvelope",
|
|
304
|
+
"OrchestratorExceptionRouter",
|
|
305
|
+
"WorkerHandler",
|
|
306
|
+
"call_parallel",
|
|
307
|
+
"fan_out",
|
|
308
|
+
]
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
from _typeshed import Incomplete
|
|
2
|
+
from agentic_exception_sdk.budget.models import AgentBudget as AgentBudget, UnlimitedBudget as UnlimitedBudget
|
|
3
|
+
from agentic_exception_sdk.budget.watchdog import BudgetWatchdog as BudgetWatchdog
|
|
4
|
+
from agentic_exception_sdk.bundle import ResilienceBundle as ResilienceBundle
|
|
5
|
+
from agentic_exception_sdk.config.validate import BundleValidationError as BundleValidationError, validate_bundle as validate_bundle
|
|
6
|
+
from agentic_exception_sdk.escalation.checkpoint import CheckpointStore as CheckpointStore, InMemoryCheckpointStore as InMemoryCheckpointStore
|
|
7
|
+
from agentic_exception_sdk.escalation.handlers import NoOpHandler as NoOpHandler
|
|
8
|
+
from agentic_exception_sdk.escalation.router import EscalationHandlerLike as EscalationHandlerLike, EscalationRouter as EscalationRouter, NoOpEscalationRouter as NoOpEscalationRouter, RecoveryDirective as RecoveryDirective
|
|
9
|
+
from agentic_exception_sdk.multi_agent.consensus import ConsensusGate as ConsensusGate, ConsensusNotReachedError as ConsensusNotReachedError
|
|
10
|
+
from agentic_exception_sdk.multi_agent.parallel import AgentOutcome as AgentOutcome, FanOutOutcomeEnvelope as FanOutOutcomeEnvelope, call_parallel as call_parallel
|
|
11
|
+
from agentic_exception_sdk.multi_agent.router import OrchestratorExceptionRouter as OrchestratorExceptionRouter, WorkerHandler as WorkerHandler, fan_out as fan_out
|
|
12
|
+
from agentic_exception_sdk.multi_agent.sla import AgentSLAPolicy as AgentSLAPolicy
|
|
13
|
+
from agentic_exception_sdk.noop import NoOpResilienceBundle as NoOpResilienceBundle
|
|
14
|
+
from agentic_exception_sdk.observability.metrics import InMemoryMetricsCollector as InMemoryMetricsCollector, MetricsCollector as MetricsCollector, NoOpMetricsCollector as NoOpMetricsCollector, PrometheusMetricsCollector as PrometheusMetricsCollector
|
|
15
|
+
from agentic_exception_sdk.observability.otel import OTelExceptionAdapter as OTelExceptionAdapter
|
|
16
|
+
from agentic_exception_sdk.observability.sink import ExceptionEventSink as ExceptionEventSink, NoOpSink as NoOpSink
|
|
17
|
+
from agentic_exception_sdk.observability.structured_log import StructuredLogEmitter as StructuredLogEmitter
|
|
18
|
+
from agentic_exception_sdk.persistence import AvailabilityMode as AvailabilityMode, Checkpoint as Checkpoint, NullProvider as NullProvider, PersistedEnvelope as PersistedEnvelope, PersistenceProvider as PersistenceProvider, ProviderCapabilities as ProviderCapabilities, attestation as attestation, get_active_provider as get_active_provider, set_active_provider as set_active_provider
|
|
19
|
+
from agentic_exception_sdk.propagation.bus import AsyncExceptionPropagationBus as AsyncExceptionPropagationBus, AsyncInMemoryBus as AsyncInMemoryBus, ExceptionPropagationBus as ExceptionPropagationBus, InMemoryBus as InMemoryBus, PropagationBufferFullError as PropagationBufferFullError
|
|
20
|
+
from agentic_exception_sdk.propagation.dlq import AsyncInMemoryDLQ as AsyncInMemoryDLQ, DeadLetterQueue as DeadLetterQueue, InMemoryDLQ as InMemoryDLQ
|
|
21
|
+
from agentic_exception_sdk.propagation.protocol import envelope_canonical_bytes as envelope_canonical_bytes, envelope_canonical_sha256 as envelope_canonical_sha256, envelope_debug_repr as envelope_debug_repr, envelope_from_json as envelope_from_json, envelope_leaf_hash as envelope_leaf_hash, envelope_to_json as envelope_to_json
|
|
22
|
+
from agentic_exception_sdk.resilience.circuit_breaker import AsyncInMemoryCircuitBreaker as AsyncInMemoryCircuitBreaker, CircuitState as CircuitState, InMemoryCircuitBreaker as InMemoryCircuitBreaker, NoOpAsyncCircuitBreaker as NoOpAsyncCircuitBreaker, NoOpCircuitBreaker as NoOpCircuitBreaker
|
|
23
|
+
from agentic_exception_sdk.resilience.compensating import CompensatingTransactionRegistry as CompensatingTransactionRegistry
|
|
24
|
+
from agentic_exception_sdk.resilience.fallback import FallbackChain as FallbackChain, NoOpFallback as NoOpFallback, OrderedFallbackChain as OrderedFallbackChain
|
|
25
|
+
from agentic_exception_sdk.resilience.retry import ExponentialBackoffRetry as ExponentialBackoffRetry, InMemoryRetryInFlightTracker as InMemoryRetryInFlightTracker, NoOpRetry as NoOpRetry, RetryContext as RetryContext, RetryInFlightEntry as RetryInFlightEntry, RetryInFlightTracker as RetryInFlightTracker
|
|
26
|
+
from agentic_exception_sdk.resilience.wrap import MISSING as MISSING, ResilientCallConfig as ResilientCallConfig, async_resilient as async_resilient, extend_lineage as extend_lineage, force_flush_exception_telemetry as force_flush_exception_telemetry, resilient as resilient
|
|
27
|
+
from agentic_exception_sdk.taxonomy.classifier import ExceptionClassifier as ExceptionClassifier
|
|
28
|
+
from agentic_exception_sdk.taxonomy.enums import AgentExceptionClass as AgentExceptionClass, EscalationLevel as EscalationLevel, ExceptionSource as ExceptionSource
|
|
29
|
+
from agentic_exception_sdk.taxonomy.envelope import AgentExceptionEnvelope as AgentExceptionEnvelope, SafeContextSnapshot as SafeContextSnapshot, SafeContextValue as SafeContextValue
|
|
30
|
+
from agentic_exception_sdk.taxonomy.errors import AgentHardKillError as AgentHardKillError, BudgetExhaustedError as BudgetExhaustedError, BudgetWarningError as BudgetWarningError, CircuitBreakerStateUnavailableError as CircuitBreakerStateUnavailableError, CompensationPartialFailureError as CompensationPartialFailureError, FallbackCapableError as FallbackCapableError, GuardRailViolationError as GuardRailViolationError, PromptInjectionError as PromptInjectionError, SLAViolationError as SLAViolationError, SecurityViolationError as SecurityViolationError, StateCorruptionError as StateCorruptionError, ToolKindMismatchError as ToolKindMismatchError, ValidationGateError as ValidationGateError
|
|
31
|
+
from agentic_exception_sdk.validation.gates import NoOpGate as NoOpGate, OutputValidationGate as OutputValidationGate, PydanticValidationGate as PydanticValidationGate
|
|
32
|
+
from agentic_exception_sdk.validation.guard_rails import AllowlistedOperations as AllowlistedOperations, GuardRailPolicy as GuardRailPolicy, NoOpGuardRails as NoOpGuardRails
|
|
33
|
+
from agentic_exception_sdk.validation.rules_version import RULES_VERSION as RULES_VERSION
|
|
34
|
+
from agentic_exception_sdk.validation.trust_boundary import TrustBoundaryValidator as TrustBoundaryValidator
|
|
35
|
+
|
|
36
|
+
__all__ = ['__version__', 'AgentExceptionClass', 'AgentExceptionEnvelope', 'AgentHardKillError', 'BudgetExhaustedError', 'BudgetWarningError', 'CircuitBreakerStateUnavailableError', 'CompensationPartialFailureError', 'EscalationLevel', 'ExceptionClassifier', 'ExceptionSource', 'FallbackCapableError', 'GuardRailViolationError', 'PromptInjectionError', 'SafeContextSnapshot', 'SafeContextValue', 'SecurityViolationError', 'SLAViolationError', 'StateCorruptionError', 'ToolKindMismatchError', 'ValidationGateError', 'BundleValidationError', 'NoOpResilienceBundle', 'ResilienceBundle', 'validate_bundle', 'MISSING', 'ResilientCallConfig', 'async_resilient', 'extend_lineage', 'force_flush_exception_telemetry', 'resilient', 'AsyncInMemoryCircuitBreaker', 'CircuitState', 'InMemoryCircuitBreaker', 'NoOpAsyncCircuitBreaker', 'NoOpCircuitBreaker', 'ExponentialBackoffRetry', 'InMemoryRetryInFlightTracker', 'NoOpRetry', 'RetryContext', 'RetryInFlightEntry', 'RetryInFlightTracker', 'FallbackChain', 'NoOpFallback', 'OrderedFallbackChain', 'CompensatingTransactionRegistry', 'AllowlistedOperations', 'GuardRailPolicy', 'NoOpGate', 'NoOpGuardRails', 'OutputValidationGate', 'PydanticValidationGate', 'RULES_VERSION', 'TrustBoundaryValidator', 'AgentBudget', 'BudgetWatchdog', 'UnlimitedBudget', 'CheckpointStore', 'EscalationHandlerLike', 'EscalationRouter', 'InMemoryCheckpointStore', 'NoOpEscalationRouter', 'NoOpHandler', 'RecoveryDirective', 'AvailabilityMode', 'Checkpoint', 'NullProvider', 'PersistedEnvelope', 'PersistenceProvider', 'ProviderCapabilities', 'attestation', 'get_active_provider', 'set_active_provider', 'AsyncExceptionPropagationBus', 'AsyncInMemoryBus', 'AsyncInMemoryDLQ', 'DeadLetterQueue', 'ExceptionPropagationBus', 'InMemoryBus', 'InMemoryDLQ', 'PropagationBufferFullError', 'envelope_canonical_bytes', 'envelope_canonical_sha256', 'envelope_debug_repr', 'envelope_from_json', 'envelope_leaf_hash', 'envelope_to_json', 'ExceptionEventSink', 'InMemoryMetricsCollector', 'MetricsCollector', 'NoOpMetricsCollector', 'NoOpSink', 'OTelExceptionAdapter', 'PrometheusMetricsCollector', 'StructuredLogEmitter', 'AgentSLAPolicy', 'AgentOutcome', 'ConsensusGate', 'ConsensusNotReachedError', 'FanOutOutcomeEnvelope', 'OrchestratorExceptionRouter', 'WorkerHandler', 'call_parallel', 'fan_out']
|
|
37
|
+
|
|
38
|
+
__version__: Incomplete
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"""Budget: agent resource models and watchdog enforcement."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from agentic_exception_sdk.budget.models import AgentBudget, UnlimitedBudget
|
|
6
|
+
from agentic_exception_sdk.budget.streaming import StreamingBudgetGuard
|
|
7
|
+
from agentic_exception_sdk.budget.watchdog import BudgetWatchdog
|
|
8
|
+
|
|
9
|
+
__all__ = [
|
|
10
|
+
"AgentBudget",
|
|
11
|
+
"BudgetWatchdog",
|
|
12
|
+
"StreamingBudgetGuard",
|
|
13
|
+
"UnlimitedBudget",
|
|
14
|
+
]
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
from agentic_exception_sdk.budget.models import AgentBudget as AgentBudget, UnlimitedBudget as UnlimitedBudget
|
|
2
|
+
from agentic_exception_sdk.budget.streaming import StreamingBudgetGuard as StreamingBudgetGuard
|
|
3
|
+
from agentic_exception_sdk.budget.watchdog import BudgetWatchdog as BudgetWatchdog
|
|
4
|
+
|
|
5
|
+
__all__ = ['AgentBudget', 'BudgetWatchdog', 'StreamingBudgetGuard', 'UnlimitedBudget']
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"""Agent budget data models.
|
|
2
|
+
|
|
3
|
+
Monetary ceilings use integer micro-USD (1 USD == 1_000_000 micro-USD).
|
|
4
|
+
Binary floating point is never used for monetary values.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
from dataclasses import dataclass
|
|
10
|
+
|
|
11
|
+
__all__ = ["AgentBudget", "UnlimitedBudget"]
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@dataclass(frozen=True)
|
|
15
|
+
class AgentBudget:
|
|
16
|
+
"""Resource ceiling configuration for an agent run.
|
|
17
|
+
|
|
18
|
+
All fields are optional. When None, that ceiling is not enforced.
|
|
19
|
+
Non-LLM workloads can ignore token/cost fields entirely; LLM-facing
|
|
20
|
+
systems should set all relevant ceilings.
|
|
21
|
+
|
|
22
|
+
Monetary ceilings use integer micro-USD where $1.00 == 1_000_000.
|
|
23
|
+
Never use binary floating point for monetary ceilings.
|
|
24
|
+
|
|
25
|
+
Attributes:
|
|
26
|
+
max_seconds: Wall-clock time limit in seconds for the entire agent run.
|
|
27
|
+
max_tool_calls: Maximum total tool call invocations allowed.
|
|
28
|
+
failure_budget: Maximum number of failed tool call attempts before escalation.
|
|
29
|
+
max_input_tokens: Maximum input tokens consumed across all LLM calls.
|
|
30
|
+
max_output_tokens: Maximum output tokens generated across all LLM calls.
|
|
31
|
+
max_total_cost_micros_usd: Maximum total cost in integer micro-USD.
|
|
32
|
+
"""
|
|
33
|
+
|
|
34
|
+
max_seconds: float | None = None
|
|
35
|
+
max_tool_calls: int | None = None
|
|
36
|
+
failure_budget: int | None = None
|
|
37
|
+
max_input_tokens: int | None = None
|
|
38
|
+
max_output_tokens: int | None = None
|
|
39
|
+
max_total_cost_micros_usd: int | None = None
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def UnlimitedBudget() -> AgentBudget:
|
|
43
|
+
"""Return an AgentBudget with no enforced limits.
|
|
44
|
+
|
|
45
|
+
Returns:
|
|
46
|
+
An AgentBudget where all ceiling fields are None.
|
|
47
|
+
"""
|
|
48
|
+
return AgentBudget()
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
|
|
3
|
+
__all__ = ['AgentBudget', 'UnlimitedBudget']
|
|
4
|
+
|
|
5
|
+
@dataclass(frozen=True)
|
|
6
|
+
class AgentBudget:
|
|
7
|
+
max_seconds: float | None = ...
|
|
8
|
+
max_tool_calls: int | None = ...
|
|
9
|
+
failure_budget: int | None = ...
|
|
10
|
+
max_input_tokens: int | None = ...
|
|
11
|
+
max_output_tokens: int | None = ...
|
|
12
|
+
max_total_cost_micros_usd: int | None = ...
|
|
13
|
+
|
|
14
|
+
def UnlimitedBudget() -> AgentBudget: ...
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
"""Streaming LLM budget enforcement.
|
|
2
|
+
|
|
3
|
+
Provides a context manager and async generator wrapper that checks the
|
|
4
|
+
BudgetWatchdog after each streamed chunk. When the budget ceiling is exceeded
|
|
5
|
+
mid-stream, raises BudgetExhaustedError to abort generation.
|
|
6
|
+
|
|
7
|
+
Usage (OpenAI-style streaming):
|
|
8
|
+
guard = StreamingBudgetGuard(watchdog, tool_name="llm-call", agent_id="agent-1")
|
|
9
|
+
with guard:
|
|
10
|
+
for chunk in openai_client.chat.completions.create(..., stream=True):
|
|
11
|
+
guard.record_chunk(token_delta=chunk.usage.completion_tokens or 1)
|
|
12
|
+
yield chunk.choices[0].delta.content
|
|
13
|
+
|
|
14
|
+
Usage (async):
|
|
15
|
+
async with guard:
|
|
16
|
+
async for chunk in async_stream:
|
|
17
|
+
await guard.arecord_chunk(token_delta=...)
|
|
18
|
+
yield chunk
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
from __future__ import annotations
|
|
22
|
+
|
|
23
|
+
from collections.abc import AsyncGenerator, AsyncIterable, Callable, Generator, Iterable
|
|
24
|
+
from typing import Literal, TypeVar
|
|
25
|
+
|
|
26
|
+
from agentic_exception_sdk.budget.watchdog import BudgetWatchdog
|
|
27
|
+
from agentic_exception_sdk.taxonomy.errors import BudgetExhaustedError
|
|
28
|
+
|
|
29
|
+
__all__ = ["StreamingBudgetGuard"]
|
|
30
|
+
|
|
31
|
+
T = TypeVar("T")
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class StreamingBudgetGuard:
|
|
35
|
+
"""Abort streaming LLM output when a BudgetWatchdog ceiling is exceeded."""
|
|
36
|
+
|
|
37
|
+
def __init__(
|
|
38
|
+
self,
|
|
39
|
+
watchdog: BudgetWatchdog,
|
|
40
|
+
*,
|
|
41
|
+
tool_name: str,
|
|
42
|
+
agent_id: str,
|
|
43
|
+
correlation_id: str | None = None,
|
|
44
|
+
) -> None:
|
|
45
|
+
self.watchdog = watchdog
|
|
46
|
+
self.tool_name = tool_name
|
|
47
|
+
self.agent_id = agent_id
|
|
48
|
+
self.correlation_id = correlation_id
|
|
49
|
+
self.total_tokens_streamed = 0
|
|
50
|
+
self.total_cost_streamed = 0.0
|
|
51
|
+
|
|
52
|
+
def __enter__(self) -> StreamingBudgetGuard:
|
|
53
|
+
return self
|
|
54
|
+
|
|
55
|
+
def __exit__(
|
|
56
|
+
self,
|
|
57
|
+
exc_type: type[BaseException] | None,
|
|
58
|
+
exc: BaseException | None,
|
|
59
|
+
traceback: object | None,
|
|
60
|
+
) -> Literal[False]:
|
|
61
|
+
return False
|
|
62
|
+
|
|
63
|
+
async def __aenter__(self) -> StreamingBudgetGuard:
|
|
64
|
+
return self
|
|
65
|
+
|
|
66
|
+
async def __aexit__(
|
|
67
|
+
self,
|
|
68
|
+
exc_type: type[BaseException] | None,
|
|
69
|
+
exc: BaseException | None,
|
|
70
|
+
traceback: object | None,
|
|
71
|
+
) -> Literal[False]:
|
|
72
|
+
return False
|
|
73
|
+
|
|
74
|
+
def record_chunk(self, token_delta: int = 1, cost_delta: float = 0.0) -> None:
|
|
75
|
+
"""Record one streamed chunk and raise immediately on budget exhaustion."""
|
|
76
|
+
cost_micros_usd = _cost_to_micros(cost_delta)
|
|
77
|
+
self.watchdog.account_stream_delta(
|
|
78
|
+
output_tokens=token_delta,
|
|
79
|
+
cost_micros_usd=cost_micros_usd,
|
|
80
|
+
)
|
|
81
|
+
self.total_tokens_streamed += token_delta
|
|
82
|
+
self.total_cost_streamed += cost_delta
|
|
83
|
+
|
|
84
|
+
async def arecord_chunk(self, token_delta: int = 1, cost_delta: float = 0.0) -> None:
|
|
85
|
+
"""Async record of one streamed chunk and raise on budget exhaustion."""
|
|
86
|
+
cost_micros_usd = _cost_to_micros(cost_delta)
|
|
87
|
+
await self.watchdog.async_reserve_tokens(
|
|
88
|
+
output_tokens=token_delta,
|
|
89
|
+
cost_micros_usd=cost_micros_usd,
|
|
90
|
+
)
|
|
91
|
+
self.total_tokens_streamed += token_delta
|
|
92
|
+
self.total_cost_streamed += cost_delta
|
|
93
|
+
|
|
94
|
+
@classmethod
|
|
95
|
+
def wrap_sync_stream(
|
|
96
|
+
cls,
|
|
97
|
+
stream: Iterable[T],
|
|
98
|
+
watchdog: BudgetWatchdog,
|
|
99
|
+
*,
|
|
100
|
+
tool_name: str,
|
|
101
|
+
agent_id: str,
|
|
102
|
+
token_extractor: Callable[[T], int] = lambda _: 1,
|
|
103
|
+
cost_extractor: Callable[[T], float] = lambda _: 0.0,
|
|
104
|
+
) -> Generator[T, None, None]:
|
|
105
|
+
"""Yield stream items while enforcing budget before each yield."""
|
|
106
|
+
guard = cls(watchdog, tool_name=tool_name, agent_id=agent_id)
|
|
107
|
+
with guard:
|
|
108
|
+
for chunk in stream:
|
|
109
|
+
try:
|
|
110
|
+
guard.record_chunk(
|
|
111
|
+
token_delta=token_extractor(chunk),
|
|
112
|
+
cost_delta=cost_extractor(chunk),
|
|
113
|
+
)
|
|
114
|
+
except BudgetExhaustedError:
|
|
115
|
+
raise
|
|
116
|
+
yield chunk
|
|
117
|
+
|
|
118
|
+
@classmethod
|
|
119
|
+
async def awrap_async_stream(
|
|
120
|
+
cls,
|
|
121
|
+
stream: AsyncIterable[T],
|
|
122
|
+
watchdog: BudgetWatchdog,
|
|
123
|
+
*,
|
|
124
|
+
tool_name: str,
|
|
125
|
+
agent_id: str,
|
|
126
|
+
token_extractor: Callable[[T], int] = lambda _: 1,
|
|
127
|
+
cost_extractor: Callable[[T], float] = lambda _: 0.0,
|
|
128
|
+
) -> AsyncGenerator[T, None]:
|
|
129
|
+
"""Async-yield stream items while enforcing budget before each yield."""
|
|
130
|
+
guard = cls(watchdog, tool_name=tool_name, agent_id=agent_id)
|
|
131
|
+
async with guard:
|
|
132
|
+
async for chunk in stream:
|
|
133
|
+
try:
|
|
134
|
+
await guard.arecord_chunk(
|
|
135
|
+
token_delta=token_extractor(chunk),
|
|
136
|
+
cost_delta=cost_extractor(chunk),
|
|
137
|
+
)
|
|
138
|
+
except BudgetExhaustedError:
|
|
139
|
+
raise
|
|
140
|
+
yield chunk
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
def _cost_to_micros(cost_delta: float) -> int:
|
|
144
|
+
return round(cost_delta * 1_000_000)
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
from _typeshed import Incomplete
|
|
2
|
+
from agentic_exception_sdk.budget.watchdog import BudgetWatchdog
|
|
3
|
+
from collections.abc import AsyncGenerator, AsyncIterable, Callable, Generator, Iterable
|
|
4
|
+
from typing import Literal, TypeVar
|
|
5
|
+
|
|
6
|
+
__all__ = ['StreamingBudgetGuard']
|
|
7
|
+
|
|
8
|
+
T = TypeVar('T')
|
|
9
|
+
|
|
10
|
+
class StreamingBudgetGuard:
|
|
11
|
+
watchdog: Incomplete
|
|
12
|
+
tool_name: Incomplete
|
|
13
|
+
agent_id: Incomplete
|
|
14
|
+
correlation_id: Incomplete
|
|
15
|
+
total_tokens_streamed: int
|
|
16
|
+
total_cost_streamed: float
|
|
17
|
+
def __init__(self, watchdog: BudgetWatchdog, *, tool_name: str, agent_id: str, correlation_id: str | None = None) -> None: ...
|
|
18
|
+
def __enter__(self) -> StreamingBudgetGuard: ...
|
|
19
|
+
def __exit__(self, exc_type: type[BaseException] | None, exc: BaseException | None, traceback: object | None) -> Literal[False]: ...
|
|
20
|
+
async def __aenter__(self) -> StreamingBudgetGuard: ...
|
|
21
|
+
async def __aexit__(self, exc_type: type[BaseException] | None, exc: BaseException | None, traceback: object | None) -> Literal[False]: ...
|
|
22
|
+
def record_chunk(self, token_delta: int = 1, cost_delta: float = 0.0) -> None: ...
|
|
23
|
+
async def arecord_chunk(self, token_delta: int = 1, cost_delta: float = 0.0) -> None: ...
|
|
24
|
+
@classmethod
|
|
25
|
+
def wrap_sync_stream(cls, stream: Iterable[T], watchdog: BudgetWatchdog, *, tool_name: str, agent_id: str, token_extractor: Callable[[T], int] = ..., cost_extractor: Callable[[T], float] = ...) -> Generator[T, None, None]: ...
|
|
26
|
+
@classmethod
|
|
27
|
+
async def awrap_async_stream(cls, stream: AsyncIterable[T], watchdog: BudgetWatchdog, *, tool_name: str, agent_id: str, token_extractor: Callable[[T], int] = ..., cost_extractor: Callable[[T], float] = ...) -> AsyncGenerator[T, None]: ...
|