Reviewer
reviewer 는 모든 mutating 작업에 이중 서명 하는 persona 입니다. 다른 worker 와 달리 coordinator 가 절대 스폰하지 않습니다 — 카탈로그는 의도적으로 제외합니다. 유일한 스폰 주체는 Class 가 "write" 또는 "destructive" 인 모든 도구를 래핑하는 ReviewGate 데코레이터입니다.
Reviewer 는 "누가 감시자를 감시하나?" 라는 질문의 답입니다.
비활성화하지 마세요.
Reviewer 가 Ongrid 에 host_restart_service 나 execute_skill 을 줄 때 안전하게 만드는 것입니다. 게이트 건너뛰기는 명시적 구성 선택이며 감사 흔적에 표면화됩니다. persona 를 "항상 승인" 으로 포크하면 감사 로그 가 모든 결정을 보여 줍니다 — 감사자가 알아챌 것입니다.
ReviewGate 데코레이터
도구 데코레이터 체인에서의 위치 (chain.go):
tenant_bind → REVIEW_GATE → timeout → audit → ratelimit → metric → <inner tool>이 정확한 순서인 이유:
timeout바깥. Reviewer 는 자체 턴 예산을 가진graph.Invoke. 내부 도구의 15 초 타임아웃 안에 래핑하면 reviewer 가 15 초 안에 끝나야 함 — 비현실적. 게이트는 자체 독립적인 60 초 천장 (DefaultReviewerTimeout) 을 운반.audit바깥. 거부는 합성 실행 행을 쓰지 않아야 함. 게이트는 대신chat_mutating_proposals행을 씁니다. Audit 은 내부 도구의 실행 만 로깅하며, 이것은 승인 시에만 일어남.tenant_bind안쪽. Proposal payload 는 ctx 에서tenant_bind가 해석하는 operatoruser_id를 포함 — 게이트는tenant_bind가 그것을 채운 후 실행되어야 함.
트리거 조건
데코레이터는 래핑된 도구의 Class 를 검사:
| Class | 게이트 동작 |
|---|---|
"read" | 통과. 내부 도구 실행. |
"write" | 가로채기. reviewer 스폰. 내부는 승인 시에만 실행. |
"destructive" | "write" 와 동일. 두 클래스 모두 게이트 통과. |
오늘 가방에 있는 구체적 Class: "write" 도구:
host_restart_service— 표준 mutating 기능.execute_skill— 마켓플레이스 설치 기능을 실행하는 마켓플레이스 shim (게이트는 기능 body 를 읽고 분류할 수 없으므로 전부 게이트).AgentTool— 예, 디스패치 프리미티브 자체가"write"인 이유는 worker 를 스폰하고 따라서 자원을 커밋하기 때문. 실무에서 reviewer 가 AgentTool 호출을 거의 게이트하지 않음 — 아래 persona 의 화이트리스트 참고.
Proposal payload
가로챌 때 게이트가 빌드:
{
"action": "host_restart_service",
"target": {"device_id": 7, "service": "nginx"},
"reason": "User reported 502; nginx error log shows OOM",
"blast_radius": "single_device",
"operator": "user_42",
"context_summary": "<coordinator's running summary of the conversation>"
}blast_radius 는 도구의 메타데이터에서 파생된 single_device | cluster | tenant_wide 중 하나. Reviewer 는 이를 사용해 "이것이 합리적인가" 결정을 가중 — tenant_wide 액션은 single_device 보다 더 높은 검토 강도.
Reviewer persona
frontmatter 하이라이트 (agents/reviewer.md 인용):
name: reviewer
description: SOP 二审 reviewer worker,对 mutating / destructive 提案做静态审查
permission_mode: read-only
max_turns: 5
model: anthropic/claude-opus-4-7 # 关键路径用最强
background: true # async: spawn returns immediately
tools:
- get_incident_detail
- get_edge_summary
- query_promql
- query_logql
- get_sop_text # planned (HLD-003 PR-D)
disallowed_tools:
- "*_skill" # wildcard — no skill execution
- run_shell
- execute_skill
- host_restart_service # explicitly: reviewer cannot itself act
- kill_process
critical_reminder: |
你是高危操作二审 reviewer。reject 是默认选项,approve 必须三条都满足:
1. 找得到对应 SOP 且明确覆盖此场景
2. 当前没有并行的同类操作(看告警 / 看运维窗口)
3. 回滚路径已知핵심 관찰:
max_turns: 5. Reviewer 는 둘러 가지 않습니다. 결정에 5 턴; persona prompt 는 명시적으로 "看不清就 reject" 라고 함.model: anthropic/claude-opus-4-7. 결정적 경로 호출은 조직의 기본과 무관하게 가장 강한 모델을 얻습니다. 리뷰는 빠른 모델로 강등되어선 안 됨 — 잘못된 승인의 비용이 느린 리뷰의 비용을 훨씬 넘어섭니다.background: true. Reviewer 가 비동기 실행. coordinator 의 UI 는 리뷰에 블록되지 않음; 리뷰의task_notification이 완료 시 다시 게시. (현재 배선에서 내부 도구는 reviewer 가 반환할 때까지 블록 — 하지만 UI 는 아니므로 실행 중 사용자는 "review pending" 을 봄.)disallowed_tools와일드카드*_skill. Reviewer 는 어떤 기능도 실행할 수 없습니다. 컨텍스트 읽기 (get_incident_detail,get_edge_summary, 텔레메트리 쿼리) 는 가능하지만 절대 행동하지 않음.run_shell,host_restart_service,kill_process없음. persona body 가 그렇게 시켰더라도 런타임 필터가 이 도구들을 제거. 심층 방어.
5 단계 워크플로
persona body 에서 reviewer 가 실행:
- SOP 찾기. 공식 절차용
get_sop_text(action). SOP 없음 → reject with"no SOP for action <X>". - 대상 상태 확인.
get_edge_summary(device_id). 디바이스 오프라인 / 재시작 루프 / 마지막 mutating 액션 5 분 이내 → reject. - 병렬 작업 확인. 마지막 10 분 동안 같은 대상을 건드린
audit:엔트리용query_logql. 병렬 액션 →"parallel operation detected; wait for X to complete"로 reject. - 알림 대비 이유 검증. 참조된 incident 용
get_incident_detail. 이유가 알림 내용과 모순됨 → reject ("operator may have misread the symptom"). - 결정.
- 승인 세 핵심 게이트 모두 통과 시. 출력
{decision: approve, sop_id, rollback_path, gates_passed}. - 거부 그 외. 출력
{decision: reject, reason, missing_gates}.
- 승인 세 핵심 게이트 모두 통과 시. 출력
3 중 3 규칙
Critical reminder 는 명시적:
reject 是默认选项,approve 必须三条都满足:
- 找得到对应 SOP 且明确覆盖此场景
- 当前没有并行的同类操作(看告警 / 看运维窗口)
- 回滚路径已知
"확실하지 않음" 은 "거부" 와 동등. 이는 의도된 보정 — 잘못된 승인 (프로덕션 손상) 과 잘못된 거부 (한 번의 추가 왕복) 간 비용 비대칭이 후자를 크게 선호합니다.
출력 포맷
Reviewer 의 최종 답신 (<task-notification> 을 통해 coordinator 로 게시):
**Decision: approve | reject**
**Gates**
- ✓ SOP-007 covers restart nginx
- ✓ node-01 status online; last mutating 17min ago
- ✓ No parallel operation
- ✓ Rollback: `systemctl start nginx`
**Notes**
{1-2 sentence risk note; included even on approve.}데코레이터는 Decision: approve (대소문자 무관, 답신의 첫 비공백 줄에 나타나야 함) 를 파싱. 그 외 모든 것 — "approve with caveats" 같은 모호한 표현 포함 — 은 거부 로 다뤄집니다.
승인 시 일어나는 일
데코레이터는:
- status=
approved, reviewer 의 결정 텍스트, SOP id 와 함께chat_mutating_proposals행 작성. - 호출이 내부 도구로 떨어지게 함.
- audit 데코레이터 (체인의 다운스트림) 가 실행 행 작성.
- 내부 도구가 정상 결과를 coordinator LLM 에 반환.
Coordinator LLM 은 정상 도구 결과를 보고 진행.
거부 시 일어나는 일
데코레이터는:
- status=
rejected, reviewer 의 이유, 누락된 게이트와 함께chat_mutating_proposals행 작성. - reviewer 의 이유를 래핑하는
ErrReviewRejected반환. - audit 데코레이터는 실행 행을 쓰지 않음 (실행 발생 안 함).
Coordinator LLM 은 에러 메시지 — review rejected: <reviewer reason> — 를 보고 상황을 사용자에게 설명할 것으로 기대됩니다. 같은 도구 호출을 재시도하지 않아야 함; dedupe 보호와 거부 이유에 대한 단기 LRU 가 LLM 이 루프하지 않도록 유지.
엣지 케이스
사용자가 운영자이자 관리자라면?
Reviewer 는 여전히 실행됩니다. "관리자라서 리뷰 건너뛰기" 플래그는 없습니다. 감사 가능성이 핵심 — reviewer 의 결정 행은 "이 액션은 시간 T 에 롤백 Y 와 SOP-X 에 대해 승인됐다" 라고 말하는 종이 흔적 입니다. 관리자 오버라이드는 흔적을 지웁니다.
get_sop_text SOP 가 없다면?
오늘 SOP 코퍼스는 희소 — get_sop_text 는 계획된 도구 (HLD-003 PR-D). 현재 MVP 에서 reviewer 는 placeholder 를 사용하고 휴리스틱으로 폴백: 프로덕션 태그 디바이스의 critical 액션은 proposal context 에 명시적 force_approve_no_sop: true 가 필요하며, coordinator 는 명시적 사용자 확인 후에만 설정 가능. SOP 코퍼스가 채워지면 교체될 것입니다.
Reviewer 가 타임아웃하면?
60 초 게이트 타임아웃이 발화. 데코레이터가 ErrReviewTimeout 반환. Coordinator LLM 은 타임아웃 에러를 보고 — 재시도가 아닌 — 사용자에게 보고해야 합니다. 지속적 reviewer 타임아웃은 매니저 측 문제 (가능성 모델 지연); 감사 로그가 SRE 가 패턴을 보게 합니다.
읽기 전용 worker 도구는?
Worker 의 읽기 전용 도구 호출 (query_promql, get_host_load 등) 은 Class: "read" 이며 절대 게이트를 트리거하지 않습니다. 오직 "write" / "destructive" 도구만. Reviewer 자체는 Class: "read" 도구만 운반하므로 reviewer worker 는 자체로 중첩 ReviewGate 를 트리거할 수 없습니다.
게이트 커스터마이징
포크에서 바꿀 만한 것:
- Reviewer 모델. 조직에 Anthropic 액세스가 없으면 frontmatter
model:을 가진 가장 강한 모델로 재작성. 게이트는 persona 가 선언한 것을 사용. - 60 초 천장. Reviewer 가 정기적으로 더 오래 걸리면
ReviewGate생성자 옵션으로 오버라이드. 30 초 아래로 떨어지지 마세요; reviewer 는 5 턴 × LLM + 도구 왕복 공간이 필요합니다. - Reviewer persona body. 팀 특화 체크리스트 (PCI 범위, change-freeze 윈도우, 온콜 캘린더) 추가. body 의 내용이 무엇이든 게이트는 최종 결정 라인이 파싱 가능하면 신경 쓰지 않음.
바꾸지 말아야 할 것:
name: reviewer— 게이트가 이름으로 조회 (DefaultReviewerAgent).disallowed_tools와일드카드*_skill— reviewer 는 자체로 액션을 수행해선 안 됨; 심층 방어 원칙상 런타임 필터가 prompt 가 아닌 이를 강제.
도구별 커스텀 reviewer (예: db 특화) 의 경우 데코레이터 생성자는 reviewerAgent 오버라이드를 수락하여 다른 도구가 다른 reviewer persona 로 라우팅. 신중히 사용 — 다중 reviewer 는 감사 흔적을 단편화.