DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Related

  • Why Your DLP Policies Fall Short the Moment AI Agents Enter the Picture
  • RAG Is Not Enough: Advanced Retrieval Architectures Using Vertex AI Search on GCP
  • The Developer's Guide to Context-Aware AI: When Your Code Documentation Becomes Intelligent
  • Hallucination Has Real Consequences — Lessons From Building AI Systems

Trending

  • Why Round-Robin Won't Save You: Load Balancing Challenges in Data Streaming Services With Heterogeneous Traffic
  • Compliance Automated Standard Solution (COMPASS), Part 11: Compliance as Code, the OSCAL MCP Server Way
  • The Hidden Cost of AI Tokens: Engineering Patterns for 10x Resource Efficiency
  • Data Contracts as the "Circuit Breaker" for Model Reliability
  1. DZone
  2. Popular
  3. Open Source
  4. Deterministic AI With OpenSymbolicAI

Deterministic AI With OpenSymbolicAI

An agentic solution that follows the PlanAndExecute approach can leverage the power of LLMs while executing deterministic code to provide reliable results.

By 
Karthik Viswanathan user avatar
Karthik Viswanathan
·
Mar. 06, 26 · Tutorial
Likes (0)
Comment
Save
Tweet
Share
2.3K Views

Join the DZone community and get the full member experience.

Join For Free

While AI agents have shifted programming away from deterministic algorithms toward probabilistic LLMs, there remains concern that the lack of determinism makes an agentic solution inherently unreliable. The question comes down to this: Is non-determinism acceptable?

The answer depends on what the solution is for. For creative endeavours such as ideation or writing fiction, non-deterministic responses can be a strength. But I'm sure we can agree that software that relies on precise results, such as those used in finance or scientific research, cannot accept non-determinism.

How to Achieve Deterministic Solutions While Leveraging the AI Agents

While approaches such as RAG and fine-tuned models can help with data accuracy, many solutions call for algorithmic precision that can only come from traditional Software Engineering principles.

OpenSymbolicAI provides a solution to this by implementing the PlanAndExecute paradigm instead of the commonly used the ReAct paradigm.

ReAct (Reason + Acting) is the standard pattern behind most "tool calling" agents. It works through a Thought-Action-Observation loop. In this pattern, the results of any tool call are passed back to the LLM, which then reasons about what to do next.

PlanAndExecute is a different approach. The LLM creates a plan for what to do (specifically, which code to run), then it executes the plan using deterministic code — code that you have written. 

OpenSymbolicAI provides an implementation of this approach in Python. Let's see how it works.

Implementation

Install the module using uv:

uv add opensymbolicai-core

Create an agent that defines operations. This example shows a calculator agent that performs mathematical operations.

Python
 
from opensymbolicai.blueprints import PlanExecute
from opensymbolicai.core import decomposition, primitive
from opensymbolicai.llm import LLMConfig


class Calculator(PlanExecute):
    """A calculator that answers math questions."""
    def __init__(self, llm: LLMConfig | None = None) -> None:
        if llm is not None:
            super().__init__(
                llm=llm,
                name="Calculator",
                description="A calculator that performs mathematical operations.",
            )


    @primitive(read_only=True)
    def add(self, a: float, b: float) -> float:
        """Add two numbers."""
        return a + b

    @primitive(read_only=True)
    def divide(self, a: float, b: float) -> float:
        """Divide a by b."""
        return a / b


    @decomposition(
        intent="What is 10 plus 5?",
        expanded_intent="Add 10 and 5",
    )
    def _add_example(self) -> float:
        result = self.add(a=10, b=5)
        return result

    @decomposition(
        intent="What is 15% of 200?",
        expanded_intent="Divide percentage by 100, then multiply by value",
    )
    def _percentage_example(self) -> float:
        decimal = self.divide(a=15, b=100)
        result = self.multiply(a=decimal, b=200)
        return result


Primitives are the basic operations your agent can use. The @primitive decorator exposes a method as a tool that the LLM can call.

Decompositions are examples that teach the agent how to break down complex problems. The LLM uses these to learn the pattern, then applies it to new questions. The @decomposition decorator exposes a method as a pattern that the LLM can apply to handle an intent derived from a prompt.

The Calculator class extends the PlanExecute class provided by the library. This makes its primitives and decompositions available for the LLM to use. The initializer takes an LLMConfig object that will be used to configure the LLM settings, such as the provider and model.

Running the Agent

This example uses Ollama as the LLM provider:

Python
 
from opensymbolicai.llm import LLMConfig, Provider

from Calculator import Calculator

if __name__ == '__main__':
    config = LLMConfig(
        provider=Provider.OLLAMA,
        model="gpt-oss:20b",
    )

    question = "What is 20% of 500?"
    calc = Calculator(llm=config)
    print(f"question = {question}")
    response = calc.run(question)

    print(f"answer = {response.result}")


Output:

Shell
 
question = What is 20% of 500?
answer = 100.0


When you ask, "What is 20% of 500?", the agent:

  1. Looks at the decomposition example for percentages
  2. Divides 20 by 100, then multiplies by 500
  3. Executes each step using your primitives
  4. Returns the final answer

Interactive Mode

You can also run agents interactively:

Python
 
while True:
    query = input(">>> ")
    if query.lower() == "quit":
        break
    response = calc.run(query)
    print(f"answer = {response.result}")


Interactive output:

Shell
 
>>> what is 20 plus 10?
answer = 30
>>> multiply 15 and 10
answer = 150


Here, I ask a slightly more complex question:

Shell
 
>>> What is 10 plus 5 minus 10?
answer = None


There is no answer, as I haven't defined a primitive for minus (or subtraction). Also, there is no definition for how to handle multiple operations in the same question.

Now, I add a primitive for subtraction and decompositions to allow the LLM to learn how to do subtraction and how to chain multiple operations:

Python
 
@primitive(read_only=True)
def subtract(self, a: float, b: float) -> float:
    """Subtract two numbers."""
    return a - b


@decomposition(
    intent="What is 10 minus 5?",
    expanded_intent="Subtract 5 from 10",
)
def _subtract_example(self) -> float:
    result = self.subtract(a=10, b=5)
    return result

@decomposition(
    intent="What is 10 plus 5 minus 10?",
    expanded_intent="Add 10 and 5 and subtract 10 from the result",
)
def _add_and_subtract_example(self) -> float:
    result = self.add(a=10, b=5)
    result = self.subtract(a=result, b=10)
    return result


I re-run the program and ask the question again. This time, I get the correct answer:

Shell
 
>>> What is 10 plus 5 minus 10?
answer = 5


While this example is very basic, it illustrates the power of an LLM coupled with precise algorithms. Such a solution is testable in the traditional sense — you can expect the same output for the same input. This is something you cannot do when relying solely on the LLM for outputs.

OpenSymbolicAI allows you to trace the plan it follows for execution. This lets you find gaps and fix them through code. It can be used with various LLM providers and also allows integration with RAG. You can use it in conjunction with tools like Claude Code to accelerate development.

For more on OpenSymbolicAI, visit the blog: https://www.opensymbolic.ai/blog. It is open source. Git repo is here: https://github.com/OpenSymbolicAI/core-py.

For more examples, check out: https://github.com/OpenSymbolicAI/examples-py.

AI RAG Open source

Opinions expressed by DZone contributors are their own.

Related

  • Why Your DLP Policies Fall Short the Moment AI Agents Enter the Picture
  • RAG Is Not Enough: Advanced Retrieval Architectures Using Vertex AI Search on GCP
  • The Developer's Guide to Context-Aware AI: When Your Code Documentation Becomes Intelligent
  • Hallucination Has Real Consequences — Lessons From Building AI Systems

Partner Resources

×

Comments

The likes didn't load as expected. Please refresh the page and try again.

  • RSS
  • X
  • Facebook

ABOUT US

  • About DZone
  • Support and feedback
  • Community research

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 215
  • Nashville, TN 37211
  • [email protected]

Let's be friends:

  • RSS
  • X
  • Facebook