@@ -9,7 +9,11 @@ import { modelKey, parseModelRef, resolveDefaultModelForAgent } from "../agents/
99import { createModelVisibilityPolicy } from "../agents/model-visibility-policy.js" ;
1010import { getRuntimeConfig } from "../config/io.js" ;
1111import { loadManifestMetadataSnapshot } from "../plugins/manifest-contract-eligibility.js" ;
12- import { buildAgentMainSessionKey , normalizeAgentId } from "../routing/session-key.js" ;
12+ import {
13+ buildAgentMainSessionKey ,
14+ normalizeAgentId ,
15+ parseAgentSessionKey ,
16+ } from "../routing/session-key.js" ;
1317import { normalizeMessageChannel } from "../utils/message-channel.js" ;
1418import { getHeader } from "./http-auth-utils.js" ;
1519import { loadGatewayModelCatalog } from "./server-model-catalog.js" ;
@@ -33,6 +37,14 @@ export {
3337
3438export const OPENCLAW_MODEL_ID = "openclaw" ;
3539export const OPENCLAW_DEFAULT_MODEL_ID = "openclaw/default" ;
40+ const RESERVED_SESSION_KEY_PREFIXES = [ "subagent:" , "acp:" , "cron:" ] as const ;
41+
42+ export class GatewaySessionKeyOverrideError extends Error {
43+ constructor ( message : string ) {
44+ super ( message ) ;
45+ this . name = "GatewaySessionKeyOverrideError" ;
46+ }
47+ }
3648
3749function resolveAgentIdFromHeader ( req : IncomingMessage ) : string | undefined {
3850 const raw =
@@ -146,6 +158,12 @@ function resolveSessionKey(params: {
146158} ) : string {
147159 const explicit = getHeader ( params . req , "x-openclaw-session-key" ) ?. trim ( ) ;
148160 if ( explicit ) {
161+ const reservedPrefix = resolveReservedSessionKeyPrefix ( explicit ) ;
162+ if ( reservedPrefix ) {
163+ throw new GatewaySessionKeyOverrideError (
164+ `x-openclaw-session-key may not target internal session namespace ${ reservedPrefix } ` ,
165+ ) ;
166+ }
149167 return explicit ;
150168 }
151169
@@ -154,6 +172,23 @@ function resolveSessionKey(params: {
154172 return buildAgentMainSessionKey ( { agentId : params . agentId , mainKey } ) ;
155173}
156174
175+ function resolveReservedSessionKeyPrefix ( sessionKey : string ) : string | undefined {
176+ const normalized = normalizeReservedSessionKeyCandidate ( sessionKey ) ;
177+ if ( ! normalized ) {
178+ return undefined ;
179+ }
180+ return RESERVED_SESSION_KEY_PREFIXES . find ( ( prefix ) => normalized . startsWith ( prefix ) ) ;
181+ }
182+
183+ function normalizeReservedSessionKeyCandidate ( sessionKey : string ) : string | undefined {
184+ const trimmed = sessionKey . trim ( ) ;
185+ if ( ! trimmed ) {
186+ return undefined ;
187+ }
188+ const normalized = parseAgentSessionKey ( trimmed ) ?. rest ?? trimmed ;
189+ return normalized . trim ( ) . toLowerCase ( ) || undefined ;
190+ }
191+
157192export function resolveGatewayRequestContext ( params : {
158193 req : IncomingMessage ;
159194 model : string | undefined ;
0 commit comments