MonadicSharp.Recovery
1.0.0
dotnet add package MonadicSharp.Recovery --version 1.0.0
NuGet\Install-Package MonadicSharp.Recovery -Version 1.0.0
<PackageReference Include="MonadicSharp.Recovery" Version="1.0.0" />
<PackageVersion Include="MonadicSharp.Recovery" Version="1.0.0" />
<PackageReference Include="MonadicSharp.Recovery" />
paket add MonadicSharp.Recovery --version 1.0.0
#r "nuget: MonadicSharp.Recovery, 1.0.0"
#:package MonadicSharp.Recovery@1.0.0
#addin nuget:?package=MonadicSharp.Recovery&version=1.0.0
#tool nuget:?package=MonadicSharp.Recovery&version=1.0.0
MonadicSharp.Recovery
Amber-track (self-healing) extension for MonadicSharp.
Adds RescueAsync and StartFixBranchAsync to your Result<T> pipelines — intercept specific failures, attempt recovery, and merge back to the success track without breaking the Railway-Oriented Programming flow.
GREEN ──── Bind → Bind → Map ─────────────────────────────► Success
│ error matches predicate
▼
AMBER ──── RescueAsync / StartFixBranchAsync ──────────────► merged → GREEN
│ all attempts fail
▼
RED ──── original error preserved ───────────────────────► Failure
Install
dotnet add package MonadicSharp.Recovery
Quick Start
using MonadicSharp.Recovery;
// Single recovery attempt (RescueAsync)
var result = await CallExternalApiAsync()
.RescueAsync(
when: ErrorPredicates.HasCode("TIMEOUT"),
recovery: _ => CallFallbackApiAsync());
// Multi-attempt fix branch with backoff (StartFixBranchAsync)
var result = await GenerateWithLlmAsync()
.StartFixBranchAsync(
when: ErrorPredicates.HasAnyCode("AI_JSON_INVALID", "AI_TIMEOUT"),
recovery: (error, attempt) => RetryWithDifferentStrategyAsync(error, attempt),
maxAttempts: 3,
delayBetweenAttempts: TimeSpan.FromSeconds(1));
Core Operators
RescueAsync — single recovery attempt
Intercepts an error matching the predicate, runs a recovery function once.
- Recovery succeeds → back to Green track
- Recovery fails → original error propagated to Red (root cause preserved)
await pipeline
.RescueAsync(
when: ErrorPredicates.HasCode("DB_TIMEOUT"),
recovery: error => FallbackRepositoryAsync(error));
StartFixBranchAsync — N-attempt fix branch
Opens a "fix branch" on a matched failure. Retry up to N times with optional backoff. The recovery function receives the attempt number so you can escalate strategy.
await pipeline
.StartFixBranchAsync(
when: ErrorPredicates.HasAnyCode("AI_JSON_INVALID", "AI_SCHEMA_MISMATCH"),
recovery: (error, attempt) => attempt switch
{
1 => RepairWithSameModelAsync(error),
_ => RepairWithFallbackModelAsync(error), // escalate on attempt 2+
},
maxAttempts: 3,
delayBetweenAttempts: TimeSpan.FromMilliseconds(500));
ErrorPredicates
Composable, combinable filters for selecting which errors enter the Amber track:
// Single code
ErrorPredicates.HasCode("AI_JSON_INVALID")
// Multiple codes (OR)
ErrorPredicates.HasAnyCode("AI_TIMEOUT", "AI_RATE_LIMIT")
// By error type
ErrorPredicates.IsOfType(ErrorType.Validation)
// Composition
ErrorPredicates.HasCode("AI_TIMEOUT")
.Or(ErrorPredicates.HasCode("AI_RATE_LIMIT"))
.And(ErrorPredicates.IsOfType(ErrorType.Validation).Not())
Observability — IRecoveryTelemetry
Implement IRecoveryTelemetry to emit events to any backend:
public class MyTelemetry : IRecoveryTelemetry
{
public void RecordAttempt(RecoveryAttemptEvent attempt)
{
// attempt.ErrorCode, attempt.AttemptNumber, attempt.Succeeded, attempt.Duration
// emit to OpenTelemetry, App Insights, Datadog, etc.
}
}
Pass the sink to any operator:
.RescueAsync(when, recovery, telemetry: new MyTelemetry())
.StartFixBranchAsync(when, recovery, telemetry: new MyTelemetry())
Reading the three-lane highway in logs
Use structured logging prefixes to filter in App Insights / Grafana:
| Log prefix | Meaning |
|---|---|
[Amber→Green] |
Error auto-healed — back on success track |
[Amber→Red] |
Recovery failed — original error propagated |
// Azure App Insights: recovery rate by error code
customEvents
| where name == "RecoveryAttempt"
| extend code = tostring(customDimensions["agentscope.recovery.error_code"])
| extend succeeded = tobool(customDimensions["agentscope.recovery.succeeded"])
| summarize total = count(), healed = countif(succeeded) by code
| extend heal_rate = round(100.0 * healed / total, 1)
Combining with MonadicSharp.AI
MonadicSharp.Recovery and MonadicSharp.AI are independent packages that compose naturally:
using MonadicSharp.Recovery;
using MonadicSharp.AI.Errors; // AiError codes
using MonadicSharp.AI.Extensions; // WithSelfHealingAsync
// Use AiError codes as predicates for Recovery operators
await pipeline
.StartFixBranchAsync(
when: ErrorPredicates.HasCode(AiError.InvalidOutputCode),
recovery: (error, attempt) => RepairOutputAsync(error, attempt));
License
MIT
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net8.0
- MonadicSharp (>= 1.4.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.0.0 | 96 | 3/17/2026 |
v1.0.0: Initial release — RescueAsync (single recovery attempt), StartFixBranchAsync (N-attempt fix branch with backoff), ErrorPredicates (composable error filters), IRecoveryTelemetry (observability interface).