From 1e3caf07d4c511a193c7cd00a86eec023d66412b Mon Sep 17 00:00:00 2001 From: sheeek Date: Wed, 7 Jan 2026 11:58:12 +0100 Subject: [PATCH] feat(sandbox): support agent-specific sandbox config override Changes to defaultSandboxConfig(): - Add optional agentId parameter - Load routing.agents[agentId].sandbox if available - Prefer agent-specific settings over global agent.sandbox Update callers in resolveSandboxContext() and ensureSandboxWorkspaceForSession() to extract agentId from sessionKey and pass it to defaultSandboxConfig(). This enables per-agent sandbox modes (e.g., main: off, family: all). --- src/agents/sandbox.ts | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/src/agents/sandbox.ts b/src/agents/sandbox.ts index d3134f04b..547553268 100644 --- a/src/agents/sandbox.ts +++ b/src/agents/sandbox.ts @@ -226,16 +226,26 @@ function resolveSandboxScopeKey(scope: SandboxScope, sessionKey: string) { return `agent:${agentId}`; } -function defaultSandboxConfig(cfg?: ClawdbotConfig): SandboxConfig { +function defaultSandboxConfig(cfg?: ClawdbotConfig, agentId?: string): SandboxConfig { const agent = cfg?.agent?.sandbox; + + // Agent-specific sandbox config overrides global + let agentSandbox: typeof agent | undefined; + if (agentId && cfg?.routing?.agents) { + const agentConfig = cfg.routing.agents[agentId]; + if (agentConfig && typeof agentConfig === "object") { + agentSandbox = agentConfig.sandbox; + } + } + return { - mode: agent?.mode ?? "off", + mode: agentSandbox?.mode ?? agent?.mode ?? "off", scope: resolveSandboxScope({ - scope: agent?.scope, - perSession: agent?.perSession, + scope: agentSandbox?.scope ?? agent?.scope, + perSession: agentSandbox?.perSession ?? agent?.perSession, }), - workspaceAccess: agent?.workspaceAccess ?? "none", - workspaceRoot: agent?.workspaceRoot ?? DEFAULT_SANDBOX_WORKSPACE_ROOT, + workspaceAccess: agentSandbox?.workspaceAccess ?? agent?.workspaceAccess ?? "none", + workspaceRoot: agentSandbox?.workspaceRoot ?? agent?.workspaceRoot ?? DEFAULT_SANDBOX_WORKSPACE_ROOT, docker: { image: agent?.docker?.image ?? DEFAULT_SANDBOX_IMAGE, containerPrefix: @@ -924,7 +934,8 @@ export async function resolveSandboxContext(params: { }): Promise { const rawSessionKey = params.sessionKey?.trim(); if (!rawSessionKey) return null; - const cfg = defaultSandboxConfig(params.config); + const agentId = resolveAgentIdFromSessionKey(rawSessionKey); + const cfg = defaultSandboxConfig(params.config, agentId); const mainKey = params.config?.session?.mainKey?.trim() || "main"; if (!shouldSandboxSession(cfg, rawSessionKey, mainKey)) return null; @@ -986,7 +997,8 @@ export async function ensureSandboxWorkspaceForSession(params: { }): Promise { const rawSessionKey = params.sessionKey?.trim(); if (!rawSessionKey) return null; - const cfg = defaultSandboxConfig(params.config); + const agentId = resolveAgentIdFromSessionKey(rawSessionKey); + const cfg = defaultSandboxConfig(params.config, agentId); const mainKey = params.config?.session?.mainKey?.trim() || "main"; if (!shouldSandboxSession(cfg, rawSessionKey, mainKey)) return null;