Guardrails Filter Tackles Complex LLM Streaming and Tool Call Challenges to Protect Sensitive Data

Developers at Cloud.ru built Guardrails Filter to mask personal data such as phone numbers, emails, passport details and names before they reach large language models. The system replaces detected values with consistent placeholders like <PHONE_1> and maintains a mapping table so original data can be restored after the model responds. Simple replacement proved insufficient because identical values must receive the same placeholder across an entire conversation history, and the model receives the full message array on every request. Streaming responses using SSE create additional difficulties since placeholders can be split across multiple chunks, requiring buffering of 10-15 characters and state tracking for reasoning, content and tool_calls. The team also had to handle JSON-inside-JSON arguments for tool calls, different field names across providers, and edge cases such as escaped newlines matching email patterns. Separate implementations were written for OpenAI Chat Completions and Anthropic Messages APIs, resulting in roughly 1,500 lines of streaming code and more than 4,000 lines of tests to ensure agent pipelines remain intact.

HabrTranslated from Russian

Read at source

Developers at Cloud.ru have shared the technical challenges encountered while building Guardrails Filter, a dedicated protection layer that prevents personal data from reaching large language models. The filter scans incoming JSON requests, locates phone numbers, email addresses, passport numbers, SNILS and names using regular expressions, and replaces them with stable placeholders such as <PHONE_1> or <PERSON_1>.

A simple substitution approach quickly proved inadequate. When two different phone numbers appear in the same conversation, replacing both with the generic token <PHONE> makes it impossible to restore the correct values after the model replies. The team therefore maintains an internal mapping table that guarantees the same real value always receives the same placeholder throughout the dialogue history.

Because LLMs are stateless between requests, Guardrails Filter must re-process the entire conversation history on every turn, rebuild the mapping table, mask the data, and then restore original values once the response arrives. With ordinary non-streaming JSON responses the task is manageable, yet streaming via SSE introduces far greater complexity.

In streaming mode, responses arrive in small chunks that may split a placeholder across multiple events. The filter therefore buffers several events until enough characters accumulate to determine whether a complete placeholder is present. Once a placeholder is identified, the original value is substituted and a new chunk is emitted to the client. This buffering adds a small latency but prevents broken placeholders from reaching users.

Tool calling adds another layer of difficulty. Model-generated function calls may contain masked values inside JSON arguments that themselves are serialized inside another JSON object. The filter must fully reconstruct each tool-call argument, validate that all braces are closed, and only then perform demasking. Failure to do so can produce invalid JSON that breaks downstream agent pipelines.

Support for the Anthropic Messages API required a completely separate implementation because its event format differs significantly from OpenAI’s Chat Completions streaming. The Messages API uses explicit lifecycle events for tool calls, while Chat Completions delivers deltas inside larger JSON objects. Separate code paths and approximately 1,000 additional lines of tests were written to handle both providers consistently.

In total, the streaming logic alone grew to roughly 1,500 lines of code, backed by more than 3,000 lines of tests. The engineering effort focused on correctly identifying the end of reasoning blocks, the completion of tool-call arguments, and the safe delivery of any remaining buffered data once the model signals the end of a response.

Meridian digestThe week's most consequential security stories, distilled into one briefing.See the digest

More in AI Security

Logical Argument Claims Full Alignment of Superintelligent AGI Is Fundamentally Impossible
Claude Account Bans Linked to IP Reputation, Device Environment and Payment Channels, But No Confirmed Formula
Local LLMs in AppSec: What Open Tools and Models Can Handle in Application Security