Personal retrospective: This article describes my own work and views. It is not an official Strangeworks publication or an endorsement by my former employer.

The first AI agents I built for optimization appeared deceptively simple.

A user could describe a problem in ordinary language. The agent would identify an objective and constraints, write Python code to construct a mathematical model, and help submit that model to an optimization solver. A second agent could retrieve the results and produce plots.

As a proof of concept, this worked surprisingly well. It also revealed why a production system could not simply be a more polished chatbot.

An optimization project is rarely one prompt, one model, and one answer. It accumulates descriptions, formulations, datasets, model versions, solver configurations, jobs, results, plots, and reports—sometimes for months. One changed constraint creates a new experimental branch; one parameter study can generate hundreds of jobs.

A conventional chat agent tends to respond by producing files and folders. At production scale, this becomes a research-data-management problem: someone must preserve which job used which model, dataset, solver, and parameters.

That observation shaped my contribution to Strangeworks Workflows. I came to see the product primarily as a data-organization system for long-running computational research, with AI agents layered on top for problem formulation and analysis.

The chat was the interface. The structured project was the product.

At a glance: I independently prototyped custom GPTs for optimization formulation, job submission, and result analysis. Those prototypes validated the concept and helped give the business confidence to fund a production project. I then acted as its scientific driver and optimization expert, designing the core Problem, Model, Instance, Job, and Result architecture that the multidisciplinary software team brought into Workflows.

Prototyping the complete loop

I began with custom GPTs because they offered a quick way to test the central hypothesis: could a language model help a user turn a real-world description into an executable optimization workflow?

I created separate prototypes for several parts of the process:

  • a CQM/QUBO builder that generated a Python function from a problem description and input-data schema;
  • an MPS builder that generated a reusable model-building function and MPS file;
  • an action that could submit a problem to Strangeworks, check its status, and retrieve its result;
  • a result-analysis and plotting assistant; and
  • a quantum-simulation assistant that translated Hamiltonians into Qiskit time-evolution circuits.

The prompts were more like interface specifications than conversational personas. They defined the expected filename, function interface, data-loading behavior, and model representation. They instructed the agent to ask for clarification when a constraint was ambiguous and to show external payloads before submission.

I also supplied example data and ran the generated functions. This mattered because a mathematical model can look convincing while being subtly wrong. During prototyping, I found issues such as incorrect indexing, inappropriate variable types, missing constraints, nonlinear expressions in supposedly linear models, and small coefficient errors.

Those failures clarified the requirements: visible and editable code, executable validation against data, structured objectives and constraints, artifact versioning, realistic evaluations, and traceability from formulation through result interpretation.

The prototypes demonstrated enough value—and exposed the right problems—to give the business and strategy team confidence to green-light a full production effort.

The production project brought together a principal technical software lead, a designer, a senior software developer, a project manager, a data scientist, and me as the scientific driver and domain expert. I was not the principal software lead or the designer. My responsibility was to define how an optimization or scientific-computing project needed to behave: its objects, relationships, experimental workflow, and analysis requirements.

Why chat history was not enough

Suppose an agent creates a model and submits it to a solver. The solver returns a job slug. At first, remembering that slug in the conversation may appear sufficient.

Now suppose the user:

  • uploads three datasets;
  • applies the same model to each dataset;
  • compares four solvers;
  • varies two parameters for each solver;
  • changes a capacity constraint;
  • regenerates the modified model;
  • repeats the comparison; and
  • later asks which formulation produced the most profitable feasible result.

The system is no longer managing one answer. It is managing a branching computational experiment.

Chat history is a poor database for this. Filenames alone are little better. A directory can tell us that results_17.json exists, but not reliably why it exists or how it relates to the user's scientific question.

I therefore designed a hierarchy of explicit application objects:

End-to-end orchestration

One request in. One result out.

The product boundary stays simple while durable work fans out across many solver jobs and recombines behind the parent job.

01
IntakeOne product request
  1. User
  2. SDK
  3. Parent
02
PrepareDurable orchestration
  1. Worker
  2. Decompose
  3. Manifest
03
Fan out / fan inParallel solver work
  1. Child1
  2. Child2
  3. ChildN
  4. Barrier
04
RecombineOne inspectable result
  1. Final
  2. Reconstruct
  3. Result

Architectural invariantEvery child result retains its original subgraph and variable mapping.

Making the hierarchy explicit changes what the agents and product can do. A model is no longer a transient code block but a reusable, versioned artifact. An instance binds it to data; a job records the solver and parameters; and a result remains connected to the computational path that produced it.

Users and agents can now operate on the same objects. A user might ask:

Compare every completed result for model version two, excluding the largest dataset, and show how solution quality changed with solver tolerance.

The analysis agent does not need to reconstruct the study from a folder of loosely named files. It can query a known structure.

A running example: loading cargo across multiple aircraft

A useful example is a multiple-aircraft cargo-loading problem.

Each cargo item has a weight, profit, and priority. Each aircraft has a weight capacity and a transportation cost. A binary decision variable,

xij∈{0,1},x_{ij} \in \{0,1\},

records whether cargo item ii is assigned to aircraft jj.

A simple formulation maximizes the profit of loaded cargo minus its transport cost:

max⁡∑i,j(pi−cj)xij.\max \sum_{i,j} \left(p_i-c_j\right)x_{ij}.

The model must ensure that:

  • a cargo item is not assigned to more than one aircraft;
  • every mandatory high-priority item is loaded; and
  • the total weight assigned to each aircraft stays within its capacity.

This is more complex than the single-aircraft QUBO used in my later AWS aircraft-cargo benchmarking article: the assignment couples cargo and aircraft.

In Workflows, the user's natural-language description would become a Problem. The generated mathematical logic would become a versioned Model. Uploading particular cargo and aircraft tables would create an Instance.

The same instance might then be submitted to:

  • a classical mixed-integer solver;
  • a quantum or quantum-inspired optimizer after conversion;
  • several solvers for comparison; or
  • the same solver with different limits, tolerances, or heuristic settings.

Every combination produces a separate job, but those jobs remain children of the same model and instance rather than becoming unrelated identifiers in a chat transcript.

Now imagine that the user adds a rule: hazardous cargo types must be separated, or each aircraft must remain balanced between loading zones. That is not merely a new run. The mathematical formulation has changed.

The new constraint should create a new model branch. Its instances, jobs, and results belong there, while the original remains reproducible and available for comparison.

This is the central reason I treated model lineage as a first-class concern. AI makes generating a revised model easy. Without versioning, that convenience can destroy the history needed to understand whether the revision improved anything.

Designing job submission as experiment construction

Once models and instances had stable identities, job submission could become more than a button that sent one request.

The system could first filter solvers according to model compatibility. It could expose relevant solver parameters, validate their ranges, and let users define parameter scans. Before submission, it could show how many jobs a proposed scan would create—an important detail when the Cartesian product of models, instances, solvers, and parameter values becomes large.

The submission design included versioned models, data-dependent model-builder functions, compatible-solver filtering, parameter forms and range scans, reusable defaults, pre-submission checks, and a stable result location for every job.

I also designed an Experiment concept: one user-triggered collection of runs across selected models, instances, solvers, and parameters. An agent could propose a parameter sweep, but it needed to explain the rigor/cost trade-off before creating it. A user could repeat a saved experiment against a new instance or compare a revised formulation against an earlier one.

This broader experiment abstraction was deprioritized, but it clarified that job submission was really experiment construction, even if the initial product exposed a simpler version.

Results were not just solver output

Optimization solvers return mathematical results: assignments, samples, energies, objective values, statuses, bounds, timings, and diagnostic information.

Those are necessary, but they are rarely the answer a user wants.

In the cargo example, the user wants to know:

  • which cargo was loaded onto which aircraft;
  • which items were excluded;
  • whether every priority item was loaded;
  • how much capacity remains on each aircraft;
  • whether every constraint was satisfied;
  • the resulting profit and cost; and
  • how that solution compares with other models or solvers.

I designed the Results and Analysis Agent around that distinction. Each job could have a problem-specific post-processing function that translated abstract variables back into their physical or business meaning. The agent would wait for jobs to complete, execute the appropriate analysis, and store both the raw result and its interpreted summary.

The result hierarchy mirrored the submission hierarchy:

problem
└── model
    └── instance
        └── solver
            └── parameter set
                └── job
                    ├── raw result
                    ├── domain interpretation
                    ├── cost and runtime
                    └── analysis code and plots

This supported comparisons across solvers, datasets, parameter values, and original or revised formulations.

For large result files, the agent should not place the entire dataset into the language-model context. I later implemented an approach in which the agent generated and ran a problem-specific analysis function over the data, returning only the derived information needed for reasoning and presentation.

This was both more scalable and more trustworthy. The user could inspect the analysis code, see which results were included, and correct a small plotting or interpretation error without asking the model to regenerate the entire project.

The multidisciplinary team carried these core model, instance, job-organization, and result-analysis concepts into Workflows. My role remained the scientific architecture and optimization logic; the production engineering and user experience were collaborative work.

Human oversight was an architectural requirement

AI-generated optimization is unusually sensitive to small semantic errors.

Choosing an integer variable where a binary variable was intended can change the problem. Omitting one constraint can produce an apparently excellent but unusable solution. Regenerating a whole model to fix a small issue can accidentally remove a previously correct detail.

My requirements therefore moved toward editable, traceable artifacts: show the mathematics and executable code, connect variables and constraints to the source description, run pre-solve checks, preserve model lineage, allow precise edits, expose analysis code, and retain raw results beside interpreted summaries.

The aim was not to remove the expert from the process. It was to let an expert work at a higher level without losing control of the mathematics.

One design principle became especially important:

The agent and the user should operate on the same structured project objects.

If the agent has a hidden representation and the user sees only prose, correcting the system becomes difficult. If both operate on versioned problems, models, instances, jobs, and results, the user can inspect and override the agent at every consequential step.

Lessons I would carry into the next agentic product

1. Prototype the entire loop

Natural-language-to-code is compelling, but the real workflow also includes data ingestion, validation, execution, status, interpretation, and revision. Prototype across those boundaries.

2. Treat generated artifacts as durable objects

Important outputs need identity, lineage, and versions. If a generated model matters enough to execute, it matters enough to preserve.

3. Separate models from instances

Formulations and their datasets change for different reasons. Separating them enables reuse, comparison, and clear provenance.

4. Design for branching

Research is not a linear chat. New constraints, datasets, and hypotheses create branches that should not be hidden in filenames.

5. Evaluate realistic use

Tiny text-only benchmarks miss production ambiguity, attached data, scale, and iterative correction. Combine realistic cases and qualitative failure analysis with automated metrics.

6. Keep deterministic work deterministic

Use agents to interpret goals and propose formulations; use ordinary software for validation, job tracking, numerical computation, and reproducible plotting.

7. Make the work inspectable

Visible models, code, parameters, provenance, and analysis turn AI from an oracle into a collaborator.

The deeper product was organization

Strangeworks described Workflows as spanning research, problem formulation, analysis, and report generation. That breadth is what made its internal data model important.

AI reduced the effort required to create each artifact. That made organization more important: when models, code, and analyses become cheaper, users accumulate them faster.

The most valuable design work was therefore not a single prompt. It was defining the structure that allowed many prompts, models, datasets, jobs, and results to remain part of one intelligible scientific project.

That is how I now think about agentic software for computational work:

The agent may accelerate each step, but the product must preserve the meaning of the journey between them.