Contents
  1. Engineering around learned behavior
    1. What the application can guarantee
  2. Contracts and boundaries
    1. Specify obligations at interfaces
    2. Separate responsibilities that change
      1. Policy and external operations
      2. Keep design visible during change
  3. State and effects
    1. Enforce invariants when state changes
    2. Track effects and unknown outcomes
      1. Safe repetition
  4. Evidence from tests
    1. Test application behavior
      1. Cases and properties
    2. Check integrations and model usefulness
  5. Failure investigation
    1. Reproduce at a useful boundary
      1. Replay and fresh inference
    2. Test explanations of a failure
      1. Preserve the finding
  6. Controlled change and release
    1. Make changes reviewable
    2. Identify the tested release
    3. Bound exposure and verify recovery
      1. Restoration and remediation
  7. Check understanding
  8. Open questions
  9. Selected talks
  10. References
  11. Talk library
← All topics

Software Engineering Fundamentals

A model can return data your program accepts while still getting the task wrong. Software engineering helps you define how the application handles that data, enforce rules when changing state, and investigate failures. The goal is to keep the system understandable, testable, and manageable as it changes. This requires distinguishing two questions: does the application uphold its obligations, and does the model perform its task usefully? Tests, diagnostic experiments, and release checks provide different evidence for answering them.

Engineering around learned behavior

What the application can guarantee

A model learns behavior from data: training shapes how it makes predictions or generates content, rather than a programmer specifying every decision directly. Machine Learning Fundamentals explains that distinction in detail.

The surrounding application turns a model response into a defined outcome. It can accept data that meets its declared contract or return an explicit validation failure for the caller to handle. Tests can supply dependency failures to check those handling paths, while an audit record preserves which check failed and why. These boundaries give the programmer specific behavior to inspect and improve.

Software tests check whether the application enforces those rules and handles the supplied outcomes correctly. Model evaluations examine whether its predictions serve the intended task: a permitted label can still misclassify the input, even when the model returns it consistently. Trainline describes this combination in Shipping complex AI applications: conventional software checks work alongside evaluations of model behavior. Both kinds of evidence matter, because explicitly programmed code can contain defects too.

The useful next step is to name those obligations. Once a component states what it accepts, what success means, and how failure appears, its callers have something concrete to check.

Contracts and boundaries

Specify obligations at interfaces

A type describes permitted values. A union can permit several alternatives; a function type describes accepted arguments and returned values. An interface names what a component exposes to callers. In TypeScript, an interface describes an object’s shape, but a descriptive name does not enforce its meaning: naming a string type “sanitized” does not sanitize its contents. The TypeScript Handbook makes these distinctions concrete.

A behavioral interface also carries obligations. A precondition states what must hold before an operation; a postcondition states what successful completion promises. An assertion makes a condition executable so a violation can be detected. Bertrand Meyer’s 1992 article Applying Design by Contract organized these responsibilities as an agreement between caller and implementation. At an untrusted boundary, the application must establish the relevant conditions before proceeding.

Checks establish separate properties

Example

A structurally valid record can still fail application checks.

The candidate reaches an eligible-proposal state only after both checks pass. Eligibility does not establish classification correctness or commit a change.
Read the diagram as text
  • Candidate record. Identifier and proposed label.
  • Validate structure.
  • Reject invalid data.
  • Check application constraints. Record exists; label is eligible.
  • Reject ineligible proposal.
  • Eligible proposal. Meaning remains to be assessed.
  • Candidate recordValidate structure: inspect.
  • Validate structureReject invalid data: fails.
  • Validate structureCheck application constraints: passes.
  • Check application constraintsReject ineligible proposal: fails.
  • Check application constraintsEligible proposal: passes.

Static checking examines code before execution. Runtime validation examines values that actually arrive. TypeScript erases ordinary type annotations when producing JavaScript, so annotating a parsed response does not install a runtime check. External data still needs inspection.

A schema supplies machine-checkable rules for that inspection. Validation should produce an explicit outcome callers can handle. For example, Zod’s safeParse returns either validated data or an error, distinguished by a success flag. This keeps invalid input from being mistaken for an ordinary result. Validation establishes only the rules encoded in the schema.

Consider a model proposing a record identifier and a label, such as {"id":"t1","label":"billing"}. Structural validation checks field presence and permitted values. Application checks establish whether the record exists and whether that label is eligible for it. Neither check establishes that the text actually concerns billing. That is a question about the classification’s meaning, requiring evidence beyond its shape.

Microsoft’s July 20, 2023 TypeChat announcement applied this boundary to generated JSON: TypeScript definitions guided output, compiler checks tested conformance, and diagnostics could request repair. Applications could then perform further processing or user validation. This is machine-readable output—data another program can consume. Structured Outputs and Tool Calling develops its generation and execution mechanisms.

Separate responsibilities that change

A module is useful when it hides a decision that callers should not need to understand. David Parnas’s December 1972 paper On the Criteria To Be Used in Decomposing Systems into Modules contrasted two decompositions of a keyword-index program. Organizing around processing stages exposed decisions that could spread changes across the system. Hiding storage and other changeable decisions behind interfaces let callers remain stable. The enduring question is which knowledge a boundary keeps private.

Cohesion groups responsibilities that logically belong together. Loose coupling allows one component to change without forcing another to change. Keeping domain rules separate from persistence and messaging helps preserve that distinction. Splitting code into services does not automatically reduce coupling; these principles also guide modules inside one application.

Hide implementation decisions

Example

The coordinator depends on responsibilities; external representations remain behind adapters.

Arrows show dependencies, not execution order. This illustrative arrangement can live in one process. A provider change may be contained by its adapter, while changed model behavior still requires evaluation.
Read the diagram as text
  • Application coordinator. Connects results without owning every implementation detail.
  • Model adapter. Hides provider requests and response envelopes.
  • Conversion and validation. Accepts data or returns explicit validation failure.
  • Application policy. Decides eligibility from explicit inputs.
  • Storage interface. Owns persistence operations and their outcomes.
  • External model service.
  • Database.
  • Application coordinatorModel adapter: depends on model interface.
  • Application coordinatorConversion and validation: depends on data contract.
  • Application coordinatorApplication policy: depends on policy decision.
  • Application coordinatorStorage interface: depends on persistence contract.
  • Model adapterExternal model service: depends on provider API.
  • Storage interfaceDatabase: depends on database operations.

A deep module hides substantial functionality behind a simple interface. Callers can use that functionality without understanding all its internal dependencies. Matt Pocock applies John Ousterhout’s deep-module principle in Software Fundamentals for AI Coding: group related behavior so developers and coding agents can locate and test it through a clear boundary. Depth concerns functionality relative to interface complexity, not a target number of files or lines.

Policy and external operations

One useful boundary separates decisions from operations. A pure function returns the same result for the same inputs and does not change pre-existing external state. Passing needed information explicitly removes hidden dependencies on mutable globals.

Gary Bernhardt’s 2012 Functional Core, Imperative Shell account applied that separation to a Twitter client. The core worked with values and decisions; the shell performed terminal, database, and network operations. This leaves decisions independently testable and reduces branching inside the code that performs effects.

For a model-assisted application, distinguish provider communication, conversion and validation, application policy, and persistence when they conceal different decisions. Dependency injection means supplying a dependency to a component instead of having the component construct it. Passing a model client as a function argument creates a substitution point; no framework is necessary.

Separation has costs. In Building Reliable Support Agents Using Effect, dependency substitution supports failure tests, but provisioning becomes difficult to trace across many layers. A wrapper earns its place by hiding a meaningful decision or providing a useful substitution point. Otherwise, it adds navigation without reducing what callers must understand.

Keep design visible during change

Those boundaries also need names that mean the same thing in discussion and code. Keep a shared design vocabulary of domain terms and a map of module responsibilities and interfaces. Use it during planning to describe which responsibility will change and how its callers will be affected. A glossary helps when its meanings guide both the conversation and the implementation.

With that boundary in place, work in steps small enough to check before extending them. Tests at the interface give feedback about behavior while refactoring changes the internals. Their usefulness still depends on choosing the right behaviors and deciding which dependencies to substitute. This connects architecture to iteration: clear, testable boundaries let developers and coding agents check a change without understanding every implementation detail at once.

Code boundaries also have behavioral limits. The 2015 paper Hidden Technical Debt in Machine Learning Systems showed how data dependencies, configuration, and feedback can couple apparently separate components. A provider adapter can contain an API change, but an unchanged interface does not establish that a replacement model makes equally useful predictions. Modularity limits implementation knowledge; behavioral compatibility still needs evidence.

State and effects

Enforce invariants when state changes

State is information that affects subsequent behavior. A transition changes that information; an invariant describes a condition valid observable states must preserve. An operation’s contract states its immediate obligations, while an invariant connects those obligations across operations. It generally must hold at the relevant entry and exit boundaries, not during every internal instruction.

Give the mutation boundary responsibility for preserving those conditions. The model supplies a proposal; the application decides whether it becomes an accepted fact. That distinction prevents a generated claim about completion from serving as its own evidence of a state change.

Reject a stale proposal

Example

Stale proposals cannot overwrite newer state.

1 / 3 · Read

Read version 3; propose a label.

Version comparison and mutation happen together.
Read the diagram as text
  • Record t1.
  • Snapshot: version 3.
  • Proposed label: billing.
  • Snapshot: version 4.
  • Conditional update.
  • Conflict; no write.
  • Record t1Snapshot: version 3: earlier snapshot.
  • Snapshot: version 3Proposed label: billing: basis.
  • Record t1Snapshot: version 4: later snapshot.
  • Proposed label: billingConditional update: expects 3.
  • Snapshot: version 4Conditional update: current: 4.
  • Conditional updateConflict; no write: mismatch.
  1. Read. Read version 3; propose a label. Active: Record t1, Snapshot: version 3, Proposed label: billing. New: Record t1, Snapshot: version 3, Proposed label: billing.
  2. Concurrent change. Another writer commits version 4. Active: Record t1, Snapshot: version 3, Proposed label: billing, Snapshot: version 4. New: Snapshot: version 4.
  3. Attempt update. Expected 3 differs from current 4; reject without writing. Active: Record t1, Snapshot: version 3, Proposed label: billing, Snapshot: version 4, Conditional update, Conflict; no write. New: Conditional update, Conflict; no write.

Checking before saving is not always enough. Two workers can read the same state, independently produce reasonable changes, and then overwrite each other. The second save loses the first worker’s update. Coordination belongs at the shared mutation boundary; independent reads and other work can remain concurrent.

Optimistic concurrency control checks that state is still current when applying a change. For one PostgreSQL row, an UPDATE matches the record identifier and the proposal’s expected version, then increments the version in the same atomic operation. A mismatch rejects the write. Every relevant writer must advance the version; multi-row invariants need additional protection.

Track effects and unknown outcomes

A side effect is an observable change beyond a function’s returned value, such as updating a database or sending a message. A satisfactory final answer says little about whether the operations used to produce it were acceptable. Separating a proposed change from the code that applies it creates a place to inspect the proposal before effects occur.

A local database transaction groups changes so they commit together or are discarded together. An application can therefore commit an operation result and its associated status in one transaction when both live in that database. An unrelated remote API call does not automatically join the transaction. Rolling back local records cannot establish that the remote system changed nothing.

One timeout, two possible histories

Example

The same client observation can conceal different remote states.

These are alternative histories, not concurrent operations. A timeout alone cannot distinguish an unapplied request from a committed change whose reply was lost.
Read the diagram as text
  • Remote mutation requested.
  • Remote state: unchanged.
  • Remote state: changed.
  • Completion reply lost.
  • Client: outcome unknown.
  • Remote mutation requestedRemote state: unchanged: request never executes.
  • Remote mutation requestedRemote state: changed: request executes.
  • Remote state: unchangedClient: outcome unknown: deadline expires without reply.
  • Remote state: changedCompletion reply lost: effect precedes acknowledgment.
  • Completion reply lostClient: outcome unknown: deadline expires without reply.

The remote effect and the caller’s knowledge are separate facts. A server may complete an operation while its response arrives after the caller’s deadline. Cancellation also does not roll back changes already made. Preserve an unknown outcome until authoritative status or reconciliation resolves it; neither a timeout nor a cancellation request establishes that repeating the action is safe.

Safe repetition

Idempotency means repeated application of the same logical operation has the same intended effect. It is a property the receiving implementation must enforce. A genuinely new operation with similar arguments may legitimately cause another effect. Recording a workflow step does not itself prevent duplicate external execution when an attempt completes its effect but fails to report its result.

Stripe’s idempotency contract illustrates why details matter. It saves the first executing request’s status and body under a key, including server failures, and rejects changed parameters. Validation failures and concurrent-execution conflicts before execution do not create saved results. Keys may be removed once at least 24 hours old; reuse after removal starts a new request. These cases require different handling, not one blanket “retry errors” rule.

Keep the operation identity while resolving an ambiguous result. Durable execution provides machinery for preserving work and continuing after interruption, but does not supply universal exactly-once external effects. Agent Runtimes and Harness Engineering develops persistence, retries, and recovery beyond this application boundary.

Evidence from tests

Test application behavior

A unit test checks a focused unit of behavior against specified expectations. A fixture supplies the preparation and cleanup needed for the test, such as an initial database. A test suite groups checks for execution. These terms describe how evidence is organized; suite membership does not establish that every requirement is covered.

A test double is a controlled substitute for a dependency. At the dependency seam, it can supply a fixed model response or raise an error. The test then establishes how the application handles that supplied behavior. It does not establish that the real model will produce the response, or how often. The substitute’s fidelity—its resemblance to the real dependency—limits the conclusion.

Derive assertions from the obligations already assigned to each boundary.
ResponsibilityControlled conditionObservable assertion
ParsingMalformed responseAn explicit failure reaches the caller.
ValidationUnknown labelThe candidate is rejected.
PolicyRecord is ineligibleNo accepted change is produced.
State transitionAcceptance condition failsStored state remains unchanged.
Effect handlingRemote acknowledgment is missingThe outcome remains unresolved, not failed.

Assert public behavior rather than private storage layouts or helper calls. A test that breaks when an internal representation changes can obstruct a correct refactoring. Conversely, a test that never checks the promised state change can pass while the application is broken.

Cases and properties

Table-driven testing runs the same check over explicit input-and-expectation pairs. pytest parametrization provides this mechanism directly. It is useful when valid, invalid, and boundary cases share one assertion structure.

Property-based testing checks an executable property over generated inputs. For example, generate proposals that violate an acceptance condition and assert that rejection leaves stored state unchanged. QuickCheck separates the property from the generator, whose admissible values and distribution need deliberate choices. Both can be wrong: if the test copies a validator’s implementation, it may repeat the same defect instead of detecting it. Finite passing cases provide evidence, not a proof over every input.

Check integrations and model usefulness

Integration tests exercise real components together. Contract tests check their described boundary agreement. Pact, for example, first tests a consumer against supplied responses and records its expected interactions. Provider verification then sends those requests to the provider and checks actual responses, with required starting conditions established for each interaction. This tests whether substitute-based assumptions agree with the provider; it does not establish complete workflow correctness or imply that a particular model provider supports Pact.

A test oracle is the rule or reference used to decide whether a result satisfies a criterion. Model evaluation gathers evidence about intended task performance. Its oracle can be an exact database assertion, a model grader, or human judgment; evaluation does not necessarily mean asking another model to score an answer. Evals and Benchmarks covers task selection, grading, and comparisons.

CheckQuestion answeredStill unproven
Unit test with a doubleDoes local code handle supplied behavior?Actual dependency behavior.
Integration or contract checkDo these components honor tested interactions?Untested workflows and task meaning.
Task evaluationDoes the system meet these success criteria?Behavior outside the examined tasks and conditions.

Keep live checks identifiable separately from repeatable local tests. They consume requests, depend on service availability, and may return varying results. Sampling more responses costs more work; provider errors and changed configuration defaults can also invalidate comparisons. A failed live run should distinguish an unavailable dependency from a completed trial with a poor answer.

Literal text equality is useful when literal text is the interface. The llmeval demonstration showed a mathematical answer failing because additional explanation violated an answer-only requirement. Where equivalent wording is acceptable, an exact snapshot instead makes wording changes look like defects. Assert the property callers need, and normalize whitespace only when the contract makes it irrelevant.

Failure investigation

Reproduce at a useful boundary

Reproduction recreates the conditions needed to observe a failure. A minimal reproducer removes circumstances while retaining that failure. Its purpose is to make the problem inspectable, not to preserve every detail of the original environment.

Preserve what explains the affected boundary: relevant input and initial state, code and configuration identities, dependency responses, and operation order. For consequential actions, retain the operation identity, attempts, and external evidence as well. A final conversational answer cannot reconstruct which operation was authorized or what the receiver confirmed.

Freeze the response, not the world

Example

Replay fixes one dependency result while downstream state remains a separate input.

Live inference and replay are alternative paths. Replay reuses a saved response; it does not verify current provider behavior or automatically restore clocks, database state, or scheduling.
Read the diagram as text
  • Model request.
  • Live model call. Produces a new response.
  • Saved response. Fixed recorded value.
  • Validation and policy. The boundary under investigation.
  • State and configuration. Must be arranged separately.
  • Observed application behavior.
  • Model requestLive model call: alternative: fresh inference.
  • Model requestSaved response: alternative: select recording.
  • Live model callValidation and policy: new response data.
  • Saved responseValidation and policy: recorded response data.
  • State and configurationValidation and policy: execution inputs.
  • Validation and policyObserved application behavior: result or failure.

Replay and fresh inference

VCR.py records HTTP interactions and supplies saved responses on later matching requests. Its strict replay mode rejects new requests rather than contacting the service. Applied to a model client, this freezes the response entering downstream code. Re-recording obtains a new response and changes the fixture.

Rerunning inference asks the model to generate a new response. In OpenAI’s archived November 2023 example, fixed seeds and request parameters improved repeatability but did not guarantee identical responses, even when the server fingerprint—a marker for model weights, infrastructure, and other server configuration—also matched. Saving the returned response preserves the historical value; saving those settings alone does not.

Saved output also does not restore database contents, clock values, or concurrent scheduling. Choose the boundary according to the failure: replay can isolate a parser defect while leaving a timing-dependent race unreproduced.

Preserve only necessary diagnostic data. VCR.py supports configured filtering of headers, request fields, and response bodies; those controls do not automatically make a recording safe. Removing credentials is useful, but removing failure-relevant content can destroy the reproducer. Check that the filtered fixture still exhibits the intended failure.

Observability supplies recorded signals for understanding execution, including calls, timing, and state transitions. Observability develops the instrumentation and retention infrastructure. Here, the goal is narrower: preserve enough evidence to run a useful diagnostic experiment.

Test explanations of a failure

A symptom is an observation; its cause is an explanation to test. State expected and actual behavior, propose competing explanations, and choose an intervention that distinguishes them. Recent changes suggest hypotheses, but timing alone does not establish causation. Keep unrelated conditions fixed where possible: changing code, model settings, and data together makes the result difficult to interpret.

Suppose malformed input crashes an application that promises an explicit rejection. Keep initial state and configuration fixed while testing these explanations.
HypothesisControlled experimentSupported conclusion
The reply violates the input contract.Validate the captured reply.Rejection establishes nonconformance, not its cause.
The application mishandles invalid input.Inject that reply through its client interface.A crash violates the promised rejection behavior.
The repair fixes rejection behavior.Compare old and repaired code using that reply.An explicit failure supports the repair for this case.

An upstream violation and a downstream defect can coexist. Locating the first observed violation narrows the investigation; it need not explain every failure. A fresh model response that happens to be valid does not exercise the broken rejection path. Repeated calls can characterize variability, but one successful rerun cannot establish that the application was repaired.

Preserve the finding

Delta debugging makes difficult cases smaller through repeated tests. Zeller and Hildebrandt’s February 2002 paper automated removing input fragments while retaining a failure, motivated partly by the effort of simplifying Mozilla bug reports. Its ddmin procedure reaches a case where no single remaining element can be removed successfully. That is neither necessarily the globally smallest case nor an explanation of the defective code. The failure check must keep identifying the same problem.

A regression is previously working behavior that breaks after a change. Turn the confirmed defect into a test of the missing obligation, so later changes retain the finding instead of requiring someone to rediscover it.

Controlled change and release

Make changes reviewable

Version control records revisions and exposes differences for inspection. A focused change has one coherent purpose, with related tests and enough context to assess its consequences. Small does not mean a universal line limit. Keep each submitted change working; separate substantial refactoring from behavior changes where practical, but include mutually dependent edits needed to make one change understandable.

Refactoring changes internal structure while preserving observable behavior, including relevant state effects. A deliberate behavior change makes a different claim and needs evidence for the new obligations.

A compact change record connects the proposed difference to its evidence.
RecordContent
IntentThe behavior to preserve or change.
DifferenceChanged code, instructions, model settings, dependencies, or relevant data artifacts.
Affected obligationsChanged assumptions, interfaces, state transitions, and effects.
EvidenceChecks performed, versions exercised, and remaining uncertainty.

Continuous integration automatically builds and checks integrated changes. Its evidence extends to the checks actually run. Prompt edits and schema changes need appropriate regression and boundary checks too, even when they happen outside application code. Scheduled failures also need to become visible rather than silently leaving old output in place.

Review examines whether assertions would fail for broken behavior, whether concurrency assumptions hold, and whether complexity serves a purpose. Passing tests do not answer those questions automatically. User-facing changes may also need a demonstration because their consequences are difficult to infer from a diff.

Review has a collaborative role as well. How to Kill the Code Review argues that architectural discussion, mentorship, and shared understanding must survive changes to implementation verification. Automated evidence can support that discussion; it does not establish that the team agrees on the intended behavior.

Identify the tested release

A release artifact is the packaged output deployed to an environment. Its identity differs from a source revision, a configuration revision, or a moving label such as “canary.” Verification should identify the exact release it exercised, including relevant configuration.

IdentityWhat it establishes
Source revisionWhich source was selected.
Build inputsDependencies, environment, and instructions used.
Artifact identifier or hashWhich packaged output is being tested or deployed.
Configuration revisionSettings paired with that artifact; include instructions and model settings where relevant.
Verification recordWhich checks exercised that release and with what outcomes.

A reproducible build recreates identical specified artifacts from the same source, environment, and instructions. Comparing bytes or cryptographic hashes checks that property. A source revision alone is insufficient. Retaining a deployable artifact and being able to rebuild it are distinct capabilities; neither reconstructs mutable runtime state.

Mainline tests may not cover a release assembled with selected fixes. Check the actual release revision and packaged artifact where their behavior matters.

External dependencies may not remain available. Anthropic’s model lifecycle documentation distinguishes deprecated models, which still function pending retirement, from retired models, whose requests fail. Partner schedules can differ. Saving an identifier therefore does not preserve the service behind it; availability must be checked when planning restoration.

Bound exposure and verify recovery

A canary release exposes a change to limited use before expansion. Compare candidate and control metrics separately: aggregate results can hide candidate failures. Choose representative traffic and an observation period that exercises relevant conditions, with acceptance and stop criteria set beforehand. There is no universal percentage or duration. Limited exposure reduces affected use; it does not make each harmful outcome acceptable.

A feature flag is runtime configuration that controls behavior. Disabling a capability differs from restoring an earlier configuration. Agents Need Feature Flags emphasizes checking controls during active work, at the next decision point, rather than only when a session starts. That can prevent further actions; it does not establish interruption of an executing tool or reversal of completed effects.

Restoration has prerequisites

Restoring software and remediating completed effects are separate operations.

Restore only an available, compatible target, then verify behavior. Completed effects require separate remediation; switching software does not erase them.
Read the diagram as text
  • Prior release.
  • Current state.
  • Available and compatible?.
  • Restore and verify.
  • Contain and investigate.
  • Completed effects.
  • Separate remediation.
  • Prior releaseAvailable and compatible?: input: availability.
  • Current stateAvailable and compatible?: input: compatibility.
  • Available and compatible?Restore and verify: control: yes.
  • Available and compatible?Contain and investigate: control: no.
  • Completed effectsSeparate remediation: requires remedy.

Restoration and remediation

Rollback restores a previously deployed version or configuration. Retain a concrete restoration target and its required configuration. After switching, verify the selected artifact, settings, and relevant observable behavior; a completed deployment command alone is not evidence that the intended service has recovered.

An older executable must also work with current state. Amazon’s rollback-safety account illustrates a new version writing compressed data its predecessor cannot read. Restoring that predecessor creates another failure. Establish compatibility before treating an available old artifact as a usable recovery target.

Completed effects require separate treatment. Compensation performs a new, business-specific action to counter earlier work. It may incur costs, preserve intervening changes, or produce a different final state. It can itself fail. Some effects require an acceptable remedy or human intervention because no operation can erase what already happened.

The release decision therefore depends on consequences as well as evidence. Identify what live exposure can safely teach, what must be established before exposure, and what remains after stopping. A clinical utterance, for example, cannot be withdrawn from the patient’s experience by rolling back software. Better offline task results and passing application tests are valuable, but neither supplies a recovery path for an irreversible action.

Open questions

  1. Behavioral compatibility across model replacements remains difficult to specify. Stable interfaces contain implementation changes, while learned behavior can shift across inputs and downstream consumers. Progress would make those behavioral dependencies easier to identify and test without promising complete isolation.

  2. Evidence of task usefulness remains bounded by its success criteria. Precise checks miss omitted requirements; open-ended graders need calibration. Progress would improve agreement with meaningful human outcomes while making each check’s limits explicit.

  3. Recovery becomes harder when dependencies cannot be retained and effects cannot be undone. Progress would provide tested restoration targets and explicit remedies that preserve service continuity without misrepresenting mitigation as reversal.

Follow the curated reading path through the speakers and demonstrations behind this entry.

19 min

AI Engineer Summit 2023 · 2023

Pragmatic AI With TypeChat

Daniel Rosenwasser

Cited in this entry

A concrete model-to-application boundary: types guide generated data, validation checks it, and diagnostics support repair. Type conformance still leaves interpretation to assess.

Watch talk
19 min

AI Engineer World's Fair 2026 · 2026

Agents Need Feature Flags

Sachin Gupta

Cited in this entry

Develops runtime control of prompt exposure and tool access, particularly why active work must observe a shutdown decision at subsequent decision points.

Watch talk

Explore more talks

The rest of the library, beyond the curated path. Cited talks support this entry; reviewed transcripts were processed in full. Metadata candidates have not been reviewed as sources or verified as topic members.

20 matching talks

TalkSpeakerEventYear
Respect The Process

Transcript reviewed

Andrew DumitAI Engineer World's Fair 20262026
Omar KhattabAI Engineer World's Fair 20252025
Dan MasonAI Engineer World's Fair 20252025
DottaAI Engineer World's Fair 20262026
Erik MeijerAI Engineer World's Fair 20262026
Vinoth GovindarajanAI Engineer World's Fair 20262026
Sandipan BhaumikAI Engineer Europe 20262026
Vikash Agrawal, LindaAI Engineer World's Fair 20252025
Fuzzing in the GenAI Era

Transcript reviewed

Leonard TangAI Engineer World's Fair 20252025
Niklas NielsenAI Engineer Summit 20232023
Sumaiya ShrabonyAI Engineer World's Fair 20262026
Lukas PeterssonAI Engineer World's Fair 20262026
Eugene YanAI Engineer World's Fair 20262026
Lukas BiewaldAI Engineer World's Fair 20242024
How to Kill the Code Review

Cited in this entry

Ankit JainAI Engineer World's Fair 20262026
Kyle MisteleAI Engineer World's Fair 20262026
Tomas ReimersAI Engineer World's Fair 20252025
Jared JoselowitzAI Engineer World's Fair 20262026
Nishant GuptaAI Engineer World's Fair 20262026
Matt PocockAI Engineer Europe 20262026

References

Coverage and source review
Processed transcripts
25 processed in full · 5 in the curated path
Automated source review
Passed
Metadata candidates
0 unreviewed; not verified topic membership
Corpus version
1bd8e407b26a07b33815594e1b2db5f41827119a2b3cb6fbf240f9fc571fc767

Automated review checks source support; it is not publication approval.

A synthesis of selected conference talks and technical references. Citations link to the source material; they do not imply that every talk on this subject is included.

  1. Google: What is Machine Learning?

    Machine learning trains software to make predictions or generate content using data. Google's rainfall example contrasts explicitly implemented physical equations with relationships learned from weather observations. This supports a brief distinction between programmed rules and learned predictions.

  2. Pragmatic AI With TypeChat

    TypeChat uses the same types to guide model output and validate the resulting data.

  3. Building Reliable Support Agents Using the Effect TypeScript Library - Michael Fester

    Effect dependency injection lets the platform substitute mock LLM providers and simulate failures while retaining the same application internals.

  4. Every Solo Agent Builder Eventually Reinvents a Worse Version of CI/CD

    An audit trail should identify the failed gate, violated contract, and reason without requiring the entire pipeline to run again.

  5. Shipping complex AI applications | Braintrust & Trainline

    Trainline treats agentic systems as a combination of deterministic software and nondeterministic model behavior, requiring quality controls from both.

  6. TypeScript Handbook: Everyday Types

    Types describe admissible values: boolean covers true and false, while a union admits values from its member types. Function annotations describe accepted arguments and returned values. An interface names an object type. Ordinary type aliases do not create distinct categories: the handbook's alias named UserInputSanitizedString still accepts an arbitrary string. Consequently, naming a type after a desired property does not establish that the property was checked.

  7. Applying Design by Contract

    A precondition is an obligation the caller must establish before invoking a routine. If it holds, the supplier owes the stated postcondition on successful completion. A class invariant describes consistent observable object states: creation establishes it and exported routines preserve it between entry and exit; it need not hold during every internal instruction. The caller can establish a precondition by reasoning from prior guarantees rather than necessarily testing it again. Application inference: a generated typed record supplies candidate data, not proof of caller authorization, business postconditions, or state invariants. The application must establish relevant obligations before acting and verify promised results or represent failure explicitly.

  8. TypeScript Handbook: The Basics

    TypeScript removes type annotations when producing JavaScript; the annotations do not change runtime behavior. Its documented compilation example retains the function body but removes parameter types. Application implication: annotating a parsed model response with a TypeScript interface does not install runtime checks on incoming values.

  9. Zod: Basic usage

    Zod validates runtime input against a schema. Its parse method returns validated data or throws a validation error identifying failed checks. safeParse instead returns a discriminated result: a success flag identifies either validated data or an error. The documentation demonstrates branching on that flag before accessing the corresponding value. Static types can also be inferred from the schema, keeping the declared shape and runtime checks connected.

  10. JSON Schema: Objects

    A schema can constrain object structure and field types, but declaring a property does not make it required. The required keyword enforces presence, while additionalProperties can reject unrecognized fields. These checks belong in application code when accepting structured model proposals. A valid object can still name the wrong account or contain an unsupported answer: structural validation checks the declared data contract, not external facts or permission to perform an operation.

  11. Introducing TypeChat

    Microsoft announced TypeChat as an experimental library on July 20, 2023, to connect natural-language requests with existing applications. It describes checking generated JSON against TypeScript definitions using the compiler and returning validation errors for repair. Its sentiment example permits three labels and branches explicitly between translation failure and successful data. The application can perform further processing or user validation after receiving a well-typed response.

  12. On the Criteria To Be Used in Decomposing Systems into Modules

    Parnas treats a module as an assigned responsibility rather than necessarily a subroutine. His keyword-index example contrasts modules organized around processing stages with modules that hide storage and other design decisions. In the latter arrangement, changing the representation of stored lines need not change its callers. He recommends beginning with difficult decisions or decisions likely to change, then concealing each behind an interface. The paper also warns that a naive implementation can introduce procedure-call overhead.

  13. Azure Architecture Center: Design for evolution

    Cohesion means grouping functionality that logically belongs together. Loose coupling means one service can change without requiring another to change. Microsoft recommends keeping domain rules within the component responsible for them and separating domain logic from infrastructure such as messaging and persistence. Splitting an application into services does not automatically remove tight coupling.

  14. "Software Fundamentals Matter More Than Ever" — Matt Pocock

    Apply John Ousterhout's deep modules: substantial functionality behind simple interfaces, rather than many shallow modules with complex interfaces.

  15. React: Keeping Components Pure

    A pure function returns the same result for the same inputs and does not change pre-existing objects or variables. React's example shows how reading and incrementing an external counter makes results depend on call order. Passing the needed value as an explicit input removes that hidden dependency.

  16. Functional Core, Imperative Shell

    Gary Bernhardt describes a Twitter client whose functional core handles values and decisions while an imperative shell performs terminal, database and network operations using those results. Separating these responsibilities makes the functional pieces independently testable and leaves fewer conditionals in the code that performs effects.

  17. Software Engineering at Google: Test Doubles

    A test double substitutes for a real dependency. Dependency injection creates a substitution point by passing a dependency to a component instead of constructing it internally; the book demonstrates this without requiring a framework. Controlled substitutes can return fixed values or trigger rare errors without contacting an external service. Their fidelity is how closely they resemble the real implementation. A test can establish the application's response to supplied behavior while leaving the real dependency untested. The authors recommend supplementing such tests with checks using real implementations and warn that excessive stubbing creates brittle tests.

  18. Building Reliable Support Agents Using the Effect TypeScript Library - Michael Fester

    The platform uses Effect schemas for runtime validation, encoding, decoding, and typed inputs and outputs, with annotated schemas also generating API documentation.

  19. Building Reliable Support Agents Using the Effect TypeScript Library - Michael Fester

    Dependency injection can make service provisioning difficult to trace across layers and subsystems.

  20. "Software Fundamentals Matter More Than Ever" — Matt Pocock

    Create and actively use a domain-driven design (DDD) ubiquitous language shared by the user, agent, and codebase.

  21. "Software Fundamentals Matter More Than Ever" — Matt Pocock

    Include the module map in the ubiquitous language and explicitly describe module and interface changes in PRDs.

  22. "Software Fundamentals Matter More Than Ever" — Matt Pocock

    Use test-driven development (TDD) to constrain the agent to small steps within the available feedback rate.

  23. "Software Fundamentals Matter More Than Ever" — Matt Pocock

    Test scope, mock boundaries, and behavior selection are dependent decisions, so merely giving an agent a test runner does not ensure useful feedback.

  24. Hidden Technical Debt in Machine Learning Systems

    Sculley and colleagues explain why maintaining an ML system requires more than maintaining its model code. Data dependencies, configuration, feedback loops and downstream consumers can couple components whose code appears separate. Changing one model input can affect how other inputs influence predictions. They distinguish ordinary improvements such as clearer APIs and better tests from additional system-level work needed to manage learned behavior. Modular code remains useful, but cannot by itself guarantee that a model change has isolated behavioral consequences.

  25. Design by Contract and Assertions

    A precondition states the caller's obligations before an operation; a postcondition states the implementation's obligations on successful return. A class invariant defines valid object states and generally must hold before and after exported operations, not necessarily during every internal statement. For a state transition from s to s', the teaching shorthand is: assuming I(s) and P(s,a), successful return must establish Q(s,a,s') and I(s'). Postconditions can relate new values to old values. Eiffel's runtime assertion checks are configurable and detect violations on executed calls.

  26. Your Agent Didn’t Fail. Your Harness Did.

    The harness should own state transitions, authority checks, ordered commits, and durable evidence; the model proposes actions.

  27. Your Agent Didn’t Fail. Your Harness Did.

    Provide one ordered commit path per mutable state boundary while allowing independent work to run concurrently.

  28. PostgreSQL 18: Transaction Isolation

    Under PostgreSQL Read Committed isolation, successive reads can observe different committed states. An UPDATE encountering a concurrently updated row waits and then rechecks its WHERE condition against the committed row version. Constructed application example: accept a proposed label only through an update matching both the record identifier and its expected version, and increment that version in the same update. If another writer has advanced the version, the stale proposal cannot satisfy the predicate. A separate preflight read does not provide this protection.

  29. "I've never seen anything scarier than an LLM with tool calls." — Erik Meijer aka @HeadinTheBox

    An agent can produce an acceptable final answer after causing harmful side effects during its computation.

  30. "I've never seen anything scarier than an LLM with tool calls." — Erik Meijer aka @HeadinTheBox

    Separate plan generation from execution so the model cannot directly run the agentic loop.

  31. PostgreSQL 18: Transactions

    A transaction groups database updates into an all-or-nothing operation. Other transactions do not observe its unfinished changes; committing makes the grouped changes visible together. BEGIN and COMMIT delimit a transaction block, while ROLLBACK discards its changes. Applied to runtime records, an operation result, its status transition, and newly pending work can be committed together when they reside in the same transactional database.

  32. gRPC lifecycle: cancellation is not rollback

    Client and server can disagree about an RPC's success: the server may finish while its response arrives after the client's deadline. gRPC explicitly warns that cancellation does not roll back changes already made. Application implication: cancellation during a mutation may leave an unknown outcome. Retain an operation identifier, query authoritative status or reconcile the resulting state, and use an idempotent retry contract before resubmitting. If an effect must be reversed, that requires a separate supported compensating operation rather than assuming cancellation undid it.

  33. Activity Definition — Temporal

    Temporal recommends idempotent activities because execution can be retried. Completed activities recorded in event history are not re-executed during workflow replay, but an activity that performs an effect and fails to report its result can run again. The application must therefore make repeated execution safe for its own business state. Persistence and replay are useful recovery mechanisms, but recording a workflow decision is different from guaranteeing that an external side effect occurred only once.

  34. Idempotent requests

    Stripe stores the first executing request's status code and response body for an idempotency key, including failures such as HTTP 500, and returns the stored result on retries. Parameter mismatches are rejected. A request rejected before execution because of validation or a conflict with a concurrently executing request does not create a saved idempotent result and can be retried. Keys may be pruned once at least 24 hours old; reuse after pruning starts a new request. Thus an in-progress conflict, a stored failure, and an expired key have different recovery semantics.

  35. Temporal Activity Execution

    An Activity Execution can comprise multiple task attempts. Temporal relies on timeouts to detect lost work, including worker crashes after invocation, and retries according to policy; limiting attempts to one prevents retry but does not prove an external effect failed. Cancellation is cooperative: activities receive service cancellation through heartbeats, can ignore it, and workflows may proceed without waiting for acceptance. A timed-out attempt may therefore continue while another attempt runs. Application consequence: treat an unconfirmed external mutation as uncertain, retain its operation identifier, reconcile against the receiving system, and use enforced idempotency or explicit recovery before repeating it. Timeout or cancellation is not evidence that a payment, message, or write was reversed.

  36. unittest — Unit testing framework

    A test case checks a particular response to specified inputs. A test suite groups cases or other suites for execution together. A fixture supplies preparation and cleanup, such as a temporary database or server. A runner executes tests and reports outcomes. Python's published example separately checks expected values, Boolean conditions, and expected exceptions; its command interface can select a module, class, or individual method.

  37. Design by Contract Introduction

    A precondition states what the caller must establish before invoking a routine. Given that condition, the implementation owes the postcondition on successful completion; it may assume the caller fulfilled the precondition. A postcondition can relate resulting state to entry state, such as count=old(count)+1 and lookup(key)=insertedValue. A class invariant expresses consistency constraints across the class's operations, such as 0≤count≤capacity. An output schema can check declared structure and value restrictions, but ordinarily does not establish that the caller was entitled to invoke the operation, that persistent state changed correctly, or that cross-operation invariants hold.

  38. Resolving an ambiguous payment request

    A timeout can leave the client unable to tell whether Stripe received or executed a request. Stripe documents retrying with the same key and parameters until a server result is obtained, using backoff. An HTTP 500 remains indeterminate: side effects may exist even though the cached response stays unchanged. Stripe may reconcile partial mutations and emit webhook events for resulting objects. Supplying a local operation identifier in metadata lets the application correlate these objects with its own pending operation. Engineering consequence: preserve pending state until authoritative provider evidence resolves it; do not infer failure solely from a timeout.

  39. Software Engineering at Google: Unit Testing

    Tests should exercise the public behavior callers rely on rather than private methods or incidental storage formats. The book contrasts assertions about serialized internals with assertions about resulting account balances. It recommends adding the missing case when fixing a bug and preserving existing tests during behavior-preserving refactoring. Tests that fail after an unrelated implementation change can impose maintenance work without identifying a real defect. Applied to model output, exact text equality is appropriate only when that exact text is part of the required behavior; otherwise the assertion should target the relevant property.

  40. pytest: How to parametrize fixtures and test functions

    Parametrization runs the same test function with multiple explicitly supplied argument sets. pytest's published example pairs each input with an expected result and identifies the particular failing case. This provides a compact mechanism for table-driven checks of valid records, rejected records and boundary conditions.

  41. QuickCheck: Executable Properties and Generated Inputs

    Property-based testing expresses a general, executable predicate over inputs, then generates many concrete cases and checks that predicate. QuickCheck separates the property from generators whose distributions and admissible inputs the programmer controls. Conditional properties can restrict applicable cases, but excessive discarded cases can make testing ineffective. Application examples include checking that serialization round-trips preserve supported values, validators reject generated violations, or protocol transitions preserve an explicit state invariant. These use deterministic assertions as the test oracle. A model may generate inputs, but model-judged fuzzing additionally depends on the judge's correctness; generating unusual examples alone does not define an executable property. Passing finite tests supplies evidence, not a proof over all inputs.

  42. Pact: How Pact works

    A consumer contract test checks whether client code sends the expected request and correctly handles a supplied response. Pact records these interactions, then provider verification sends the requests to the provider and compares actual responses with the consumer's expectations. Provider states establish necessary preconditions, such as an existing user. These complementary checks test whether the substitute-based assumptions agree with the provider for the described interactions.

  43. Demystifying evals for AI agents

    An agent evaluation separates a task and its success criteria from repeated trials, execution transcripts, graders, and final environment outcomes. A booking claim in a transcript is different from an actual reservation in the database. The system under test includes both model and agent harness. Code-based checks suit precise state or test assertions; model graders cover more open-ended properties but require calibration; human review helps establish the standard. Capability suites explore difficult behavior, while regression suites protect behavior that already works.

  44. Best Practices for Evaluating Large Language Model Applications with llmeval: Niklas Nielsen

    Repeated samples and explicit pass thresholds provide a better view of test stability than a single completion.

  45. SWE-rebench: Lessons from Evaluating Coding Agents on Real Software Engineering Tasks — Ibragim Badertdinov, Nebius

    Define retry and failure policies, check model configuration defaults, and validate the evaluation infrastructure against an external benchmark before interpreting experiments.

  46. Best Practices for Evaluating Large Language Model Applications with llmeval: Niklas Nielsen

    A model can return the right mathematical result while violating an exact-output contract through explanatory text or whitespace.

  47. Simplifying and Isolating Failure-Inducing Input

    Zeller and Hildebrandt automate the reduction of failure-inducing inputs through repeated tests. Their ddmin procedure removes parts while retaining the failure, stopping when no single remaining input element can be removed successfully. A related procedure isolates differences between passing and failing cases. The paper motivates this with Mozilla's burden of simplifying bug reports and demonstrates reductions of HTML and user actions. The purpose is to remove irrelevant circumstances so the remaining failure is easier to investigate.

  48. Your Agent Didn’t Fail. Your Harness Did.

    Trace one real run from trigger identity through inherited state, authority, execution attempts, and surviving external evidence.

  49. VCR.py: Usage

    VCR.py records HTTP interactions and later supplies the saved response when the corresponding request is made. Its none recording mode rejects new requests instead of contacting the service. Applied to a model integration, replaying a captured response can reproduce downstream parsing and policy behavior without performing new inference. Re-recording obtains a new dependency response and changes the fixture.

  50. OpenAI Cookbook: How to make your completions outputs consistent with the new seed parameter

    OpenAI's November 6, 2023 example describes keeping the seed and request parameters fixed and comparing a system fingerprint representing model weights, infrastructure and other server configuration. It explicitly warns that responses can still differ even when those values match. A seed therefore offered improved repeatability, not a guarantee of reconstructing an identical historical response.

  51. VCR.py: Advanced Features

    VCR.py supports removing or replacing sensitive request headers, query parameters and posted fields before recording. Custom callbacks can modify or omit requests and responses, including sensitive response bodies. Request matchers determine whether an incoming request corresponds to a recorded interaction. These controls let debugging fixtures retain selected behavior without automatically retaining every credential or payload field.

  52. Production Evals For Agentic AI Systems

    Treat agent traces as distributed tracing for autonomous workflows, recording execution structure rather than relying on ordinary logs alone.

  53. Google SRE: Effective Troubleshooting

    Troubleshooting proceeds from observations to possible explanations and tests that discriminate between them. Google recommends recording expected and actual behavior, preserving a reproducible case, examining data at component boundaries and injecting known inputs. Experiments must account for confounders: testing connectivity from a workstation can mislead when access differs from the application server. Diagnostic interventions can themselves change behavior, including logging that worsens latency or resource changes that alter races. Recent deployments and configuration changes help generate hypotheses but temporal correlation does not establish causation.

  54. Every Solo Agent Builder Eventually Reinvents a Worse Version of CI/CD

    The speaker identifies regression testing, CI monitoring, and contract testing as recurring operational needs in independently built agent systems.

  55. Loop Engineering from first principles

    Persist review-derived instructions in a version-controlled feedback file and reload it on every actuator run.

  56. Google Engineering Practices: Small CLs

    Google defines an appropriately small change by conceptual focus: one self-contained change with related tests and enough context for review. A new API may need a usage example in the same change to make its consequences understandable. The guide recommends separating substantial refactoring from behavior changes and keeping the system working after each submitted change. It argues that focused changes are easier to review, reason about and roll back.

  57. Google Engineering Practices: What to look for in a code review

    Review should consider functionality, edge cases, concurrency, unnecessary complexity and the validity of tests. Google asks reviewers whether assertions would fail for broken behavior and whether implementation changes would cause misleading failures. Tests themselves require human assessment. User-facing changes may need a demonstration because their consequences are difficult to infer from a diff; races and deadlocks also require deliberate reasoning beyond simply running the code.

  58. Shipping complex AI applications | Braintrust & Trainline

    Managed prompts and parameters can enable shared editing without application code changes, but should retain version control and synchronization discipline.

  59. How to Kill the Code Review

    Verification should preserve team alignment alongside semantic accuracy; the speaker identifies alignment as missing from his earlier five-layers trust model.

  60. Google SRE: Release Engineering

    Google's described release process links binaries to source revisions and build identifiers, archives change reports with artifacts, and gives packages unique version identities. Continuous tests detect failures after source changes, while release tests run against the actual release revision, which can differ from mainline after selected fixes. System tests also exercise packaged artifacts. Configuration can be snapshotted and released alongside binaries while retaining separate package identities. A moving label such as canary is distinct from an immutable package version.

  61. Reproducible Builds: Definitions

    A reproducible build allows another party to recreate identical specified artifacts from the same source, build environment and instructions. Relevant inputs commonly include dependency versions, configuration flags and environment variables. Reproducibility is checked by comparing artifact bytes, commonly through cryptographic hashes. Recording a source revision alone therefore does not completely describe a reproducible build.

  62. Claude Platform Docs: Model deprecations

    Anthropic distinguishes deprecated models, which remain functional pending retirement, from retired models, whose requests fail. Partner-operated platforms can have different retirement schedules. It advises testing applications with replacement models before retirement. Consequently, retaining an old model identifier in a release record does not establish that the corresponding service will remain available for rollback or reproduction.

  63. Google SRE Workbook: Canarying Releases

    A canary exposes a change to a limited portion of service use for a limited time and evaluates whether to expand it. Google recommends comparing candidate and control metrics separately, because aggregate metrics can hide candidate failures. Unacceptable differences should pause or reverse deployment or prompt investigation. Exposure size and duration must provide representative traffic, including relevant load conditions. Metrics should reflect user-visible problems, and acceptance criteria must balance missed defects against false alarms.

  64. Agents Need Feature Flags

    Ship agent-wide and per-tool kill switches first, and ensure in-flight work checks them at the next decision point.

  65. Continuous deployment — AWS Prescriptive Guidance

    AWS recommends staged model validation using offline tests, defined promotion metrics and runbooks, and the ability to switch between versioned models. It defines rollback as reverting to a previous deployment version when errors or unexpected behavior arise. Shadow evaluation runs a candidate alongside the existing model while the earlier model continues supplying production outputs.

  66. Your Agent Didn’t Fail. Your Harness Did.

    Internal acceptance does not prove the intended result appeared at the user-visible boundary.

  67. Amazon Builders' Library: Ensuring rollback safety during deployments

    Restoring an earlier software version is safe only if that version can work with the state and protocols now present. Amazon illustrates a new version writing compressed data that the previous version cannot read: restoring the old executable would introduce failures. Its staged format-change example first prepares readers, then activates new writers. After activation, rollback can return to the prepared version but not necessarily the original version. The report emphasizes verifying compatibility and completed deployment stages instead of assuming that individually working versions can coexist or replace each other safely.

  68. Compensating Transaction pattern

    Compensation performs new, business-specific actions to counter completed steps of an eventually consistent workflow. It differs from transaction rollback: intervening concurrent work must be preserved, the exact original state may be unattainable, and cancellation may incur charges. Record completed steps and the information needed to compensate them. Compensation order need not exactly reverse execution, and some steps can run in parallel. Compensation can itself fail, so persist progress, resume from failure, and make retryable steps idempotent. Where automated recovery is impossible, alert an operator with diagnostic information. For irreversible effects, an application must define an acceptable remedy or escalation rather than claim the action has been undone.

  69. Shipping AI to a Million Patients Without an A/B Test

    An already-delivered clinical utterance cannot be undone, so reactive rollout monitoring cannot substitute for evidence gathered before exposure.

  70. On Engineering AI Systems that Endure The Bitter Lesson

    The speaker presents DSPy as a framework that separates application definitions from evolving model adapters, inference modules, and optimizers, with signatures as a first-class concept.

  71. LangGraph Functional API: deterministic resumption and idempotency

    Functional API resumption restarts the entrypoint and restores completed task and subgraph results from checkpoints. Ordinary entrypoint code runs again. Put randomness, clock reads, model calls and individual side effects inside tasks so persisted results can be reused. Keep task and interrupt ordering consistent with the recorded execution. A task that started but did not finish can execute again, including when an external effect occurred before its result was saved. Checkpointing therefore does not replace idempotency keys or checks for previously completed effects. Reusing a saved model result preserves that recorded value; calling the model again is a new inference, not reconstruction of an identical historical response.

  72. Pragmatic AI With TypeChat

    Compiler diagnostics can become feedback for a subsequent model repair request.

  73. Building Reliable Support Agents Using the Effect TypeScript Library - Michael Fester

    Happy-path clarity can create a false sense of safety when upstream error handlers silently consume failures.

  74. Shipping complex AI applications | Braintrust & Trainline

    Use deterministic scoring for codifiable requirements and LLM-as-a-judge scoring for nuanced criteria that cannot readily be expressed as rules.

  75. Agents Need Feature Flags

    Route cohorts to versioned prompts and promote a candidate only after observing its behavior against a baseline.