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

Disclosure: I supplied the professional experience, design decisions, constraints, trade-offs, and review direction for this case study.

OpenAI Codex generated the initial clean-room implementation. I remain responsible for the accuracy of the claims, the architectural choices, and the decision to publish. No private source code or customer data was used.

At a glance: The implementation tests whether stable contracts, durable parent/child jobs, explicit submission policy, and replaceable execution strategies can contain provider change. The code is inspectable evidence for those decisions, not a production framework or a reconstruction of a private system.

The engineering problem was change

An optimization platform does not integrate with a single, stable kind of solver. One provider may offer a conventional asynchronous API. Another may offer only a blocking call. A third may accept asynchronous work but leave its consumer to enforce a concurrency limit. Models, variable labels, status vocabularies, objective conventions, result collections, and runtime fields can all disagree. Provider APIs and SDKs can also change significantly after an integration ships.

That makes "can we submit a model?" the least interesting architectural question. The useful question is:

How cheaply and safely can the product absorb the next provider, the next API revision, and the next operational constraint?

This case study turns my answer into executable evidence. It is informed by my work on optimization services at Strangeworks, whose public documentation describes the optimization product and its provider backends. It is not a reproduction of that system. The code uses fictional providers, a tiny local exact solver, synthetic usage units, and no cloud services.

What I inherited and what I decided

Attribution matters in an architecture case study.

I did not design the surrounding platform authentication or the foundational parent/child job pattern. Those were constraints I worked within. My own contributions included designing the user-facing optimization SDK, proposing a dedicated shared boundary for optimization models and conversions, and making the detailed choices for solver integrations: where conversion belonged, which responsibility sat in the common optimization layer, which sat beside the provider, and when a remote execution mechanism was appropriate.

I also prototyped and documented the use of Modal as one remote execution option and helped bring that pattern into production integrations. The choice was deliberately selective. A provider with a sound asynchronous lifecycle did not need an extra execution substrate. A provider with only a blocking solve operation did. An unusual case was an asynchronous provider whose concurrency limit was not enforced by its own API; there, the remote layer also served as a queue and capacity gate.

The architecture was designed with the expectation that many more solvers would arrive. That expectation proved accurate. The integration capability was also used across multiple external, customer-facing optimization case-study projects. I do not identify those customers, workloads, commercial limits, or private implementation details here. The relevant point is the change pressure: the same product surface had to remain coherent while the provider estate and project needs varied underneath it.

Start with forces, not boxes

The design was motivated by recurring failure modes and costs:

  • large model uploads competing with request timeouts;
  • a parent job existing even if child creation failed;
  • long-running work requiring scheduled reconciliation;
  • provider statuses and result shapes that did not agree;
  • variable remapping and objective offsets that had to be restored exactly;
  • many returned solutions that should not be collapsed to one;
  • provider-specific runtime and usage reconciliation;
  • expensive submissions for which a blind retry could duplicate cost; and
  • integrations becoming difficult to maintain when conversions appeared in several services.

Those forces lead to five decisions in this demonstration.

1. Separate the data plane from the control plane

Upload the immutable model first. Create the workflow with a compact artifact reference, provider selection, and parameters. Download the model close to the provider boundary.

This reduces the size and timeout exposure of control requests. It also gives the SDK useful artifact operations: download a model from an earlier job, inspect it, and deliberately resubmit it with different parameters.

The reference implementation stores content-addressed artifacts on disk. A production system could put the same port over an object store. That deployment choice should not alter job semantics.

2. Give provider execution one source of truth

The child record is authoritative for the actual solver execution: remote identifier, provider status, raw-result retrieval, normalized result, and provider error.

The parent is the user-facing workflow. It does not call the provider. Its own reconciler reads persisted child state and projects a stable public lifecycle. A child can be polled while the parent is projected independently because leases are scoped to job identifiers, not to an entire parent/child tree.

This distinction makes eventual consistency explicit. A child may have completed while its parent still awaits normalized-result attachment. The parent becomes complete only after that artifact is present and valid.

The first case study intentionally models exactly one child. Multiple-child aggregation introduces a different set of partial-success and cancellation policies and deserves a separate treatment rather than an accidental generalization.

3. Centralize contracts that must survive provider change

Variable remapping, objective offsets, model transformations, result normalization, and usage conventions can recur across a long integration path. If every service invents its own version, a provider change creates several places to update and several opportunities to disagree.

The most stable package in this repository therefore owns:

  • the canonical binary quadratic model;
  • immutable artifact references;
  • samples and sample sets;
  • normalized result envelopes;
  • duration and synthetic usage types; and
  • the provider conversion protocol.

The demonstration includes two deliberately incompatible fictional provider APIs. Their model terms, nesting, result collections, objective fields, and runtime fields differ. Only their conversions know this. Both restore the user's variable labels and objective offset, preserve all eight solutions, and produce the same best objective through the same SDK.

This is an anti-corruption layer, not a universal provider schema. Provider details should remain outside it; otherwise the supposedly stable package becomes a catalogue of every integration's quirks.

4. Choose execution strategy per integration

The orchestration core consumes one provider lifecycle, but that lifecycle can be implemented in three ways:

  1. map a provider's native asynchronous API;
  2. place a blocking operation behind an asynchronous execution bridge; or
  3. wrap an asynchronous provider with an external capacity gate.

The local bridge uses a thread executor so anyone can run the case study for free. A hosted remote-job system or a platform such as Modal could implement the same boundary in production. The important architectural choice is not a vendor. It is preventing the hosting mechanism from leaking into the SDK, canonical contracts, or job domain.

5. Treat submission retry as a cost and correctness policy

An HTTP failure is not always proof that a solver rejected a request. The provider may have accepted expensive work and lost the response. Submitting again can duplicate both execution and cost.

The default policy here is therefore "submit once." An explicit provider rejection is recorded with safe evidence. A failure that may have occurred after request transmission is marked ambiguous for manual reconciliation. No automatic resubmission occurs unless an adapter can prove that an idempotency key or provider lookup makes it safe.

Read operations such as status polling can have a different policy. Lumping submission and polling into a generic retry decorator would erase the most important semantic difference between them.

From experience to clean-room evidence

I used a five-stage methodology:

  1. Describe the pressures. I wrote down the integration problems, lifecycle semantics, ownership boundaries, and decisions from professional experience without consulting private source.
  2. Remove private specifics. Internal names, topology, schemas, customer identities, pricing, incidents, credentials, and provider contracts were explicitly excluded.
  3. State decisions before implementation. An architecture charter and decision records define what the code must demonstrate.
  4. Use AI to generate a clean-room implementation. Codex translated my direction into an initial package, tests, diagrams, and prose through staged commits and pull requests.
  5. Test the predicted changes. A breaking provider v2, a blocking provider, a capacity-limited wrapper, failure injection, leases, and dependency rules act as architecture fitness functions.

The commit history matters. An initial charter is followed by canonical contracts, then lifecycle semantics, durable infrastructure, reconciliation, provider strategies, the SDK, and finally the case-study narrative. The result can be reviewed as a sequence of decisions rather than a single AI-generated code dump.

Why I am leaning into the AI-assisted workflow

For this kind of portfolio project, hiding AI use would make the evidence less credible. The more interesting capability is using AI without surrendering engineering responsibility.

I used AI as:

  • an implementation accelerator after the design constraints were explicit;
  • a challenger that forced implicit lifecycle rules into named states and failure cases;
  • a generator of incompatible provider fixtures and architecture tests;
  • a drafting partner for diagrams, decision records, and this article; and
  • a consistency aid across code, tests, prose, and the staged review history.

I did not use AI as the source of my professional experience, an authority on what happened in a private system, or a substitute for confidentiality review. Generated code can be coherent and still encode the wrong policy. Generated prose can turn a qualified memory into an overconfident claim. Those risks make human gates more important: inspect the diff, run the evidence, verify every attribution, remove unsupported specifics, and keep the repository private until publication review is complete.

That is also a useful hiring signal. Modern engineering is not measured by how many characters a person types unaided. It is measured by whether they can frame the right system, make sound trade-offs, direct tools effectively, recognize failure modes, verify the output, and remain accountable for what ships.

What the repository proves—and what it does not

The package proves that the stated boundaries work for the included change scenarios. Its tests enforce dependency direction, lifecycle transitions, artifact integrity, polling leases, failure behavior, provider evolution, capacity release, result validation, and the stable SDK.

It does not prove production scalability, security, availability, commercial billing accuracy, or equivalence to the Strangeworks platform. It contains one process, SQLite, local files, one child per parent, synthetic workloads, and a solver capped at 16 variables. Those are honest boundaries, not hidden gaps.

The core architectural lesson is smaller:

Design around the changes you expect, isolate the side effects you cannot safely repeat, and make the promised boundaries executable.

The solver you have not met yet will still surprise you. Good architecture decides how far that surprise is allowed to travel.