Local C++ AI agent using Ollama tool calling and a custom arithmetic parser for deterministic calculations.
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2026-09-13 16:56:01 -04:00
diagrams initial commit 2026-09-13 16:53:13 -04:00
agent.cpp initial commit 2026-09-13 16:53:13 -04:00
LICENSE initial commit 2026-09-13 16:53:13 -04:00
README.md Update README.md 2026-09-13 16:56:01 -04:00

Ollama Calculator Agent

A local C++ AI agent using Ollama tool calling and a custom arithmetic parser for deterministic calculations. The language model handles natural-language interaction and decides when to invoke a calculator, while a hand-written C++ parser evaluates the arithmetic expression and returns the result to the model.

Why This Project

Language models are useful for interpreting user intent, but arithmetic is better delegated to deterministic software. This project implements that separation explicitly: the model orchestrates the task; the C++ tool performs the calculation.

It is a small demonstration of several ideas used in agentic AI systems:

  • structured LLM tool/function calling;
  • tool-schema validation and dispatch;
  • deterministic execution outside the model;
  • feeding tool results back into the conversation;
  • retry and recovery logic for malformed model output;
  • conversation-state management across multi-step interactions.

Features

  • Local inference through Ollama's /api/chat endpoint
  • Ollama tool-calling API integration
  • Hand-written recursive-descent arithmetic parser
  • Standard operator precedence and parentheses
  • Unary + and -
  • Integer and decimal arithmetic
  • Division-by-zero and malformed-expression detection
  • Validation of tool names and arguments
  • Detection of tool calls emitted incorrectly as plain text
  • Clean retries from an unpolluted conversation state
  • Multi-turn interactive command-line chat

Architecture

The agent follows a simple tool-use loop:

  1. The user sends a natural-language request.
  2. The C++ application sends the conversation and Calculator tool schema to Ollama.
  3. If the model issues a valid tool call, the application validates it.
  4. The arithmetic expression is evaluated by the local recursive-descent parser.
  5. The tool result is appended to the conversation as a tool message.
  6. Ollama receives the updated conversation and produces the final answer.
  7. If a small model emits a malformed or fake tool call, the turn is retried from a clean copy of the conversation.

The calculator never uses eval, a shell, generated C++ code, or an external mathematics service.

Arithmetic Parser

The calculator uses a recursive-descent parser with the grammar:

factor     := NUMBER | '(' expression ')' | ('-' | '+') factor
term       := factor (('*' | '/') factor)*
expression := term (('+' | '-') term)*

This directly implements conventional arithmetic precedence:

Supported examples include:

1 + 1
234 * 432 + 482
-(3 + 4) * 2
12.5 / (2 + 3)

Requirements

  • C++17 or newer
  • Ollama installed and running
  • An Ollama model with tool-calling support
  • libcurl
  • nlohmann/json

The default model in agent.cpp is:

llama3.2:1b

You can change the MODEL constant to another locally installed tool-capable Ollama model.

Installation

Debian / Ubuntu

Install the C++ dependencies:

sudo apt install libcurl4-openssl-dev nlohmann-json3-dev

Install Ollama separately, then pull the default model:

ollama pull llama3.2:1b

Build

g++ -std=c++17 -O2 -Wall -Wextra agent.cpp -o agent -lcurl

Run

Make sure Ollama is running:

ollama serve

Then start the agent:

./agent

Type quit or exit to end the session.

Example

You: what is (987654 * 321 + 456789 * 123) - (7890 * 456 + 12345 * 678) + 9012 * 345

Attempt 1/10
Tool call received.
Tool: Calculator
Arguments: {"expression":"(987654 * 321 + 456789 * 123) - (7890 * 456 + 12345 * 678) + 9012 * 345"}
Result: 364363371
Agent: The result of the calculation is: 364363371

Reliability and Retry Handling

Small local models do not always follow a tool schema perfectly. A model may occasionally print something resembling a tool call as ordinary text instead of issuing a structured call.

The agent checks for these cases and retries the turn from a clean copy of the conversation:

Attempt 1/10
Attempt failed: Model returned a fake tool call as text.
Retrying with a clean attempt...

Attempt 2/10
Tool call received.

A failed attempt is not committed to conversation history. If all attempts fail, the unanswered user message is removed rather than leaving the conversation in an inconsistent state.

Scope and Limitations

This is a focused educational and portfolio project rather than a production agent framework. The arithmetic parser supports basic arithmetic but not functions, variables, exponentiation, arbitrary-precision numbers, or symbolic mathematics. HTTP requests target the default local Ollama endpoint at localhost:11434, and the retry policy is intentionally simple.

Security

Arithmetic expressions are interpreted by the custom parser only. They are not executed as shell commands, dynamically evaluated as C++ code, or passed to an external evaluator. This substantially limits the execution surface for calculator inputs, although the parser itself should still be treated as a demonstration implementation rather than a hardened production mathematics engine.

License

This project is licensed under the MIT License. See LICENSE for details.