A consulta interna select Id from @tmp
não criará uma lista dinâmica de IDs para você neste caso. Você está trabalhando com diferentes escopos. Você precisa de algo que construirá essa lista de IDs para você e, em seguida, concatenará a lista com o restante de sua criação de SQL dinâmica.
Funciona no seu caso estático porque a consulta interna está dentro do mesmo escopo que o resto do seu SQL.
Você poderia contornar isso alterando @tmp para uma tabela temporária em vez de uma variável de tabela e removendo a concatenação.
DECLARE @UserId VARCHAR(10) = 72;
CREATE TABLE #tmp ( Id VARCHAR(10));
INSERT #tmp exec [dbo].[GetAllSubExecutorsByUserId] @Source = @UserId;
DECLARE @SQL VARCHAR(max);
SELECT @SQL = 'SELECT * FROM tasks ';
SELECT @SQL = @SQL + 'WHERE Executor IN (select Id from #tmp)';
EXEC(@SQL);
DROP TABLE #tmp
Isso move o escopo da tabela temporária e permite gerar uma única instrução SQL para realizar sua consulta, independentemente de quantos registros estão na tabela.
Você também pode se livrar do SQL dinâmico fazendo isso.
DECLARE @UserId VARCHAR(10) = 72;
CREATE TABLE #tmp ( Id VARCHAR(10));
INSERT #tmp exec [dbo].[GetAllSubExecutorsByUserId] @Source = @UserId;
SELECT * FROM tasks WHERE Executor IN (select Id from #tmp)
DROP TABLE #tmp