# Air-Gapped Rig-Edge WITSML Telemetry with Local Small Language Models (SLMs)

> Source: <https://dev.to/greybeard00007/air-gapped-rig-edge-witsml-telemetry-with-local-small-language-models-slms-165m>
> Published: 2026-11-05 04:42:33+00:00

*Originally published with interactive math formulas and diagrams at [eng.kcklayton.com](https://eng.kcklayton.com/blog/rig-edge-witsml-local-slm-telemetry/)*

Drilling rigs—whether stationed offshore in deepwater or operating across remote onshore basins—share a common operational reality: **high-latency, bandwidth-constrained, and intermittent satellite connectivity (VSAT)**.

Round-trip satellite pings routinely exceed $600\text{ to }1200\text{ ms}$, with atmospheric attenuation or antenna line-of-sight blockage causing frequent dropouts. When a high-pressure gas influx (kick) enters the wellbore, or when a bottom-hole assembly (BHA) experiences catastrophic stick-slip oscillation, seconds count. Routing real-time sensor telemetry to a remote cloud datacenter for LLM inference or anomaly classification introduces unacceptable operational latency and single-point-of-failure exposure.

To solve this, our drilling architecture decouples real-time rig surveillance into an **Air-Gapped Edge Intelligence Stack** running local deterministic filters and quantized Small Language Models (SLMs) directly on rig-site hardware.

Modern drilling rigs generate high-frequency telemetry across dozens of channels via the **WITSML** (Wellsite Information Transfer Standard Markup Language) and **WITS** (Wellsite Information Transfer Specification) standards:

```
flowchart TD
    subgraph RigFloor["Rig Floor & PWD Instrumentation"]
        Sensors["Rig Sensors (Flow, SPP, Pit, Hookload)"]
        PWD["Downhole MWD / PWD Telemetry"]
    end

    subgraph RigEdge["Edge Server (Rig Doghouse / Rig Server Room)"]
        WITSMLAgent["WITSML Edge Agent<br/>(1-sec Poller & In-Memory Ring Buffer)"]
        MathEngine["Deterministic Physics Filters<br/>(Flow In/Out Differential, Pit Rate)"]
        LocalSLM["Local SLM Inference Engine<br/>(Ollama / llama.cpp - Qwen / Mistral)"]
        RigDisplay["Local Rig Doghouse Alarm & HMI"]
    end

    subgraph RemoteCloud["Corporate Headquarters / Real-Time Operations Center (RTOC)"]
        CloudMesh["Event-Driven Telemetry Mesh"]
        RemoteDashboard["Engineering Dashboard"]
    end

    Sensors -->|WITS / WITSML| WITSMLAgent
    PWD -->|Mud Pulse / EM| WITSMLAgent
    WITSMLAgent --> MathEngine
    MathEngine -->|Anomaly Context Window| LocalSLM
    LocalSLM -->|Sub-second Triage & Root Cause| RigDisplay
    WITSMLAgent -.->|Async Delta Sync via VSAT (When Online)| CloudMesh
    CloudMesh -.-> RemoteDashboard
```

Language models should never replace basic physics calculations. Calculating flow differential ($\Delta Q = Q_{\text{out}} - Q_{\text{in}}$) or standpipe pressure derivatives ($\frac{dP}{dt}$) requires deterministic arithmetic, not probabilistic token generation.

The edge agent runs a **two-tier architecture**:

The [`witsml-edge-agent`](https://github.com/Greybeard00007/witsml-edge-agent) maintains a rolling in-memory ring buffer (defaulting to 300 seconds of 1-second records). A high-speed Rust/Python physics worker evaluates:

When Tier 1 triggers an anomaly condition, it compiles a structured JSON context payload capturing the pre-event baseline, trigger metrics, current rig state (drilling, tripping, circulating, reaming), and recent downhole events.

This payload is dispatched via localhost IPC to [`ai-gateway-sentinel`](https://github.com/Greybeard00007/ai-gateway-sentinel), which interfaces directly with an embedded Ollama or `llama.cpp` instance running a quantized $7\text{B}$ or $3\text{B}$ parameter model (e.g., `mistral-7b-instruct-q4_K_M` or `qwen2.5-coder-7b`).

Here is how the edge agent structures the telemetry window and queries the local edge engine:

``` python
import numpy as np
from dataclasses import dataclass
from typing import List, Optional
import httpx

@dataclass
class TelemetryPoint:
    timestamp: float
    depth_ft: float
    rop_fph: float
    spp_psi: float
    flow_out_pct: float
    pit_total_bbl: float
    pumps_active: bool

class RigEdgeAnomalyDetector:
    def __init__(self, ollama_url: str = "http://127.0.0.1:11434"):
        self.buffer: List[TelemetryPoint] = []
        self.max_buffer_size = 300
        self.ollama_url = ollama_url
        self.anomaly_cooldown = 0

    def push(self, point: TelemetryPoint) -> Optional[dict]:
        self.buffer.append(point)
        if len(self.buffer) > self.max_buffer_size:
            self.buffer.pop(0)

        # Require at least 30 seconds of stable baseline
        if len(self.buffer) < 30:
            return None

        # Deterministic trigger checks
        recent = self.buffer[-5:]
        baseline = self.buffer[-30:-5]

        avg_baseline_pit = np.mean([p.pit_total_bbl for p in baseline])
        current_pit = recent[-1].pit_total_bbl
        pit_gain = current_pit - avg_baseline_pit

        # Condition: Flowing with pumps off, or pit gain > 10 bbl
        flow_anomaly = (not recent[-1].pumps_active) and (recent[-1].flow_out_pct > 3.0)
        kick_indicator = pit_gain > 10.0

        if (flow_anomaly or kick_indicator) and self.anomaly_cooldown == 0:
            self.anomaly_cooldown = 60 # Cooldown to avoid prompt flooding
            return self._triage_with_local_slm(point, pit_gain, flow_anomaly)

        if self.anomaly_cooldown > 0:
            self.anomaly_cooldown -= 1

        return None

    def _triage_with_local_slm(self, pt: TelemetryPoint, pit_gain: float, flow_anomaly: bool) -> dict:
        prompt = f"""[RIG ALARM TRIAGE - HIGH PRIORITY]
You are a senior drilling superintendent and well control advisor running on an edge rig computer.
Current Telemetry:
- Hole Depth: {pt.depth_ft:.1f} ft
- Standpipe Pressure: {pt.spp_psi:.0f} psi
- Pumps Active: {pt.pumps_active}
- Flow Out: {pt.flow_out_pct:.1f}%
- Total Pit Gain: {pt.pit_gain:.1f} bbl
- Flow Anomaly Flag: {flow_anomaly}

Provide a concise, 3-bullet assessment:
1. Probable Root Cause (e.g., Formation Influx vs. Pit Transfer vs. Sensor Drift)
2. Immediate Verification Step for Driller (e.g., Space out and perform flow check)
3. Well Control Level (Green / Yellow / Red Alert)
Format response as strictly actionable guidance for the rig crew."""

        try:
            with httpx.Client(timeout=4.0) as client:
                res = client.post(
                    f"{self.ollama_url}/api/generate",
                    json={"model": "mistral:7b-instruct-q4_K_M", "prompt": prompt, "stream": False}
                )
                if res.status_code == 200:
                    return {"status": "ALERT", "assessment": res.json().get("response", "")}
        except Exception as e:
            # Deterministic failsafe if local inference times out
            return {"status": "ALERT", "assessment": "LOCAL SLM TIMEOUT - EXECUTE FLOW CHECK IMMEDIATELY"}
        return {"status": "ALERT", "assessment": "UNVERIFIED ANOMALY - INITIATE FLOW CHECK"}
```

Testing deployed on an industrial fanless rig-floor edge PC (Intel Core i7-12700E, 32GB DDR5, running Ubuntu Core 24.04 LTS):

| Model / Quantization | Parameter Size | Memory Footprint | Edge Inference Latency | Deterministic Filter Latency | Cloud Round-Trip (VSAT) | 
|---|---|---|---|---|---|
| **Deterministic Rule Filter** | N/A | $< 40\text{ MB}$ | **$0.4\text{ ms}$** | Baseline | N/A | 
| **Qwen 2.5 3B (Q4_K_M)** | $3.1\text{B}$ | $1.9\text{ GB}$ | **$210\text{ ms}$** | $+0.4\text{ ms}$ | $1,800\text{ ms}$ | 
| **Mistral 7B Instruct (Q4_K_M)** | $7.2\text{B}$ | $4.4\text{ GB}$ | **$490\text{ ms}$** | $+0.4\text{ ms}$ | $2,100\text{ ms}$ | 
| **Llama 3.1 8B (Q4_K_M)** | $8.0\text{B}$ | $4.9\text{ GB}$ | **$580\text{ ms}$** | $+0.4\text{ ms}$ | $2,300\text{ ms}$ | 

By running locally:

The [`witsml-edge-agent`](https://github.com/Greybeard00007/witsml-edge-agent) and [` ai-gateway-sentinel`](https://github.com/Greybeard00007/ai-gateway-sentinel) work alongside our [`kill-sheet-calculations`](https://github.com/Greybeard00007/kill-sheet-calculations) library. When a kick is verified, the edge agent can automatically push shut-in drillpipe pressure (SIDPP), shut-in casing pressure (SICP), and pit volume gain into the kill calculation engine, rendering a fully populated, IADC-compliant kill sheet within seconds of well shut-in.
