Building Reliable AI DevOps Agents: Engineering Practices for Nondeterministic LLM Output

trunk · Tech · 2025 · source Agentic: yes · promotional bias: low · source-backed · extracted with prompt 0.5.5 (schema v2)

Generated from extraction.json — do not edit by hand. Every claim cites verbatim source evidence; stated means the quote directly asserts the claim, implied means it supports it indirectly.

Problem

Domain: AI DevOps agents for CI failure analysis

Trunk wanted an AI agent to perform DevOps and developer-experience work in CI, especially root-cause analysis for test failures, while controlling nondeterministic LLM output enough for production use.

Constraints:

Architecture

Trunk built a narrow RCA agent for CI test failures instead of an everything agent. It uses existing Flaky Tests infrastructure and historical stack traces, preprocesses and groups similar failures to fit the LLM context window, and posts summaries to GitHub PRs. The team changed from Claude to Gemini when Gemini produced more deterministic tool calls, accepted some reasoning tradeoff, and wrapped the model with system prompts, tool execution, structured output validation, capped reruns, subagents for relevant structured extraction and summarization, LangSmith observability, unit tests with mocked LLM responses, integration/e2e tests that call the LLM, and PR-comment feedback forms for internal dogfooding.

Diagram confidence: explicit (topology described by the source).

flowchart LR
  ci-failure-inputs[CI failure inputs] --> flaky-tests-history[Flaky Tests history]
  ci-failure-inputs --> failure-preprocessor[Failure preprocessor]
  flaky-tests-history --> rca-agent[RCA agent]
  failure-preprocessor --> rca-agent
  rca-agent --> gemini-model-layer[Gemini model layer]
  gemini-model-layer --> tool-execution-layer[Tool execution layer]
  tool-execution-layer --> langsmith-observability[LangSmith observability]
  rca-agent --> structured-output-validator[Structured output validator]
  structured-output-validator --> subagent-summarizers[Subagent summarizers]
  subagent-summarizers --> github-pr-comment[GitHub PR comment]
  structured-output-validator --> github-pr-comment
  github-pr-comment --> feedback-form[Feedback form]
  feedback-form --> langsmith-observability
  langsmith-observability --> test-suite[Test suite]
  test-suite --> rca-agent
Drag to pan · scroll or use +/− to zoom · reconstructed from the source's described component topology

Components

Component Role Interacts with
CI failure inputs Test failures and stack traces from CI pipelines that need root-cause analysis. Flaky Tests history, Failure preprocessor
Flaky Tests history Existing Trunk feature storing historical stack traces and infrastructure for the RCA use case. CI failure inputs, RCA agent
Failure preprocessor Groups similar failures and removes non-relevant information so CI logs and historical runs fit inside model context. CI failure inputs, RCA agent
RCA agent Examines CI failures and produces developer-facing root-cause summaries for pull requests. Flaky Tests history, Failure preprocessor, Gemini model layer, Tool execution layer, Structured output validator, GitHub PR comment
Gemini model layer Model selected for more reproducible tool calling after prompt tuning with Claude proved insufficient. RCA agent, Tool execution layer
Tool execution layer Agent tools whose executions, errors, inputs, and outputs are captured for debugging. RCA agent, LangSmith observability
Structured output validator Checks deterministic output requirements such as character limits and triggers capped reruns when cost-effective. RCA agent, Subagent summarizers, GitHub PR comment
Subagent summarizers Extract relevant structured outputs, summarize them, and funnel concise information to the user. Structured output validator, GitHub PR comment
LangSmith observability Observes agent inputs, outputs, and tool calls so failures and regressions can be investigated. Tool execution layer, Feedback form, Test suite
GitHub PR comment Developer-facing delivery channel for RCA summaries. RCA agent, Structured output validator, Subagent summarizers, Feedback form
Feedback form Attached to agent PR comments so developers can leave positive and negative feedback. GitHub PR comment, LangSmith observability
Test suite Unit, integration, eval, and end-to-end tests covering the non-LLM system and the full agent workflow. LangSmith observability, RCA agent

Data flow

A CI failure and its historical stack traces flow from Trunk's Flaky Tests infrastructure into preprocessing that groups similar failures and removes irrelevant log data. The RCA agent analyzes the reduced failure context with a model layer selected for reliable tool calls, uses tools whose executions are monitored, validates structured and user-facing output, reruns bounded failures when cost-effective, posts concise summaries to GitHub PRs, and collects developer feedback from the same PR comments. Unit tests mock LLM responses, while integration/e2e tests and LangSmith traces expose real LLM behavior and regressions across the whole workflow.

6 supporting quotes
“test for failure right away and pivot if necessary. At Trunk, we started by focusing on root cause analysis (RCA) for test failures. Our existing Flaky Tests feature stores historical stack traces from test failures in CI, so we already have a rich dataset and existing infrastructure to support”article, stated
“Our existing Flaky Tests feature stores historical stack traces from test failures in CI, so we already have a rich dataset and existing infrastructure”article, stated
“We group similar failures and remove non-relevant info so we stay within our LLM’s context limit when processing CI logs.”article, stated
“Flipping to Gemini solved the problem. Tool calls became more reproducible at the expense of some LLM reasoning.”article, stated
“we have a feedback form attached to the PR comments left by the agent so devs can leave feedback, both positive and negative.”article, stated
“We currently use LangSmith for observability of our agent’s inputs, outputs, and tool calls.) Eating our dog food helps us build confidence that what we’re doing is actually valuable. ## Lesson 4: Traditional testing is still”article, stated

Why this architecture

Trunk chose a narrow RCA workflow because small, real-data use cases make failure modes visible quickly and let the team pivot before building an overbroad agent. It switched models because prompt pressure alone did not make tool calling deterministic enough. It tests the non-LLM system with mocks while still running integration and end-to-end LLM calls because both conventional software behavior and live model weirdness matter. It validates output and uses subagents because developer-facing PR comments must be concise and actionable.

5 supporting quotes
“But access to a bunch of tools doesn’t mean the agent will know how to use them properly. Our advice: don’t build the everything agent from the start. Pick out one or two use cases, and get them working well. This will give you a good feel for writing system prompts,”article, stated
“If you start small, then you can test for failure right away and pivot if necessary. At Trunk, we started by focusing on root cause analysis (RCA) for test failures. Our existing Flaky Tests feature stores historical stack traces from test failures in CI, so”article, stated
“Tyler, one of our engineers, almost went crazy trying to tweak our main prompt so that Claude would call our tools in a more deterministic manner.”article, stated
“Set the LLM aside for a minute, it is still important to properly test the rest of your system.** We need to know that the tools we build are properly tested, that we are providing the correct information to the LLM, and that we handle structured LLM output”article, stated
“Your ability to manage the verbosity of outputs will play a big role in the end-user experience of your agents.”article, stated

Models used: Claude for early prompt/tool-calling experiments · Gemini for more reproducible tool calling · LLM network responses mocked with Vercel AI SDK tooling · Subagents for structured extraction and summarization

Scale

Alternatives considered (roads not taken)

Build an everything agent

Rejected because: A mega-prompt and many tools do not guarantee the agent will use tools properly, and broad scope delays learning from real failures.

“data as fast as possible It is tempting to build an “everything agent”. An “everything agent” can and will do anything and everything. It might be magic. It could be run on a single model, with”article, stated
“access to a bunch of tools doesn’t mean the agent will know how to use them properly. Our advice: don’t build the everything agent from the start. Pick out one or two use cases, and get them working well. This will give you a good feel for writing system”article, stated

Keep trying to prompt Claude into deterministic tool calls

Rejected because: After extensive prompt tweaking, switching to Gemini made tool calls more reproducible.

“At some point, you can only capitalize and bold markdown so many times before you start to go crazy. If “DO NOT EVER SUGGEST THAT THE USER JUST CLOSE THEIR PR” appears in your prompt, perhaps it is time for a different approach. Instead, change the”article, stated
“JUST CLOSE THEIR PR” appears in your prompt, perhaps it is time for a different approach. Instead, change the model powering your agent. Tyler, one of our engineers, almost went crazy trying to tweak our main prompt so that Claude would call our tools in”article, stated

Rely only on LLM-calling integration tests

Rejected because: The surrounding tools, inputs, outputs, and structured-response handling still need deterministic unit tests with mocked LLM responses.

“This doesn’t mean you shouldn’t run integration and end-to-end tests that call the LLM. These tests provide additional examples of potentially bad output that lead to better error handling. But this shouldn’t be the sole focus of your testing efforts. In”article, stated
“provide additional examples of potentially bad output that lead to better error handling. But this shouldn’t be the sole focus of your testing efforts. In addition to our unit tests, we have integration tests and evals for the entire workflow, providing observability into”article, stated

Feed raw CI logs and all history directly into the LLM

Rejected because: A single CI log can blow the context window, so grouping and removing irrelevant data is necessary.

“input to look like.) Secret lesson 1.1: The LLM also doesn’t need to do everything for you. Preprocess data when it makes sense. We group similar failures and remove non-relevant info so we stay within our LLM’s context limit when processing CI logs.”article, stated
“Otherwise, a single log can blow the context window, much less historical logs from the last X runs. Starting small and pivoting fast also relates to the next lesson… ## Lesson 2: Don’t be afraid to break up with your”article, stated

Let the agent write long PR-comment essays

Rejected because: Even correct information fails as user experience when developers cannot quickly find the actionable part.

“typewriters will eventually write the complete works of Shakespeare. And at any given time, an LLM might write Hamlet in a PR comment. They occasionally output like they are in high school, desperately trying to reach the assignment word limit. Good user”article, stated
“correct information that helps solve a problem, but it is a failed experience for users if the info is buried in a novel. But unlike traditional”article, stated

Patterns

eval-driven-development (quality)

Trunk combines mocked unit tests, integration tests, evals, and end-to-end workflow tests so prompt and agent changes can be measured rather than guessed.

“In addition to our unit tests, we have integration tests and evals for the entire workflow”article, stated
“makes it easier for us to catch regressions and A/B test prompt tweaks.”article, stated

model-routing (modeling)

The team changed the agent's model when empirical tool-calling reliability mattered more than Claude's reasoning quality for this workflow.

“Flipping to Gemini solved the problem. Tool calls became more reproducible at the expense of some LLM reasoning.”article, stated
“Different LLMs excel at different tasks, and it might take some experimentation to figure out which model is best suited to solve your problem.”article, stated

observability-tracing (monitoring)

LangSmith tracks the agent's inputs, outputs, and tool calls, while feedback forms expose which PR-comment results developers found useful or problematic.

“We currently use LangSmith for observability of our agent’s inputs, outputs, and tool calls.”article, stated
“provides valuable feedback so we can investigate exactly what is going on behind the scenes when we produce both good and bad outputs.”article, stated

context-compaction (context)

The system groups similar failures and removes irrelevant CI-log information to keep historical test data within the model context window.

“We group similar failures and remove non-relevant info so we stay within our LLM’s context limit when processing CI logs.”article, stated

structured-output-contract (reliability)

Trunk validates LLM inputs and outputs and reruns when deterministic output constraints, such as character limits, fail.

“So validate your inputs, your outputs, and make sure that different test cases are handled by mocking out the LLM”article, stated
“If the agent fails to meet deterministic output validation, like surpassing a character limit, we can rerun it.”article, stated

tool-use-orchestration (architecture)

The RCA agent uses tools and subagents for structured extraction and summarization, with tool executions monitored as potential failure points.

“Subagents are used to extract relevant, structured outputs, summarize them, and funnel them to the user.”article, stated
“capture usage metrics and errors at every stage where things could go off the rails, such as tool executions and LLM outputs.”article, stated

human-in-the-loop-gate (feedback)

Internal developers and project managers dogfood the agent and provide feedback before broader user exposure.

“Use what you are building. Get your team to use it. Get your project manager to use it.”article, stated
“This is the best way to get feedback before putting your agent in front of actual users”article, stated

Tradeoffs

Start with RCA for test failures

Chose A narrow CI failure-analysis agent over A general DevOps everything agent.

Rationale: A focused use case used existing failure data, exposed edge cases quickly, and produced something real users could try.

“At Trunk, we started by focusing on root cause analysis (RCA) for test failures.”article, stated
“Real data also exposes your agent to edge cases, so you can see what the LLM does when it is fed unexpected results.”article, stated

Switch from Claude to Gemini

Chose More reproducible Gemini tool calls over Claude plus increasingly forceful prompt tuning.

Rationale: Tool-call determinism mattered enough that Trunk accepted some reduction in reasoning quality.

“Flipping to Gemini solved the problem. Tool calls became more reproducible at the expense of some LLM reasoning.”article, stated
“Different LLMs excel at different tasks, and it might take some experimentation to figure out which model is best suited to solve your problem.”article, stated

Mock LLM responses in unit tests

Chose Deterministic service-style unit tests over Calling the live LLM for every test case.

Rationale: Mocking enables repeatable tests for tools, inputs, outputs, and error handling while live tests remain useful for discovering bad model behavior.

“mocking out the LLM like you would any other service when writing unit tests.”article, stated
“These tests provide additional examples of potentially bad output that lead to better error handling.”article, stated

Preprocess failure logs

Chose Grouped and trimmed failure context over Passing full CI logs and all history directly to the model.

Rationale: Preprocessing preserves relevant signal while avoiding context-window blowups from large logs.

“Preprocess data when it makes sense. We group similar failures and remove non-relevant info so we stay within our LLM’s context limit when processing CI logs.”article, stated
“We group similar failures and remove non-relevant info so we stay within our LLM’s context limit when processing CI logs.”article, stated

Use bounded reruns for deterministic output failures

Chose Rerun on validation failure when cost-effective and capped over Accepting malformed or overlong user-facing output.

Rationale: Reruns can improve output quality when prices allow, but the retry budget must be capped.

“If the agent fails to meet deterministic output validation, like surpassing a character limit, we can rerun it.”article, stated
“(Provided that reruns are cost-effective and capped at N retries. As prices of LLMs continue to drop, reruns become much more feasible.”article, stated

Gotchas (what bit them)

Prompt emphasis could not make Claude's tool calls deterministic enough.

Root cause: The team kept escalating prompt wording, but the model still did not call tools reliably for the workflow.

Resolution: Switch the model powering the agent to Gemini and accept a reasoning-quality tradeoff.

“appears in your prompt, perhaps it is time for a different approach.”article, stated
“Tool calls became more reproducible at the expense of some LLM reasoning.”article, stated

An everything-agent scope hides whether the agent can solve any task well.

Root cause: Adding many tools and a mega-prompt does not teach the model how to use them properly.

Resolution: Start with one or two use cases and test against real data quickly.

“It could be run on a single model, with one mega prompt attempting to handle multiple things.”article, stated
“Our advice: don’t build the everything agent from the start. **Pick out one or two use cases, and get them working well.”article, stated

Raw CI logs can blow the model context window.

Root cause: A single log may be too large, and historical runs multiply that context pressure.

Resolution: Group similar failures and strip non-relevant information before the LLM sees the data.

“Otherwise, a single log can blow the context window, much less historical logs from the last X runs.”article, stated
“We group similar failures and remove non-relevant info so we stay within our LLM’s context limit when processing CI logs.”article, stated

Correct RCA content can still fail the user if it is too verbose.

Root cause: The model may bury actionable information in long, essay-like PR comments.

Resolution: Treat output format as user experience, validate deterministic output constraints, and use subagents to extract and summarize.

“And at any given time, an LLM might write Hamlet in a PR comment. They occasionally output like they are in high school, desperately trying to reach the assignment word limit.”article, stated
“Good user experiences enable users to complete tasks quickly. Good UX is intuitive.”article, stated

Testing only the LLM output misses failures in the rest of the system.

Root cause: Tools, input packaging, structured output handling, and non-LLM code paths can break independently of the model response.

Resolution: Use traditional unit tests with mocked LLM responses, plus integration and e2e tests for real model behavior.

“Evaluating the output of your LLM is only part of the testing loop.”article, stated
“We use MSW and Vercel’s AI SDK mock tooling to mock the LLM network responses.”article, stated

Evaluation

Trunk evaluates reliability with layered tests and real usage feedback: unit tests mock LLM network responses, integration and e2e tests call the LLM for full workflow behavior, evals and observability catch regressions and prompt A/B effects, LangSmith traces inputs/outputs/tool calls, and developer feedback forms on PR comments expose good and bad outputs from dogfooding.

Metrics: Deterministic tool-call reproducibility · Structured input and output validation pass/fail · Character-limit and verbosity checks · Unit, integration, eval, and end-to-end workflow test results · Tool execution errors and LLM output errors · Positive and negative feedback from PR-comment forms · Regression and A/B prompt-tweak outcomes

4 supporting quotes
“We need to know that the tools we build are properly tested, that we are providing the correct information to the LLM, and that we handle structured LLM output properly.”article, stated
“In addition to our unit tests, we have integration tests and evals for the entire workflow”article, stated
“In addition to our unit tests, we have integration tests and evals for the entire workflow, providing observability into each step of the agent’s process. This is an important part of our developer experience loop and makes it easier for us to catch regressions and A/B test prompt tweaks.”article, stated
“capture usage metrics and errors at every stage where things could go off the rails, such as tool executions and LLM outputs.”article, stated

Outcomes

The source reports a focused RCA use case, one or two use cases as the recommended initial scope, a target of avoiding an agent that fails 50% of the time, dogfooding on the main Trunk monorepo, and a waitlist for a CI-failure RCA agent. It does not disclose user counts, CI volume, latency, or cost.

4 supporting quotes
“these lessons helped us build an agent that produced better output, more reliable tests so we can make incremental tweaks and measure progress”article, stated
“Eating our dog food helps us build confidence that what we’re doing is actually valuable.”article, stated
“If you’re interested in trying our AI DevOps agent (that handles RCA for flaky tests and CI failure very well), the waitlist is open.”article, stated
“AI tools don’t have to take you from 0 to 1. Going from 0 to 0.5 can still be a massive speed boost”article, stated