---
title: "AI Lab Project Building Part 3: Problem Solver"
date: 2026-03-19
summary: Problem Solver was built around one constraint, never spend an inference the user didn't ask for. Four prompt contracts, two sliders that default to one, and a step sequence you can inspect and rewind.
status: published
tags: ai lab, problem solver, sequential inference, prompt contracts, ux, testing
mediaSourcePath: /ai-lab/problem-solving/app.html
mediaSourceSelector: .problem-solver-layout, main
mediaSourceTheme: dark
imageAlt: Problem Solver's step-by-step workbench with scenario, candidates, analysis, solutions, and plan.
imageCaption: Every generation is a click. That is the feature.
---

# AI Lab Project Building Part 3: Problem Solver

Problem Solver was built around one hard constraint: don't spend a generation the user didn't ask for. Every model call is explicit, sequential, and triggered by a click. No background generation, no speculative branching, no "we went ahead and did the next step for you."

That constraint made the app slower to use than it could be. It also made it the clearest demonstration in the AI Lab of what I mean when I say human in the loop.

## The workflow

The flow at [/ai-lab/problem-solving/app.html](/ai-lab/problem-solving/app.html) is deliberately narrow:

1. You describe a rough scenario.
2. The app proposes a bounded set of candidate problems.
3. You pick one for analysis.
4. The app proposes a bounded set of solutions.
5. You pick one and get an action plan.

Two sliders control how many candidates and how many solutions get generated, one through five, and both default to one. That default alone avoids most of the wasted inference I've seen in tools that fan out first and ask later.

## Four prompt contracts

The backend has a separate prompt key for each stage: `problemSolver.identify.v1`, `problemSolver.analyze.v1`, `problemSolver.solutions.v1`, and `problemSolver.plan.v1`. Each one is a structured contract with a defined response shape, and each is independently testable. The version suffix is there so I can change a contract without silently changing the behavior of a saved session that was created under the old one.

Splitting the stages kept every prompt small and specific. One prompt that tries to identify, analyze, and solve in a single pass produces long, hedged output. Four prompts that each do one thing produce output I can assert on.

## Why sequential gating

Three reasons, all practical.

Both the local and the production inference paths have limited capacity. Sequential steps give me predictable latency and keep token spend proportional to what the visitor actually wanted to see.

Debugging is cleaner. Each piece of output maps to exactly one request at exactly one step. When something looks wrong, I know which prompt produced it.

Testing is reproducible. A user path through the app is a fixed sequence of clicks and responses, which means the end-to-end spec can mock each stage and assert the transitions between them.

## State you can inspect

Sessions persist under `ai-lab-problem-solver-state`, with create, select, delete, and reset controls. The progression is visible in the UI, and you can return to an earlier validated step without triggering another model call. Copy controls exist for the analysis and the plan, because the output is meant to leave the app.

## What I tested hardest

For a process-heavy app, control state matters at least as much as response quality:

- Step transitions are deterministic
- Controls stay disabled until their prerequisites are met
- Each stage has its own error message when a request fails
- No horizontal overflow at the common breakpoints
- Labels, control names, and contrast pass in both themes

The spec files are layered the same way as the rest of the lab: unit tests for state and parsing helpers, integration tests that assert prompt keys and request order, end-to-end tests for the full workflow, and a UI-controls spec for session management and copy actions.

## What it proves

A constrained inference workflow can still feel capable. Visitors get agency over every branch. I get strong levers on cost and quality. And the app is a working argument for a design position I keep coming back to: the human deciding what happens next isn't a limitation on the AI, it's the interface.

- Previous: [AI Lab Project Building Part 2: Promptpad](/blog/ai-lab-project-building-part-2-promptpad/)
- Next: [AI Lab Project Building Part 4: Agent Agenda](/blog/ai-lab-project-building-part-4-agent-agenda/)
