- 명령은 모두 `~/aio-01d4-stu/Last3Mon/69`에서, `uv run tools/flow.py call <웹훅 경로> <요청>` (첫 줄 `HTTP 코드 · 걸린 시간`, 그 아래 응답 JSON. `-v`를 붙이면 보낸 요청 JSON도 함께. `$`로 시작하는 출력 예는 `-v` 없이 응답만).
{"draft": "[프린터 드라이버 업데이트 안내]\n…\n문의는 IT팀 김민지에게 연락 바랍니다."}
```
- 번호 · 메일 주소가 **빠지고**, 날짜 · 시간은 **그대로**, 그리고 **새로 생긴 정보가 없어야** 합니다. 수업 준비 때 한 번은 작성자가 지운 번호 대신 `(내선 1234)`를 지어냈습니다.
- 고쳐 쓰지 않고 처음과 같은 초안이 오면 작성자가 `previous_draft` · `feedback`을 읽지 않는 것입니다. 공지 팀을 만들기 **전에** 작성자부터 고칩니다.
<details><summary>▶ 1단계 · 계약이 안 맞으면</summary>
결과 칸 이름이 다르면(`text` 대신 `draft`, `ok` 대신 `passed`) 공지 팀 쪽에서 맞추지 말고 **그 역할을** 계약대로 고칩니다. 그래야 다른 사람의 역할(`reference/lab02-start-reviewer.json`)과도 바꿔 끼울 수 있습니다.
</details>
---
## 예제 2 · 공지 팀 (25분)
**만들 것**: 공지 요청을 받아 작성자 → 검토자 순으로 부르고, 통과하지 못하면 검토 의견을 주어 **한 번** 고쳐 쓰게 한 뒤 다시 검토하는 워크플로우.
| 조건 | 값 |
| --- | --- |
| 저장할 파일 | `my-work/notice.json` (오늘 끝까지 이 파일을 고쳐 나감) |
| 웹훅 · 계약 | [AGENTS.md](AGENTS.md) 3절 공지 팀 (`my-notice`) |
| 결과 | 한 번에 통과 `게시 가능` · 고쳐서 통과 `수정 후 게시 가능` · 고쳐도 실패 `담당자 확인`. `published`, `rounds`, `notice`, `codes` (고쳐 썼으면 `first_codes`) |
| 테스트 | `cases/lab02.json` |
### ① 보내는 요청
Lab 01과 같은 공지 요청 넷: `requests/notice-mail.json`, `notice-vpn.json`, `notice-phone.json`, `notice-empty.json`. 공지 팀이 받는 것은 **작성자와 같은** 요청입니다.
**관찰**: `notice-phone`에서 고쳐 쓴 공지를 처음 초안과 비교해 봅니다. 전화번호만 빠졌나요, 다른 것도 바뀌었나요? n8n **Executions**에서 `my-notice` 한 번에 `my-writer`, `my-reviewer` 실행이 몇 개씩 생겼나요?
<details><summary>▶ 1단계 · 흐름을 먼저 그리기</summary>
`DESIGN.md` 3절에 mermaid로 그립니다. 작성 → 검토 → 통과? → (예) 게시 / (아니오) 고쳐 쓰기 → 다시 검토 → 통과? 각 화살표에 **무엇이 넘어가는지**(draft, issues)를 적습니다. ③의 결과 셋이 그림의 어느 끝인지 표시합니다.
</details>
<details><summary>▶ 2단계 · 왜 "한 번만"인가</summary>
"통과할 때까지 고쳐라"라고 하면 어떻게 될까요? 작성자와 검토자가 끝없이 주고받거나, 고칠수록 이상한 글이 될 수 있습니다. 고쳐 쓰기 횟수와 그 뒤에 할 일을 요청문에 정확히 적습니다. n8n에서 같은 역할을 두 번 부르는 방법은 [AGENTS.md](AGENTS.md) 5절 HTTP Request의 주의를 봅니다.
</details>
<details><summary>▶ 3단계 · 넘기는 값의 출처</summary>
다시 검토할 때 검토자에게 주는 `facts`는 어디서 가져오나요? 고쳐 쓴 작성자가 사실을 바꿔 전했다면? 사실은 **처음 요청에서** 가져와야 검토가 의미가 있습니다. `feedback`은 검토 결과의 무엇으로 만들지도 정합니다 (예제 1 ④에서 직접 넣어 본 모양).
한 노드에서 두 노드로 함께 보내고(Fork), 둘이 끝나면 하나로 모읍니다(Join). [AGENTS.md](AGENTS.md) 5·6절의 Merge와 연결 예를 봅니다. 통과한 길이 두 개(`게시 가능`, `수정 후 게시 가능`)인데, 정리자를 두 번 만들지 않으려면?
</details>
<details><summary>▶ 2단계 · 정리자의 "하지 않는 일"</summary>
정리자가 공지를 줄이면서 날짜를 바꾸거나, 지운 연락처를 되살리면 검토가 소용없어집니다. 정리자에게 무엇을 금지할지, 테스트가 무엇으로 확인하는지(④의 `not_contains`) 봅니다. 정리자 결과는 다시 검토하지 않아도 될까요? 내 생각을 `DESIGN.md`에 적습니다.
</details>
<details><summary>▶ 3단계 · 시간 재기 · 정말 동시에 돌았나</summary>
정리자를 붙이기 전(`lab02` 보고서, 수업 준비 때 2.0~4.1초)과 뒤(`lab02-challenge` 보고서)의 `seconds`를 비교합니다. 그리고 n8n **Executions**에서 `my-notice` 실행 하나를 열어 `Make title`, `Make chat message`(내가 붙인 두 정리자 노드)를 하나씩 눌러 봅니다. 각 노드의 **시작 시각과 걸린 시간**을 적어 보세요.
- 두 노드가 거의 같은 시각에 시작했나요, 하나가 끝난 시각에 다른 하나가 시작했나요?
- 늘어난 시간은 두 정리자 시간의 **합**에 가까운가요, **긴 쪽**에 가까운가요?
설계(서로 기다릴 필요 없음)와 n8n이 실제로 돌리는 방식이 같은지 `DESIGN.md`에 적습니다. 68일차 3단계 교안에서 본 "같은 HTTP 노드의 항목은 함께, 갈래는 차례로"도 떠올려 봅니다.
</details>
## 막혔을 때
| 증상 | 할 일 |
| --- | --- |
| 응답 500 `{"message": "Error in workflow"}` | 부른 역할이 400·404를 돌려줬을 수 있습니다. `call my-writer` · `call my-reviewer`로 하나씩 직접 불러 보고, Executions에서 빨간 노드 확인 (Lab 03에서 다룸) |
| 공지 팀이 404 | 아직 push하지 않았거나 웹훅 경로가 `my-notice`가 아님 |
| 좋은 공지인데 계속 `담당자 확인` | `call my-reviewer`로 그 초안을 직접 검토해 `issues.detail`을 봅니다. 검토자의 거짓 경보일 수 있음 (Lab 01 과제 ▶ 3단계) |
| 고쳐 쓴 공지에 새 번호(내선 등) | 작성자 지시문의 "고칠 때 새 정보를 더하지 않는다"를 확인 (예제 1 ④로 직접 시험) |
| 공지 팀이 계속 안 됨 | `cp reference/lab02-example2-pipeline.json my-work/notice.json` 후 push |
## 확인
- [ ] 예제 1: 두 역할을 직접 불러 계약을 확인하고, 고쳐 쓰기를 `call my-writer '{...}'`로 시험했다.