Skip to content
This repository was archived by the owner on Jun 23, 2026. It is now read-only.

phanselm315/inventory-intelligence-agent

Repository files navigation

Inventory Intelligence Agent

Inventory is the single largest piece of working capital a mid-market distributor or manufacturer ties up -- and it is almost always overstocked, mis-segmented, and quietly carrying dead SKUs no one has flagged. This demo shows an AI agent surfacing the EBITDA and the cash inside it for a single portco, then proving the play scales fund-wide.

Point the agent at a portfolio company's inventory snapshot and 24 months of demand history. It segments the catalog by ABC x XYZ, sizes variability-driven safety stock and EOQ-driven cycle stock, surfaces the dead and long-tail SKUs the working capital is buried in, and turns the result into a board-ready EBITDA bridge -- for one portfolio company, then across the fund.

Built as a portfolio-company value-creation demo. All data in this repo is synthetic; the figures are illustrative, but the logic is production-grade.


Why this exists

Inventory is the largest single chunk of working capital on a distributor or manufacturer's balance sheet, and the one private- equity workstream that rarely makes it out of the operating partner's "we'll get to it" pile. Procurement is well-trodden. Freight is now well-trodden. Inventory sits under both, drives both, and is the lever where the cash release shows up on the bank statement -- not just on the income statement. Published mid-market inventory programs commonly target 20-40% inventory reduction without service-level erosion; this pilot is built so the diagnostic walks a reader through exactly that logic.

Today that work is bought from inventory consultants and supply-chain practices -- A&M, Maine Pointe, Argon & Co, the McKinsey Operations practice. A mid-market inventory diagnostic typically runs 6-16 weeks at mid-six to seven figures and produces a point-in-time slide deck plus a SKU-by-SKU action list. The diagnostic itself, though, is now automatable. The math under the deck -- ABC / XYZ segmentation, variability-driven safety stock, EOQ-driven reorder policy, dead-stock identification, obsolescence reserve sizing -- is arithmetic, and arithmetic scales.

Inventory consulting engagement Inventory Intelligence Agent
Cost Mid-six to seven figures API usage -- single-digit dollars per run
Time to first output 6-16 weeks Under a minute
Cadence One-off, point-in-time Re-run on every inventory snapshot
Output Slide deck + SKU action list EBITDA bridge + sensitivity + vendor playbook
Portfolio coverage One company per engagement Same agent across every inventory-intensive portco

The unlock isn't the single-company saving. It's that the same agent runs against every portfolio company -- turning a one-off cash-release exercise into a repeatable, fund-level value-creation lever, and surfacing the cross-portco safety-stock pooling no single company has on its own.


The scenario: Meridian Industrial Supply

Meridian Industrial Supply is the same ~$220M-revenue, fourteen- branch Midwest industrial distributor of MRO, safety, and packaging products that anchors the Procurement Spend Intelligence Agent. Acquired by Hadrian Capital Partners, Fund III via a roll-up of three regional distributors, Meridian now runs on three different ERP instances (NetSuite, Sage Intacct, and a legacy AS/400) that have never been consolidated. Its item master shows ~3,000 SKUs; roughly 1,200 are actively managed and the rest is a long tail accumulated through the roll-up, branch by branch, with no central spec governance. Current inventory carries at roughly seven months of cover -- the "decentralized, padded-for-safety-we-never- measured" state of an unmanaged mid-market distributor. With Hadrian's next portfolio-ops review on the calendar, inventory is the single largest piece of working capital nobody has actually examined -- which is exactly where this agent starts.


What the agent does

Part 1 -- The single-portco diagnostic. Point the agent at Meridian's long-format inventory file (one row per SKU per month, demand + standing item attributes). It builds the TTM item master, runs the per-SKU demand forecast with a hold-out-validated forward sigma, segments the catalog into the 3x3 ABC x XYZ grid with a service-level target assigned per cell, computes variability-driven safety stock and EOQ-rounded cycle stock, and surfaces the dead and long-tail SKUs the working capital is buried in. Savings are decomposed lever by lever -- safety stock right-sizing, cycle stock / EOQ optimization, SKU rationalization, and obsolescence reserve correction -- never a single black-box percentage. The result rolls into a board-ready EBITDA bridge with downside / base / upside flow- through, a sensitivity table on realization haircut x flow-through, and a vendor stock-policy playbook the operating partner can take into a vendor review the next day.

Part 2 -- The portfolio rollup. One company is not a fund -- and inventory is the lever where the fund-level math compounds. Part 2 re-runs the diagnostic across the six inventory-intensive Hadrian Capital Partners, Fund III portfolio companies (Brightpath Logistics is excluded -- a freight / logistics business carries cargo, not inventory), builds the unified fund-wide canonical-SKU map (a "Grade 8 fastener 1/2 x 2" in three portcos under three different SKU IDs collapses to one canonical part), and applies a tiered cross-portco safety-stock pooling discount (8% / 15% / 22% for light pooling / base / full bloc, mirroring the procurement and freight agents' tiered structure). The pooling math uses the classical sqrt(N) bound -- holding pooled safety stock on a shared canonical SKU at one fund-level node releases roughly (1 - 1 / sqrt(N)) of the redundant SS across N portcos for the same fill rate. The savings roll into a fund-level EBITDA and enterprise-value bridge, each company valued at its own entry multiple. No multiple expansion; value creation is purely operational.


Architecture

flowchart LR
    G[data_gen.py] --> I[inventory.csv · Meridian]
    G --> IS[inventory_*.csv<br/>other five portcos]
    I --> F[forecast.py<br/>hold-out validated mean + sigma]
    IS --> F
    F --> D[diagnostic.py<br/>Part 1 — ABC × XYZ · 4 levers<br/>EBITDA bridge · sensitivity]
    D --> PF[portfolio.py<br/>Part 2 — fund rollup<br/>shared canonical map · sqrt(N) pooling]
    D --> PB[playbook.py<br/>vendor stock-policy + SKU rationalization<br/>model-written commentary]
    PF --> PB
    SEED[scripts/seed_llm_cache.py] -->|one-time, real API| PC[playbook_cache.json]
    PC --> PB
    D --> VZ[viz.py · Plotly]
    PF --> VZ
    PB --> VZ
    D --> APP[app.py · Streamlit]
    PF --> APP
    PB --> APP
    D --> NB[notebook.ipynb]
    VZ --> APP
    VZ --> NB
Loading

The agent automates the end-to-end workflow an inventory consultant runs by hand. The analytics underneath -- the segmentation, the policy math, the lever decomposition, the entire fund rollup -- are fully deterministic: every figure traces to a row in the inventory file and explicit arithmetic, and no model ever sits between an input and a number, so the output is auditable line by line. A language model is used at one step only -- writing the vendor stock-policy talking points and the SKU rationalization commentary -- and that layer is provider-agnostic: Claude by default, swappable for any model. Its output is cached alongside the data, so mock mode runs fully offline and reproducibly; the model is called only when the cache is explicitly rebuilt. The Streamlit app, the walkthrough notebook, and the CLI runner share the same src/ modules, so the interactive demo and the deep-dive can never drift apart.


Methodology & assumptions

This section earns the trust of a finance reader: every assumption the agent makes is stated here, and every one is exposed as a named, tunable parameter in config.py.

Data. The agent's input is inventory.csv -- a long-format inventory + demand history file of the kind any ERP or planning system produces: NetSuite, SAP, Oracle, Microsoft Dynamics. A roll-up like Meridian rarely keeps that data in one place -- it is usually spread across three to five disconnected systems, and consolidating it into a single file is the real first step of any engagement (which is itself a symptom of the fragmentation the demo sets out to fix). Each row is one (sku, month) demand observation with the SKU's standing attributes denormalized onto the row. ~30,000 rows for Meridian, ~13-20k for the other five inventory-intensive portcos. All data is synthetic, generated by src/data_gen.py under a fixed seed; per-portco TTM COGS is scaled to (entry revenue * sector COGS %) so the dollar magnitudes reconcile to the shared portfolio.csv fund master. Meridian's $220M revenue and fourteen-branch profile are scenario premises inherited from the procurement agent, not derived figures.

Forecasting. The diagnostic sizes safety stock off the standard deviation of monthly demand forecast error, not off in-sample residuals. The default is a naive-mean forecast with the hold-out RMSE as the forward-looking sigma -- the model most mid-market inventory tools actually run, and the math the safety-stock formula downstream cares about. An ETS upgrade for the A-class items is a roadmap option (config.USE_PROPHET-style toggle, off by default). The sibling agents in the suite keep their analytic stacks tight; the inventory diagnostic is no different.

ABC x XYZ segmentation. A/B/C is set by trailing-12-month COGS contribution (80% / 15% / 5% by cumulative share). X/Y/Z is set by coefficient of variation of monthly demand (CV cutoffs at 0.50 and 1.00). The resulting 3x3 cell drives the service-level target -- AX at 99%, CZ at 85%, the rest interpolated. Real inventory planning segments service this way; a flat "two weeks of cover" rule is what the diagnostic replaces.

Inventory policy. Variable-demand-and-variable-lead-time safety stock:

SS = z * sqrt( LT * sigma_d^2 + d_bar^2 * sigma_LT^2 )

EOQ rounded up to vendor MOQ:

EOQ = sqrt( 2 * D * S / H )

Reorder point:

ROP = d_bar * LT + SS

Defaults: S = $75 per order, H = 22% of unit cost annual carrying.

Network redundancy. A single-site EOQ + SS calculation under- states the realistic floor for a multi-branch distributor -- each branch needs its own working stock and pipeline inventory. The recommended on-hand position is scaled by a per-branch multiplier (10% per additional branch beyond the first). For Meridian's 14 branches: 2.3x the single-site optimum, landing recommended DIO at the 60-70 day range a real distributor of this size actually runs.

Savings levers (Part 1). Gross savings are decomposed into four named levers -- safety stock right-sizing, cycle-stock / EOQ, SKU rationalization, and obsolescence reserve correction -- never a single black-box percentage. Each lever's gross modeled opportunity is then cut by a uniform realization haircut (default 33%) -- the share that operational friction, change-management drag, and the always-present gap between identified and captured value keeps off the table. Realization mirrors the procurement and freight agents' 33% haircut for consistency across the suite.

The first three levers release working capital (one-time cash); the recurring EBITDA contribution comes from the carrying-cost saving on the released inventory (released * H%) plus the avoided obsolescence write-downs the diagnostic catches before they hit the income statement. The obsolescence component is sized off Meridian's historical 2.1% of-COGS write-down rate, recovering 60% of that drift under a disciplined reserve.

Cross-portco safety-stock pooling (Part 2). For each canonical part appearing in two or more portcos, the classical pooling math says holding pooled SS at one fund-level node releases roughly (1 - 1 / sqrt(N)) of the SS the N portcos hold independently. The 8% / 15% / 22% tiers reflect the share of that theoretical maximum a real pooling program lands -- light pooling (preferred-vendor program with portco-by-portco visibility) captures ~8% of the theoretical; base (fund-wide planning / VMI) captures ~15%; full bloc (single fund-managed central DC) captures ~22%. Benchmarked to published mid-market supply-chain consulting ranges, not supplier quotes.

Cross-agent guardrails. Vendor unit-cost reduction is owned by the Procurement Spend Intelligence Agent at the fund level -- the inventory agent's new combined-volume purchase quantities feed the procurement agent's tier-break model, but the inventory agent does NOT claim the unit-cost EBITDA. Inbound shipment cost is owned by the Freight Carrier Optimization Agent -- the inventory agent's reorder-frequency changes (higher EOQ, fewer orders per year on most SKUs) feed the freight agent's lane model, but the inventory agent does NOT claim the freight savings. DSO is owned by the Working Capital Agent; the inventory agent owns DIO. The two are different components of the cash conversion cycle; both flow to the cash bridge at different positions, so they do not double-count. All three boundaries are flagged in config.py as explicit constants.

EBITDA & value. Inventory savings flow to EBITDA at 70% / 80% / 90% (downside / base / upside) to account for leakage and trade-offs. The recurring component is treated as above-the-line opex reduction (lower carrying cost + avoided write-downs); pre-tax. Enterprise value created equals the recurring EBITDA lift times the entry multiple -- no multiple expansion. The one-time working-capital cash release is valued separately and goes 1:1 to deleveraging.

Reproducibility & scope. Mock mode is the default -- the seeded data generator and the cached LLM playbook produce byte-identical results offline, and the real API is touched only by the one-time seed script. Scope is the six inventory-intensive Hadrian Fund III portfolio companies. Brightpath Logistics (PC4) is excluded -- a freight / logistics business carries cargo, not inventory.


Illustrative results

Two synthetic runs -- one company, then the fund.

Part 1 -- Meridian Industrial Supply. The four-lever model on Meridian's ~30,000-row synthetic year ($147.5M TTM COGS, 1,200 actively-managed SKUs, current inventory $94.7M / DIO 212 days):

  • $14.31M of working-capital release on a right-sized inventory policy -- DIO falls from 212 to 67 days, recommended inventory $30.0M. The release is decomposed lever by lever: SKU rationalization $11.25M, safety stock right-sizing $2.34M, cycle-stock / EOQ $0.72M.
  • $1.25M of recurring EBITDA from obsolescence reserve correction -- avoided write-downs on at-risk and likely-obsolete stock the diagnostic catches before they hit the income statement.
  • A base-case EBITDA bridge (80% flow-through): a $3.51M recurring EBITDA lift and $33.4M of enterprise value created at the 9.5x entry multiple.
  • Across downside / base / upside flow-through (70 / 80 / 90%): a $3.08M-$3.95M EBITDA lift.

Part 2 -- the Fund III rollup. The diagnostic re-run across the six inventory-intensive Hadrian Capital Partners, Fund III portfolio companies (Meridian + Crestline Packaging + Talon Fabricated Metals + Keystone Building Products + Vector Equipment + MidCon Plastics; Brightpath Logistics excluded):

  • $39.36M of standalone working-capital release across the six portcos -- the sum of each portco optimizing alone, before any cross-portco leverage.
  • $10.58M of standalone recurring EBITDA lift, base case -- 30.2% of the six companies' $35.05M combined entry EBITDA.
  • A cross-portco safety-stock pooling layer on the 144 shared canonical SKUs adds a further $0.10M of recurring EBITDA at the base 15% tier (the inventory pooling lever is bounded by sqrt(N) rather than by combined spend, so its incremental sits well below the procurement leverage layer -- inventory's lift lives in the standalone diagnostic, not the pooling layer).
  • At the base case: a $10.68M combined recurring EBITDA lift and $97.0M of enterprise value created, each portco held at its own entry multiple.
  • The one-time working-capital cash release adds $39.80M of deleveraging.
  • On $153.0M of invested equity, an implied +0.89x MOIC lift (operating +0.63x, cash deleveraging +0.26x).

All figures are synthetic and illustrative. Reproduce them with python run_demo.py.


Quickstart

pip install -r requirements.txt

python run_demo.py                      # full pipeline in the terminal
streamlit run app.py                    # interactive app
jupyter notebook notebook.ipynb         # walkthrough notebook

Mock mode (default). With no API key set, the agent runs end-to- end against the cached playbook committed in data/playbook_cache.json. No key, no network, byte-identical results on every run.

Live mode. To rebuild the playbook cache against a live model, copy .env.example to .env and add an ANTHROPIC_API_KEY, then run python scripts/seed_llm_cache.py. The LLM layer is provider- agnostic -- set INVENTORY_MODEL, INVENTORY_ENDPOINT and INVENTORY_KEY_ENV in the environment to point at any provider.

The Streamlit app is built to deploy as-is to Hugging Face Spaces for the public demo.


Repo structure

inventory-intelligence-agent/
├── README.md
├── LESSONS_LEARNED.md
├── requirements.txt
├── .env.example              live-mode key (mock needs none)
├── app.py                    Streamlit app
├── run_demo.py               command-line runner
├── notebook.ipynb            walkthrough notebook
├── config.py                 every tunable assumption, in one file
├── data/
│   ├── inventory.csv          ~30k synthetic Meridian (sku x month) rows
│   ├── inventory_*.csv        per-portco inventory files for the other five
│   ├── portfolio.csv          fund master -- entry economics per portco
│   └── playbook_cache.json   cached vendor + SKU commentary
├── src/
│   ├── data_gen.py           seeded synthetic inventory generator (all 6 portcos)
│   ├── forecast.py           per-SKU mean + hold-out RMSE sigma
│   ├── diagnostic.py         Part 1 -- single-portco diagnostic, 4 levers, EBITDA bridge
│   ├── portfolio.py          Part 2 -- fund rollup, sqrt(N) pooling, fund value bridge
│   ├── playbook.py           vendor + SKU playbook (LLM layer, cached)
│   └── viz.py                Plotly visualizations
└── scripts/
    └── seed_llm_cache.py     one-time real-API call to refresh the cache

What this demo signals

This repository is a hiring artifact as much as a tool. Here is what it is built to show:

  • He finds the lever. Inventory is rarely the headline lever in a 100-day plan; pricing and procurement usually are. The demo opens by identifying inventory as the largest trapped, controllable piece of working capital at Meridian -- before optimizing anything. That is the judgment a value-creation team hires for: knowing where margin and cash actually hide.

  • He speaks the language of a value-creation plan. The output isn't "savings." It's an EBITDA bridge with downside / base / upside flow-through, a sensitivity table, a fund-level enterprise- value roll-up, a working-capital release flowed to deleveraging, and an implied MOIC lift on invested equity -- structured the way a deal team and a board expect to receive it.

  • He thinks at the fund level. Part 2 takes the single-portco play and runs it across six Hadrian companies, with the seventh (Brightpath Logistics) explicitly excluded for cause. He isn't optimizing one company's inventory -- he's building a repeatable, portfolio-wide value-creation lever, identifying the cross-portco canonical-SKU pool, and pricing what fund-level pooling actually captures over what a single portco can do. That is how operating partners are measured.

  • He builds, not just models. This is a working application: a modular codebase, a deterministic analytical pipeline, a provider- agnostic LLM layer with reproducible offline mode, an interactive app, and a walkthrough notebook. He can carry a thesis from data to model to shipped tool without a team behind him.

  • He doesn't oversell. Every assumption is explicit and tunable, Brightpath is excluded from the inventory rollup where it doesn't belong, freight savings are flagged as owned by the freight agent (not double-counted), procurement unit-cost savings are flagged as owned by the procurement agent (also not double-counted), and implementation risk is stated up front. The analysis is built to survive scrutiny from someone who does this for a living.


Who built this

Built by Peter Hanselmann -- a Chicago-based finance and accounting professional with a private-equity background, including Kirkland & Ellis and Kinzie Capital Partners. All code, data, and analysis in this repo are his own.


Get in touch

Two ways to take this further.

If you build value-creation or operations teams -- this repo is a more honest writing sample than a resume. It shows how I frame an EBITDA opportunity, how I think across a portfolio, and that I can ship the tool, not just the deck. If that's the kind of operator you want on your team, I'd like to talk.

If you run a portfolio and want this pointed at real inventory data -- the demo runs fully offline in mock mode, so you can see the logic end to end before anything touches your numbers. Moving it onto a real company's inventory file is a column-mapping exercise, not a rebuild. Happy to walk a team through what that would take.

Reach me on LinkedIn: linkedin.com/in/peter-c-hanselmann-cpa.


Disclaimer

Every SKU, vendor, portfolio company, and figure in this repository is synthetic. Meridian Industrial Supply, the Hadrian Capital Partners portfolio, and every supplier name in the data set are fictional. The working-capital and EBITDA figures are illustrative and exist to demonstrate the agent's logic. This tool supports inventory diagnostic analysis; it is not legal, tax, or financial advice.

© 2026 Peter Hanselmann. All rights reserved. This repository is public so it can be read and evaluated; it is not licensed for reuse, redistribution, or commercial use.

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors