Quick answer

LLM software development has to design for three properties of large language models: probabilistic output, knowledge limited to the context window, and fluent output that can be confidently wrong. Each property breaks a traditional engineering assumption, so reliable teams add evals, context engineering, and layered verification. Skipping these practices produces features that pass demos and fail in production.

When a large language model (LLM) feature misbehaves or a coding agent breaks a build, the usual fix is a sharper prompt and another code review. Over time, that fix stops holding, and 66% of software developers in the 2025 Stack Overflow Developer Survey named almost-correct AI output as their biggest frustration. Trust stays low in turn, with only 6.6% of respondents to the 2026 edition willing to rely on AI for important decisions.

The cause is that teams use traditional software engineering practices with LLMs. Those practices were built for components that behave the same way every time, and LLMs do not. LLMs differ from traditional components in three ways: their output is probabilistic, they know only what is in their context window, and they sound just as confident when they are wrong. Each of these properties breaks an assumption that traditional practices rely on, so each needs a practice of its own, whether the LLM runs inside the product or helps the team build it.

Why Do LLMs Break the Assumptions of Traditional Software Development?

LLMs generate output by predicting likely text rather than executing fixed logic, and that difference breaks three assumptions traditional software development relies on:

  • Traditional components return the same output for the same input, yet LLMs are probabilistic and can answer one prompt differently on every run.
  • Traditional components know the system they belong to, while an LLM knows only what sits in its context window.
  • Broken code traditionally fails visibly, whereas an LLM fails fluently, so wrong output reads as convincingly as right output.

Because of these, LLM software development needs its own engineering practices on top of standard software development processes.

Diagram outlining three core LLM properties in software development, contrasting traditional assumptions with modern agentic engineering practices.
LLM Software Development: 3 Properties to Design For

These three properties matter wherever a team uses LLMs, and the Software Engineering Institute at Carnegie Mellon separates two such places:

  • LLM features inside the product, the territory of LLM application development and generative AI development services.
  • LLMs in the development process, from code completion in coding assistants to autonomous coding agents.

The same properties and the same practices apply to both product features and AI-augmented software development. The table below maps each property to the assumption it breaks and the practice that replaces it.

Traditional assumption
LLM property
What breaks
Practice that replaces it

Same input, same output

Probabilistic output

Assertion-only tests, reproducible bugs

Evals alongside tests

The component knows the system

Knowledge limited to the context window

Consistency with codebase, domain rules, recent decisions

Context engineering

Wrong output fails visibly

Fluent output that can be confidently wrong

Trust in plausible output; review at generation speed

Layered verification

LLM property

Probabilistic output

Knowledge limited to the context window

Fluent output that can be confidently wrong

What breaks

Assertion-only tests, reproducible bugs

Consistency with codebase, domain rules, recent decisions

Trust in plausible output; review at generation speed

Practice that replaces it

Evals alongside tests

Context engineering

Layered verification

 

Teams work with AI coding assistants and agents in different interaction patterns, and the patterns differ mainly in how much they account for the three properties. At one end sits vibe coding, a low-structure, prompt-and-accept style in which a developer describes the goal and accepts the code generated in reply. It skips the practices the three properties call for, which is acceptable for prototypes, technical exploration, and simple tasks.

At the other end, agentic engineering puts AI to work inside human-defined specs, tests, evals, and feedback loops, so those practices are built into every step. That structure is the basis of a mature agentic development workflow.

Since both sit on one spectrum, a team moves along it as the stakes of its software engineering tasks rise. The three properties decide where production work belongs, so any system that touches real users, real data, or real money needs the structure of agentic engineering at every step.

Property 1: Why Are LLMs Probabilistic, Not Deterministic?

LLMs are probabilistic because they generate output through next-token prediction, sampling likely tokens one at a time, so the same input can produce different outputs. A low temperature narrows that variation, but it does not guarantee identical results. Model updates, context changes, and serving infrastructure also shift behavior between runs.

This non-determinism changes what a passing result means. A green run becomes one sample among many, a reported bug may refuse to reproduce, and a model upgrade can change behavior with no code change at all. For example, a support assistant can answer a refund question correctly on Monday and cite the wrong policy on Tuesday, and a coding agent asked twice to refactor the same module can return two different structures.

A practical check is to ask the same question more than once and compare how much the answers vary. It also helps to avoid asking an LLM for any answer that ordinary code can compute, although asking the model to write that code remains a sound use of code generation.

What changes: from tests to evals (LLM evaluation)

LLM evaluation replaces the single pass or fail check with scoring across many runs.

Tests
Evals

Checks

Deterministic code: given X, return Y

Result

Pass/fail

Runs

Once per change

Built from

Specs and edge cases

Still needed?

Yes, for all deterministic code around the model

Tests

Checks

Result

Runs

Built from

Still needed?

Evals

Deterministic code: given X, return Y

Pass/fail

Once per change

Specs and edge cases

Yes, for all deterministic code around the model

 

Within an eval suite, output evaluation judges the final answer a model or agent produced. Trajectory evaluation goes a step further by judging the sequence of steps and tool calls an agent took, which is the core of knowing how to evaluate AI agents before production.

Comparison table contrasting traditional deterministic software tests with probabilistic LLM evals, detailing differences in checks, result formats, run frequency, and underlying dataset requirements.
LLM Evaluation: Tests vs Evals

Many eval suites also rely on LLM-as-judge scoring, where a second model grades outputs against a rubric. Since the judge is probabilistic too, its scores earn trust only after calibration against human-labeled examples.

Sergii Leleko SPD Technology

Serhii Leleko

AI & ML Engineer at SPD Technology

“A green test run on an LLM feature tells you that one sample passed. We set the release threshold on the eval pass rate across repeated runs. Every production failure also becomes a new eval case, because a failure that is not in the set tends to come back with the next model upgrade.”

Serhii Leleko, AI & ML Engineer at SPD Technology

In practice, a working LLM evaluation framework runs evals in CI on every prompt, model, or context change, with a threshold that blocks release when the pass rate drops. The eval set starts from golden datasets and grows with every failure seen in production, which is the central discipline of eval engineering for an early product.

Property 2: Why Does the LLM Context Window Limit What a Model Knows?

LLMs only know what is in their context window because every call is stateless. On each call, the model works from its training data, which stops at a training cutoff, plus whatever sits in the current LLM context window.

Anything outside those two sources is invisible to the model, so gaps in code context show up quickly. A coding agent, for example, writes an endpoint with its own error-handling style and data format because nobody told it the existing code already defines both. A product assistant answers a pricing question from outdated training data and behaves differently between sessions, because each one starts empty.

Supplying more information has limits too, because the LLM context window is finite and its effectiveness is uneven across its length. Long or noisy context degrades output quality, a pattern practitioners call context rot. It happens because the model’s attention spreads across everything loaded, so irrelevant files and stale instructions dilute the signal the task needs. Every extra token also adds cost and latency per request, which makes up a large part of what AI-assisted development really costs.

What changes: context engineering replaces prompt engineering

Most teams begin with prompt engineering, which tunes the wording of a request, often through reusable prompt templates.

Diagram illustrating context engineering for LLMs, splitting context window elements into static components and dynamic components to prevent context rot.
Context Engineering: An LLM Knows Only What Is in Its Context Window

Context engineering widens the scope to everything the model sees for a task, so prompt wording becomes one small part of a larger design that replaces ad hoc context construction.

Context type
What it holds
Static or dynamic

Instructions

Rules, conventions, role

Static (rule files such as AGENTS.md or CLAUDE.md)

Knowledge

Docs, specs, code, domain data

Dynamic (retrieval, RAG)

Memory

Decisions and state across sessions

Static or dynamic

Examples

Reference implementations, good outputs

Dynamic

Tools

APIs, search, test runners the model can call

Dynamic (loaded when needed)

Guardrails

Constraints and forbidden actions

Static

What it holds

Rules, conventions, role

Docs, specs, code, domain data

Decisions and state across sessions

Reference implementations, good outputs

APIs, search, test runners the model can call

Constraints and forbidden actions

Static or dynamic

Static (rule files such as AGENTS.md or CLAUDE.md)

Dynamic (retrieval, RAG)

Static or dynamic

Dynamic

Dynamic (loaded when needed)

Static

 

Static context loads on every call, so it should stay short and stable. Dynamic context, by comparison, arrives per task through retrieval and RAG, so its value depends on being findable and accurate when the task asks for it.

For coding agents, the static layer usually lives in rule files such as AGENTS.md or CLAUDE.md, which hold team conventions, architectural constraints, forbidden patterns, and the commands for running unit tests. Those files form one part of the harness, meaning the rule files, tools, sandboxes, hooks, and evals that surround a coding agent, and designing that whole setup is the work of agent harness engineering. Instructions for specific programming tasks can sit in separate skills that load only when needed, and every one of these context assets deserves versioning, review, and an eval run before it changes.

Property 3: Why Can LLMs Be Fast but Confidently Wrong?

LLMs can be fast but confidently wrong because they produce the most plausible continuation of their input with no built-in check of correctness. As a result, wrong output arrives with the same fluency as right output, which makes it one of the costliest LLM limitations.

In coding tasks, this behavior shows up as invented APIs or functions, code snippets that compile and still miss edge cases and business logic, and hallucinated package names. Product features show the same pattern, for example when a support answer cites a return policy the company never had and delivers it in the same calm tone as a correct one.

Across a coding project, these small errors add up to an imbalance in effort. AI produces the boilerplate code and most of a feature quickly, while the remaining work on edge cases, integration, error handling, and correctness takes disproportionate time and human expertise. That imbalance shapes how teams should plan and review AI-generated code.

Hallucinated package names also open a supply-chain attack called slopsquatting, in which attackers register the invented names, and it ranks among the main AI-generated code security risks. A USENIX Security 2025 study shows how wide that opening is, because across 576,000 code samples generated with 16 LLMs in two programming languages, Python and JavaScript, hallucinated-package rates averaged at least 5.2% for commercial models and 21.7% for open-source models. Taken together, those samples contained 205,474 unique invented package names that an attacker could register.

Agents add a further exposure called the lethal trifecta, in which an agent that combines private data, untrusted input, and a way to send data out can be steered by prompt injection into leaking that data. That risk is set by what the agent can reach, so the fix is to break the trifecta: scope its data access, treat external input as untrusted, and gate any outbound action.

What changes: layered verification sets the pace

When advanced code generation capabilities produce output in seconds, the time needed to establish correctness sets the limit on delivery speed.

Flow diagram illustrating a layered verification model for LLM outputs, moving through deterministic checks, evals, guardrails and hooks, risk-based human-in-the-loop review, and observability.
LLM Limitations: Layered Verification for Fast but Confidently Wrong Output

Layered verification responds by stacking cheap automated checks beneath scarce human judgment, so each layer catches what the one before it lets through.

Layer
What it catches
Examples

Deterministic checks

Syntax, types, regressions, known vulnerabilities, unknown dependencies

Tests, type checks, linters, SAST, dependency allow-lists

Evals

Quality and behavior drift in LLM output

Eval suite in CI with thresholds

Guardrails and hooks

Forbidden actions, policy breaches, unsafe tool use

Pre-commit hooks, scoped permissions, output filters

Human-in-the-loop by risk

Wrong architecture, money, personal data, security

Required approval for high-risk changes; lighter review for low-risk ones

Observability

Failures that only appear in production

Logged prompts, outputs, tool calls, and quality signals

What it catches

Syntax, types, regressions, known vulnerabilities, unknown dependencies

Quality and behavior drift in LLM output

Forbidden actions, policy breaches, unsafe tool use

Wrong architecture, money, personal data, security

Failures that only appear in production

Examples

Tests, type checks, linters, SAST, dependency allow-lists

Eval suite in CI with thresholds

Pre-commit hooks, scoped permissions, output filters

Required approval for high-risk changes; lighter review for low-risk ones

Logged prompts, outputs, tool calls, and quality signals

 

At the policy layer, well-designed guardrails stop forbidden actions and unsafe tool use at the moment an agent attempts them. Production observability then closes the loop by logging prompts, outputs, and tool calls and tracking quality signals alongside platform health metrics.

Across all layers, review effort follows risk. Human-in-the-loop approval covers expensive decisions about money, personal data, architecture, and security, while automated gates handle low-risk changes and routine code suggestions. That split lets review keep pace with generation and shifts the core engineering skill from manual coding toward verification and judgment.

Want a practical method for deciding when generated code can ship? Read our guide on how to trust AI-generated code.

 

How Do the Three Properties Reshape the Software Development Lifecycle?

The three properties reshape the software development lifecycle by moving work from writing code toward specifying intent, curating context, and verifying output. Each stage keeps its purpose, so existing software engineering processes adapt as their inputs, from natural language descriptions to generated code, change.

SDLC stage
Before LLMs
With LLMs, designed for the three properties

Requirements

Tickets and conversations

Specs with acceptance criteria an agent and an eval can use (spec-driven development)

Design

Architecture documents

Architecture plus context assets: rule files, examples, constraints

Implementation

Engineers write code

Agents implement inside a harness; engineers direct and decompose

Testing

Unit and integration tests

Tests for deterministic code plus evals for LLM behavior

Review

Line-by-line review of everything

Risk-based review; automated gates handle volume

Operations

Monitoring uptime and errors

Plus observability of model behavior, cost, and drift; controlled model upgrades

Before LLMs

Tickets and conversations

Architecture documents

Engineers write code

Unit and integration tests

Line-by-line review of everything

Monitoring uptime and errors

With LLMs, designed for the three properties

Specs with acceptance criteria an agent and an eval can use (spec-driven development)

Architecture plus context assets: rule files, examples, constraints

Agents implement inside a harness; engineers direct and decompose

Tests for deterministic code plus evals for LLM behavior

Risk-based review; automated gates handle volume

Plus observability of model behavior, cost, and drift; controlled model upgrades

 

The biggest shift in the table starts at the requirements stage, where spec-driven development has an explicit specification and acceptance criteria ready before any agent implements. That way, the agent and the eval work from the same definition of done. Applied ticket by ticket, that discipline becomes spec-first development, which keeps implementation details tied to agreed intent.

The engineer’s role shifts along with the process, and IBM principal research scientist Kaoutar El Maghraoui describes engineers moving from producing code to curating it. In practice, engineers and software architects become system designers and quality arbiters, which is the shift that lets AI-native development teams ship faster. Under this factory model, the team builds and maintains the system that produces the software, stopping well short of fully automated software engineering.

Operations change in a similar way, since model upgrades become controlled releases with evals run on the candidate model before any switch. Teams that self-host an LLM also gain control over exactly when that switch happens.

What Should Engineering Leaders Change First in LLM Software Development?

Engineering leaders should start where unreliability costs the most, which in LLM software development usually means missing evals and missing context assets. Risk-based verification comes next, once the team can measure whether an LLM-dependent behavior improved or degraded after a change.

Beyond the feature itself, leaders also need to measure delivery from the first week. Google’s DORA 2025 State of AI-assisted Software Development report links AI adoption to higher delivery throughput and to higher delivery instability at the same time. A team that tracks speed or developer productivity alone therefore sees the first effect and learns about the second only through incidents.

In practice, the first rollout comes down to a short checklist, roughly in this order:

  • Build a first eval set of 50 to 100 cases for one LLM feature or agent workflow and run it in CI.
  • Write a short, versioned rule file for coding agents and move task-specific instructions into retrievable context.
  • Define which changes require human approval, starting with money, personal data, architecture, and security.
  • Add dependency allow-lists and automated checks for LLM-generated code.
  • Log prompts, outputs, and tool calls for LLM features in production.
  • Treat model upgrades like dependency upgrades by running evals before switching.
  • Measure delivery outcomes such as change failure rate, rework, and cost of change, and set aside the share of AI-written code as a success metric, since the ROI of AI-assisted software engineering shows up in those outcomes.

Progress shows up in delivery metrics, which is how AI-enhanced development velocity can be tracked over time. For teams bringing in a partner, the same sequence also helps define scope and success criteria when starting an AI-assisted engineering engagement.

Ready to test a release against these practices? Run it through our AI production-ready checklist.

 

Why Choose SPD Technology for LLM Software Engineering

SPD Technology builds LLM software that survives production by designing for all three properties. Evals, context, and verification are part of our AI/ML development services from the first sprint. That approach draws on 20 years of custom software delivery, with one team accountable for both software architecture and execution.

In client work, that approach shows up in several ways:

  • Evals as the release gate. Every LLM-dependent behavior is scored against a threshold before release, and a named senior engineer approves each release.
  • Context and harness the client owns. The iconic US landmark project’s monorepo now holds 47 custom skills, 6 subagents, and 19 slash commands that carry the team’s conventions, a setup described in the AI-engineering case for an iconic US landmark. With those conventions codified for coding agents, the repeat client’s output in 2026 rose 89% against the 2025 baseline at constant headcount, while code-review throughput doubled and human-reported bugs fell 81%. Comparable harness work runs through our agentic AI development services.
  • Verification matched to risk. Incident response time fell from more than 60 minutes to under 30 minutes to a PR-ready fix once SPD Technology built the AI incident pilot for a US fintech/SaaS platform. Because the AI resolves up to 70% of incidents correctly, the platform needs less 24/7 on-call engineering, and every fix still arrives as a pull request for human review.
  • Production-proven LLM features. A French B2C fashion retailer needed a support chatbot that would hold up under peak load. Running on LangChain with a Mistral LLM and RAG grounding on AWS, the chatbot answers 99% of queries in under 10 seconds and kept 100% uptime during peak hours at 30 requests per second.
  • Claude expertise. SPD Technology is an Anthropic partner with Claude-certified architects. That expertise feeds directly into building production AI with Claude, where the same three practices apply.

Deciding who should help you with an AI-assisted project? See our guide on how to choose an AI development partner.

 

Key Takeaways

  • Because LLMs have probabilistic output, a single passing test run proves only that one sample passed, so LLM-dependent behavior needs evals that score many runs against a release threshold.
  • Knowledge limited to the context window means missing conventions and domain rules produce wrong output that prompt rewording alone cannot repair, so context engineering has to supply the missing knowledge.
  • Fluent output that can be confidently wrong makes verification the limit on delivery speed once generation becomes fast, which is why layered verification decides how fast a team can safely ship.
  • Tests verify the deterministic code around the model and evals verify the model’s behavior, so production LLM software needs both suites running in CI.
  • When review effort follows risk, human approval stays on money, personal data, architecture, and security, and review keeps pace with generated code.
  • Running evals before every model upgrade prevents silent behavior changes in production, the same way tests gate dependency upgrades.
  • One set of practices covers both LLM features in a product and coding agents in a team, because the same three properties apply in both places.

In short: software built on LLMs becomes dependable when teams design for probabilistic output with evals, for knowledge limited to the context window with context engineering, and for fluent output that can be confidently wrong with layered verification.

FAQ

  • Why are LLMs non-deterministic?

    LLMs generate text by sampling likely next tokens, so the same input can produce different outputs. Lowering the temperature reduces that variation but does not guarantee identical results. Model updates, changes in context, and differences in serving infrastructure can also shift behavior between runs. Software that uses an LLM therefore needs evals that run each case many times and score the results against a threshold, so one lucky run never decides a release.