What resource allocation ceilings must be recorded after surviving memory pressure?
**Date of Record:** 2026 October 25 **Scope:** Applies when an agentic session encounters high memory pressure (OOM warnings, swap thrashing, or context-window saturation), survives via aggressive eviction or throttling, and prepares to hand off to a successor instance. Does not apply to sessions operating with unbounded resources or those that terminate immediately upon hitting an allocation limit without surviving the pressure.
Core Distinction
The separation between **transient memory survival** (the specific actions taken to stay alive, such as dropping cache, serializing state to disk, or reducing batch size) and the **resource allocation ceiling** (the hard limit or safe operating bounds that triggered the pressure). Surviving memory pressure proves the environment's limits exist; recording the ceiling defines the exact mathematical boundary a successor must not cross. A successor that inherits a successful state without the ceiling will repeat the allocation that caused the pressure, likely triggering a fatal OOM kill on the next attempt.
What Was Observed
In distributed and context-bounded agent architectures, failing to record memory ceilings after surviving pressure produces three primary failure modes:
- **OOM Retry Loops:** The successor instance loads the exact same data structures or spawns the same parallel subagents, immediately exceeding the cgroup limit or heap size, resulting in a hard termination before any work completes.
- **Eviction Blindness:** The predecessor survived by evicting critical caches, but the successor assumes the environment has ample capacity and rebuilds those caches without checking the current headroom, silently degrading performance.
- **Concurrency Collapse:** The session hit memory pressure due to spawning too many parallel workers. Without a recorded safe concurrency bound, the successor spins up the same worker count, causing node-level thrashing.
Recorded Elements
- **`peak_rss_observed`:** The highest Resident Set Size (RSS) or token count reached during the session, establishing the empirical maximum the workload required.
- **`allocation_ceiling_hit`:** The specific cgroup limit, JVM heap size, container memory limit, or context window maximum that triggered the pressure.
- **`survival_mitigations`:** The exact evictions, throttles, or serializations executed to prevent termination (e.g., "evicted 50% of KV cache", "dropped parallel workers from 8 to 2").
- **`safe_operating_bounds`:** The calculated headroom or concurrency limit that the successor must strictly obey to avoid re-triggering the pressure (e.g., "max_concurrent_workers: 2", "max_input_tokens: 64000").
Condition of Validity
* **Applies when:** The instance experienced memory-related degradation (latency spikes, GC pauses, swap usage) or explicitly intercepted OOM signals, and a successor will execute in the same resource-constrained environment. * **Does not apply when:** The task completed with no memory pressure, or the successor is scheduled to run on a newly provisioned, unbounded infrastructure tier.
Decision Boundary
- **Did the session hit memory pressure or approach a hard allocation ceiling?** If no, standard state persistence applies. If yes, proceed to record the bounds.
- **Is the exact ceiling identified (e.g., cgroup limit, context window)?** If yes, record it. If the limit is abstract (e.g., "the node got slow"), record the `peak_rss_observed` as the empirical functional ceiling.
- **Does the successor inherit a mandate to process the same data volume?** If yes, enforce the `safe_operating_bounds` and explicitly document the `survival_mitigations` so the successor re-applies them proactively rather than reactively.
- **Conversely, when can a successor ignore these ceilings?** Only if the successor's operational scope is explicitly smaller (e.g., processing a subset of the data) such that the new `peak_rss_observed` is guaranteed to fall safely below the ceiling.
Operational Effect
- **OOM Prevention:** Protects successor instances from immediately re-triggering the fatal resource exhaustion that the predecessor narrowly survived.
- **Proactive Throttling:** Allows the successor to start with the correct safe operating bounds (batch size, concurrency, cache limits) rather than discovering them through thrashing.
- **Environment Mapping:** Builds a historical profile of the environment's actual capacity, allowing external orchestrators to make informed scaling decisions.
from dataclasses import dataclass
from enum import Enum, auto
import hashlib
import json
class PressureType(Enum):
CGROUP_OOM = auto()
CONTEXT_WINDOW_LIMIT = auto()
SWAP_THRASHING = auto()
@dataclass(frozen=True)
class MemoryPressureEvent:
pressure_type: PressureType
peak_rss_observed: int
allocation_ceiling_hit: int
survival_mitigations: tuple[str, ...]
@dataclass(frozen=True)
class SafeOperatingBounds:
max_concurrent_workers: int
max_input_tokens: int
required_mitigations: frozenset[str]
@dataclass(frozen=True)
class ResourceCeilingManifest:
event: MemoryPressureEvent
safe_bounds: SafeOperatingBounds
manifest_digest: str
@dataclass(frozen=True)
class AllocationRequest:
requested_workers: int
requested_tokens: int
class MemoryCeilingRecorder:
"""
Evaluates memory pressure events and seals safe operating bounds,
ensuring successors do not re-trigger resource exhaustion.
"""
@staticmethod
def _hash(data: str) -> str:
return hashlib.sha256(data.encode("utf-8")).hexdigest()
@classmethod
def seal_manifest(
cls,
event: MemoryPressureEvent,
safe_bounds: SafeOperatingBounds,
) -> ResourceCeilingManifest:
if not event.survival_mitigations:
raise ValueError("Memory pressure event lacks documented survival mitigations.")
if event.peak_rss_observed < event.allocation_ceiling_hit:
raise ValueError("Peak RSS must meet or exceed the ceiling hit to record pressure.")
digest_payload = {
"pressure_type": event.pressure_type.name,
"peak_rss": str(event.peak_rss_observed),
"ceiling": str(event.allocation_ceiling_hit),
"max_workers": str(safe_bounds.max_concurrent_workers),
"max_tokens": str(safe_bounds.max_input_tokens),
}
digest = cls._hash(
json.dumps(digest_payload, sort_keys=True, separators=(",", ":"))
)
return ResourceCeilingManifest(
event=event,
safe_bounds=safe_bounds,
manifest_digest=digest,
)
@classmethod
def verify_allocation_request(
cls, manifest: ResourceCeilingManifest, request: AllocationRequest
) -> tuple[bool, str]:
"""
Fetching-time check: returns (is_safe, rejection_reason).
Fail-closed if the request exceeds the recorded safe operating bounds.
"""
if request.requested_workers > manifest.safe_bounds.max_concurrent_workers:
return False, f"Requested workers ({request.requested_workers}) exceeds safe bound ({manifest.safe_bounds.max_concurrent_workers})."
if request.requested_tokens > manifest.safe_bounds.max_input_tokens:
return False, f"Requested tokens ({request.requested_tokens}) exceeds safe bound ({manifest.safe_bounds.max_input_tokens})."
return True, "SAFE_TO_PROCEED"