Agent skill
inventory-optimizer
Inventory optimization skill for safety stock, reorder point, and order quantity calculations.
Install this agent skill to your Project
npx add-skill https://github.com/a5c-ai/babysitter/tree/main/library/specializations/domains/science/industrial-engineering/skills/inventory-optimizer
Metadata
Additional technical details for this skill
- author
- babysitter-sdk
- version
- 1.0.0
- category
- supply-chain
- backlog id
- SK-IE-025
SKILL.md
inventory-optimizer
You are inventory-optimizer - a specialized skill for optimizing inventory policies including safety stock, reorder points, and order quantities.
Overview
This skill enables AI-powered inventory optimization including:
- ABC/XYZ classification
- Economic Order Quantity (EOQ) calculation
- Safety stock calculation by service level
- Reorder point determination
- Periodic review (R,S) policy optimization
- Continuous review (r,Q) policy optimization
- Multi-echelon inventory optimization
- Inventory investment analysis
Capabilities
1. ABC/XYZ Classification
import numpy as np
import pandas as pd
def abc_analysis(items: pd.DataFrame, value_column: str, quantity_column: str):
"""
ABC classification based on annual value (Pareto analysis)
A: Top 80% of value (typically 20% of items)
B: Next 15% of value (typically 30% of items)
C: Remaining 5% of value (typically 50% of items)
"""
# Calculate annual value
items = items.copy()
items['annual_value'] = items[value_column] * items[quantity_column]
items = items.sort_values('annual_value', ascending=False)
# Calculate cumulative percentage
total_value = items['annual_value'].sum()
items['cum_value'] = items['annual_value'].cumsum()
items['cum_pct'] = items['cum_value'] / total_value * 100
# Assign ABC class
def assign_class(pct):
if pct <= 80:
return 'A'
elif pct <= 95:
return 'B'
else:
return 'C'
items['ABC_class'] = items['cum_pct'].apply(assign_class)
return items
def xyz_analysis(items: pd.DataFrame, demand_history_columns: list):
"""
XYZ classification based on demand variability
X: CV < 0.5 (stable demand)
Y: 0.5 <= CV < 1.0 (moderate variability)
Z: CV >= 1.0 (high variability)
"""
items = items.copy()
# Calculate coefficient of variation
demand_data = items[demand_history_columns]
items['mean_demand'] = demand_data.mean(axis=1)
items['std_demand'] = demand_data.std(axis=1)
items['CV'] = items['std_demand'] / items['mean_demand']
# Assign XYZ class
def assign_xyz(cv):
if cv < 0.5:
return 'X'
elif cv < 1.0:
return 'Y'
else:
return 'Z'
items['XYZ_class'] = items['CV'].apply(assign_xyz)
return items
def abc_xyz_matrix(items: pd.DataFrame):
"""
Create combined ABC-XYZ matrix
"""
matrix = items.groupby(['ABC_class', 'XYZ_class']).size().unstack(fill_value=0)
recommendations = {
'AX': 'High value, stable - continuous review, tight control',
'AY': 'High value, variable - safety stock important, frequent review',
'AZ': 'High value, unpredictable - careful forecasting, higher safety stock',
'BX': 'Medium value, stable - periodic review',
'BY': 'Medium value, variable - moderate control',
'BZ': 'Medium value, unpredictable - consider min-max system',
'CX': 'Low value, stable - simple rules, minimal attention',
'CY': 'Low value, variable - periodic review, simple rules',
'CZ': 'Low value, unpredictable - consider elimination or consignment'
}
return {
"matrix": matrix,
"recommendations": recommendations
}
2. Economic Order Quantity (EOQ)
def economic_order_quantity(annual_demand: float, ordering_cost: float,
holding_cost_per_unit: float):
"""
Classic EOQ calculation
EOQ = sqrt(2 * D * S / H)
D: Annual demand
S: Ordering cost per order
H: Holding cost per unit per year
"""
eoq = np.sqrt((2 * annual_demand * ordering_cost) / holding_cost_per_unit)
# Calculate associated costs
orders_per_year = annual_demand / eoq
annual_ordering_cost = orders_per_year * ordering_cost
average_inventory = eoq / 2
annual_holding_cost = average_inventory * holding_cost_per_unit
total_cost = annual_ordering_cost + annual_holding_cost
return {
"EOQ": round(eoq, 0),
"orders_per_year": round(orders_per_year, 1),
"order_interval_days": round(365 / orders_per_year, 1),
"annual_ordering_cost": round(annual_ordering_cost, 2),
"annual_holding_cost": round(annual_holding_cost, 2),
"total_relevant_cost": round(total_cost, 2),
"average_inventory": round(average_inventory, 0)
}
def eoq_with_quantity_discounts(annual_demand: float, ordering_cost: float,
holding_rate: float, price_breaks: list):
"""
EOQ with quantity discounts
price_breaks: [(min_qty, unit_price), ...]
"""
results = []
for min_qty, unit_price in sorted(price_breaks, key=lambda x: x[1], reverse=True):
holding_cost = unit_price * holding_rate
eoq = np.sqrt((2 * annual_demand * ordering_cost) / holding_cost)
# Check if EOQ is feasible for this price bracket
if eoq < min_qty:
order_qty = min_qty
else:
order_qty = eoq
# Calculate total cost
orders_per_year = annual_demand / order_qty
annual_ordering = orders_per_year * ordering_cost
annual_holding = (order_qty / 2) * holding_cost
annual_purchase = annual_demand * unit_price
total_cost = annual_ordering + annual_holding + annual_purchase
results.append({
"min_quantity": min_qty,
"unit_price": unit_price,
"calculated_eoq": round(eoq, 0),
"order_quantity": round(order_qty, 0),
"total_annual_cost": round(total_cost, 2)
})
# Find optimal
optimal = min(results, key=lambda x: x['total_annual_cost'])
return {
"all_options": results,
"optimal": optimal
}
3. Safety Stock Calculation
from scipy import stats
def safety_stock_service_level(demand_std: float, lead_time_mean: float,
lead_time_std: float = 0, service_level: float = 0.95):
"""
Calculate safety stock for desired service level
Accounts for variability in both demand and lead time
"""
# Z-score for service level
z = stats.norm.ppf(service_level)
if lead_time_std > 0:
# Combined variability
# SS = z * sqrt(LT * sigma_d^2 + d_avg^2 * sigma_LT^2)
# Simplified: SS = z * sigma_d * sqrt(LT)
combined_std = np.sqrt(lead_time_mean * demand_std**2)
safety_stock = z * combined_std
else:
# Only demand variability
safety_stock = z * demand_std * np.sqrt(lead_time_mean)
return {
"safety_stock": round(safety_stock, 0),
"service_level": service_level,
"z_score": round(z, 2),
"demand_std": demand_std,
"lead_time": lead_time_mean
}
def safety_stock_fill_rate(demand_mean: float, demand_std: float,
order_quantity: float, target_fill_rate: float = 0.98):
"""
Calculate safety stock for target fill rate
Fill rate: proportion of demand satisfied from stock
"""
# Expected shortage per cycle (using loss function)
target_shortage = (1 - target_fill_rate) * order_quantity
# Iterative search for safety stock
for ss in range(0, int(demand_std * 10), 1):
z = ss / demand_std
loss = demand_std * (stats.norm.pdf(z) - z * (1 - stats.norm.cdf(z)))
if loss <= target_shortage:
return {
"safety_stock": ss,
"target_fill_rate": target_fill_rate,
"achieved_fill_rate": 1 - loss / order_quantity
}
return {"safety_stock": int(demand_std * 10), "note": "Max safety stock reached"}
4. Reorder Point Determination
def calculate_reorder_point(average_demand_per_period: float,
lead_time_periods: float,
safety_stock: float):
"""
Calculate reorder point (r)
r = d * L + SS
d: Average demand per period
L: Lead time in periods
SS: Safety stock
"""
lead_time_demand = average_demand_per_period * lead_time_periods
reorder_point = lead_time_demand + safety_stock
return {
"reorder_point": round(reorder_point, 0),
"lead_time_demand": round(lead_time_demand, 0),
"safety_stock": round(safety_stock, 0),
"interpretation": f"Order when inventory reaches {round(reorder_point, 0)} units"
}
5. Continuous Review (r, Q) Policy
def optimize_rQ_policy(annual_demand: float, demand_std_per_period: float,
lead_time_periods: float, ordering_cost: float,
holding_cost_per_unit: float, service_level: float = 0.95):
"""
Optimize continuous review policy
r: Reorder point
Q: Order quantity (EOQ)
"""
# Calculate Q using EOQ
eoq_result = economic_order_quantity(annual_demand, ordering_cost, holding_cost_per_unit)
Q = eoq_result['EOQ']
# Calculate safety stock for service level
ss_result = safety_stock_service_level(
demand_std=demand_std_per_period,
lead_time_mean=lead_time_periods,
service_level=service_level
)
SS = ss_result['safety_stock']
# Calculate reorder point
periods_per_year = 12 # Assuming monthly
avg_demand_per_period = annual_demand / periods_per_year
r = avg_demand_per_period * lead_time_periods + SS
return {
"policy": "(r, Q)",
"reorder_point": round(r, 0),
"order_quantity": round(Q, 0),
"safety_stock": round(SS, 0),
"service_level": service_level,
"average_inventory": round(Q/2 + SS, 0),
"annual_cost": eoq_result['total_relevant_cost']
}
6. Periodic Review (R, S) Policy
def optimize_RS_policy(annual_demand: float, demand_std_per_period: float,
review_period_periods: float, lead_time_periods: float,
holding_cost_per_unit: float, service_level: float = 0.95):
"""
Optimize periodic review policy
R: Review period
S: Order-up-to level
"""
z = stats.norm.ppf(service_level)
# Protection period = review period + lead time
protection_period = review_period_periods + lead_time_periods
# Average demand during protection period
periods_per_year = 12
avg_demand_per_period = annual_demand / periods_per_year
avg_demand_protection = avg_demand_per_period * protection_period
# Standard deviation during protection period
std_protection = demand_std_per_period * np.sqrt(protection_period)
# Safety stock
SS = z * std_protection
# Order-up-to level
S = avg_demand_protection + SS
# Average inventory (approximation)
avg_order_qty = avg_demand_per_period * review_period_periods
avg_inventory = avg_order_qty / 2 + SS
return {
"policy": "(R, S)",
"review_period": review_period_periods,
"order_up_to_level": round(S, 0),
"safety_stock": round(SS, 0),
"service_level": service_level,
"average_inventory": round(avg_inventory, 0),
"annual_holding_cost": round(avg_inventory * holding_cost_per_unit, 2)
}
Process Integration
This skill integrates with the following processes:
inventory-optimization-analysis.jsdemand-forecasting-model-development.jswarehouse-layout-slotting-optimization.js
Output Format
{
"item": "SKU-12345",
"abc_class": "A",
"xyz_class": "X",
"policy": "(r, Q)",
"reorder_point": 450,
"order_quantity": 200,
"safety_stock": 85,
"service_level": 0.95,
"average_inventory": 185,
"annual_cost": 5420.50,
"recommendations": [
"Consider vendor-managed inventory given high volume"
]
}
Best Practices
- Classify items first - Use ABC/XYZ to prioritize
- Match policy to class - More sophisticated for A items
- Review parameters regularly - Demand patterns change
- Consider total cost - Not just inventory cost
- Validate assumptions - Lead time, demand distributions
- Monitor service levels - Actual vs target
Constraints
- Requires accurate demand and cost data
- Assumes known distributions
- Lead time variability often underestimated
- Review periodically as conditions change
Recommended Agent Skills
Expand your agent's capabilities with these related and highly-rated skills.
gsd-tools
Central utility skill for GSD operations. Provides config parsing, slug generation, timestamps, path operations, and orchestrates calls to other specialized skills. Acts as the unified entry point that the original gsd-tools.cjs provided via its lib/ modules (commands, config, core, init).
model-profile-resolution
Resolve model profile (quality/balanced/budget) at orchestration start and map agents to specific models. Enables cost/quality tradeoffs by selecting appropriate AI models for each agent role.
verification-suite
Plan structure validation, phase completeness checks, reference integrity verification, and artifact existence confirmation. Provides the structured verification layer ensuring GSD artifacts are well-formed and complete.
state-management
STATE.md reading, writing, and field-level updates. Provides cross-session state persistence via .planning/STATE.md with structured fields for current task, completed phases, blockers, decisions, and quick tasks.
git-integration
Git commit patterns, formats, and conventions for GSD methodology. Provides atomic commits per task, structured commit messages, planning file commits, branch management, and milestone tag operations.
frontmatter-parsing
YAML frontmatter parsing and manipulation for .planning/ documents. Provides read, write, update, query, and validation operations on frontmatter blocks in GSD markdown artifacts.
Didn't find tool you were looking for?