Semantic Kernel in a Legacy .NET Product: What Surprised Us After 6 Months in Production Blackthorn Vision, a Microsoft-partnered .NET and AI development company, replaced a custom prompt orchestration layer with Semantic Kernel in a production healthcare SaaS product. After six months, the team found that Semantic Kernel's plugin system and context management improved code testability and maintainability, but real user inputs in production caused unexpected argument formats and exceptions that staging had missed. The team added explicit input validation to every plugin function to handle noisy production data. We have been running Semantic Kernel in a production .NET SaaS product in the healthcare data space for six months. The integration replaced a custom prompt orchestration layer that the team had built directly against the Azure OpenAI SDK. It was not a greenfield project. It was a system with real users, real data, and real production constraints from day one. At Blackthorn Vision https://blackthorn-vision.com/ , a Microsoft-partnered .NET and AI development company helping enterprise teams build and modernize complex software products, we have now run several Azure OpenAI and Semantic Kernel integrations using our AI and machine learning development https://blackthorn-vision.com/machine-learning-and-ai-development/ practice and .NET development services https://blackthorn-vision.com/technologies/net-development-services/ past the demo stage and into sustained production. This post covers what we found after six months that we did not fully anticipate going in: the things that staging missed, the things we had to rebuild, and the things that worked better than we expected. The honest answer is that we did not start with Semantic Kernel. The initial integration used direct Azure OpenAI SDK calls wired into ASP.NET Core controllers. It worked for the first three months of limited rollout and covered the basic prompt-response pattern the feature needed. Two things broke it at broader rollout. The first was context management: as conversations grew longer, token costs increased significantly with every additional turn because the full history was being sent with each request. The second was plugin orchestration: the product needed the AI feature to call .NET business logic during inference, and managing that through manual function-calling patterns in the raw SDK produced code that was difficult to test and increasingly fragile. Semantic Kernel solved both. The value of Semantic Kernel is not the SDK itself. The value is giving enterprise .NET teams an orchestration layer that fits naturally into existing dependency injection, logging, security, and service boundaries. Semantic Kernel provided a structured foundation for managing context, The plugin system let us expose existing C service methods to the model as callable functions, using the dependency injection registration the application already had. The migration from raw SDK to Semantic Kernel took about two weeks and the resulting code was significantly more testable and maintainable. Most proof-of-concept implementations never encounter the issues below because they are tested with a handful of users rather than sustained production traffic. What we did not fully appreciate was how much Semantic Kernel's production behavior would differ from its staging behavior, and specifically where it would differ. In staging, we tested plugins with a defined set of representative prompts. The model called the right functions with the right arguments in almost every case. Production looked different within the first week. Real user inputs are noisier than test inputs. Users phrase requests in ways that the model interprets ambiguously. In several cases, the model called a plugin function with an unexpected argument format: an empty string where an integer was expected, a partial value where a full record identifier was required, or a null where the function assumed a populated object. The functions had no input validation because they had never needed it in staging. In production, invalid arguments caused exceptions that surfaced as generic AI feature errors, with no visibility into which plugin had been called or what argument it had received. The fix was two-part. First, we added explicit input validation to every plugin function before any business logic executes: KernelFunction, Description "Retrieves account summary for a given tenant" public async Task