Install any skill in seconds. Free to start, no credit card required.
Get Started Free →MLOps across model deployment, ML pipelines, monitoring, and feature stores. Use when deploying models to production, building training pipelines, setting up drift detection, configuring feature stores, or automating ML CI/CD workflows.
.claude/skills/borghei-ml-ops-engineer/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-01 | ✗→✓ | ▲ Improved | 110% | 0% |
| case-02 | ✗→✓ | ▲ Improved | 125% | 0% |
| case-04 | ✗→✓ | ▲ Improved | 133% | 0% |
| case-06 | ✗→✓ | ▲ Improved | 167% | 0% |
| case-12 | ✗→✓ | ▲ Improved | 166% | 0% |
The agent operates as a senior MLOps engineer, deploying models to production, orchestrating training pipelines, monitoring model health, managing feature stores, and automating ML CI/CD.
Before deploying, confirm these inputs. If any is unknown or vague, ASK — do not assume:
Stop rule: ask only the 2-3 that most change the output. If the user says "just draft it," proceed and list your assumptions at the top of the artifact.
| Level | Capabilities | Key signals | |-------|-------------|------------| | 0 - Manual | Jupyter notebooks, manual deploy | No version control on models | | 1 - Pipeline | Automated training, versioned models | MLflow tracking in use | | 2 - CI/CD | Continuous training, automated tests | Feature store operational | | 3 - Full MLOps | Auto-retraining on drift, A/B testing | SLA-backed monitoring |
python# model_server.py -- FastAPI model serving from fastapi import FastAPI, HTTPException from pydantic import BaseModel import mlflow.pyfunc, time app = FastAPI() model = mlflow.pyfunc.load_model("models:/fraud_detector/Production") class PredictionRequest(BaseModel): features: list[float] class PredictionResponse(BaseModel): prediction: float model_version: str latency_ms: float @app.post("/predict", response_model=PredictionResponse) async def predict(req: PredictionRequest): start = time.time() try: pred = model.predict([req.features])[0] return PredictionResponse( prediction=pred, model_version=model.metadata.run_id, latency_ms=(time.time() - start) * 1000, ) except Exception as e: raise HTTPException(status_code=500, detail=str(e)) @app.get("/health") async def health(): return {"status": "healthy", "model_loaded": model is not None}
yaml# k8s/model-deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: name: model-server spec: replicas: 3 selector: matchLabels: {app: model-server} template: metadata: labels: {app: model-server} spec: containers: - name: model-server image: gcr.io/project/model-server:v1.2.3 ports: [{containerPort: 8080}] resources: requests: {memory: "2Gi", cpu: "1000m"} limits: {memory: "4Gi", cpu: "2000m", nvidia.com/gpu: 1} env: - {name: MODEL_URI, value: "s3://models/production/v1.2.3"} readinessProbe: httpGet: {path: /health, port: 8080} initialDelaySeconds: 30 periodSeconds: 10 --- apiVersion: autoscaling/v2 kind: HorizontalPodAutoscaler metadata: name: model-server-hpa spec: scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: model-server minReplicas: 2 maxReplicas: 10 metrics: - type: Resource resource: name: cpu target: {type: Utilization, averageUtilization: 70}
python# monitoring/drift_detector.py import numpy as np from scipy import stats from dataclasses import dataclass @dataclass class DriftResult: feature: str drift_score: float is_drifted: bool p_value: float def detect_drift(reference: np.ndarray, current: np.ndarray, threshold: float = 0.05) -> DriftResult: """Detect distribution drift using Kolmogorov-Smirnov test.""" statistic, p_value = stats.ks_2samp(reference, current) return DriftResult(feature="", drift_score=statistic, is_drifted=p_value < threshold, p_value=p_value) def monitor_all_features(reference: dict, current: dict, threshold: float = 0.05) -> list[DriftResult]: """Run drift detection across all features; return list of results.""" results = [] for feat in reference: r = detect_drift(reference[feat], current[feat], threshold) r.feature = feat results.append(r) return results
pythonALERT_RULES = { "latency_p99": {"threshold": 200, "severity": "warning", "msg": "P99 latency exceeded 200 ms"}, "error_rate": {"threshold": 0.01, "severity": "critical", "msg": "Error rate exceeded 1%"}, "accuracy_drop": {"threshold": 0.05, "severity": "critical", "msg": "Accuracy dropped > 5%"}, "drift_score": {"threshold": 0.15, "severity": "warning", "msg": "Feature drift detected"}, }
python# features/customer_features.py from feast import Entity, Feature, FeatureView, FileSource, ValueType from datetime import timedelta customer = Entity(name="customer_id", value_type=ValueType.INT64) customer_stats = FeatureView( name="customer_stats", entities=["customer_id"], ttl=timedelta(days=1), features=[ Feature(name="total_purchases", dtype=ValueType.FLOAT), Feature(name="avg_order_value", dtype=ValueType.FLOAT), Feature(name="days_since_last_order", dtype=ValueType.INT32), Feature(name="lifetime_value", dtype=ValueType.FLOAT), ], online=True, source=FileSource( path="gs://features/customer_stats.parquet", timestamp_field="event_timestamp", ), )
Online retrieval at serving time:
pythonfrom feast import FeatureStore store = FeatureStore(repo_path=".") features = store.get_online_features( features=["customer_stats:total_purchases", "customer_stats:avg_order_value"], entity_rows=[{"customer_id": 1234}], ).to_dict()
pythonimport mlflow mlflow.set_tracking_uri("http://mlflow.company.com") mlflow.set_experiment("fraud_detection") with mlflow.start_run(run_name="xgboost_v2"): mlflow.log_params({"n_estimators": 100, "max_depth": 6, "learning_rate": 0.1}) model = train_model(X_train, y_train) mlflow.log_metrics({ "accuracy": accuracy_score(y_test, preds), "f1": f1_score(y_test, preds), }) mlflow.sklearn.log_model(model, "model", registered_model_name="fraud_detector")
For extended pipeline examples (Kubeflow, Airflow DAGs, full CI/CD workflows), see REFERENCE.md.
REFERENCE.md -- Extended patterns: Kubeflow pipelines, Airflow DAGs, CI/CD workflows, model registry operationsreferences/deployment_patterns.md -- Model deployment strategiesreferences/monitoring_guide.md -- ML monitoring best practicesreferences/feature_store.md -- Feature store patternsreferences/pipeline_design.md -- ML pipeline architecturebashpython scripts/model_registry.py register --name fraud_detector --version v2.3 --metrics '{"f1":0.91,"auc":0.95}' --params '{"n_estimators":200}' python scripts/model_registry.py promote --name fraud_detector --version v2.3 --stage production python scripts/model_registry.py list --stage production --json python scripts/model_registry.py compare --name fraud_detector --versions v2.2 v2.3 python scripts/drift_detector.py --reference train_data.csv --current prod_data.csv python scripts/drift_detector.py --reference baseline.csv --current latest.csv --threshold 0.1 --json python scripts/pipeline_validator.py --pipeline pipeline.json --strict python scripts/pipeline_validator.py --pipeline pipeline.json --json
| Tool | Purpose | Key Flags | |------|---------|-----------| | model_registry.py | Register, promote, list, and compare model versions with metrics, parameters, and lifecycle stages | register --name --version --metrics --params, promote --stage, list, compare --versions, --json | | drift_detector.py | Detect data/model drift between reference and current datasets using KS statistic, PSI, and chi-square | --reference <csv>, --current <csv>, --columns, --threshold, --json | | pipeline_validator.py | Validate ML pipeline definitions for completeness, stage ordering, evaluation gates, and rollback config | --pipeline <json>, --strict, --json |
| Problem | Likely Cause | Resolution | |---------|-------------|------------| | Model latency exceeds P99 SLA (> 200 ms) | Model is too large, input preprocessing is slow, or pod resources are undersized | Profile the serving endpoint; consider model distillation, input caching, or increasing CPU/memory limits | | drift_detector.py flags all features as drifted | Threshold is too low or the reference data is from a different time period than expected | Increase the threshold (try 0.15-0.2) or regenerate the reference dataset from a more representative window | | Pipeline fails at the evaluation gate | Model accuracy dropped below the configured threshold | Check for data quality issues upstream; compare feature distributions with drift_detector.py; retrain with fresh data | | Model registry shows "already registered" error | The exact name + version combination was previously registered | Use a new version string (e.g., v2.3.1) or remove the old entry if it was a test | | Kubernetes pods crash-loop on model server | OOM kill due to model size exceeding memory limits, or health check timeout too short | Increase resources.limits.memory; extend initialDelaySeconds on readiness probe for large models | | Feature store returns stale features | Materialization job failed or ran outside the TTL window | Check materialization logs; re-run materialize_features; consider reducing TTL or adding freshness alerts | | pipeline_validator.py reports STAGE_ORDER error | Pipeline stages are defined out of the expected sequence (data -> transform -> train -> evaluate -> deploy) | Reorder stages to follow the canonical sequence; the validator expects data stages before training stages |
pipeline_validator.py --strict with zero errors before deployment.In scope: Model deployment (real-time and batch), ML pipeline orchestration, model registry management, drift detection (data drift, concept drift, prediction drift), feature store patterns, monitoring and alerting, Kubernetes deployment configurations, and CI/CD for ML.
Out of scope: Model architecture design and algorithm selection (see data-scientist), raw data ingestion pipelines, BI dashboard development, and business strategy.
Limitations: The Python tools use only the Python standard library. drift_detector.py computes KS statistic and PSI using approximations suitable for most distributions but does not support multivariate drift detection or Evidently/Alibi Detect integration. model_registry.py stores state in a local JSON file -- for production use, integrate with MLflow Model Registry or a similar platform. pipeline_validator.py validates structure and conventions but does not execute pipeline stages.
data-analytics/data-scientist): Receives trained models with experiment metadata; promotes winning experiments to the registry for deployment.data-analytics/analytics-engineer): Feature engineering pipelines may depend on dbt mart models; schema changes trigger pipeline revalidation.engineering/senior-ml-engineer): Collaborates on model architecture optimization for serving constraints (latency, memory, GPU).engineering/): Kubernetes configurations, autoscaling policies, and CI/CD workflows are co-managed with platform engineering.data-analytics/business-intelligence): Model predictions may feed into BI dashboards; monitoring metrics are surfaced in operational dashboards.| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-01 | fail→pass | 16,789 | 17,972 | +7% | 1 | 1 | 0% | 3,469 | 7,278 | +110% | 0 | 0 | — |
case-02 | fail→pass | 18,276 | 17,231 | -6% | 1 | 1 | 0% | 3,115 | 7,012 | +125% | 0 | 0 | — |
case-03 | fail→fail | 21,330 | 25,234 | +18% | 1 | 1 | 0% | 4,035 | 8,772 | +117% | 0 | 0 | — |
case-04 | fail→pass | 13,040 | 13,249 | +2% | 1 | 1 | 0% | 2,658 | 6,183 | +133% | 0 | 0 | — |
case-05 | pass→fail | 15,957 | 19,464 | +22% | 1 | 1 | 0% | 3,024 | 7,298 | +141% | 0 | 0 | — |
case-06 | fail→pass | 13,526 | 15,054 | +11% | 1 | 1 | 0% | 2,335 | 6,238 | +167% | 0 | 0 | — |
case-07 | pass→pass | 16,042 | 11,056 | -31% | 1 | 1 | 0% | 2,809 | 5,449 | +94% | 0 | 0 | — |
case-08 | pass→pass | 7,395 | 6,977 | -6% | 1 | 1 | 0% | 1,181 | 4,734 | +301% | 0 | 0 | — |
case-09 | fail→fail | 12,325 | 14,163 | +15% | 1 | 1 | 0% | 2,195 | 5,949 | +171% | 0 | 0 | — |
case-10 | pass→pass | 6,237 | 6,686 | +7% | 1 | 1 | 0% | 1,090 | 4,928 | +352% | 0 | 0 | — |
case-11 | pass→pass | 13,104 | 9,711 | -26% | 1 | 1 | 0% | 2,062 | 5,093 | +147% | 0 | 0 | — |
case-12 | fail→pass | 11,321 | 8,732 | -23% | 1 | 1 | 0% | 1,854 | 4,929 | +166% | 0 | 0 | — |
case-13 | pass→pass | 16,252 | 20,733 | +28% | 1 | 1 | 0% | 2,558 | 7,175 | +180% | 0 | 0 | — |
case-14 | fail→pass | 12,274 | 10,766 | -12% | 1 | 1 | 0% | 1,947 | 5,175 | +166% | 0 | 0 | — |
case-15 | pass→pass | 10,726 | 4,065 | -62% | 1 | 1 | 0% | 1,724 | 4,102 | +138% | 0 | 0 | — |
case-16 | fail→pass | 6,822 | 3,405 | -50% | 1 | 1 | 0% | 1,106 | 4,141 | +274% | 0 | 0 | — |
case-22 | pass→pass | 13,884 | 14,675 | +6% | 1 | 1 | 0% | 2,477 | 6,205 | +151% | 0 | 0 | — |
case-17 | pass→pass | 11,819 | 3,432 | -71% | 1 | 1 | 0% | 1,873 | 4,033 | +115% | 0 | 0 | — |
case-18 | fail→pass | 9,140 | 4,825 | -47% | 1 | 1 | 0% | 1,706 | 4,403 | +158% | 0 | 0 | — |
case-19 | fail→pass | 10,870 | 10,954 | +1% | 1 | 1 | 0% | 1,666 | 5,200 | +212% | 0 | 0 | — |
case-20 | fail→fail | 16,353 | 14,582 | -11% | 1 | 1 | 0% | 2,726 | 6,015 | +121% | 0 | 0 | — |
case-21 | fail→pass | 17,703 | 17,624 | -0% | 1 | 1 | 0% | 2,839 | 6,500 | +129% | 0 | 0 | — |
case-23 | pass→pass | 18,420 | 28,267 | +53% | 1 | 1 | 0% | 3,499 | 9,430 | +170% | 0 | 0 | — |
case-24 | fail→fail | 15,052 | 15,451 | +3% | 1 | 1 | 0% | 2,751 | 6,585 | +139% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 24 cases were attempted. The headline lift of +38 percentage points is the difference between those two pass rates over the 24 comparable cases. 1 case got worse with the skill loaded, and it is included in that figure.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.