두 agent 사이의 핸드셰이크 프로토콜
Agent 간에도 "계약"이 필요합니다. request_id가 계약 번호입니다.
왜 프로토콜이 필요한가?
s09에서 send_message로 어떤 내용이든 전송할 수 있습니다. 하지만 두 agent가 특정 사안에 합의해야 할 때 (예: "나 지금 종료해도 돼?")—단순한 문자열로는 부족합니다. 필요한 것:
- 요청에 명확한 신원(request_id)이 있어야 응답이 올바른 곳에 연결됩니다.
- 상태 기계: pending → approved | rejected, 각 상태의 결과가 명확합니다.
- 일관된 필드: 양측 모두
approve: true가 무엇을 의미하는지 압니다.
이것이 shutdown_request / shutdown_response / plan_approval / plan_approval_response가 존재하는 이유입니다.
Shutdown 프로토콜 전체 흐름
lead가 alice를 종료시키려 합니다:
lead: # shutdown_request 전송, 서버가 request_id 기록 req_id = uuid4()[:8] shutdown_requests[req_id] = {"target": "alice", "status": "pending"} send("alice", "shutdown_request", extra={"request_id": req_id}) alice: # 다음 루프에서 메일함 읽고 shutdown_request 발견 # 결정: 현재 작업 완료 후 응답, 승인 tool_use("shutdown_response", request_id=req_id, approve=True) lead: # shutdown_response 수신, tracker를 approved로 업데이트 shutdown_requests[req_id]["status"] = "approved" # alice 스레드가 shutdown 수락을 감지해 should_exit = true로 설정, 루프 종료
Shutdown FSM 시각화
상태 기계가 각 단계를 거치는 것을 보세요. alice는 reject할 수도 있습니다—"중요한 작업 중이라 지금은 멈출 수 없다"고 말할 수 있습니다.
Plan Approval · 같은 패턴, 다른 도메인
teammate가 큰 작업을 시작하기 전에 계획을 lead에게 승인 요청합니다:
alice: tool_use("plan_approval", plan="auth 모듈 전체를 jwt로 재작성하려 합니다") # alice는 계속 idle하며 lead를 기다립니다 lead: # alice의 plan_approval_response 요청 확인 tool_use("plan_approval", request_id="...", approve=False, feedback="auth는 건드리지 마세요, 다음 달에 전체 refactor 예정")
s10 소스를 보면 두 프로토콜이 완전히 같은 request_id 추적 패턴을 사용합니다—딕셔너리 이름만 다릅니다 (shutdown_requests vs plan_requests). 이것이 "하나의 패턴, 두 가지 도메인"입니다.
왜 공통 Protocol 기반 클래스로 추상화하지 않나요? s10은 의도적으로 추상화하지 않습니다. 이유: 지금은 프로토콜이 두 개뿐이라 추상화의 이득이 아직 명확하지 않습니다; 명시적으로 두 개를 작성하면 각각 독립적으로 이해할 수 있습니다. 네 번째, 다섯 번째 프로토콜이 생기면 그때 리팩토링합니다 (rule of three).