diff --git a/src/config/types.agents.ts b/src/config/types.agents.ts index a979506a2ab..a806fe05f32 100644 --- a/src/config/types.agents.ts +++ b/src/config/types.agents.ts @@ -41,6 +41,8 @@ export type AgentRouteBinding = { agentId: string; comment?: string; match: AgentBindingMatch; + /** When "main", group/channel messages matching this binding route to the agent's main session. */ + groupScope?: "main" | "per-channel"; }; export type AgentAcpBinding = { diff --git a/src/config/zod-schema.agents.ts b/src/config/zod-schema.agents.ts index 5dddfc9813a..8c732f9a16d 100644 --- a/src/config/zod-schema.agents.ts +++ b/src/config/zod-schema.agents.ts @@ -40,6 +40,7 @@ const RouteBindingSchema = z agentId: z.string(), comment: z.string().optional(), match: BindingMatchSchema, + groupScope: z.union([z.literal("main"), z.literal("per-channel")]).optional(), }) .strict(); diff --git a/src/config/zod-schema.session.ts b/src/config/zod-schema.session.ts index c2b3d280d51..3f4b6a24d80 100644 --- a/src/config/zod-schema.session.ts +++ b/src/config/zod-schema.session.ts @@ -34,7 +34,6 @@ export const SessionSchema = z z.literal("per-account-channel-peer"), ]) .optional(), - groupScope: z.union([z.literal("main"), z.literal("per-channel")]).optional(), identityLinks: z.record(z.string(), z.array(z.string())).optional(), resetTriggers: z.array(z.string()).optional(), idleMinutes: z.number().int().positive().optional(), diff --git a/src/routing/resolve-route.ts b/src/routing/resolve-route.ts index 7e814f3d357..bd5ab8bd68d 100644 --- a/src/routing/resolve-route.ts +++ b/src/routing/resolve-route.ts @@ -628,11 +628,6 @@ export function resolveAgentRoute(input: ResolveAgentRouteInput): ResolvedAgentR const memberRoleIds = input.memberRoleIds ?? []; const memberRoleIdSet = new Set(memberRoleIds); const dmScope = input.cfg.session?.dmScope ?? "main"; - const groupScope = - ((input.cfg.session as Record | undefined)?.groupScope as - | "main" - | "per-channel" - | undefined) ?? "per-channel"; const identityLinks = input.cfg.session?.identityLinks; const shouldLogDebug = shouldLogVerbose(); const parentPeer = input.parentPeer @@ -666,7 +661,11 @@ export function resolveAgentRoute(input: ResolveAgentRouteInput): ResolvedAgentR const bindings = getEvaluatedBindingsForChannelAccount(input.cfg, channel, accountId); const bindingsIndex = getEvaluatedBindingIndexForChannelAccount(input.cfg, channel, accountId); - const choose = (agentId: string, matchedBy: ResolvedAgentRoute["matchedBy"]) => { + const choose = ( + agentId: string, + matchedBy: ResolvedAgentRoute["matchedBy"], + bindingGroupScope?: "main" | "per-channel", + ) => { const resolvedAgentId = pickFirstExistingAgentId(input.cfg, agentId); const sessionKey = buildAgentSessionKey({ agentId: resolvedAgentId, @@ -674,7 +673,7 @@ export function resolveAgentRoute(input: ResolveAgentRouteInput): ResolvedAgentR accountId, peer, dmScope, - groupScope, + groupScope: bindingGroupScope ?? "per-channel", identityLinks, }).toLowerCase(); const mainSessionKey = buildAgentMainSessionKey({ @@ -805,7 +804,8 @@ export function resolveAgentRoute(input: ResolveAgentRouteInput): ResolvedAgentR if (shouldLogDebug) { logDebug(`[routing] match: matchedBy=${tier.matchedBy} agentId=${matched.binding.agentId}`); } - return choose(matched.binding.agentId, tier.matchedBy); + const routeBinding = matched.binding as { groupScope?: "main" | "per-channel" }; + return choose(matched.binding.agentId, tier.matchedBy, routeBinding.groupScope); } }