644b397fb2
The conversation loop hardcodes max_compression_attempts = 3. Sessions that legitimately need more rounds are stranded: on a restart history reload, incompressible tool schemas can keep the per-request estimate above the compressor threshold even though the message floor compresses correctly, so three rounds cannot clear it and the turn dies with "Context length exceeded: max compression attempts (3) reached" — the same failure class as #62605, where the rough estimate similarly leaves 3 retries short. Make the cap a config key, compression.max_attempts: - default 3 = identical to today, so an unset key is behavior-neutral; - parsed and validated in agent_init alongside the other compression.* keys (>= 1, hard-capped at 10, non-integer values fall back to 3), attached as agent.max_compression_attempts; - the loop reads it via getattr(agent, "max_compression_attempts", 3), so objects without the attribute keep the prior behavior; - documented in the DEFAULT_CONFIG compression block. Tests pin the parse/validate/attach seam: default preserved, custom value honored, floor and ceiling enforced, garbage tolerated, and the loop-side getattr degradation. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>