Why the harness is the product
The model is not the agent. The harness is.
NVIDIA’s research on agent architecture puts it bluntly: the harness around a model “can account for double-digit swings in benchmark results and significant differences in token cost, with the same underlying model.” Swapping to a smarter model is the small lever. How you feed it context, type its outputs, let it act and persist its state is the big one.
Java teams have had excellent LLM integration libraries for years. jOpenAgent sits in a different category. It brings the six capabilities that separate an agent from a chat completion call onto the JVM, and it does so without asking you to learn a new programming model first.
A raw LLM SDK gives you
- A
Stringin and aStringout. You write the parser, the retry and the repair prompt yourself. - A context window you fill by hand, with whole objects serialised into text.
- A fixed tool menu, so anything conditional or iterative goes back through the model one turn at a time.
- State that lives only in a growing message list you have to prune.
- No trace and no span tree, so “why did it do that?” is unanswerable after the fact.
- No way to tell whether last week’s prompt change made things better or worse.
jOpenAgent gives you
- A method signature as a typed contract, bound and validated by reflection, with bounded retry that feeds the error back to the model.
- Progressive disclosure, so the model sees a bounded description of a live object rather than a text dump.
- Code as action: the model writes Java and it runs against a live
selfin a JShell sandbox. - Durable, typed state on the agent object, plus cross-session memory and self-summarising history.
- Every LLM call, tool call and code execution as a nested span, exported as JSON, ATIF, OTLP or Langfuse.
- A built-in eval harness, so a prompt change becomes a measurement instead of a hunch.