Spaces:
Sleeping
title: Optichain-Inventory-V1 Environment Server
emoji: π
colorFrom: blue
colorTo: indigo
sdk: docker
pinned: false
app_port: 7860
tags:
- openenv
OptiChain-Env: AI-Native Supply Chain Optimization
A Meta OpenEnv Hackathon Submission (2026)
OptiChain-Env is a high-fidelity inventory management environment built strictly to the Meta OpenEnv specification. It challenges AI agents to act as Supply Chain Managers, navigating varying demand signals, shipping disruptions, and strict liquidity constraints over a 30-day simulation.
Unlike standard CLI-only environments, OptiChain ships with a live dashboard that visualises the agent's reasoning, JSON action schema, and per-step newsvendor rewards in real-time.
Environment Description
OptiChain simulates a single-SKU retailer running a 30-day episode. Each day the agent observes current stock, cash, shipment pipeline, and yesterday's sales, then decides how many units to order and whether to expedite shipping. Orders are deducted from cash immediately; inventory arrives after the lead time. At end-of-day, stochastic customer demand is served from on-hand stock β any unmet demand is lost (stockout) and any leftover stock incurs holding cost.
Core mechanics:
- Episode length: 30 days (fixed)
- Product:
SKU-LAPTOPβ order cost $800, margin $400/unit, holding cost $2/unit/day, stockout penalty $100/unit - Lead times: Standard 2 days (4 days under crisis), Expedited 1 day ($100 surcharge/unit)
- Demand: Stochastic Poisson-like variation around task-specific base demand
- Cash constraint: Orders exceeding available cash are partially or fully rejected β the observation reports accepted/rejected quantities so the agent can react
Reward β Newsvendor Inspired
Each step returns a bounded [0, 1] reward based on the classic newsvendor overage/underage tradeoff:
| Scenario | Formula | Rewards |
|---|---|---|
| Overage (stockout == 0) | 1 - (remaining / stock_before) |
Efficient sell-through |
| Underage (stockout > 0) | 1 - (missed / demand) |
High service level |
step_reward:[0, 1]β newsvendor score for the daytotal_reward: cumulative sum of all step rewards (max 30)grader_score:total_reward / max_daysβ normalised to[0, 1], this is the official hackathon score
The success threshold is grader_score >= 0.1.
Action Space
class PurchaseOrder(BaseModel):
product_id: str # e.g. "SKU-LAPTOP"
quantity: int # >= 0
expedite_shipping: bool # True = 1-day, False = standard
class SupplyChainAction(Action):
orders: List[PurchaseOrder] # empty list = do nothing
Example action (order 15 units, standard shipping):
{ "orders": [ { "product_id": "SKU-LAPTOP", "quantity": 15, "expedite_shipping": false } ] }
Observation Space
class ProductStatus(BaseModel):
product_id: str
current_stock: int # on-hand inventory
incoming_shipments: Dict[int, int] # {days_until_arrival: qty}
sales_yesterday: int
lost_sales_yesterday: int
holding_cost_per_unit: float
stockout_penalty_per_unit: float
margin_per_unit: float
class SupplyChainObservation(Observation):
current_day: int # 1..30
total_days: int # always 30
cash_balance: float
warehouse_status: List[ProductStatus]
market_trend_signal: str # task-specific forecast hint
last_order_accepted: int # units accepted last step
last_order_rejected: int # units rejected (insufficient cash)
reward: float # last step_reward
done: bool
Task Curriculum
| Task ID | Name | Starting Cash | Initial Stock | Challenge |
|---|---|---|---|---|
task_01_easy |
Stable Demand | $30,000 | 50 | Constant ~10 units/day demand. Baseline reasoning test. |
task_02_medium |
Holiday Spike | $50,000 | 20 | Black Friday spike (10 β 40 units/day) on Day 10. Requires pre-loading. |
task_03_hard |
Supply Crisis | $30,000 | 30 | Standard lead time jumps from 2 to 4 days. Expedited option costs $100/unit extra. |
OpenEnv Endpoints
The environment exposes the full OpenEnv HTTP API:
| Method | Path | Purpose |
|---|---|---|
POST |
/reset |
Start a new episode. Body: { "task_id": "...", "seed": 42 } |
POST |
/step |
Submit a SupplyChainAction. Returns observation, reward breakdown, done flag, info |
GET |
/state |
Current episode metadata without side effects |
GET |
/grader |
Normalised episode score [0, 1] |
GET |
/health |
Liveness probe for Hugging Face Spaces |
GET |
/tasks |
List all available tasks and action schema |
GET |
/schema |
JSON schemas for Action / Observation / Reward / State |
GET |
/ |
Live dashboard UI |
POST |
/demo/step_sim |
Dashboard bridge: run LLM agent β step env β return both |
Project Structure
OptiChain-Env/
βββ env/
β βββ core.py # Simulation engine (inherits openenv Environment)
β βββ schemas.py # Pydantic Action/Observation/Reward/State models
βββ server/
β βββ app.py # FastAPI server β canonical OpenEnv entry point
βββ static/
β βββ index.html # Real-time dashboard UI
βββ app/
β βββ main.py # Legacy re-export shim (server.app:app)
βββ inference.py # Multi-agent LLM baseline (Analyst + Executor + guardrails)
βββ openenv.yaml # OpenEnv spec (spec_version: 1)
βββ pyproject.toml # Build config + dependencies
βββ requirements.txt # pip install target
βββ Dockerfile # HF Spaces deployment image
βββ .env.example # LLM API config template
Setup Instructions
1. Clone and install
git clone https://github.com/YOUR_USERNAME/OptiChain-Env.git
cd OptiChain-Env
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -r requirements.txt
Python 3.11+ is required.
2. Validate the OpenEnv spec
openenv validate .
Expected output: [OK] : Ready for multi-mode deployment.
3. Run the server locally
uvicorn server.app:app --host 0.0.0.0 --port 7860 --reload
- Dashboard: http://localhost:7860
- Swagger UI: http://localhost:7860/docs
4. (Optional) Configure the LLM baseline
The bundled multi-agent baseline in inference.py is OpenAI-compatible. Copy .env.example to .env and set:
API_BASE_URL=https://api.groq.com/openai/v1 # or http://localhost:11434/v1 for Ollama
API_KEY=your_key_here
MODEL_NAME=llama-3.3-70b-versatile # or llama3.2:3b for Ollama
Run the baseline end-to-end:
python inference.py
Structured logs ([START], [STEP], [END]) are emitted to stdout.
5. Deploy to Hugging Face Spaces
openenv push --repo-id YOUR_USERNAME/optichain-env
Then add API_BASE_URL, API_KEY, and MODEL_NAME as Space Secrets (Settings β Repository secrets).
Multi-Agent Baseline
inference.py implements a Planner β Executor β Guardrails pipeline to keep small/local LLMs reliable:
- Analyst agent β free-form reasoning over observation + order feedback loop
- Executor agent β converts Analyst reasoning to strict
SupplyChainActionJSON - Python guardrails β clip orders to
min(affordable_qty, demand_based_useful_qty)and gate by lead time near episode end
This pattern defeats three failure modes common in small-LLM supply-chain agents:
- Ghost orders β silently-rejected orders the LLM believes succeeded
- Logic-tag dissonance β reasoning says "order 10" but JSON outputs
quantity: 51 - Overstocking β hoarding cash and inventory far beyond demand horizon
License
MIT β see LICENSE.