What ORPilot gets right about AI optimization agents

Bold text Interview First beside an isometric dispatch console, a chat bubble and faint route lines in the background.

Every few months a store owner asks me the same question: can AI work out the cheapest way to split orders across warehouses, or how much of each SKU to buy next quarter. The demo is easy. Hand a chat model five products and two warehouses and it writes plausible solver code in one go. Point it at the real catalog, with years of order history behind it, and it falls apart.

Guangrui Xie ran into the same wall from the operations research side and wrote it up on Towards Data Science, along with ORPilot, the open-source agent he built in response. I care less about the solver math than about the shape of the pipeline, because the same failures show up whenever you bolt an AI feature onto a WooCommerce store, whether that’s a full AI optimization agent or a modest restocking suggestion.

Where the demo breaks

The first failure has nothing to do with model quality. The brief is incomplete, and the gaps are exactly the things the owner considers too obvious to mention: this carrier has a noon cutoff, these two SKUs never ship together, oversized items go on a pallet whatever the weight. Xie describes it this way:

An AI system that starts modeling before these details are nailed down produces a model that is technically correct but practically wrong.

So the model optimizes the wrong problem at full confidence, and nothing in the generated code throws an error to warn you.

Second, size. Xie’s example problem has a demand table of three million entries, 500 customers by 500 products by 12 periods, and he is right that you cannot paste that into a prompt. A store version is smaller but the same shape: demand per SKU per month across a full catalog and a couple of years is past anything that belongs in a context window, and every row you do paste in is one more place for the model to misread a number.

Third, and this is where the hours go, the data you have is not the data the model needs. WooCommerce keeps orders as header rows with line items. A restocking model wants demand per SKU per period. A shipping model wants zones or distances, and you have postcodes. That gap is real engineering, and it’s deterministic engineering, so it has no business living inside a prompt.

The common wrong fix is to push harder on the prompt: paste the whole CSV, raise the context limit, put the constraints in paragraph six. It fails twice. More raw data in context is more surface for mistakes. And nothing survives the session, so next month’s updated numbers mean starting the conversation over. Xie calls the existing LLM-for-OR tools textbook-world tools, which matches what I see with stores: they were validated on problems where every number is printed in the problem statement.

What an AI optimization agent needs before code

ORPilot’s core move is refusing to write code early. Its first agent interviews you, one question per turn, and does not stop until the objective, the decision variables, the constraints and the data requirements are all pinned down; then it reads back a structured summary you can correct. The next agent turns that spec into a schema, tells you exactly which tables and columns it needs, validates the files, and adjusts if you say you only have GPS coordinates instead of the distance matrix it asked for.

The next stage is the one I would steal outright, derived parameters. The model needs demand per period and you have an order ledger, so a separate agent generates a script, runs it in a sandbox, and writes the result back as CSV. On a store that stage is a plain PHP file and WP-CLI, and it needs no AI at all:

<?php
// Derived parameter: monthly demand per SKU from the order ledger.
$demand = array();

$orders = wc_get_orders( array(
    'status' => array( 'wc-completed' ),
    'limit'  => -1,
) );

foreach ( $orders as $order ) {
    $created = $order->get_date_created();
    if ( ! $created ) {
        continue;
    }
    $period = $created->date( 'Y-m' );

    foreach ( $order->get_items() as $item ) {
        $product = $item->get_product();
        $sku     = $product ? $product->get_sku() : $item->get_name();
        $demand[ $period ][ $sku ] += $item->get_quantity();
    }
}

$fp = fopen( 'demand.csv', 'w' );
fputcsv( $fp, array( 'period', 'sku', 'quantity' ) );
foreach ( $demand as $period => $skus ) {
    foreach ( $skus as $sku => $qty ) {
        fputcsv( $fp, array( $period, $sku, $qty ) );
    }
}
fclose( $fp );

Run it with wp eval-file demand.php --user=1 and hand the CSV to whatever comes next. The model never reads the order table directly. Passing data by reference instead of by value keeps large problems workable and keeps the hallucination surface small, since the model only sees a handful of typed columns it asked for rather than a dump of order rows. It’s the same argument I make about WooCommerce analytics that should ask questions before counting.

Only then does ORPilot generate solver code, for Gurobi, CPLEX, PuLP, Pyomo or OR-Tools, execute it in a sandbox, and feed the full traceback back on failure, including infeasible results. Xie says most failures clear in one or two retries, and the reason a retry is cheap at that point is that the problem is pinned and the data is model-ready, so the model fixes a code mistake instead of redesigning the model. For a store owner the backend note matters too: OR-Tools is free and Apache licensed, while Gurobi and CPLEX cost money. The tool itself is on GitHub and the solver docs for the free option are at developers.google.com/optimization.

What I’d copy, and what I wouldn’t

For client work I’d copy the gates and skip the autonomy. An interview gate and a schema gate translate directly to a store project: a short spec the owner confirms in plain language, and a fixed export format the code reads. The autonomous part, generated Python executing itself in a sandbox, is fine for research and not something I’d put on a client box. I’d have the tool write the script, read it myself, then run it, and I’d apply the same checks you’d run before turning any AI feature loose on a store.

The other piece worth copying is the saved model. ORPilot emits a solver-agnostic JSON representation, so re-running on fresh data or switching backends never calls the LLM again. The store equivalent is the spec file, the export script and the solver script in the repo, plus a monthly WP-CLI run on cron. The AI gets used once, at design time, and the recurring run costs nothing and has no model in it to hallucinate. I have not pointed ORPilot at a store problem myself yet, so treat this as borrowed design until I’ve tested it on real store data.

On a client site this week I’d write the export script first, get the spec signed off in plain language, and only then let anything generate solver code. If you have a store decision like that on your desk, say shipping splits or purchase quantities, that’s the kind of work I do. Send me the messy brief and I’ll start with questions, the same way this tool does.

author avatar
Ahmad Wael
I'm a WordPress and WooCommerce developer with 15+ years of experience building custom e-commerce solutions and plugins. I specialize in PHP development, following WordPress coding standards to deliver clean, maintainable code. Currently, I'm exploring AI and e-commerce by building multi-agent systems and SaaS products that integrate technologies like Google Gemini API with WordPress platforms, approaching every project with a commitment to performance, security, and exceptional user experience.

Leave a Comment