Designing Language-Safe AI Systems: Deterministic Guardrails for Multilingual Enterprise AI

Large Language Models are exceptionally good at producing fluent text.
They are not inherently good at knowing when not to answer.

In regulated or compliance-sensitive environments, this distinction is critical.
A linguistically plausible answer that is not grounded in official documentation is often worse than no answer at all.

This article describes a practical architecture for handling language detection, translation intent, and multilingual retrieval in an enterprise AI system — with a strong emphasis on determinism, evidence-first behavior, and hallucination prevention.

The examples are intentionally domain-neutral, but the patterns apply to legal, regulatory, financial, and policy-driven systems.


The Core Problem

Consider these seemingly simple user questions:

"What is E104?"
"Slovenski prevod za E104?"
"Hrvatski prevod za E104?"
"Kaj je E104 v slovaščini?"
"Slovenski prevod za Curcumin?"

At first glance, these look like:

  • definitions
  • translations
  • or simple multilingual queries

A naïve LLM-only approach will happily generate answers for all of them.

But in a regulated environment, each of these questions carries a different risk profile:

  • Some require retrieval
  • Some require translation
  • Some require terminology resolution
  • Some should result in a deterministic refusal

The challenge is not generating text —
it is deciding which answers are allowed to exist.


Key Design Principle: Evidence Before Language

The system described here follows one non-negotiable rule:

Language is applied after evidence is proven, never before.

This means:

  • Language preference never expands the answer space
  • Translation never invents facts
  • Missing official wording is explicitly acknowledged

Continue reading “Designing Language-Safe AI Systems: Deterministic Guardrails for Multilingual Enterprise AI”

End-to-End Integration Testing for Agent-Based Systems with .NET Aspire

Modern agent-based systems are rarely a single executable. They typically consist of multiple cooperating components: agent hosts, orchestrators, background workers, and external dependencies such as Redis, search engines, or AI services.

Testing such systems effectively requires more than unit tests—it requires repeatable, automated, end-to-end integration tests that reflect real runtime behavior.

In this post, I’ll walk through how we implemented stable, fully automated Aspire-based integration tests for an agent system using xUnit and .NET Aspire, without exposing domain-specific details.


Why Traditional Integration Tests Fall Short

In distributed agent architectures, common testing approaches often break down:

  • Running services manually (dotnet run) before tests is error-prone
  • Static ports and connection strings cause conflicts
  • “Is the service ready?” becomes guesswork
  • CI behavior diverges from local development

What we wanted instead was:

  • A single command to run tests
  • The same topology locally and in CI
  • Deterministic startup and shutdown
  • Explicit readiness signaling

This is exactly what .NET Aspire’s testing infrastructure is designed for.


The Aspire Testing Model

Aspire introduces a powerful concept:
tests can bootstrap the entire distributed application.

Using Aspire.Hosting.Testing, an xUnit test can:

  • Start the AppHost
  • Launch all dependent services (agent host, Redis, etc.)
  • Discover dynamically assigned ports
  • Communicate via real HTTP endpoints
  • Tear everything down automatically

In other words, the test becomes the orchestrator.

Continue reading “End-to-End Integration Testing for Agent-Based Systems with .NET Aspire”

Solving Hierarchical List Parsing in Legal Documents (Without LLM Guessing)

When working with legal or regulatory documents (such as EU legislation), one of the deceptively hard problems is correctly modeling hierarchical lists. These documents are full of nested structures like:

  • numbered paragraphs (1., 2.),
  • lettered items ((a), (b)),
  • roman numerals ((i), (ii), (iii)),

often mixed with free-text paragraphs, definitions, and exceptions.

At first glance, this looks simple. In practice, it’s one of the main sources of downstream errors in search, retrieval, and AI-assisted answering.

The Core Problem

HTML representations of legal texts (e.g. EUR-Lex) are structurally inconsistent:

  • nesting depth is not reliable,
  • list items are often rendered using generic <div> grids,
  • numbering may reset visually without resetting the DOM hierarchy,
  • multiple paragraphs can belong to the same logical list item.

If you naïvely chunk text or rely on DOM depth alone, you end up with:

  • definitions split across chunks,
  • list items grouped incorrectly,
  • or worst of all: unrelated provisions merged together.

Once this happens, downstream agents or LLMs are forced to guess structure — which leads to hallucinations, missing conditions, or incorrect legal interpretations.

The Design Goal

The goal was not to “understand” the document using an LLM.

The goal was to:

  • encode the document’s logical structure deterministically at index time, so that:
    • list hierarchy is explicit,
    • grouping is stable,
    • and retrieval can be purely mechanical.

In other words: make the data correct so the AI doesn’t have to be clever.

Continue reading “Solving Hierarchical List Parsing in Legal Documents (Without LLM Guessing)”

From “Table 1” to Searchable Knowledge

A Practical Guide to Handling Large Legal Tables in RAG Pipelines

When working with legal documents—especially EU legislation like EUR-Lex—you quickly run into a hard problem: tables.

Not small tables.
Not friendly tables.
But hundreds-row, multi-page tables buried inside 300+ page PDFs, translated into 20+ languages.

If you are building a Retrieval-Augmented Generation (RAG) system, naïvely embedding these tables almost always fails. You end up with embeddings that contain nothing more than:

“Table 1”

…and none of the actual data users are searching for.

This post describes a production-grade approach to handling large legal tables in a RAG pipeline, based on real issues encountered while indexing EU regulations (e.g. Regulation (EC) No 1333/2008).


The Core Problem

Let’s start with a real example from EUR-Lex:

ANNEX III
PART 6
Table 1 — Definitions of groups of food additives

The table itself contains hundreds of rows like:

  • E 170 — Calcium carbonate
  • E 260 — Acetic acid
  • E 261 — Potassium acetates

What goes wrong in many pipelines

  1. The table heading (“Table 1”) is detected as a section.
  2. The actual <table> element is ignored or stored separately.
  3. Embeddings are generated from the heading text only.

Result:

Embedding text length: 7
Embedding content: "Table 1"

The data exists visually—but not semantically.


Design Goals

We defined a few non-negotiable goals:

  1. The table must be searchable
    Queries like “E170 calcium carbonate” must hit the table.
  2. IDs must be stable and human-readable
    ANNEX_III_PART_6_TABLE_1 is better than _TBL0.
  3. Structured data must be preserved
    We want JSON rows for precise answering, not just text.
  4. Embeddings must stay within limits
    Some tables have hundreds of rows.
Continue reading “From “Table 1” to Searchable Knowledge”

Why General AI Assistants Aren’t Enough: The Case for Domain-Specific Enterprise AI Systems

Over the past two years, the tech landscape has been transformed by generative AI tools like Microsoft Copilot, ChatGPT, Gemini, and others. These assistants have become essential for daily productivity: they summarize documents, write code, answer questions, and drastically improve workflows.

But as soon as organizations begin exploring serious automation of regulated, multi-step, domain-specific processes, one reality becomes clear:

General-purpose AI assistants are not built for high-precision enterprise use cases.

This isn’t a flaw — it’s simply not their mission.
For enterprise-grade scenarios, businesses require specialized, data-aware, multi-agent AI systems designed for accuracy, compliance, and internal knowledge integration.

Here’s why.


1. Data Access ≠ Domain Understanding

Copilot and similar tools can read files from SharePoint, Teams, OneDrive, and other sources.
However, access alone does not create understanding.

General assistants cannot:

  • interpret industry-specific document structures,
  • follow multi-step regulatory logic,
  • understand cross-referenced obligations,
  • map documents across markets or jurisdictions,
  • align internal and external rules,
  • or execute deterministic procedures.

They are trained for broad, generic reasoning — not domain-structured reasoning.

Domain-specific enterprise AI systems, in contrast, are built to:

  • model relationships between documents,
  • extract structured information,
  • classify data reliably,
  • apply rule-based logic,
  • and reason across heterogeneous sources.

2. Enterprise AI Requires Traceability — Not Just an Answer

General AI models work probabilistically: they return the most likely answer.

Enterprise workflows demand something different:

  • exact citations,
  • section and paragraph references,
  • version and source transparency,
  • reproducibility,
  • evidence of reasoning,
  • strict alignment with regulatory text.

Productivity assistants cannot guarantee any of these.
Enterprise AI must — especially in domains such as:

  • compliance,
  • legal obligations,
  • regulatory affairs,
  • quality assurance,
  • product safety,
  • documentation governance.

Without traceability, AI cannot operate in regulated environments.

Continue reading “Why General AI Assistants Aren’t Enough: The Case for Domain-Specific Enterprise AI Systems”

Building a Custom Notification Center for SharePoint On-Prem – My Thrive 2023 Session

At Thrive Conference 2023, I delivered a session focused on something I’ve been working with for over 15 years: SharePoint On-Premises.
Specifically, I presented how to build a modern, unified Notification Center that brings SharePoint alerts into the modern world—similar to notification models users know from Facebook, LinkedIn, Twitter, Teams, and other platforms.

This solution is not a workaround or enhancement of “Alert Me.”
It is a complete three-step architecture, built specifically for SharePoint On-Prem environments where modern cloud features are not available.

All content in this post comes directly from the session’s slides.
📑 Slides: https://rasper87.blog/wp-content/uploads/2025/11/spnotificationcenter_thrive2023.pdf


Why a Custom Notification Center?

SharePoint’s built-in Alert Me feature is simple, but limited:

  • Users must manually turn it on
  • Notifications arrive only via email or SMS
  • Emails are often ignored
  • The look & feel is outdated
  • No unified overview of activities across the portal

Modern intranets need something more:

  • Centralized
  • Non-intrusive
  • Always visible
  • Configurable
  • Secure
  • And ideally: looks and behaves like notifications in social networks

This is exactly what the Notification Center provides.

Continue reading “Building a Custom Notification Center for SharePoint On-Prem – My Thrive 2023 Session”

My Four NTK 2022 Sessions – Published at Last

Back in 2022, I had one of my most active conference years ever.
I delivered four separate talks at the NTK conference—covering .NET MAUI, Blazor, cross-platform development, and even a deep dive into one of the very first production .NET MAUI apps in Slovenia.

For various reasons, I never managed to publish these sessions on my blog, even though I did that regularly in previous years. So today I’m finally fixing that and adding all four NTK 2022 talks here—better late than never.

After 2022, I took a two-year break from speaking…
…but this year, I’m back on stage again. 😊

Below are summaries of all four talks in the order they were delivered.


1) Build a Mobile or Desktop App with .NET MAUI

📍 Europa B+D
📑 Slides: https://rasper87.blog/wp-content/uploads/2025/11/1_ustvarimobilnoalinamiznodotnetmaui.pdf

This session introduced the fundamentals of .NET MAUI, Microsoft’s modern cross-platform framework that allows developers to build native mobile and desktop applications from a single shared codebase.

Key topics:

  • One project for Android, iOS, Windows, macOS, and Linux
  • Native access to device-specific features
  • UI built with XAML that compiles to native controls
  • Live demos covering:
    • layouts
    • navigation
    • REST API calls
    • using a local SQLite database
    • handling platform-specific features
  • Introduction to MAUI + Blazor Hybrid, enabling HTML/CSS/C# UI inside a native MAUI shell

The goal was to give attendees a clear picture of how MAUI simplifies cross-platform development and why it’s becoming a key part of the .NET ecosystem.


2) .NET MAUI Blazor – Build a Universal App with HTML, CSS, and C#

📍 Emerald 1
📑 Slides: https://rasper87.blog/wp-content/uploads/2025/11/2_mauiblazor.pdf

The second session focused on the powerful combination of .NET MAUI + Blazor, showing how developers can build a single codebase that runs as:

  • a desktop app
  • a mobile app
  • and even a web app

all by using HTML, CSS, and C#.

Highlights:

  • Explanation of MAUI Blazor architecture
  • Benefits of reusing the same components across platforms
  • How BlazorWebView integrates web UI inside a native MAUI app
  • Multiple live demos demonstrating shared UI logic

The session showed how MAUI Blazor provides a path for .NET developers who prefer web technologies but still want native performance and full device access.

Continue reading “My Four NTK 2022 Sessions – Published at Last”

Bringing Back My .NET MAUI Content – Starting With an Older Video (in Slovenian)

A few days ago I realized that although I’ve been actively following .NET MAUI since the very first preview releases, my blog doesn’t really show that story. In the last few years I simply didn’t have enough time to keep this place updated, which means that a lot of MAUI-related content never made it here.

So, let’s start fixing that.

Today I’m sharing a short video I recorded three years ago, back when I was still working in one of my previous companies (not my most recent one). It’s not a deeply technical, developer-oriented presentation, but more of a high-level overview that introduces the platform and what it enables.

Video: https://www.youtube.com/watch?v=WaGi6dnsTTI

Why .NET MAUI matters

.NET MAUI is a cross-platform framework that allows you to build a single application from one shared codebase, and run it on:

  • Windows
  • macOS
  • Linux
  • iOS
  • Android

This means that the same logic, UI structure, and project architecture can power desktop and mobile experiences at the same time.

And if you combine .NET MAUI with Blazor, you push this even further — a single codebase can serve:

  • Desktop apps
  • Mobile apps
  • Web applications

All with shared components, shared UI logic, and shared development patterns.

About the video

Unfortunately, the video is recorded in Slovenian and not in English — sorry to all my non-Slovenian readers — but it still gives a good introductory overview of the concepts, goals, and the direction Microsoft was taking with MAUI at the time.

Even though the video is older, the core ideas remain relevant, and it’s a nice warm-up for all the new MAUI-related content I plan to publish here.

More MAUI content coming soon

I’ve been following .NET MAUI closely from the very beginning, experimenting with previews, RC versions, and release builds. Now that I’m restarting my writing cadence, I’ll finally start sharing more of that knowledge here.

More articles, samples, and insights on .NET MAUI and Blazor Hybrid apps are coming — I promise.

That’s all folks!

Cheers!
Gašper Rupnik

{End.}

Continuing with the Microsoft Agent Framework – Practical Examples 06–10 for Real-World Development

A few weeks ago, I published an article titled
Getting Started with the Microsoft Agent Framework and Azure OpenAI – My First Five .NET 9 Samples,
where I walked through the foundational building blocks of the Agent Framework—basic agents, tool invocation, streaming output, and structured responses.

This article is the direct continuation of that series.

While my current work focuses on much more advanced multi-agent systems—where layered knowledge processing, document pipelines, and context-routing play a crucial role—I still believe that the best way to understand a new technology is through clear, minimal, practical samples.

So in this follow-up, I want to share the next set of examples that helped me understand the deeper capabilities of the framework.
These are Examples 06–10, and they focus on persistence, custom storage, observability, dependency injection, and MCP tool hosting.

Let’s dive in.


Example 06 — Persistent Threads: Saving & Restoring Long-Running Conversations

One of the major strengths of the Microsoft Agent Framework is the ability to maintain conversational state across messages, sessions, and even application restarts.
This is critical if you’re building:

  • personal assistants
  • developer copilots
  • chat interfaces
  • multi-step reasoning chains
  • or anything that needs user-specific memory

In Example 06, the agent:

  1. Starts a new conversation thread
  2. Answers a developer-related question
  3. Serializes the thread using thread.Serialize()
  4. Saves the serialized state to disk (or any storage)
  5. Reloads it later
  6. Resumes the conversation with full continuity

Why this matters:

  • Enables long-lived, multi-turn conversations
  • You can manage per-user memory in your own storage
  • Perfect for web apps, bots, and multi-agent orchestration
  • Unlocks real “assistant-like” behavior

This is the first step toward user-level persistent AI.

Continue reading “Continuing with the Microsoft Agent Framework – Practical Examples 06–10 for Real-World Development”

Exploring the New Aspire 13 Pipeline Model: Customizable, Flexible, and Future-Ready

Ever since I first saw the early discussions around Aspire 13, I couldn’t get the upcoming publishing and deployment changes out of my head. The new pipeline model represents a major step forward in how Aspire applications can be published, packaged, and shipped — especially for teams building containerized solutions or multi-service platforms.

So, I decided to dive in early and see what this means in practice.

Background: What Changed?

In Aspire pre-13, customizing the publish or deployment pipeline required workarounds, since the publish flow was relatively fixed. Modifying or injecting custom logic usually meant hooking into lifecycle events or adding custom tasks in less intuitive places.

With Aspire 13, we now have a first-class pipeline model:

  • Pipeline steps can be added and named
  • Steps can define dependencies (dependsOn) and ordering constraints (requiredBy)
  • The output model is now managed through a Pipeline Output Service
  • The pipeline is both easier to read and easier to extend

This was explained extremely well in Safia’s article:
👉 https://blog.safia.rocks/2025/11/03/aspire-pipelines/

Setting Up an Early Preview

Since Aspire 13 is not officially released yet, I installed a daily build of the Aspire CLI and created a fresh project using the template:

aspire update
    - daily

aspire new
    - Blazor & Minimal API starter

I then added the preview pipeline-enabled Docker hosting package:

<PackageReference Include="Aspire.Hosting.Docker"
                  Version="13.1.0-preview.1.25555.14" />

Inside the AppHost project, I configured the app to emit Docker Compose output:

builder.AddDockerComposeEnvironment("env");

Then I generated the publish output using the Aspire CLI:

aspire publish --output-path publish-output

This produced the .env file and docker-compose.yml needed for containerized deployment.

Continue reading “Exploring the New Aspire 13 Pipeline Model: Customizable, Flexible, and Future-Ready”

Website Powered by WordPress.com.

Up ↑