Enterprise AI Bootcamp Demo 4

7. Two steps replaced by code

planner: model (claude-sonnet-5)manual search: local stubtickets and parts: synthetic training dataMCP 2026-07-28
The improvement does not come from making the model better. It comes from deleting two factors from the product. Every step you can write as code is an exponent you no longer pay.

The delta

Step by step

StepWhat it decidesAll agenticHybridIn the hybrid
s1_parseExtract the machine variant from the request100.0%100.0%agentic
s2_historyRetrieve comparable ticket history100.0%100.0%agentic
s3_diagnoseChoose the fault code the symptom implies47.5%85.0%deterministic code
s4_partTurn the fault plus variant into a part number55.0%85.0%deterministic code
s5_stockDecide source-from-stock or order, on lead time85.0%85.0%agentic
s6_composeCompose the work order45.0%85.0%agentic

Two steps changed. Step 3, symptom to fault code, became a nearest-centroid classifier fitted on the ticket corpus. Step 4, fault plus variant to part number, became a dictionary lookup. Steps 1, 2, 5 and 6 are identical in both configurations, and the agent still makes the tool calls.

Notice that steps 4, 5 and 6 in the hybrid column match step 3 exactly. That is not a coincidence or a bug: once the diagnosis is right, the rest is deterministic, so they cannot fail independently. The whole workflow's reliability collapses onto one number, and that number is now the only thing worth improving.

Why these two steps and not the others

The published arithmetic points the same way. Six steps at p = 0.90 is 53.1%; four at 0.90 plus two at 0.9995 — ordinary software reliability, not perfection — is 65.5%, a gain of 12.4 points. At p = 0.85 the same swap is worth 14.4 points. Those are computed, not measured, and are shown here as the reference the measured delta above should be read against.

This is also why field-service diagnosis sits on the Cognition side of the multi-agent argument rather than the Anthropic side. A repair recommendation is one coherent artefact with high dependency between steps: the part depends on the fault, which depends on the history. “Actions carry implicit decisions, and conflicting decisions carry bad results.” Adding a second agent to that adds a negotiation nobody can observe.

The held-out evaluation of the classifier

Ten symptom phrasings, one per fault, written in a reporter's words and present in no ticket. The margin column is the gap to the runner-up; below 0.02 the classifier declares the case ambiguous and refuses, which costs coverage and is why the workflow figure is lower than the raw accuracy.

ExpectedPredictedCorrectMarginHeld-out phrasing
F-101F-101yes0.0035runs hot and drops out on a temperature fault once it has been working hard for a while
F-102F-102yes0.1281there is oil showing up where it should not be, downstream of the machine
F-103F-103yes0.0056it will not come up to pressure and the tools are starving
F-104F-104yes0.1781we are getting water through to the tools every shift
F-105F-105yes0.2323keeps kicking the overload out when we try to start it
F-106F-104no0.0035there is a bad shake at the drive end that gets worse through the day
F-107F-107yes0.2426output has dropped off and the service indicator is showing red
F-108F-108yes0.3235the controller will not hold the set point, it hunts up and down
F-109F-109yes0.1590there is fluid weeping out underneath near the shaft
F-110F-110yes0.1636the cooler is not doing its job, outlet is far too warm for the ambient

The code that replaced the two steps

This is the running source of pipeline/deterministic.py, read with inspect.getsource at render time.

def diagnose(symptom: str, *, top_k: int = 2) -> dict[str, Any]:
    """Symptom text to fault code. Deterministic, ~1 ms, no model call."""
    m = _model()
    df, n = m["df"], m["n"]
    q: dict[str, float] = defaultdict(float)
    for f in _features(symptom):
        q[f] += 1.0
    qv = {f: (1 + math.log(c)) * math.log((n + 1) / (df.get(f, 0) + 0.5))
          for f, c in q.items()}
    qn = math.sqrt(sum(v * v for v in qv.values())) or 1.0
    scored = []
    for code, cen in m["centroids"].items():
        s = sum(v * cen.get(f, 0.0) for f, v in qv.items()) / qn
        scored.append((s, code))
    scored.sort(reverse=True)
    best = scored[0]
    runner = scored[1] if len(scored) > 1 else (0.0, None)
    margin = best[0] - runner[0]
    return {
        "fault_code": best[1],
        "score": round(best[0], 4),
        "runner_up": runner[1],
        "margin": round(margin, 4),
        # The stop condition the Skill specifies. Two ways to abstain: the top
        # two classes are effectively tied, or nothing scored high enough to be
        # a diagnosis at all. Abstaining converts a wrong answer into a
        # question, which is the correct trade in a field-service setting.
        "ambiguous": margin < MIN_MARGIN or best[0] < MIN_SCORE,
        "abstain_reason": ("tied with the runner-up" if margin < MIN_MARGIN else
                           ("no fault scored above the floor" if best[0] < MIN_SCORE
                            else "")),
        "top": [(c, round(s, 4)) for s, c in scored[:top_k]],
    }
def select_part(fault_code: str, model_variant: str) -> str | None:
    """A catalogue lookup. One line, and it cannot be wrong given its inputs."""
    return store.canonical_part(fault_code, model_variant)

def sourcing(part_no: str | None) -> str | None:
    """A threshold comparison. Three branches."""
    p = store.PARTS_BY_NO.get(part_no or "")
    if not p:
        return None
    if p["stock_qty"] > 0:
        return "source from stock"
    if p["lead_time_days"] <= LEAD_TIME_THRESHOLD_DAYS:
        return "order, lead time within target"
    return "order, escalate on lead time"
Measured over the artefact on screen 6; classifier source read at render time. Nothing on this screen is hardcoded; the source is in Demo4/pipeline/.