{"slug": "build-smarter-ai-agents-use-deterministic-code-before-calling-an-llm", "title": "Build Smarter AI Agents: Use Deterministic Code Before Calling an LLM", "summary": "A developer outlined an architecture for AI agents that routes known, repeatable problems through deterministic code before escalating to an LLM, using a CI/CD failure-investigation agent as the example. In the approach, a small C# function matches known build errors such as NU1301 and CS0246 and returns tested guidance, reserving model calls for unfamiliar or ambiguous failures. The developer argues this cuts inference costs, improves response times and makes agent behavior more predictable.", "body_md": "There is a tempting assumption when building AI-powered applications: if an LLM can make a decision, why not ask it to make that decision every time?\n\nIt sounds reasonable. The model is already part of the application, it can interpret context, and it can handle a wide range of situations.\n\nBut there is a catch.\n\n**Not every problem needs reasoning. Some problems just need code.**\n\nIf an AI agent repeatedly solves the same problem, it may be time to turn that solution into a deterministic function. Doing so can reduce inference costs, improve response times, and make the system more predictable.\n\nThis is a small architectural decision with potentially significant benefits.\n\nImagine an AI agent that investigates failed CI/CD pipelines.\n\nWhenever a build fails, the agent:\n\nThis is a useful application of an LLM. Build logs can be long, unfamiliar, and sometimes ambiguous. The agent may need to connect several clues before identifying the root cause.\n\nNow imagine that the same known error appears repeatedly:\n\n```\nerror NU1301: Unable to load the service index for source.\n```\n\nAfter investigating the issue, the agent determines that the package feed is temporarily unavailable and recommends retrying package restore.\n\nThe next time the same failure occurs, should the application ask the LLM to investigate everything again?\n\nWhat about the hundredth time?\n\nProbably not. Once the pattern is understood, we can handle it with ordinary application code.\n\nFor example, we could introduce a small C# function that recognizes known build errors:\n\n```\npublic string AnalyzeBuildFailure(string logs)\n{\n    if (logs.Contains(\"NU1301\", StringComparison.OrdinalIgnoreCase))\n    {\n        return \"NuGet feed may be unavailable. Check connectivity and retry package restore.\";\n    }\n\n    if (logs.Contains(\"CS0246\", StringComparison.OrdinalIgnoreCase))\n    {\n        return \"A type or namespace could not be found. Check using directives and project references.\";\n    }\n\n    if (logs.Contains(\"401 Unauthorized\", StringComparison.OrdinalIgnoreCase))\n    {\n        return \"Authentication failed. Check the credentials or token used by the pipeline.\";\n    }\n\n    return \"Unknown failure. Further investigation is required.\";\n}\n```\n\nThis is a simplified example; a production implementation should account for log structure, error context, false matches, and the possibility that one error message has multiple causes.\n\nThe important idea is that known patterns can be handled without an LLM call.\n\nInstead of sending every failure to a model, the application can first check whether it recognizes the issue. If it does, it follows a tested path. If it does not, it can escalate the problem to the LLM.\n\nThat gives us a useful division of responsibility:\n\nDeterministic code produces the same result for the same input, assuming the same relevant state and execution environment.\n\nFor example:\n\n```\npublic decimal CalculateTotal(\n    decimal subtotal,\n    decimal taxRate)\n{\n    return subtotal + (subtotal * taxRate);\n}\n```\n\nGiven the same values, this function returns the same result. There is no need for an LLM to interpret the request or generate a calculation.\n\nCompare that with asking an LLM to calculate an invoice total. The model may produce the correct answer, but it introduces unnecessary uncertainty into a task that should be handled by precise, testable business logic.\n\nThis distinction matters:\n\n| Use deterministic code when... | Use an LLM when... | \n|---|---|\n| The rules are known and explicit | The rules need to be inferred from context | \n| The result must be precise and repeatable | The input is ambiguous or unstructured | \n| The task involves calculations or validation | The task involves interpretation or summarization | \n| The same decision is made frequently | The situation is unfamiliar or requires flexible reasoning | \n\nAn LLM is not a replacement for every function in an application. It is a tool for the parts of a problem where language understanding and flexible reasoning add value.\n\nThere are two practical principles worth keeping in mind.\n\nConsider a small business invoicing application.\n\nSome features might include:\n\nThese are ordinary business rules. They belong in application code, supported by unit tests.\n\nOther features may benefit from an LLM:\n\nThe goal is not to make the application less intelligent. It is to use the right tool for each responsibility.\n\nSuppose an agent repeatedly investigates API failures and discovers that a particular class of failures is caused by expired access tokens.\n\nInitially, the LLM may be useful because it needs to examine logs and understand the situation.\n\nBut once the pattern is confirmed, checking token expiration is straightforward:\n\n```\npublic bool IsTokenExpired(DateTime expiresAtUtc)\n{\n    return expiresAtUtc <= DateTime.UtcNow;\n}\n```\n\nThe application can now perform this check directly.\n\nThe same idea applies to repeated decisions in many domains:\n\nA repeated LLM decision is an opportunity to ask: **Can we capture what we have learned as a reliable software rule?**\n\nA practical AI agent does not need to choose between traditional code and an LLM. It can use both.\n\nConsider a simplified workflow for our CI failure investigation agent:\n\n```\n                 CI Pipeline Failure\n                          |\n                          v\n                Read and collect logs\n                          |\n                          v\n                 Check known patterns\n                          |\n                +---------+---------+\n                |                   |\n             Recognized          Unknown\n                |                   |\n                v                   v\n          Deterministic         Send context\n             handler             to LLM\n                |                   |\n                v                   v\n          Apply known fix       Investigate\n          or recommendation    and reason\n                |                   |\n                +---------+---------+\n                          |\n                          v\n                  Validate the result\n                          |\n                          v\n                 Report the outcome\n```\n\nThe deterministic path handles situations the system already understands. The LLM path handles cases that need further investigation.\n\nThere is an important engineering detail here: **recognizing a known pattern is not the same as proving its cause.**\n\nFor example, an error code may have multiple possible causes. A rule-based handler should only take an automated action when the evidence and risk level justify it. Otherwise, it should provide a safe recommendation or escalate to the LLM or a human.\n\nThis is why validation, tests, observability, and clear fallback behavior remain essential.\n\nThere is another interesting part of this idea: AI coding tools can help us create the deterministic code that reduces future LLM usage.\n\nFor example, a developer can ask an AI coding assistant to:\n\nThe generated implementation still needs to be reviewed and tested. An AI-generated function is not automatically correct just because it is deterministic.\n\nBut AI can reduce the effort required to turn a discovered pattern into maintainable, tested software.\n\nThis creates an interesting feedback loop:\n\nOver time, the system can handle a larger share of familiar situations without inference.\n\nPotentially, yes.\n\nA more capable agent does not necessarily need to make more model calls. In a well-designed system, repeated reasoning can gradually become reusable software.\n\nThat does not mean every LLM interaction should be replaced with a rule. Real-world inputs change, edge cases appear, and some decisions remain inherently ambiguous. The system still needs a way to handle cases that do not match known patterns.\n\nThe objective is not to eliminate LLM calls. It is to make each call worthwhile.\n\nA useful way to think about the architecture is:\n\nOne of the biggest opportunities in AI-assisted development may not be adding AI to more parts of an application. It may be using AI to build better software around the places where AI is genuinely needed.\n\nWhen an LLM solves a problem once, it provides an answer.\n\nWhen we understand that solution, verify it, and turn it into tested code, we create something reusable.\n\nThat code can run repeatedly, predictably, and without another inference call.\n\n**The best AI architecture may not be the one that calls an LLM for everything. It may be the one that knows exactly when not to.**\n\nAnd perhaps one of the most valuable uses of AI is helping us write the code that makes future AI calls unnecessary.", "url": "https://wpnews.pro/news/build-smarter-ai-agents-use-deterministic-code-before-calling-an-llm", "canonical_source": "https://dev.to/naimulkarim/build-smarter-ai-agents-use-deterministic-code-before-calling-an-llm-3ipc", "published_at": "2026-11-13 01:41:02+00:00", "updated_at": "2026-11-13 01:49:41.588591+00:00", "lang": "en", "topics": ["ai-agents", "ai-tools", "artificial-intelligence", "developer-tools"], "entities": ["NuGet", "C#"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/build-smarter-ai-agents-use-deterministic-code-before-calling-an-llm", "markdown": "https://wpnews.pro/news/build-smarter-ai-agents-use-deterministic-code-before-calling-an-llm.md", "text": "https://wpnews.pro/news/build-smarter-ai-agents-use-deterministic-code-before-calling-an-llm.txt", "jsonld": "https://wpnews.pro/news/build-smarter-ai-agents-use-deterministic-code-before-calling-an-llm.jsonld"}}