If you only open one file, open START_HERE.md.
Edge Capacity Gate evaluates RAM, disk, and thermal before dispatching
Playwright / spawn-worker / deep-research, and returns
STATUS: CAPACITY_PRESSURE instead of crashing the inference process.
On Jetson-class and laptop agents, the heavy tool and the LLM share one
box. LangGraph can hide tools from the next model call; LiteLLM caps
USD. Neither stops this turn’s browser from eating the KV cache.
Missing psutil is not 0% RAM.
Suggested GitHub / PyPI name: edge-capacity-gate
| Who | What they get |
|---|---|
| You (the technician) | evaluate_capacity + should_block_heavy in ten minutes. |
| AI agents / harnesses | A STATUS / WHY / USE_INSTEAD packet as the tool result, plus a cheap inspect tool still visible. |
| People talking to those agents | Fewer OOM killer events and fewer sitrep storms from the same deny. |
Cloud agents whose browser runs on a different machine from the LLM. Teams that already fail-closed when RAM sensors are missing and dedupe operator pages. People looking for a USD budgeter — that is LiteLLM.
flowchart LR
C[Tool call] --> H{heavy?}
H -->|no| R[Run cheap tool]
H -->|yes| E[evaluate_capacity]
E -->|pressure| P[STATUS CAPACITY_PRESSURE]
E -->|headroom| T[Dispatch Playwright]
P --> D{dedupe window?}
D -->|fresh| S[one sitrep]
D -->|recent| N[packet only]
| Style | When |
|---|---|
| In-process (recommended) | Call should_block_heavy before tool_registry[name](**args). |
| Harness | Hide playwright_* when pressure is true; keep inspect_system_health. |
| Both | Dispatcher returns the packet; the chat model only reads it. |
This kernel has no MCP server. Pair epistemic-deny for allowlist
packets (same family, different STATUS) and agent-review-envelope
if you enqueue a sitrep (optional; needs that sibling on PYTHONPATH).
chmod +x scripts/smoke.sh
./scripts/smoke.sh
# optional
export AGENT_HOME=/tmp/edge-capacity-gate-demo
python3 -m pip install -e ".[sensors]"
python3 examples/quickstart.pySuccess is a printed snapshot whose memory_sensor is ok or missing
(never a fake memory_percent=0.0 when the sensor is gone) and, under
pressure, a packet that starts with STATUS: CAPACITY_PRESSURE and
includes USE_INSTEAD:. Two denies inside 900s must not enqueue two
sitreps. That rigidity is the product.
| Resource | Minimum |
|---|---|
| OS | Linux, macOS, or Windows with Python 3.10+ |
| RAM | This kernel is for hosts where the LLM and browser share RAM |
| GPU | None required for the library; local inference is the reason it exists |
| Network | None |
Optional extra: psutil (pip install -e ".[sensors]"). Without it,
memory_sensor=missing and heavy tools are refused — not treated as
0% used. Thermal JSON is optional; missing is UNKNOWN, not NORMAL.
| File | What it does | What you change it for |
|---|---|---|
START_HERE.md |
First-use, 10 minutes | You usually do not |
README.md |
Product + hidden dynamics | Forks / rename |
docs/INTEGRATION.md |
Dispatcher + harness recipes | Tool names |
docs/ADVANCED.md |
Playwright OOM vs budgeters (search article) | Architecture debates |
capacity_gate.py |
Evaluate / deny / dedupe | Thresholds, heavy list |
paths.py |
AGENT_HOME stub |
Rarely |
examples/quickstart.py |
First snapshot | Learning |
tests/ |
Missing sensor ≠ 0%; packet; dedupe | Behavior changes |
scripts/smoke.sh |
unittest + quickstart | CI locally |
.env.example |
Env names | Copy to .env (never commit .env) |
| Kernel | Why |
|---|---|
epistemic-deny |
Allowlist packets. Capacity is not a permission miss — same shape, different STATUS. |
agent-review-envelope |
Speech dual-control. Capacity sitreps belong in the outbox, once per window. |
sidecar-occupancy |
HTTP 503 is a lock. This kernel is RAM/thermal, not a sidecar mutex. |
| Curiosity-Docker | House-style START_HERE; not a capacity gate. |
These dynamics show up after someone else runs this in a real loop. Ordinary READMEs skip them; they are why the kernel exists.
| Lens | In this kernel |
|---|---|
| Hidden principle | A missing occupancy sensor must not look like 0% used (or NORMAL thermal). Mapping None → 0.0 fail-opens the gate forever. |
| Recurring pattern | Deny heavy tools before dispatch. Same packet family as epistemic denies (STATUS / WHY / USE_INSTEAD). Dedupe sitreps with a wall-clock marker. |
| Mental model | Adopters think “psutil percent is a float, default 0.” The governing model is unknown ≠ free. LangGraph post_model_hook is a conversation guardrail, not a RAM budget. LiteLLM max_budget is USD. |
| Feedback loop | No dedupe → every denied Playwright pages the human → model retries → sitrep storm → operators stop having an opinion (per Cynical0n3 NotebookLM systems). |
| Hidden incentive | The model wants to “just screenshot.” The box wants to keep the KV cache. They share DRAM. Cheap to skip the pre-check “just this once.” |
| Leverage point | pressure_dedupe_seconds (default 900). memory_sensor / thermal_sensor fields. Hide playwright_* when pressure; keep a cheap inspect tool. |
| Asymmetry | RAM unknown → refuse heavy tools. Thermal JSON missing → UNKNOWN (visible) and only blocks if you list it in block_heavy_when_thermal. Do not copy the RAM rule onto optional thermals without meaning to. |
| Cause → effect | Browser + local LLM on one box without a pre-check → OOM killer / paging “slow as molasses.” Packet → model uses inspect tools. Marker → one sitrep per window. |
| Second-order | Once copied, teams will chart “deny rate” and raise memory_percent_max or stub psutil to return 0 so the demo never blocks. That metric is the next OOM. Count OOM events and sitreps per hour, not denials. |
| Opportunity | Edge / ARM / laptop agents. Search: Playwright OOM local LLM. |
| Risk if copied blindly | Enqueue on every deny without the marker file. Treat missing psutil as 0%. Add an MCP tool that bypasses the gate. |
Deeper case studies: docs/ADVANCED.md. Wiring: docs/INTEGRATION.md.
MIT. See LICENSE.
If the gate kept Playwright from eating the KV cache and you want more edge tools, coffee and electricity help. Optional.



