Solutions · AI agents · Filter pipeline

Middleware for inference.

Cross-cutting concerns are the same whether you serve HTTP or call a model: logging, validation, redaction, throttling, retry. ASP.NET Core solved them with the onion-pattern middleware pipeline. LM-Kit brings the same idea to AI: FilterPipeline with IPromptFilter, ICompletionFilter, and IToolInvocationFilter stages that wrap every call.

Three filter kinds Composable Async, cancellable

IPromptFilter

Inspect or rewrite the prompt before inference. Redact PII, inject context, enforce policy.

ICompletionFilter

Validate or rewrite the completion. Strip leaked secrets, enforce length, salvage malformed JSON.

IToolInvocationFilter

Wrap every tool call. Approve, deny, retry, log, or transform arguments and results.

Why a pipeline

Cross-cutting concerns do not belong in business code.

If you have ever sprinkled PII redaction logic across five agent methods, you know the cost. Filters move those concerns into composable, testable units. Each filter has one job; the pipeline runs them in order. Adding a new concern means writing one class, not editing twenty call sites.

Onion pattern

Filters wrap inner filters. Pre-processing runs outside-in, post-processing runs inside-out. Familiar to anyone who has written ASP.NET middleware.

Async and cancellable

Every filter receives a CancellationToken. Slow filters do not strand a stuck agent.

Per-agent, per-conversation

Build a pipeline once, attach it to one or many agents, or to a MultiTurnConversation. Tests run against the same pipeline as production.

Short-circuit

A filter can decide not to call the next stage. Useful for cache hits, policy denials, or canned responses on safe topics.

Compose with permissions

Permission policies and filters work together. Filters add domain-specific logic on top of the typed permission framework.

Observable

Filters integrate with the tracing layer. Every filter run produces a span; failures and short-circuits are tagged.

Three filters in a pipeline

Redact, log, and salvage.

A prompt filter strips emails and phone numbers from the user prompt before inference runs.

RedactPiiFilter.cs
using LMKit.Inference.Filters;

public sealed class RedactPiiFilter : IPromptFilter
{
    public async Task InvokeAsync(PromptFilterContext ctx, PromptFilterDelegate next)
    {
        ctx.Prompt = Redactor.RedactEmails(Redactor.RedactPhoneNumbers(ctx.Prompt));
        await next(ctx);            // pass to next filter / inference
    }
}
Versus the alternatives

Hand-rolled wrappers do not compose.

LangChain callbacks

Callbacks fire alongside execution but cannot rewrite prompts or short-circuit. Cross-cutting concerns end up duplicated in chain code.

Semantic Kernel filters

Filters exist (function invocation, prompt rendering) but the pipeline is less composable and tied to the kernel lifecycle.

LM-Kit FilterPipeline

ASP.NET-style onion pattern, three first-class filter kinds, async/cancellable, attached per-agent or per-conversation, observable by default.

Related capabilities

Filters plus the rest.

Permissions

Combine declarative policies with custom filter logic for domain-specific approval flows.

Permissions page

Resilience

Retries and circuit breakers handle transient failure; filters handle semantic failure.

Resilience page

Observability

Every filter run produces a span. Audit trails for free.

Observability page

PII extraction

Pair the redaction filter with LM-Kit's own PII extraction model for higher-fidelity scrubbing.

PII extraction page

Demos & docs

Build it. Read it. Try it.

Working console demos on GitHub, step-by-step how-to guides on the docs site, and the API reference for the classes used on this page.

Cross-cutting concerns. One pipeline.

Get Community Edition Download