← Back to PRs

#20394: feat(gateway): make chat history byte limit configurable via gateway.maxChatHistoryBytes

by mgratch open 2026-02-18 21:24 View on GitHub →
gateway size: XS
## Summary - **Problem:** The chat history byte budget (`DEFAULT_MAX_CHAT_HISTORY_MESSAGES_BYTES`, 6 MB) is hardcoded. Sessions containing base64-encoded images (browser screenshots, uploaded photos) easily exceed this, causing **silent truncation** — older messages simply vanish from `chat.history` responses with no error or warning. - **Why it matters:** Users lose conversation context without any indication that it happened. For workflows involving computer use or image-heavy conversations, 6 MB can be exhausted within a handful of exchanges. - **What changed:** Added `gateway.maxChatHistoryBytes` config key in `openclaw.json`. The value is read once at startup and sets the internal `maxChatHistoryMessagesBytes` limit. Falls back to 6 MB when unset. - **What did NOT change:** The default behavior is identical — no existing deployments are affected. The existing `getMaxChatHistoryMessagesBytes()` getter and `__setMaxChatHistoryMessagesBytesForTest()` test helper are untouched. ## Change Type (select all) - [ ] Bug fix - [x] Feature - [ ] Refactor - [ ] Docs - [ ] Security hardening - [ ] Chore/infra ## Scope (select all touched areas) - [x] Gateway / orchestration - [ ] Skills / tool execution - [ ] Auth / tokens - [x] Memory / storage - [ ] Integrations - [x] API / contracts - [ ] UI / DX - [ ] CI/CD / infra ## Linked Issue/PR - No linked issue — this is a standalone feature request. ## User-visible / Behavior Changes - New optional config key: `gateway.maxChatHistoryBytes` (number, bytes). When set in `openclaw.json`, overrides the default 6 MB chat history byte budget. - Sessions that previously experienced silent history truncation can now retain full history by raising this limit. - Default behavior is unchanged when the key is absent. ## Security Impact (required) - New permissions/capabilities? `No` - Secrets/tokens handling changed? `No` - New/changed network calls? `No` - Command/tool execution surface changed? `No` - Data access scope changed? `No` ## Repro + Verification ### Environment - OS: macOS / Linux (Docker) - Runtime/container: OpenClaw v2026.2.18 - Model/provider: Any - Integration/channel: WebSocket (Control UI / WebChat / Slack) - Relevant config: `{ "gateway": { "maxChatHistoryBytes": 52428800 } }` (50 MB) ### Steps 1. Start a session with computer use or image uploads, generating several base64-encoded screenshots in the conversation. 2. Once the session JSONL exceeds ~6 MB of message content, reconnect or request chat history. 3. Observe that older messages are silently missing from the history response. 4. Set `gateway.maxChatHistoryBytes` to a higher value, restart, and repeat. ### Expected - With a higher limit, full conversation history is returned. ### Actual - Without this change: messages silently disappear once the 6 MB budget is exceeded. No error, no truncation indicator. ## Evidence - [ ] Failing test/log before + passing after - [ ] Trace/log snippets - [ ] Screenshot/recording - [ ] Perf numbers (if relevant) Evidence will be provided after testing on the fork build. The implementation follows the exact same pattern as the existing `__setMaxChatHistoryMessagesBytesForTest()` — same variable, same validation logic. ## Human Verification (required) - **Verified scenarios:** Code review confirms `maxChatHistoryMessagesBytes` is the sole variable controlling the budget, accessed only via `getMaxChatHistoryMessagesBytes()`. The new `initMaxChatHistoryBytes()` sets it with identical validation to the existing test setter. - **Edge cases checked:** Invalid config values (negative, zero, NaN, non-number) all fall back to the 6 MB default. Omitting the key preserves existing behavior. - **What I did not verify:** Behavior with extremely large history limits on memory-constrained systems. ## Compatibility / Migration - Backward compatible? `Yes` — the default is unchanged; no config migration needed. - Config/env changes? `Yes` — new optional key `gateway.maxChatHistoryBytes`. - Migration needed? `No` ## Failure Recovery (if this breaks) - **How to disable/revert:** Remove `gateway.maxChatHistoryBytes` from `openclaw.json` and restart. The gateway reverts to the hardcoded 6 MB default. - **Files/config to restore:** `openclaw.json` only. - **Known bad symptoms:** Setting an extremely large value could increase memory usage when serializing history responses for sessions with very large transcripts. ## Risks and Mitigations - **Risk:** Large history limits increase memory consumption when the gateway serializes chat history for delivery. - **Mitigation:** This is an opt-in config on a self-hosted, typically single-user system. The default remains 6 MB. The operator chooses the tradeoff between history completeness and memory usage. <!-- greptile_comment --> <h3>Greptile Summary</h3> Adds a new optional config key `gateway.maxChatHistoryBytes` to override the hardcoded 6 MB chat history byte budget. The implementation adds an `initMaxChatHistoryBytes()` initializer in `server-constants.ts` called once at gateway startup via `server-runtime-state.ts`, with proper validation (positive, finite number). - **Critical: Missing zod schema entry.** The gateway config object in `src/config/zod-schema.ts` uses `.strict()`, which rejects unrecognized keys. Since `maxChatHistoryBytes` was not added to the zod schema, setting this config key will cause a **validation error** at startup, making the feature unusable. This must be added before merging. - No tests were added for the new `initMaxChatHistoryBytes` function. The existing test helper `__setMaxChatHistoryMessagesBytesForTest` has corresponding e2e tests — similar coverage for the config-driven path would be good to have. - Consider adding a note to the JSDoc that values exceeding `MAX_PAYLOAD_BYTES` (25 MB) may cause WebSocket disconnects, since the history response is sent as a single WS message. <h3>Confidence Score: 2/5</h3> - This PR has a blocking bug: the new config key will be rejected by zod strict validation, making the feature non-functional. - The TypeScript type and runtime initializer are correct, but the missing zod schema entry means the config key will fail validation on any deployment that uses it. The `.strict()` on the gateway schema object actively rejects unknown keys. This is a functional blocker for the advertised feature. - `src/config/zod-schema.ts` — needs `maxChatHistoryBytes` added to the gateway zod schema before this feature can work. <sub>Last reviewed commit: 843c5ed</sub> <!-- greptile_other_comments_section --> <sub>(3/5) Reply to the agent's comments like "Can you suggest a fix for this @greptileai?" or ask follow-up questions!</sub> <!-- /greptile_comment -->

Most Similar PRs