This is the syntax you're looking for:
awk ' function testfunc(fileN, my_year, cmd) { cmd = "grep \"key_word\" " fileN cmd | getline my_year close(cmd) return(my_year) } BEGIN {OFS="\t"} {printf "%s\t%s\t%s\t", $8, testfunc($8), $9}'
BUT as I mentioned in my comment - don't do this, it's the wrong approach for whatever it is you're trying to do.
Note that you cannot use singe quotes within a single-quote-delimited script.
EDIT: let me try to clarify my point about using a different approach. You seem to have a file, let's call it "file1" that has another file name in it's 8th field, and some other value you care about in it's 9th field. All of the files named in that 8th field each contain a line containing the text "key_word" and what you want printed out is that the 8th field from file1 then a tab then the key-word line from the named file, then the 9th field from file1.
That can be written as (just one possible solution):
gawk -v OFS='\t' ' ARGIND < ARGC { if (/key_word/) my_year[FILENAME] = $0; nextfile } { print $8, my_year[$8], $9 } ' $(awk '{print $8}' file1 | sort -u) file1
i.e. call awk once on "file1" to get the list of files that contain the date info you want then pass that list of files to awk again ahead of "file1" so all of the info you need when finally processing file1 gets stored in an array.
The above uses GNU awk's "nextfile" for efficiency but that's not required and GNU awks ARGIND for clarity but you can replace ARGIND < ARGC with FILENAME!=ARGV[ARGC] in a non-gawk solution.
There are many alternative solutions, it all depends what you're really trying to do....