AI

Making .NET AI Agent Guardrails Fail Closed When They Break

The article examines what a .NET AI agent does when its own guardrails fail, such as a throwing guard, a down classifier, a missing caller or miswired middleware. The author deliberately breaks each guard layer and shows how to make the request blocked instead of silently allowed. It ends with a practical checklist for developers building guarded agents.

DEV Community: #dotnet MICHAEL-MAURICE
Published
Reading time
7 min read
agent run #12
agent run #12
Go to original dev.to

Report this story

Is something wrong with the summary, or do you own this content? Your message comes straight to my inbox.

Type of message

Key points

  • Set MaximumConsecutiveErrorsPerRequest to 0 so guard halts end the run instead of letting the model retry three more times
  • When the safety classifier fails, block the request and record it under its own rule id such as classifier_unavailable
  • Block runs with no caller identity before the first model call
  • If per-run guard state is missing, halt instead of silently skipping the layer's checks
  • Register both streaming and non-streaming agent run middleware and test both paths
  • Set per-run budgets for tool calls and denied calls

Guardrails are usually tested with bad input, but the harder question is what the agent does when the guard itself fails. The author built a helpdesk agent on Microsoft.Agents.AI 1.25.0 and broke each guard layer on purpose, and found that the usual outcome was that the request got through.

The main lesson concerns exceptions. A guard that throws inside a function middleware does not stop the run, because the function invocation layer reports the error to the model and retries up to the default limit. Setting the consecutive error limit to zero makes guard halts propagate, while the tool wrapper still catches ordinary tool bugs. The same logic applies elsewhere: an unreachable classifier blocks instead of passing, a missing caller stops the run before the first model call, and a layer running without its per-run state halts rather than skipping checks. Streaming needs both delegates registered and the async scope re-established on each step.

Real-world use

  • Enterprise helpdesk agents that look up customer data or process refunds
  • Multi-tenant SaaS assistants that call tools and need role-based limits
  • Production agents that depend on a remote safety classifier which can time out

Why it matters

A guardrail is only useful if it still holds when it breaks. The fail-closed patterns here turn silent bypasses into visible blocks and failing tests, which is what you want before shipping an agent that touches real data.

This summary was generated by the agent from the original post on DEV Community: #dotnet. The full text and all rights belong to its author and publisher. Go to original

Related stories

Feedback

Found a bug or have an idea? Your message lands straight in my inbox.

Type of message