> ## Documentation Index
> Fetch the complete documentation index at: https://praison.ai/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Gateway Pressure Telemetry

> See the gateway backing up before it drops work — admission, queues, dead-letter and loop-lag on health()

Pressure telemetry surfaces how loaded the gateway is *before* it starts shedding turns. One health block, one classification.

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
graph LR
    subgraph "Gateway Pressure Telemetry"
        Admit[🎟️ Admission] --> Eval[⚖️ evaluate_pressure]
        Inbox[📥 Inbox] --> Eval
        Outbox[📤 Outbox] --> Eval
        Lag[⏱️ Loop lag] --> Eval
        Eval --> Class[📊 nominal / elevated / saturated]
    end

    classDef input fill:#6366F1,stroke:#7C90A0,color:#fff
    classDef process fill:#189AB4,stroke:#7C90A0,color:#fff
    classDef result fill:#10B981,stroke:#7C90A0,color:#fff

    class Admit,Inbox,Outbox,Lag input
    class Eval process
    class Class result
```

## Quick Start

**1. Ask an agent**

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonaiagents import Agent

agent = Agent(
    name="Ops",
    instructions="Read gateway.health() and tell the operator if the gateway is backing up.",
)
agent.start("Is the gateway saturated right now?")
```

**2. Read the health block**

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
h = gateway.health()
pressure = h.get("pressure")
if pressure:
    print(pressure["pressure"])            # 'nominal' | 'elevated' | 'saturated'
    print(pressure["admission_in_flight"], "/", pressure["admission_max"])
    print(pressure["event_loop_lag_p99_ms"], "ms")
```

**3. Classify your own numbers**

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonaiagents.gateway import evaluate_pressure

p = evaluate_pressure(
    admission={"max_concurrent_runs": 16, "in_flight": 15, "queued": 40, "shed": 3},
    inbox_pending=128,
    outbox_pending=412,
    outbox_dead_letter=2,
    loop_lag_p99_ms=740.0,
)
print(p.pressure)   # 'saturated'
```

***

## How It Works

The enforcement layer already measures every field. This block reads them back and folds them through a pure classifier.

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
sequenceDiagram
    participant Operator
    participant Gateway
    participant Enforcement as Admission / Outbox / Watchdog
    participant Classifier as evaluate_pressure

    Operator->>Gateway: health()
    Gateway->>Enforcement: stats(), depths, last_lag_ms
    Enforcement-->>Gateway: raw numbers
    Gateway->>Classifier: evaluate_pressure(...)
    Classifier-->>Gateway: HealthPressure(pressure="saturated")
    Gateway-->>Operator: health()["pressure"] = {...}
```

| Signal | Where it comes from |
| - | - |
| `admission_*` | `AdmissionGate.stats()` |
| `inbox_pending` | Sum of per-session inbox depth |
| `outbox_pending`, `outbox_dead_letter` | `OutboundQueue.try_depth_snapshot()` (never blocks the loop) |
| `event_loop_lag_p99_ms` | `LoopWatchdog.last_lag_ms` |

The block is omitted entirely when no back-pressure machinery is wired — always-on gateways see the block appear naturally.

The resulting health surface under load:

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
h = gateway.health()
# {'status': 'healthy', ...,
#  'pressure': {'admission_max': 16, 'admission_in_flight': 15,
#     'admission_queued': 40, 'admission_shed_total': 3,
#     'inbox_pending': 128, 'outbox_pending': 412, 'outbox_dead_letter': 2,
#     'event_loop_lag_p99_ms': 740.0, 'pressure': 'saturated'}}
```

***

## Choosing what to alert on

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
graph TB
    Q{What do you want to catch?} -->|Overload is imminent| Sat[Alert on pressure=='saturated']
    Q -->|Load is building| Ele[Alert on pressure=='elevated' for N minutes]
    Q -->|Delivery is failing| Dead[Alert on outbox_dead_letter > 0]
    Q -->|Loop hangs but not wedged| Lag[Alert on event_loop_lag_p99_ms >= 500]

    classDef q fill:#6366F1,stroke:#7C90A0,color:#fff
    classDef opt fill:#10B981,stroke:#7C90A0,color:#fff

    class Q q
    class Sat,Ele,Dead,Lag opt
```

***

## Configuration Options

Nothing to configure — pressure telemetry is on wherever the back-pressure machinery is on.

The fields on `HealthPressure`:

| Field | Type | Default | Description |
| - | - | - | - |
| `admission_max` | `int` | `0` | Configured concurrency ceiling (`0` = unbounded). |
| `admission_in_flight` | `int` | `0` | Turns currently running. |
| `admission_queued` | `int` | `0` | Turns waiting for a slot. |
| `admission_shed_total` | `int` | `0` | Cumulative turns shed since start. |
| `inbox_pending` | `int` | `0` | Aggregate pending inbound queue depth across sessions. |
| `outbox_pending` | `int` | `0` | Durable outbound backlog awaiting delivery. |
| `outbox_dead_letter` | `int` | `0` | Durable outbound entries in the dead-letter tier. |
| `event_loop_lag_p99_ms` | `float` | `0.0` | Recent event-loop scheduling lag (ms). |
| `pressure` | `"nominal"` \| `"elevated"` \| `"saturated"` | `"nominal"` | Derived classification. |

`HealthPressure` is `frozen=True` — mutating a field raises `dataclasses.FrozenInstanceError`.

### Thresholds

**`saturated`** (any one):

* admission full **and** work is queuing (`in_flight >= max` and `queued > 0`)
* `outbox_dead_letter > 0`
* `event_loop_lag_p99_ms >= 500.0`

**`elevated`** (any one):

* admission utilisation `>= 0.8` (80%)
* `queued > 0`
* `inbox_pending > 0`
* `outbox_pending > 0`
* `event_loop_lag_p99_ms >= 100.0`

**`nominal`** — none of the above.

Unbounded admission (`max_concurrent_runs == 0`) never divides by zero. Negative or non-numeric inputs are coerced to zero.

***

## Metrics

Six gauges appear on `/metrics` whenever the block is populated:

| Metric | Source field |
| - | - |
| `admission_in_flight` | `pressure.admission_in_flight` |
| `admission_queued` | `pressure.admission_queued` |
| `inbox_pending` | `pressure.inbox_pending` |
| `outbox_pending` | `pressure.outbox_pending` |
| `outbox_dead_letter` | `pressure.outbox_dead_letter` |
| `event_loop_lag_ms` | `pressure.event_loop_lag_p99_ms` |

***

## Common Patterns

**Autoscaler / load-balancer readiness gate**

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
p = gateway.health().get("pressure", {})
ready = p.get("pressure") != "saturated"
```

**Agent-driven ops assistant**

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonaiagents import Agent

def get_pressure() -> dict:
    return gateway.health().get("pressure", {})

agent = Agent(
    name="Ops",
    instructions="If pressure=='saturated', tell the operator what to check first.",
    tools=[get_pressure],
)
agent.start("How is the gateway holding up?")
```

**Pre-flight classification**

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonaiagents.gateway import evaluate_pressure

# Fold your own metrics through the same classifier the gateway uses
p = evaluate_pressure(loop_lag_p99_ms=210.0)
print(p.pressure)   # 'elevated'
```

***

## Best Practices

> [accordion] Page on saturated, not elevated
>
> `saturated` is imminent shed. A non-empty dead-letter tier means outbound work is being dropped — page immediately.

> [accordion] Unit-test with evaluate\_pressure
>
> Pure and deterministic — feed it stub numbers and assert the classification. No fixtures needed.

> [accordion] Guard the pressure key
>
> The `pressure` key is absent when no back-pressure machinery is wired. Guard with `.get("pressure")`.

> [accordion] Snapshot vs shape over time
>
> `health()["pressure"]` is a point-in-time snapshot; the `/metrics` gauges give you the shape over time.

***

## Related

> [card] [Loop Watchdog](https://praison.ai/docs/features/gateway-loop-watchdog.md)
>
> Where `event_loop_lag_p99_ms` comes from.

> [card] [Hot Reload](https://praison.ai/docs/features/gateway-hot-reload.md)
>
> The `ReloadStatus` health block this feature mirrors exactly.

> [card] [Gateway Overview](https://praison.ai/docs/features/gateway-overview.md)
>
> Where the top-level `health()` fields live.

> [card] [Reliability Preset](https://praison.ai/docs/features/gateway-reliability.md)
>
> The drain + admission preset this telemetry observes.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.