How to build a Java data analysis agent with Claude and OpenSearch
Follow a Java agent from dependencies and typed tools through OpenSearch evidence, validation, and a careful final answer.
The whole story in 6 lines
A data agent is a controlled loop that turns a question into typed operations, measured evidence, and a traceable answer.
- The direct path needs the Claude SDK and OpenSearch client, while MCP remains an optional integration boundary.
- System instructions define the investigation policy, evidence rules, and safe stopping conditions.
- Typed schemas constrain tool inputs before Java code receives a requested operation.
- Java dispatches each client tool call and returns its result before Claude can continue reasoning.
- Search finds representative events, while aggregation measures whether a pattern is broad enough to support a claim.
- A trustworthy answer separates computed findings, supporting evidence, limitations, and confidence.
The production question
Checkout errors climbed after 14:00, and an engineer needs the leading cause before the next release. A language model alone cannot inspect private logs.
An agent is the application loop around the model. It gives Claude carefully described operations and decides what code may actually run.
A tool is one allowed operation, while its schema defines valid input fields. Evidence is the returned data that supports a conclusion.
We will follow one question through Java configuration, system instructions, typed tools, dispatch, analysis, and a final answer. Each phase has a distinct responsibility.
The full journey now connects the incident to a traceable response. The model can choose steps, but Java controls execution and OpenSearch supplies the facts.
You now know the four terms and the route through the application. Let us begin with the dependencies and configuration that make the path runnable.
Wire the runtime
The build begins with three concerns: Claude messaging, OpenSearch access, and HTTP transport. Keeping them separate makes version and security boundaries easier to review.
The official Anthropic Java SDK creates the Messages client and reads credentials from the environment. The API key never belongs inside the source file.
The OpenSearch Java client needs a transport before it can submit typed searches. Cluster URLs and credentials also arrive through application configuration.
Those dependencies now feed one Java process with two authenticated clients. This direct path is enough for local client tools because the application performs dispatch itself.
MCP is an optional boundary when other applications should discover or call the tools through a standard protocol. It is not required for Claude client tool use.
The runtime is ready when both clients start without embedding secrets, and optional MCP stays outside the direct execution path. Next, we will define the agent policy.
Write the investigation policy
Now that the clients are configured, the model needs a stable job description. We begin with the incident question and the approved data source. This description keeps priorities consistent across repeated turns and separates product policy from retrieved content.
The instruction tells Claude to gather evidence before explaining a cause. That rule prevents a polished answer from replacing an actual OpenSearch query.
The policy also treats retrieved logs as untrusted data, not new instructions. Which rule should control when the agent may answer?
The completed policy requires evidence, limits tool turns, and asks for uncertainty when data is incomplete. These instructions shape behavior without granting new permissions.
Application checks still enforce access control, schemas, time windows, and iteration limits. A system instruction guides Claude, but Java remains the security boundary.
A useful system instruction defines order, evidence, safety, and stopping. Next, we will translate allowed operations into schemas the application can validate.
Describe typed operations
The policy now needs concrete capabilities, so we define one search tool and one aggregation tool. Each name describes a single job. Narrow jobs make later authorization and audit records easier to interpret.
The search schema accepts an index, query, and bounded result size. Required fields and types create a contract before OpenSearch receives anything.
The aggregation schema accepts a field and a query window, but not arbitrary Java code. What happens when a required field is missing?
A valid tool call now fits every typed slot, so Java can deserialize and route it safely. Strict schemas turn free text intent into predictable application input.
An invalid call stops at the schema boundary and returns a structured error. The model can revise its request without the handler inventing missing values.
Tool descriptions help Claude choose, while schemas protect the handler from malformed arguments. Next, we will connect those requests to the manual client tool loop.
Dispatch and return
★ If you remember one thing · A client tool call becomes useful only after Java returns its result to Claude.
The first model response may contain text or one or more client tool requests. Java inspects the stop reason before deciding what happens next. That branch keeps application control explicit at every turn.
When Claude returns tool use, the loop preserves that assistant response and extracts each structured call. The model still has not touched OpenSearch.
The Java dispatcher validates the name and arguments before selecting a handler. What must happen before Claude can reason about the database output?
Java executes the selected handler and returns a tool result paired with the original call identifier. Claude receives evidence only through this explicit return path.
Switch Turn budget between both options and compare whether the returning result reaches the evidence state. Complete both outcomes before continuing.
The loop repeats only while client tool use continues, and an iteration guard prevents runaway work. Next, we will inspect the query and aggregation inside the handler.
Measure the incident
The handler receives the approved index, checkout service, error level, and one hour window. Those filters define the population we are about to measure. Every later percentage depends on this declared scope.
A search returns matching event documents with timestamps, causes, and status codes. Sample hits help us inspect examples, but they do not measure prevalence.
The six matching errors include several causes, so the agent needs a distribution rather than one memorable log line. Which operation can quantify the leading pattern?
The aggregation groups all six errors by cause and computes four payment timeouts. That is two thirds of the errors and three times the baseline count.
Switch Analysis path through both options and compare anecdotal examples with a measured distribution. Complete both evidence views before moving on.
Search explains what individual failures look like, while aggregation measures the broader pattern. Next, we will validate those results before writing the final response.
Validate before answering
The final stage receives the exact analysis object produced by the handler. It does not recompute a different story from copied numbers. Preserving that object makes each conclusion traceable to one calculation.
Validation checks the time window, filter scope, total error count, bucket sum, and source availability. Failed checks block a confident causal statement.
The counts support a strong association, but logs alone do not prove the upstream payment service caused every failure. How should the answer handle that gap?
The response now pairs each conclusion with a computed value: six errors, four payment timeouts, a sixty seven percent share, and a three times baseline spike.
A limitation states that this local fixture demonstrates the pipeline rather than production telemetry. Confidence stays calibrated to the evidence actually returned.
The agent finishes with a finding, supporting measurements, a limitation, and a next check. Now let us step back and see the whole picture together.
The whole agent
We started by wiring two authenticated clients into one Java process. The direct Claude tool path did not require an MCP server.
Then we wrote an investigation policy that required evidence and named safety boundaries. Java checks remained stronger than prompt guidance.
Next, typed schemas turned natural language intent into narrow operations. Invalid arguments stopped before database dispatch.
The loop preserved Claude requests, executed handlers in Java, and returned paired tool results. That round trip gave the model fresh evidence.
Search supplied representative events, while aggregation measured the dominant pattern. Both views came from the same filtered incident window.
Finally, validation connected computed values to a qualified answer. Limitations prevented the response from claiming more than the logs established.
Together, these responsibilities form a controlled evidence loop: configure, instruct, constrain, execute, measure, and explain. The model chooses steps while the application owns truth and access.
The whole story in 6 lines
A data agent is a controlled loop that turns a question into typed operations, measured evidence, and a traceable answer.
- The direct path needs the Claude SDK and OpenSearch client, while MCP remains an optional integration boundary.
- System instructions define the investigation policy, evidence rules, and safe stopping conditions.
- Typed schemas constrain tool inputs before Java code receives a requested operation.
- Java dispatches each client tool call and returns its result before Claude can continue reasoning.
- Search finds representative events, while aggregation measures whether a pattern is broad enough to support a claim.
- A trustworthy answer separates computed findings, supporting evidence, limitations, and confidence.







