iron-prow local-provider safety adapter: model-ID preflight, readiness gate, and length-bounding for lm-supply local inference.
Install
| Product | Versions |
|---|---|
| .NET |
README
iron-prow
safe-inference gateway โ every LLM call's first gate.
provider selection (frontier โจ LAN GpuStack) ยท guardrail ยท resilience โ delivered as a standardMicrosoft.Extensions.AI.IChatClient.
๋ ๊ฐ๋ ํ์: frontier/LAN ๊ฒ์ดํธ์จ์ด(A) and local-provider safety(B).
์ญํ ยท๋ฒ์ยท์ค๊ณ ๊ทผ๊ฑฐ๋ CHARTER.md ์ฐธ์กฐ.
์ด๋ฏธ ์์ฒด ๋ฐฐ์ (providerยทresilienceยทguardrail)์ ๊ฐ์ง ์ฑ์ ์ด๊ด์ docs/ADOPTION.md ์ฐธ์กฐ.
Packages
| Package | ์ญํ |
|---|---|
IronProw.Core |
๊ฒ์ดํธ์จ์ด ๊ณ์ฝ, resilience, ์ ํ ๋ก์ง โ iyulab ๊ตฌํ ์์กด 0 |
IronProw.IronHive |
IronHive provider ์ด๋ํฐ โ OpenAI ยท Anthropic ยท GoogleAI (frontier) ยท GpuStack ยท OpenAI-Compatible/Ollama (LAN) |
IronProw.FluxGuard |
FluxGuard guardrail ์ด๋ํฐ (IGuard ๊ตฌํ) |
IronProw.LMSupply |
๋ก์ปฌ ์ถ๋ก ์์ ๋ํผ (length-bounding + readiness gate) |
dotnet add package IronProw.Core
dotnet add package IronProw.IronHive # frontier provider adapters
dotnet add package IronProw.FluxGuard # guardrail adapter
dotnet add package IronProw.LMSupply # local-provider safety adapter
Quick Start
A. Frontier / LAN ๊ฒ์ดํธ์จ์ด
IronHive ๊ธฐ๋ฐ frontier provider + FluxGuard guardrail์ ๋ฑ๋กํ๋ค.
DI ์ปจํ
์ด๋๊ฐ ํ์ค IChatClient๋ฅผ resolveํ๋ฉฐ, ๊ฒ์ดํธ์จ์ด๊ฐ selectionยทretryยท์
์ถ๋ ฅ ๊ฒ์ฌ๋ฅผ ์๋ ์ฒ๋ฆฌํ๋ค.
using IronProw.Core;
using IronProw.IronHive;
using IronProw.FluxGuard;
using Microsoft.Extensions.AI;
using Microsoft.Extensions.DependencyInjection;
services.AddIronProw()
.AddIronHiveOpenAI(
id: "openai",
priority: 10,
modelId: "gpt-4o",
configure: cfg => cfg.ApiKey = Environment.GetEnvironmentVariable("OPENAI_API_KEY")!)
.AddIronHiveAnthropic(
id: "anthropic",
priority: 5,
modelId: "claude-opus-4-5",
configure: cfg => cfg.ApiKey = Environment.GetEnvironmentVariable("ANTHROPIC_API_KEY")!)
.UseFluxGuard(); // Standard preset (L1 regex guards, offline)
// ํ์ค Microsoft.Extensions.AI.IChatClient ๋ฐํ
IChatClient chat = host.Services.GetRequiredService<IChatClient>();
var response = await chat.GetResponseAsync("Hello");
IronProw.IronHive๋ ๋ค์ฏ ๊ฐ์ง provider ์ด๋ํฐ๋ฅผ ์ ๊ณตํ๋ค:
AddIronHiveOpenAIยทAddIronHiveAnthropicยทAddIronHiveGoogleAIโ frontier (ProviderKind.Frontier)AddIronHiveGpuStackโ LAN GpuStack (ProviderKind.Lan, key-optional).cfg => cfg.BaseUrl = "http://gpustack.lan:8080"ํํ๋ก endpoint ์ง์ .AddIronHiveOpenAICompatibleโ LAN generic OpenAI-ํธํ(OllamaยทLMStudioยทvLLMยทllama.cpp server,ProviderKind.Lan, key-optional). ํ์ค/v1API ํ๋ฉด์ ๋ ธ์ถํ๋ ์๋ํฌ์ธํธ๋ฅผ ๋์์ผ๋ก ํ๋ฉฐ ๊ธฐ๋ณธ endpoint๋ Ollama์http://localhost:11434.cfg => cfg.BaseUrl = "http://localhost:1234"(LMStudio)์ฒ๋ผ override.
services.AddIronProw()
.AddIronHiveOpenAICompatible(
id: "ollama",
priority: 20, // LAN ์ฐ์ โ frontier๋ณด๋ค ๋๊ฒ ๋๋ฉด ๋ก์ปฌ ๋จผ์ ์๋
modelId: "llama3.2",
configure: cfg => cfg.BaseUrl = "http://localhost:11434"); // key ๋ถํ์
UseFluxGuard() (ํ๋ผ๋ฏธํฐ ์์) ๋ Standard preset(L1 regex, offline)์ ์ ์ฉํ๋ค.
์ปค์คํ
FluxGuard ์ธ์คํด์ค๋ฅผ ์ฃผ์
ํ๋ ค๋ฉด UseFluxGuard(IFluxGuard) ์ค๋ฒ๋ก๋๋ฅผ ์ฌ์ฉํ๋ค.
fail mode: ๊ธฐ๋ณธ์ fail-closed(๋ถํ์ค verdict ์ฐจ๋จ). ๊ฐ์ฉ์ฑ์ ์ฐ์ ํ๋ ์๋น์๋ UseFluxGuard(failMode: FluxGuardFailMode.Open)์ผ๋ก opt-in โ Flagged/NeedsEscalation์ ํต๊ณผ์ํจ๋ค(์ ์๋ Block์ mode ๋ฌด๊ด ํญ์ ์ฐจ๋จ).
B. Local-provider safety (lm-supply / ONNX / DirectML)
๋ก์ปฌ ์ถ๋ก ์ iron-prow ์์ ๋ ์ด์ด๋ก ๊ฐ์ผ๋ค. lm-supply ์์ฑ์(IGeneratorModel/ITextGenerator)๋ฅผ ๊ทธ๋๋ก ๋๊ธฐ๋ฉด iron-prow๊ฐ ๋ด๋ถ GeneratorChatClient ๋ธ๋ฆฌ์ง๋ก IChatClient์ ์ ์์ํจ๋ค โ ์๋น์๊ฐ ๋ธ๋ฆฌ์ง๋ฅผ ์ง์ ์์ฑํ ํ์๊ฐ ์๋ค.
using IronProw.Core;
using IronProw.LMSupply;
using IronProw.FluxGuard;
using LMSupply.Generator;
using Microsoft.Extensions.AI;
using Microsoft.Extensions.DependencyInjection;
// generator: lm-supply๊ฐ ๋ก๋ํ IGeneratorModel/ITextGenerator (์๋ช
์ฃผ๊ธฐ๋ ํธ์ถ์ ์์ ).
// ์: var generator = await LocalGenerator.LoadAsync("gguf:default", options, null, ct);
// probe: IReadinessProbe โ ๋ชจ๋ธ ๋ก๋ ์ํ๋ฅผ ๋ณด๊ณ ํ๋ ๊ตฌํ์ฒด.
// lm-supply GeneratorPool ๊ธฐ๋ฐ์ GeneratorPoolProbe๋ฅผ ์ฌ์ฉํ๋ค.
// GeneratorPool ์์ด LoadAsync๋ก ๋จ์ผ ๋ชจ๋ธ์ ์ง์ ๋ก๋ํ๋ ๊ฒฝ์ฐ
// (์: textree)๋ LazyReadinessProbe(() => loaded, [modelId])๋ฅผ ์ฌ์ฉํ๋ค.
services.AddIronProw()
.AddLMSupplyLocal(
id: "local-phi3",
priority: 20,
generator: generator,
probe: probe,
options: new LocalSafetyOptions { DefaultMaxOutputTokens = 1024 })
.UseFluxGuard();
IChatClient chat = host.Services.GetRequiredService<IChatClient>();
AddLMSupplyLocal์ด ์ ๊ณตํ๋ safety:
- bridge โ
GeneratorChatClient๊ฐ lm-supply ์์ฑ์๋ฅผIChatClient๋ก ์ ์(role ๋งคํ,MaxOutputTokensโMaxNewTokens, sampler/tool ์ ํ, streaming flatten). ์ด๋ฏธ ๋ธ๋ฆฌ์ง๋IChatClient๋ฅผ ๋ณด์ ํ ํธ์ถ์(์: ironhive-host)๋AddLMSupplyLocal(..., IChatClient rawClient, ...)์ค๋ฒ๋ก๋๋ฅผ ์ธ ์ ์๋ค. - model-ID preflight โ
IReadinessProbe.GetAvailableModelIdsAsync๋ก ๋ชจ๋ธ ์กด์ฌ ๊ฒ์ฆ - readiness gate โ
IReadinessProbe.IsReadyAsync๋ก ๋ก๋ ์๋ฃ ํ์ธ - length-bounding โ
LocalSafetyOptions.DefaultMaxOutputTokens(๋ฏธ์ค์ ํธ์ถ์ ์๋ ์ ์ฉ, ๊ธฐ๋ณธ 512) - reasoning default โ
LocalSafetyOptions.DefaultReasoningEffort(๋ฏธ์ค์ ํธ์ถ์ ์๋ ์ ์ฉ, ๊ธฐ๋ณธReasoningEffort.None). thinking ๊ธฐ๋ณธ-on ๋ชจ๋ธ(Gemma 4ยทQwen3)์ ์์ ์์ฐ์ reasoning ์ ์ ๋ถ ์จ ๋น ๋ต +FinishReason.Length๋ฅผ ๋๋ ค์ค ์ ์๋ค โ ์์ ๋ํผ์ ๊ณ์ฝ์ ยซ์์ฐ์ ๋ต์ ์ด๋คยป๋ผ ๊ธฐ๋ณธ์ off. ๋ชจ๋ธ ๊ธฐ๋ณธ์ ์ ์งํ๋ ค๋ฉดnull. - reasoning ์ด๋ฐ โ ๋ธ๋ฆฌ์ง๊ฐ ํ์ค
ChatOptions.Reasoning์ lm-supplyThinkingMode๋ก ๋ฒ์ญํ๋ค(Effort.NoneโOff, ๊ทธ ์ธโOn, nullโ๋ชจ๋ธ ๊ธฐ๋ณธ). ๋ชจ๋ธ์ด ๋ธ reasoning ์TextReasoningContent๋ก ์๋ต์ ์ค๋ฆฐ๋ค(ReasoningOutput.None์ด๋ฉด ๋ฒ๋ฆผ) โ ๋น ๋ต์ด ์ ๋น์๋์ง ์๋น์๊ฐ ๋ณผ ์ ์๋ค. - ๊ณ์ธก โ
ChatResponse.ModelIdยทUsage(llama-server ์ prompt/completion ํ ํฐ; ONNX ๋ null)ยทGetService<ChatClientMetadata>()(ProviderName = "LMSupply").
๊ฒฝ๋ ๊ฒฝ๋ก โ ๋จ์ผ local provider (๊ฒ์ดํธ์จ์ด ์์ด)
ํด๋ฐฑ ๋์ 2๋ฒ์งธ provider๊ฐ ์๋ local-first ๋จ์ผ provider ์๋น์(์: textree)์๊ฒ๋ ๊ฒ์ดํธ์จ์ด์ registryยทselectionยทresilience ๋ ์ด์ด๊ฐ ์ ๋ถ inertํ๋ค. ์ด ๊ฒฝ์ฐ BuildLocalSafeClient๊ฐ ๋ธ๋ฆฌ์ง+์์ wrap๋ง ์กฐ๋ฆฝํ plain IChatClient๋ฅผ ๋ฑ๋ก ์์ด ๋ฐํํ๋ค:
using IronProw.LMSupply;
using Microsoft.Extensions.AI;
// ๊ฒ์ดํธ์จ์ด(AddIronProw/๋น๋/๋ ์ง์คํธ๋ฆฌ) ์์ด guarded local client ์ง์ ์กฐ๋ฆฝ.
IChatClient chat = LMSupplyExtensions.BuildLocalSafeClient(
generator, // lm-supply ITextGenerator (ํธ์ถ์ ์์ )
probe, // IReadinessProbe
new LocalSafetyOptions { DefaultMaxOutputTokens = 1024 }); // ์ ํ (๊ธฐ๋ณธ 512)
๋์ผํ safety(preflightยทreadiness gateยทlength-bounding)๋ฅผ ๋ฐ๋ selection/fallback/resilience ์ค๋ฒํค๋๊ฐ ์๋ค. ๋ค์ค providerยท์ฐ์ ์์ ์ ํยทprovider-level fallback์ด ํ์ํด์ง๋ฉด AddLMSupplyLocal๋ก ์ ํํ๋ค.
๋ ๊ฐ๋ ์กฐํฉ
๋ ๊ฐ๋๋ฅผ ๊ฐ์ DI ๋ฑ๋ก์์ ์กฐํฉํ ์ ์๋ค. priority๊ฐ ๋์ provider๊ฐ ๋จผ์ ์ ํ๋๊ณ , fallback ์ ๋ฎ์ ์ฐ์ ์์ provider๋ก ๊ฐ๋ฑ๋๋ค.
services.AddIronProw()
.AddIronHiveOpenAI("openai", priority: 10, "gpt-4o",
cfg => cfg.ApiKey = Environment.GetEnvironmentVariable("OPENAI_API_KEY")!)
.AddLMSupplyLocal("local", priority: 20, generator, probe)
.UseFluxGuard()
.Configure(opt =>
{
opt.EnableFallback = true; // ๊ธฐ๋ณธ๊ฐ
opt.Resilience.MaxRetries = 3; // ๊ธฐ๋ณธ๊ฐ: 2
opt.Resilience.BaseDelay = TimeSpan.FromMilliseconds(300); // ๊ธฐ๋ณธ๊ฐ: 200ms
opt.Resilience.FailureThreshold = 3; // ์ฐ์ ์คํจ Nํ๋ฉด cooldown (๊ธฐ๋ณธ๊ฐ: 3, 0 = ๋)
opt.Resilience.Cooldown = TimeSpan.FromSeconds(30); // cooldown ๋์ ํ์์ (๊ธฐ๋ณธ๊ฐ: 30s)
opt.OnTransition = t => // retry/fallback/exhausted ์ด๋ฒคํธ (UI ์นฉ ๋ฑ)
Console.WriteLine($"[{t.Kind}] {t.ProviderId} ({t.ProviderIndex + 1}/{t.TotalProviders})");
});
provider ๊ฑด๊ฐ ๊ธฐ์ต(0.4.0+): ๊ฒ์ดํธ์จ์ด๋ provider ๋ณ ์ฐ์ ์คํจ๋ฅผ ๊ธฐ์ตํ๋ค. FailureThreshold ํ ์ฐ์์ผ๋ก ๊ฐ๋ฑ ๋์ ์คํจ(retry ์์งยทfallback-eligible)๊ฐ ๋๋ฉด ๊ทธ provider ๋ Cooldown ๋์ ํ์์๋ก ๋ฐ๋ฆฐ๋ค โ ์ ์ธ๊ฐ ์๋๋ผ ํ์์๋ผ ๊ฑด๊ฐํ provider ๊ฐ ํ๋๋ ์์ผ๋ฉด ์ฌ์ ํ ์๋๋๊ณ , ํ ๋ฒ ์ฑ๊ณตํ๋ฉด ๊ธฐ๋ก์ด ์ง์์ง๋ค. ๊ทธ ์ ์ ์ฃฝ์ LAN provider ๊ฐ ๋งค ํธ์ถ์ retry ์์ฐ(๊ธฐ๋ณธ 2ํ + backoff)์ ๋ฌผ๋ฆฐ ๋ค์์ผ ๋ค์ provider ๋ก ๋์ด๊ฐ๋ค. ๋ฐ๋ฆฐ provider ๋ OnTransition ์ ProwTransitionKind.Skipped ๋ก ๋ณด๊ณ ๋๋ค. EnableFallback = false ๋ฉด ๊ฑด๊ฐ ๊ธฐ์ต๋ ๋ผ์ฐํ
์ ์ฐ์ง ์๋๋ค(๊ทธ ์ค์ ์ ๋ป์ด ยซ์ ๋ provider ๋ฅผ ๋ฐ๊พธ์ง ์๋๋คยป๋ผ์). ์ฐ๊ฒฐ ๊ฑฐ๋ถยท์ด๋ฆ ํด์ ์คํจ(HttpRequestError.ConnectionError/NameResolutionError)๋ retry ๊ฐ ์๋๋ผ ์ฆ์ fallback ์ผ๋ก ๋ถ๋ฅ๋๋ค โ ์๋ํฌ์ธํธ๊ฐ ๋ฐ์ ๊ฒ ์๋๋ผ ์๋ ๊ฒ์ด๋ผ์.
OnTransition(์ ํ)์ ๊ฐ ๊ฒ์ดํธ์จ์ด ์ ํ(retry / fallback / exhausted / skipped)๋ง๋ค ํธ์ถ๋๋ best-effort ์ฝ๋ฐฑ์ด๋ค. ์๋น์๊ฐ ์ด๋ provider๋ก ๊ฐ๋ฑ๋๋์ง UI์ ํ์(์: resilience ์นฉ)ํ ์ ์๋ค. ์ฝ๋ฐฑ์ด ๋์ง๋ ์์ธ๋ ์ผ์ผ์ง๋ฉฐ ์ถ๋ก ์ ์ ๋ ๊นจ์ง ์๋๋ค. ๋ฏธ์ค์ ์ ๋์์ ๊ธฐ์กด๊ณผ ๋์ผ(๋ฌด๋ณด๊ณ ).
์คํธ๋ฆฌ๋ฐ ๋๋ฑ์ฑ: retryยทfallback์ GetResponseAsync์ GetStreamingResponseAsync ์์ชฝ์ ๋์ผํ๊ฒ ์ ์ฉ๋๋ค. ์คํธ๋ฆฌ๋ฐ์ ๋ณต์๋ ฅ ์ฐฝ์ "์ฒซ ChatResponseUpdate๊ฐ yield๋๊ธฐ ์ " ์ด๋ค โ ์ฒซ ์ฒญํฌ ์ด์ ์ ๋ฐ์ํ ์คํจ(์: OpenAI ํธํ ํธ์ถ์ด ์ฒซ MoveNextAsync์์ ๋์ง๋ connection-refused / 404 / model-not-found)๋ same-provider retry(Retryable) ๋๋ next-provider fallback(FallbackEligible)์ผ๋ก ์ฒ๋ฆฌ๋๋ค. ์ฒซ ์ฒญํฌ๊ฐ emit๋ ๋ค์ ์คํจ๋ provider๋ฅผ ๋ฐ๊พธ๋ฉด ์ด์ค emit์ด ๋๋ฏ๋ก ๊ทธ๋๋ก ์ ํ๋๋ค.
๋ฉํฐํ ๋ํธ โ per-tenant provider resolution
๊ธฐ๋ณธ AddProvider/AddLMSupplyLocal ๊ฒฝ๋ก๋ provider ์งํฉ์ด ํ๋ก์ธ์ค ์๋ช
๋์ ๊ณ ์ ์ธ ์๋น์(๋ฐ์คํฌํ ์์ด์ ํธ, ๋จ์ผ ์ ์ )๋ฅผ ์ํ ๊ฒ์ด๋ค. ์ํฌ์คํ์ด์ค๋ง๋ค provider ์งํฉยทconfigยทsecret์ด ๋ค๋ฅธ ๋ฉํฐํ
๋ํธ ์๋ฒ ์๋น์๋ AddTenantResolver๋ก per-tenant ๊ฒ์ดํธ์จ์ด๋ฅผ ๋ฐํ์์ buildํ๋ค.
// startup โ ๋จ์ผ ํ
๋ํธ AddProvider ๊ฒฝ๋ก์ ๋ณ์กด(๋ฌดํ๊ท)
services.AddIronProw()
.UseFluxGuard()
.AddTenantResolver((sp, tenant) => // ์ ๊ท ํ๋ฉด
sp.GetRequiredService<ProviderService>() // consumer ๊ตฌํ
.ResolveRegistrations(tenant)); // per-workspace ์งํฉ โ ProviderRegistration[]
// per-request (์์ฒญ ์ค์ฝํ์์ resolve)
var client = scopedSp.GetRequiredService<IIronProwFactory>().ForTenant(workspaceId);
await client.GetResponseAsync(msgs, options, ct); // guarded: select/retry/fallback/guard
ForTenant(tenant)์ ํด๋น ํ ๋ํธ์ provider ์งํฉ์ผ๋กSelectingChatClient๋ฅผ ์ฌ์กฐ๋ฆฝํ๋ค โ selector/guard/classifier/options๋ ๊ณต์ (์ฌ์ฌ์ฉ), registry๋ง per-tenant. tenant ํค๋ iron-prow์ opaque(resolver๊ฐ ํด์).IIronProwFactory๋ scoped๋ก ๋ฑ๋ก๋๋ฏ๋ก ์์ฒญ ์ค์ฝํ์์ resolveํด์ผ resolverยทprovider factory๊ฐ ์์ฒญ ๋ฒ์ ์๋น์ค(์: ๋ณตํธํ๋ ์ํฌ์คํ์ด์ค secret)๋ฅผ ๋ณธ๋ค.- async๋ ์๋ฅ์์: resolver์
ProviderRegistration.ClientFactory๋ ๋ชจ๋ sync๋ค. ์ํฌ์คํ์ด์ค secret์ async DB ๋ก๋ยท๋ณตํธํ๋ consumer์ ์์ฒญ ๋ฏธ๋ค์จ์ด์์ ์ํํด scoped ์๋น์ค์ stashํ๊ณ , resolver๋ ๊ทธ๊ฒ์ sync๋ก ์ฝ๋๋ค. (์์ฒญ๋น async ๋ก๋๊ฐ ํ์๋ผ๋ฉด ํฅํForTenantAsync์ค๋ฒ๋ก๋๊ฐ ์์ additive๋ก ์ถ๊ฐ๋ ์ ์๋ค.) - ๋ฐํ๋ client๋ ๋งค ์์ฒญ build(์ฐ๊ฒฐ ์์ยท์ ๋น์ฉ)๋ค. consumer๊ฐ provider factory์์
HttpClient๋ฑ disposable์ ์ฅ๋ฉด ์๋ช ์ consumer ์ฑ ์์ด๋ค. - ๋จ์ผ ํ
๋ํธ ๊ฒฝ๋ก(
AddProvider/AddLMSupplyLocal, singletonIChatClient)๋ ์์ ๋ฌด๋ณ๊ฒฝ์ผ๋ก ๋ณ์กดํ๋ค.
Crash-fallback ์ ํ
LocalSafetyChatClient(๊ฐ๋ B)๋ IReadinessProbe๋ก ๋ก์ปฌ ์ถ๋ก ๋ถ๊ฐ๋ฅผ ๊ฐ์งํ๊ณ , ๊ฒ์ดํธ์จ์ด SelectingChatClient์ provider-level fallback์ผ๋ก ์น๊ฒฉํ๋ค. ์ด๊ฒ์ ๊ฒ์ดํธ์จ์ด ์์ค fallback(M2-4 ๋ฒ์)์ด๋ค.
์ง์ง ํ๋์จ์ด ์์ค fallback(์: ONNX GenAI DirectML โ CPU)์ upstream lm-supply์ ์ฑ
์์ด๋ค.
lm-supply 0.35.x ๊ธฐ์ค, ONNX GenAI ์์ฑ ๊ฒฝ๋ก๋ DirectML โ CPU ํด๋ฐฑ์ด ์๋ค(์๋ฒ ๋ฉ ๊ฒฝ๋กยทllama-server ๊ฒฝ๋ก๋ ๋ณด์ ). iron-prow๋ ์ด gap์ ๊ฐ์ธ์ง ์๋๋ค โ upstream์ด ์์ ๋๋ฉด iron-prow ๋ณ๊ฒฝ ์์ด ์ด๋์ด ํก์๋๋ค.
๋ ๊ฐ๋ ํ์ ์ค๊ณ
iron-prow๋ ๋ ์๋๋ฆฌ์ค๋ฅผ ๋ ๋ฆฝ์ ์ด๋ฉด์๋ ์กฐํฉ ๊ฐ๋ฅํ๊ฒ ์ปค๋ฒํ๋ค:
| ๊ฐ๋ | ์ง์ ์ | ์ฑ ์ |
|---|---|---|
| A. Frontier / LAN | AddIronHiveOpenAI ยท AddIronHiveAnthropic ยท AddIronHiveGoogleAI ยท AddIronHiveGpuStack ยท AddIronHiveOpenAICompatible |
provider ๋ ์ง์คํธ๋ฆฌ, ์ฐ์ ์์ ์ ํ, retry, provider-level fallback, ์ ํ ์ด๋ฒคํธ(OnTransition) |
| B. local-provider safety | AddLMSupplyLocal |
model-ID preflight, readiness gate, length-bounding, crashโfallback |
์ด๋ ํ ๊ฐ๋๋ง ๊ตฌํํ๋ฉด ์์์ ์ ๋ฐ์ ๋์น๋ค (CHARTER ยง๊ธฐ๋ฅ ํ๋ฉด).UseFluxGuard()๋ ๋ ๊ฐ๋ ๊ณตํต โ ๊ด๋ฌธ์์ ์ผ๊ด ์ ์ฉ๋๋ค.
โ ๏ธ The guard is opt-in.
AddIronProw()installs a defaultNullGuardthat allows all traffic. A gateway withoutUseFluxGuard()(or a customUseGuard(...)) performs NO input/output guardrail checks. Always register a guard in production.
See also
CHARTER.mdโ iron-prow ์ ์ฒด์ฑ, ๋ฒ์, ์์กด ๊ท์น, ๋ก๋๋งต ์ต์ปค
License
MIT
Changes from Previous Version
Adoption Assessment
Assess this package against its supported frameworks, license, maintenance signals and dependency graph before making it a project standard.
Related Guides & Workflows
Learn how to evaluate, integrate, or audit this package in your .NET project.