A RAG copilot can retrieve relevant documentation, summarize policy language, and help a user phrase a question. It should not be the final authority for totals, dates, eligibility decisions, or other outcomes where an incorrect value changes what a user can do.
The practical boundary is straightforward: use retrieval for explanatory evidence, use the language model to interpret requests and coordinate allowed operations, and use deterministic application services for exact work. This RAG copilot deterministic calculations pattern keeps the conversational experience while placing business-critical results in code with defined behavior and tests.
For Java teams, tool calling provides the connection point. Spring AI and LangChain4j document ways to expose Java functions as tools. The model can select an allowed operation and supply structured arguments, while the JVM service calculates the result. Spring AI’s tool documentation and LangChain4j’s tools guide describe these approaches.
Use RAG for evidence and tools for exact outcomes
Retrieval-augmented generation supplies external context to a model. That is useful when a user asks what a policy says, which product terms apply, or where supporting documentation can be found. Retrieval does not turn a language model into a deterministic evaluator of the policy.
Language models generate text probabilistically. A response may sound complete even when it contains an arithmetic error, applies the wrong date boundary, or omits a condition from a rule. Research on mathematical reasoning identifies failure modes in multi-step quantitative work, including errors that can compound across a reasoning chain. For an application, a plausible answer is not the same thing as a verified result. Research on LLM mathematical reasoning failures provides useful context for this limitation.
Assign each part of a request to the component that can own it:
- RAG retrieval: Finds relevant policy text, documentation, account notes, or product specifications.
- LLM: Interprets the request, asks for missing information, selects an allowed operation, and explains returned results.
- Deterministic service: Calculates values, evaluates versioned rules, and returns authoritative data from approved systems.
- React UI: Distinguishes explanatory sources from verified operation results and presents pending, completed, or unavailable states clearly.
This is a division of responsibility, not a rejection of AI. It lets a copilot remain useful without treating generated prose as a rules engine.
Decide which requests must use a deterministic service
Do not route solely because a request contains a number. “Why did my renewal price change?” may need both a deterministic quote calculation and retrieved contract or product context. A better routing question is: Would an incorrect answer affect money, a deadline, an entitlement, compliance, a record, or an operational decision?
| Request characteristic | Primary path | Example | Response content |
|---|---|---|---|
| Needs an explanation of documentation or policy | RAG plus LLM | “What does the travel policy cover?” | Explanation with retrieved references |
| Requires arithmetic or conversion | Deterministic calculation tool | “What is the prorated invoice total?” | Verified result and relevant inputs |
| Depends on dates, time zones, or calendars | Deterministic date service | “When does this trial end?” | Resolved date and applicable context |
| Evaluates a rule or entitlement | Versioned rules service | “Is this customer eligible for a refund?” | Decision and rule version |
| Combines explanation and a specific outcome | Retrieve, calculate, then explain | “Why is this claim not payable?” | Verified outcome plus supporting explanation |
| Requests a consequential change | Authorized tool with confirmation | “Apply the discount to this order.” | Proposed change before execution |
This does not require a separate microservice for every calculation. A small application can begin with a focused Spring bean or domain module. The important requirement is an authoritative implementation outside model-generated text, with defined inputs, stable semantics, and suitable tests.
Design tools as narrow, versioned contracts
A tool is an interface between a non-deterministic planner and deterministic domain code. Treat it as a product contract, not as a generic method the model may invoke.
Use explicit input types
A financial operation should receive money values and currency rather than an ambiguous decimal. A date operation should receive a local date or ISO-8601 timestamp, a named time zone where required, and any relevant calendar context. An eligibility operation should receive stable identifiers or validated domain facts, rather than a free-form summary produced by the model.
OpenAI’s function-calling guide describes defining tools with JSON Schema so a model can produce structured arguments for external functions. The schema boundary is valuable because the application can validate argument shape before it executes the business operation. OpenAI’s function-calling documentation covers this structured tool-call pattern.
Return metadata with the result
A scalar alone is rarely enough. A quote result can include the total, currency, calculation version, and effective time. A rules result can include a decision, rule-set version, contributing facts appropriate for the caller, and a user-safe reason code.
Return that metadata from the authoritative service. Do not make the model reconstruct it from a bare number. The UI can then render a structured result directly, and operational logs can preserve the versioned outcome used in the conversation.
Separate user-safe output from internal diagnostics
Tool results may contain sensitive data or implementation details that should not enter model context or the user interface. Define which fields are safe for explanation, which are safe for display, and which are reserved for service logs or authorized operators. Response shaping belongs in the service boundary and authorization model, not solely in a prompt.
Version rule semantics
Business logic changes. Including a calculation or policy version in the result gives teams a way to identify which semantics produced a response. It also supports investigation when a user sees a different result after a rule update.
A Java pattern: domain service first, tool adapter second
Start with domain code that is independently callable and independently testable. Keep the LLM-facing adapter thin: it accepts a validated request, delegates to domain code, and serializes an approved response.
Spring AI documents annotated tool methods and callback-based options for connecting application functions to chat models. LangChain4j also documents annotated tools and typed Java integrations. Spring AI and LangChain4j are implementation references, not replacements for the domain boundary.
public record ProrationRequest(
BigDecimal monthlyPrice,
LocalDate serviceStart,
LocalDate serviceEnd,
ZoneId billingZone,
String currency
) {}
public record ProrationResult(
BigDecimal total,
String currency,
String calculationVersion,
LocalDate effectiveStart,
LocalDate effectiveEnd
) {}
@Service
public class ProrationService {
public ProrationResult calculate(ProrationRequest request) {
// Domain logic is implemented and tested independently of the model.
throw new UnsupportedOperationException("Implement domain calculation");
}
}
The example deliberately does not prescribe a proration formula. Products differ on period definitions, inclusivity, rounding, credits, and tax treatment. Those decisions belong in approved domain logic and test cases, not in a tool description or prompt.
The adapter should expose only the operation that the copilot needs. Its description should state what the tool calculates, which inputs it requires, and what it excludes. Avoid a generic tool that grants access to unrelated business operations.
Constrain model orchestration and execution
A model can request a tool call, but application code should validate and execute it. Anthropic’s tool-use documentation likewise describes schema-defined tools that are executed by client-side application code. Anthropic’s tool-use documentation illustrates the same boundary: structured model output is not permission to perform unrestricted work.
Apply practical controls at execution time:
- Authorize the user for the underlying operation, not just for access to chat.
- Validate tool arguments as untrusted input.
- Allowlist tool names, identifiers, enum values, and action scopes.
- Return an explicit unavailable state when an authoritative system cannot verify a result.
- Record the tool name, normalized inputs, result version, request identity, and correlation information with appropriate data minimization.
- Require confirmation before mutations or other consequential actions.
The model can still explain a returned result conversationally. However, the amount, decision, date, and version shown as authoritative should come from the deterministic response rather than model-generated prose.
Build React UX around provenance and status
A dependable backend can still confuse users if the UI renders retrieved passages, generated explanation, and verified results as indistinguishable chat text. Model the conversation as typed events instead of a single markdown stream.
Useful message parts include retrieved citations, a pending tool request, a completed calculation result, an approval request, and a narrative response. This lets React render each item with an appropriate component and state.
The Vercel AI SDK documents tool definitions, tool execution, and UI integration patterns for chat applications, including tool invocation states. Its tools documentation is useful for understanding the UI implications of tool calling: execution has states beyond plain assistant text.
Render verified results as structured UI
Place a compact result component near the assistant response. It can show the operation label, verified result, relevant inputs, effective date or time zone where applicable, and calculation version. Use wording such as “Verified calculation” only when a deterministic service actually returned the result.
Represent pending and failed verification honestly
While an operation runs, show that the system is checking a rule or calculating a value. When an authoritative source is unavailable, state that the result could not be verified. Do not present generated text as a substitute for a verified answer.
Keep explanatory and operational sources distinct
A retrieved policy document may explain the rule, while a rules service decides a particular case. Render document citations with explanatory text and rule-version metadata with the decision. That distinction helps users understand both the basis for the explanation and the source of the exact outcome.
Implementation checklist
- Identify copilot intents involving money, dates, permissions, eligibility, compliance, or operational state.
- Name the authoritative service and owner for each intent.
- Define typed request and response contracts, including units, currencies, time zones, and rule versions where relevant.
- Test domain behavior for boundary conditions, invalid input, and applicable historical rules.
- Expose only necessary operations through focused tool adapters.
- Validate and authorize every tool call when it executes.
- Return machine-readable metadata alongside user-safe explanatory fields.
- Render retrieval and deterministic outputs as distinct React message parts.
- Add confirmation for mutations and preserve an appropriate audit record for executed actions.
- Test tool failures, malformed arguments, stale data, and denied permissions as chat flows.
FAQ
Can a RAG system calculate simple totals?
It can generate an answer, but a total that matters to users or operations should be calculated by deterministic code. A service provides defined inputs, repeatable behavior, and test coverage.
Do we need a microservice for every calculation?
No. The boundary can start as a well-owned module or Spring bean. Extract a separate service when ownership, deployment, scaling, or reuse needs justify it.
Should the LLM receive the full tool result?
Provide only the fields needed for the explanation. Decide separately what the React UI may display, and keep sensitive diagnostics or irrelevant data out of model context.
How can the UI show that an answer was verified?
Attach structured tool-result metadata to the chat event, including the operation, outcome, and logic version. Render it in a dedicated component instead of relying on the model’s prose to claim verification.
Sources
- Spring AI Tool Calling Reference Documentation
- LangChain4j Tools and Function Calling Guide
- OpenAI Function Calling Guide
- Vercel AI SDK Tools and Tool Calling Documentation
- Large Language Models and Mathematical Reasoning Failures
- Anthropic Tool Use Documentation
Editorial note: AI assisted with research and drafting. Sources were selected for verification.
Full-Stack Developer & Solutions Architect · Casablanca, Morocco
7+ years building Java/Spring Boot/Angular enterprise solutions. Former Senior Software Engineer at NTT Data and Satec. Authorized Google Workspace and Microsoft 365 Partner for Morocco.