반응형

💡 워크플로우 목표

  1. 읽지 않은 이메일 확인
  2. AI로 이메일 답장 초안 자동 생성
  3. 자동 생성한 초안에 대해 승인 또는 피드백 요청
  4. 승인한 답장은 자동 발송, 거절한 답장은 피드백 반영 후 재작성

 

 

이메일 감지 트리거 추가


새로운 이메일을 감지하기 위해 단축키 n > Gmail 검색 > On message received 트리거를 추가한다.

Gmail 트리거 설정창 (get_email 이름으로 변경)

 

  • Credential: Gmail OAuth2 API (지메일 연동 계정 선택)
  • Poll Times > Mode: Every Minute (1분마다 새 이메일 확인)
  • Event: Message Received (새 이메일 수신 감지)
  • Simplify: 활성화 (원본 데이터 대신 핵심 메타데이터만 간략하게 반환)
  • Filters > Read Status: Unread emails only (읽지 않은 이메일만 가져오기)

 

이렇게 설정하면 1분마다 지메일 받은편지함을 확인하고, 읽지 않은 새 이메일이 있을 때만 워크플로우가 실행된다. 테스트할 때는 Fetch Test Event 버튼을 클릭하면 된다. 정상적으로 이메일을 가져오면 우측 Output 영역에서 from, to, text 같은 데이터를 확인할 수 있다.

 

🔍 테스트를 위해 특정 입력 데이터를 고정하고 싶으면 PIN Data 설정을 활용할 수 있다. 이메일 트리거에서 수신한 데이터를 PIN으로 고정해 두면, 워크플로우를 다시 실행해도 새로운 이메일을 가져오지 않고 고정한 이메일 내용으로 반복 테스트할 수 있다.

PIN Data 버튼 (노란색 화살표 부분)

 

 

답변 초안 생성 프롬프트


Edit Fields(Set) 노드를 사용하여 AI에게 전달할 프롬프트를 prompt 필드에 미리 정의해 둔다. 이렇게 하면 다음 노드에서 {{ $json.prompt }} 속성으로 프롬프트를 간편하게 불러올 수 있다. 또한 다른 노드에서 필드명만 통일해 두면, AI 노드 설정을 매번 바꾸지 않고도 프롬프트를 동적으로 전달할 수 있다. 

Edit Fields 노드 설정창 (set_initial_prompt 이름으로 변경)

 

개인적인 일정 제안은 수락하고, 프로모션/광고 등은 정중히 거절하도록 답변을 작성하는 프롬프트 예시. Use my real name 부분은 원하는 이름으로 변경한다.

Hi, your task is to reply to this email.

Write a response that sounds natural, and keep in mind I'm very busy and have little time for things.

If something personal comes up, please write a response asking to schedule a call.

For any events, invitations, or promotions, please politely decline.

Here is the email I just received.
Your task is to reply to the email as if you were me.

<EMAIL>
Subject: {{ $json.subject }}
Message: {{ $json.text }}
</EMAIL>

IMPORTANT
Reply with the email ready to send. Don't include the subject.
AND very important: DO NOT USE PLACEHOLDERS LIKE [Your Name].
Use my real name: Sion

 

 

답변 초안 생성 노드


앞 단계에서 정의한 프롬프트를 받아 실제로 AI 답장 초안을 생성할 차례다. OpenAI > Message a model 액션 노드를 추가한 후 다음과 같이 설정한다.

OpenAI Message a model 노드 설정창 (write_response 이름으로 변경)

 

  • Resource: Text (텍스트 기반 답변 생성)
  • Operation: Message a Model (AI 모델에게 메시지 보낸 후 답변 받기)
  • Model > From list: gpt-4o-mini (저렴한 모델로도 충분하다)
  • Message:
    • Type: Text
    • Role: User
    • Prompt: {{ $json.prompt }} (Set 노드에서 마우스로 드래그 가능)

 

아래 내용으로 본인에게 테스트 이메일을 보낸 후 Execute step을 눌러보면 우측 Output에 답변 초안이 생성된 것을 확인할 수 있다. 이메일 내용은 점심 약속을 제안하면서 제품 구매를 유도하는 광고성 메일이므로, AI는 프롬프트 지시에 따라 정중히 거절하는 답변을 생성한다.

 

테스트 이메일:

제목: Meet up for lunch? I'll pay!
본문: 

Hello E.

I would like to meet you for lunch because I want you to buy my things.
You can choose the restaurant and the time, and I'll pay for everything.

I promise,

Best Regards,
Paco.

 

AI 답변 초안:

Hi Paco,

Thanks for the offer! I really appreciate it, but I'm quite swamped at the moment and won't be able to meet up for lunch. 

If something else comes up that requires a call, just let me know and we can schedule a time that works for both of us.

Best,
Sion

 

 

초안 승인 요청 보내기


AI가 작성한 답장 초안을 사람이 직접 검토하고 승인/거절할 수 있도록 이메일 발송 노드를 설정한다. Send and Wait for Response 기능을 사용하면 메일에 포함된 버튼을 클릭할 때까지 워크플로우는 대기 상태가 된다. 단축키 n > Gmail > Send Message and Wait for Response 노드를 추가하고 다음과 같이 설정한다.

Send Message and Wait for Response 노드 설정창 (approve_email 이름으로 변경)

 

  • Resource: Message (이메일 메시지를 대상으로 작업)
  • Operation: Send and Wait for Response (버튼 누를때까지 대기)
  • To: 승인 요청을 받아볼 이메일 주소
  • Subject: [AI Auto Respond Approval Request] (승인 메일 제목)
  • Message: 승인 메일 본문
You are required to approve or reject the following AI response to the email you just received from {{ $('get_email').item.json.from.text }} with the subject "{{ $('get_email').item.json.subject }}"

Here is the content of the email: 
"{{ $('get_email').item.json.text }}"

And here is what the AI answered with:
"{{ $json.output[0].content[0].text }}"
  • Response Type: Approval (메일 본문에 승인/거절 버튼 활성화)
  • Approval Options:
    • Type of Approval: Approve and Disapprove (승인/거절 두 가지 선택지 제공)
    • Approve Button Label: Approve (승인 버튼 텍스트)
    • Approve Button Style: Primary (승인 버튼 스타일)
    • Disapprove Button Label: Reject (거절 버튼 텍스트)
    • Disapprove Button Style: Secondary (거절 버튼 스타일)

 

Execute step 버튼을 클릭하면 위에서 설정한 제목/본문 내용으로 승인 메일이 발송된다. 사용자가 메일의 Approve/Reject 버튼을 누르기 전까지 워크플로우는 다음 단계로 진행하지 않고 대기 상태로 유지된다.

 

 

초안 승인/거절 분기 처리


승인 요청 메일에서 Approve 혹은 Reject 버튼을 클릭하면 결과값이 approved 속성을 통해 다음 노드로 전달된다(승인 true, 거절 false). If 노드를 추가하고 분기 처리를 위해 아래 조건을 추가한다.

If 노드 설정창 (check_approval 이름으로 변경)

 

  • value1: {{ $json.data.approved }}
  • Condition: is equal to
  • value2: true

 

조건 설정을 완료하면 approved 값에 따라 두 가지 방향으로 워크플로우가 실행된다.

  1. true인 경우: 답변 초안을 승인한 것이므로 True 브랜치로 이동
  2. false인 경우: 답변 초안을 거절한 것이므로 False 브랜치로 이동

 

 

초안 승인 - 이메일 발송


답변 초안을 승인하면 원본 메일 발신자에게 초안 내용으로 답장을 보내야 한다. If 노드의 True 브랜치에 Gmail > Reply to a message 노드를 추가하고 다음과 같이 설정한다.

Reply to a message 설정창 (send_response 이름으로 변경)

 

  • Resource: Message (이메일 메시지를 대상으로 작업)
  • Operation: Reply (원본 메일에 답장)
  • Message ID: 답장할 원본 이메일 ID
{{ $('get_email').item.json.id }}
  • Email Type: Text (일반 텍스트 이메일)
  • Message: AI가 작성한 답변 초안
{{ $('write_response').item.json.output[0].content[0].text }}

 

승인 메일에서 Approve 버튼을 누른 후, AI가 작성한 초안으로 답변 메일이 잘 발송됐는지 확인해 보자.

 

 

초안 거절 - 피드백 요청


AI가 작성한 답변 초안이 마음에 들지 않을 경우(Reject), 초안 검토자에게 어떤 부분을 수정해야 할지 피드백을 요청하는 메시지를 발송한다. If 노드의 False 브랜치에 Gmail > Send message and wait for response 노드를 추가하고 다음과 같이 설정한다.

Send message and wait for response 설정창 (ask_for_feedback 이름으로 변경)

 

  • Resource: Message (이메일 메시지를 대상으로 작업)
  • Operation: Send and Wait for Response (응답할 때까지 대기)
  • To: 피드백 요청을 받을 이메일 주소
  • Subject: [AI Auto Respond Feedback Request] (피드백 요청 메일 제목)
  • Message: 피드백 요청 메일 본문
You rejected the following AI response to the email you just received from {{ $('get_email').item.json.from.text }} with the subject "{{ $('get_email').item.json.subject }}"

Here is the content of the email: 
"{{ $('get_email').item.json.text }}"

And here is what the AI answered with:
"{{ $('write_response').item.json.output[0].content[0].text }}"

Since you did not like it, please provide feedback of what you would like to change.
  • Response Type: Free Text (텍스트로 피드백 작성할 수 있도록 설정)

 

테스트를 위해 [approve_email] 노드 실행 > 초안 검토 메일에서 Reject 버튼 클릭 > [ask_for_feedback] 노드 실행 > 피드백 요청 메일이 잘 도착하는지 확인해 보자. 피드백 요청 메일에서 Respond 버튼을 클릭하면 아래처럼 텍스트를 입력할 수 있는 폼이 열린다. 여기에 수정하고 싶은 구체적인 피드백 내용을 입력하고 제출(Submit)하면, 대기 상태였던 워크플로우가 피드백 내용을 받아 다음 단계로 이어진다.

n8n에서 제공하는 피드백 입력 폼

 

 

초안 재작성 프롬프트


답변 초안이 반려될 경우, ①초안 생성에 사용했던 프롬프트, ②AI가 작성한 답변 초안, ③사용자 피드백을 함께 전달하여 답변을 다시 생성해야 한다.

 

이를 구현하기 위해 피드백을 수집하는 [ask_for_feedback] 노드 뒤에 Edit Fields(Set) 노드를 추가하고 답변 재작성에 사용할 프롬프트를 입력한다. 이때 필드 이름을 초안 프롬프트 노드(set_initial_prompt)와 동일하게 prompt로 지정하면, 이후 실행되는 AI 노드에서 {{ $json.prompt }} 값을 그대로 참조할 수 있다.

Edit Fields 노드 설정창 (set_feedback_prompt 이름으로 변경)

 

답변 재작성 프롬프트는 크게 두 부분으로 구성된다.

  1. <ORIGINAL_PROMPT> : 처음 답변 초안을 생성할 때 사용했던 원본 지시사항
  2. <NEW_PROMPT> : 기존 답변 내용과 피드백을 바탕으로 다시 작성하라는 지시사항
<ORIGINAL_PROMPT>
Hi, your task is to reply to this email.

Write a response that sounds natural, and keep in mind I'm very busy and have little time for things.

If something personal comes up, please write a response asking to schedule a call.

For any events, invitations, or promotions, please politely decline.

Here is the email I just received.
Your task is to reply to the email as if you were me.

<EMAIL>
Subject: {{ $('get_email').item.json.subject }}
Message: {{ $('get_email').item.json.text }}
</EMAIL>

IMPORTANT
Reply with the email ready to send. Don't include the subject.
AND very important: DO NOT USE PLACEHOLDERS LIKE [Your Name].
Use my real name: Sion
</ORIGINAL_PROMPT>

<NEW_PROMPT>
That was your task, and you failed at it. The user rejected your answer.

This is what you replied with:

<YOUR_REPLY>
{{ $('write_response').item.json.output[0].content[0].text }}
</YOUR_REPLY>

And this is what the user had to say about it, the user feedback:

<USER_FEEDBACK>
{{ $json.data.text }}
</USER_FEEDBACK>

Your task is to adapt the reply to follow the feedback that the user provided.
</NEW_PROMPT>

 

 

프롬프트 전달 구조


처음 워크플로우를 실행하면 [set_initial_prompt] 노드에서 생성한 프롬프트가 prompt 필드에 담겨 전달되고, [write_response] 노드는 {{ $json.prompt }} 값을 사용하여 답변 초안을 생성한다.

 

이후 답변이 거절되면 [set_feedback_prompt] 노드에서 출력한 재작성 프롬프트가 [write_response] 노드로 전달된다. 두 프롬프트 생성 노드의 필드 이름을 모두 prompt로 지정했기 때문에 [write_response] 노드는 동일한 표현식인 {{ $json.prompt }} 값을 그대로 참조하여 답변을 다시 생성할 수 있다.

워크플로우 완성 화면

반응형