Conditional INSERT with a nested CTE?
For the purpose of this question, I'll assume employee_details.name to be defined UNIQUE. Else, the whole operation wouldn't make sense.

You cannot nest a data-modifying CTE like you tried (as you already found out the hard way) - and you don't need to. This query would achieve your objective:

WITH e AS (
   SELECT name, employee_id
   FROM   employee_details
   WHERE  name = 'jack bauer'
   )
 , i1 AS (
   INSERT INTO employee             -- no target columns!
   SELECT                           -- empty SELECT list!
   WHERE NOT EXISTS (SELECT FROM e)
   RETURNING id
   )
 , i2 AS (
   INSERT INTO employee_details (name, employee_id) 
   SELECT 'jack bauer', id
   FROM   i1
   RETURNING name, employee_id
   )
SELECT employee_id, name FROM e
UNION ALL 
SELECT employee_id, name FROM i2;


The core feature is the INSERT with no target columns and an empty SELECT. Postgres fills all columns not listed in the SELECT with default values. This way we can replace the unconditional VALUES (default) with a conditional INSERT. The CTE i1 only inserts a row if the given name was not found.

The manual:


  If no list of [target] column names is given at all, the default is all the
  columns of the table in their declared order; [...]
  
  Each column not present in the explicit or implicit column list will
  be filled with a default value, either its declared default value or
  null if there is none.


This is a Postgres specific extension of the standard:


  Also, the case in which a column name list is omitted, but not all the
  columns are filled from the VALUES clause or query, is disallowed by the standard.


The final CTE i2 only inserts a row if i1 returned a row. Voilá.

This is subject to race conditions under concurrent write load to the same tables. If you need to rule that out, you need to do more. Related:


How to use RETURNING with ON CONFLICT in PostgreSQL?


Without the complications from the conditional INSERT in the 2nd table, this would boil down to a common case of SELECT or INSERT:


Is SELECT or INSERT in a function prone to race conditions?


Aside


"id" text DEFAULT gen_random_uuid()



I'd strongly advise to use the data type uuid to store UUIDs.


Would index lookup be noticeably faster with char vs varchar when all values are 36 chars
What is the optimal data type for an MD5 field?