Object-Oriented Prompt Engineering for JavaEst. 2026 · MIT License
PrOOPt

“A Java library that keeps LLMs on a need-to-know basis.”

Chapter One

The What, the Why and the How

In which a coffee mug learns to delegate.

PrOOPt is an open-source Java library that applies Object-Oriented principles to LLM prompt engineering. Instead of handing your entire process to a frontier model and hoping for the best, PrOOPt lets you declare — at the function level — exactly where AI has authority and where deterministic code takes over.

Think of it as dependency injection for intelligence. You wire the model into specific annotated functions, not into your entire application. Every @PromptFunction is a governance decision. Every @CodeFunction is a line the LLM cannot cross. Every orchestrator plan is auditable from the first step to the last.

The philosophy is simple: LLMs should reason about problems, not compute answers. When you forbid computation, you force genuine reasoning.


The Closed-Book Exam

Here is a small story about a student. (Every good library starts with a small story about a student.)

When a student sits an open-book exam, they find the nearest worked example, map the new problem onto it, and substitute values. Understanding is optional. When the same student sits a closed-book exam and must show their work, understanding becomes mandatory. They must identify the problem class, recall the applicable theorem, derive each step, and verify the result. The constraint does not limit intelligence — it forces it.

A language model is the world's most well-read open-book student. Ask it to explain Gaussian elimination and it will do so with clarity and precision. Ask it to perform Gaussian elimination on a novel system of equations, and it does not reason through the steps. It predicts them. Often the answer is correct. Sometimes it is not. And critically — the model cannot tell the difference.

PrOOPt closes the book.

By making computation structurally impossible for the LLM — by routing all arithmetic, all matrix operations, all deterministic logic to @CodeFunction methods that the LLM can invoke but cannot replicate — PrOOPt removes the interpolation shortcut entirely. The LLM cannot recall an answer. It must reason toward one.


Three Annotations to Remember

That is the whole cast. Three annotations, each with a clear job and no ambitions about anyone else's.

① @PromptFunction — the prompt as a SOLID function

An LLM-backed method that behaves like ordinary Java. Write the method signature, declare the prompt template, and return null. PrOOPt intercepts the call, enriches the prompt, routes it to the declared model tier, and autoboxes the model's answer into whatever Java type you declared. Be it a LocalDate, a POJO or an enum — your return type is the contract, and PrOOPt honours it.

@PromptFunction(
    model = ModelTier.LOCAL,
    prompt = "Extract the contract date: {text}",
    description = "Extracts signing date"
)
public LocalDate extractDate(String text) {
    text = text.trim(); // optional pre-processing
    return null;        // PrOOPt takes over
}

② @CodeFunction — the line the LLM cannot cross

Marks a method as deterministic Java. It has a full implementation and is registered in the orchestrator's tool registry. The LLM knows it exists. It can invoke it. It can never replace it. Use it for math, validation, formatting, business rules, and everything deterministic. The compiler doesn't hallucinate. Neither does Math.pow().

@CodeFunction(
    description = "Computes compound interest"
)
public static double compoundInterest(
        double principal, double rate, int years) {
    return principal * Math.pow(1 + rate, years);
}

③ @PromptOrchestrator — the brain that may not do arithmetic

The autonomous agent brain. It receives your system prompt and a registry of every discovered tool, then generates a DAG execution plan — which functions to call, in what order, and which to run in parallel. The LLM reasons about the problem structure. It does not compute. It cannot compute. That constraint is not a limitation — it is the architecture of reliable intelligence.

@PromptOrchestrator(
    prompt = "You are a legal analyst.",
    planMode = PlanMode.DYNAMIC,
    model = ModelTier.CLOUD_ADVANCED,
    parallel = true
)
@PromptFunctionScan
public class LegalAnalyzer extends BaseOrchestrator {
    public static void main(String[] args) {
        PrOOPt.run(LegalAnalyzer.class, args);
    }
}

And Then the Mug Got a Sibling

PrOOPt States takes the same idea — natural language as a governed, auditable contract — and applies it to state. Annotate a plain Java object with @Persona, describe its fields with @Trait, and the LLM manages how that entity changes over time: in response to events, on schedules, even during quiet hours when it sits alone with its thoughts. Everything is persisted, queryable, and recorded in a history table with a named cause.

Game characters that remember. Synthetic citizens that form opinions. Services that keep diaries. It sounds whimsical, and it is — but it is whimsy with a database schema. Start with States: Getting Started.


The Practical Bits

Built for Java 17+ (the project baseline is Java 21, because the orchestrator likes its virtual threads). Ships with an embedded ONNX Runtime for local inference — nothing leaves the JVM unless you say so. Zero external processes. One Maven dependency. MIT licence.

Because great ideas often have humble beginnings.

PrOOPt
The mug sees everything. The mug logs everything.

PrOOPt doesn't ask you to trust the framework with your data. It asks you to read three annotations and verify for yourself.