#20394: feat(gateway): make chat history byte limit configurable via gateway.maxChatHistoryBytes
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
#20381: feat(gateway): make chat history byte limit configurable via `gatew...
by mgratch · 2026-02-18
92.6%
#13679: feat(gateway): make WebSocket maxPayload configurable
by andydoucet · 2026-02-10
78.3%
#16006: fix(gateway): reduce chat.history byte cap from 6 MB to 2 MB
by fagemx · 2026-02-14
78.3%
#8360: Gateway: cap oversized transcript entries
by halbot2010 · 2026-02-03
77.8%
#11788: feat: inter-agent communication via CLI scripts
by jingkang0822 · 2026-02-08
74.5%
#6805: fix: increase WebSocket MAX_PAYLOAD_BYTES to 6MB for attachments
by cortexuvula · 2026-02-02
74.4%
#16125: feat(gateway): add stuck session detection
by CyberSinister · 2026-02-14
74.2%
#14309: fix(ui): resolve chat event session key mismatch
by justonlyforyou · 2026-02-11
73.5%
#8713: feat: gateway memory monitor, install linger, docs and failover
by quratus · 2026-02-04
73.4%
#3182: fix(gateway): use canonical session key in chat.send
by chrisherold · 2026-01-28
73.1%