diff --git a/apps/backend/internal/agent/runtime/lifecycle/manager_execution.go b/apps/backend/internal/agent/runtime/lifecycle/manager_execution.go index fd7d398f38..d140d213b2 100644 --- a/apps/backend/internal/agent/runtime/lifecycle/manager_execution.go +++ b/apps/backend/internal/agent/runtime/lifecycle/manager_execution.go @@ -391,6 +391,21 @@ func (m *Manager) createExecution(ctx context.Context, taskID string, info *Work return nil, fmt.Errorf("agent type %q not found in registry", info.AgentID) } + // Forward AgentProfile.EnvVars to the runtime instance. The Launch / + // ResumeSession paths merge these into req.Env via buildEnvForExecution + // before calling LaunchAgent; the lazy workspace-only path (any + // GetOrEnsureExecution* caller after backend restart) lands here directly, + // so without this merge the runtime instance gets spawned with empty env + // and CLAUDE_CONFIG_DIR (and any other workspace profile var) is lost. + // The agent subprocess inherits the instance env via agentctl, and ACP + // session/load then looks under the wrong SDK root → -32002 Resource not + // found. + env := map[string]string{} + m.mergeAgentProfileEnv(ctx, info.AgentProfileID, env) + if len(env) == 0 { + env = nil + } + req := &ExecutorCreateRequest{ InstanceID: executionID, TaskID: taskID, @@ -399,6 +414,7 @@ func (m *Manager) createExecution(ctx context.Context, taskID string, info *Work AgentProfileID: info.AgentProfileID, WorkspacePath: info.WorkspacePath, Protocol: string(agentConfig.Runtime().Protocol), + Env: env, AgentConfig: agentConfig, Metadata: info.Metadata, PreviousExecutionID: info.AgentExecutionID, @@ -414,6 +430,14 @@ func (m *Manager) createExecution(ctx context.Context, taskID string, info *Work execution := runtimeInstance.ToAgentExecution(req) execution.RuntimeName = rt.Name() + // Cache the resolved profile env on the execution so a subsequent + // configureAndStartAgent (when this workspace-only execution is promoted) + // reuses it via mergeAgentProfileEnvForExecution instead of doing another + // secret-store round-trip. Mirrors the Launch path (manager_launch.go). + if env != nil { + m.cacheResolvedProfileEnv(execution, env) + } + // Set the ACP session ID for session resumption if info.ACPSessionID != "" { execution.ACPSessionID = info.ACPSessionID