Modern QA2026Making Agents Deterministic Enough for CI — tiles
Log inJoin
83 / 108 · 03 Agentic Testing Architectures · The Determinism Spectrum← prev⊞ allnext →☰ Read as one page

11.4Making Agents Deterministic Enough for CI

If you want to use agents in CI pipelines where non-determinism breaks builds, apply these techniques:

Technique 1: Fix the Seed

# Deterministic model output via temperature=0 and fixed seed
response = client.chat.completions.create(
    model="gpt-5.5",
    messages=messages,
    temperature=0,
    seed=42  # Fixed seed for reproducibility
)

Limitation: Even with temperature=0 and a fixed seed, LLM outputs are not guaranteed to be identical across API versions or model updates.

Technique 2: Cache Agent Decisions

class DeterministicAgent:
    """Replays cached decisions for reproducibility."""
    def __init__(self, cache_path: str):
        self.cache = self.load_cache(cache_path)
        self.step = 0

    def next_action(self):
        if self.step in self.cache:
            action = self.cache[self.step]  # Replay cached decision
        else:
            action = self.llm.decide()       # Generate new decision
            self.cache[self.step] = action   # Record for next run
        self.step += 1
        return action

    def save_cache(self):
        """Save decisions for future deterministic replays."""
        with open(self.cache_path, "w") as f:
            json.dump(self.cache, f)

How it works: On the first run, the agent generates decisions and caches them. On subsequent runs, it replays the cached decisions exactly. If the page changes and a cached decision becomes invalid, the cache is invalidated and a new decision is generated.

Technique 3: Assert on Outcomes, Not Paths

# BAD: asserts the exact sequence of agent actions
assert agent.history == [
    "navigate /login",
    "type email test@test.com",
    "type password secret",
    "click submit"
]

# GOOD: asserts the final state regardless of how the agent got there
assert agent.browser.url == "https://app.example.com/dashboard"
assert "Welcome" in agent.browser.text("h1")

This is the most practical technique. The agent may take a different path on each run, but the test passes as long as the final state is correct.

Technique 4: Measure Stability with Repeat Runs (pass^k)

Before promoting an agentic test into any pipeline, quantify its non-determinism instead of guessing:

def pass_at_all_k(test, k: int = 5) -> float:
    """Run the same test k times; it is stable only if ALL k runs pass."""
    results = [test.run() for _ in range(k)]
    return all(r.status == "pass" for r in results)

A test that passes 95% of individual runs sounds solid -- but the probability that it passes 5 consecutive runs is only 0.95^5 ≈ 77%. This "pass^k" style of repeat-run evaluation is the standard way to measure agent reliability as of July 2026, and it is covered in depth in Testing Agentic Systems.