제안하는 Claude, 심문하는 Claude
자동매매 봇의 하루에 헤드리스 Claude를 역할별로 박아 넣은 기록 — 뉴스 수집, 조간회의, 반대 심문, 저녁 자가 감사, 그리고 역할마다 다른 실패의 기본값.
하려던 것
자동매매 봇은 모의투자에서 규칙 방식과 Claude 방식을 A/B로 돌리고 있다. Claude 방식은 매일 아침 헤드리스 claude -p 한 번으로 목표 비중을 제안받아 가상 장부에 집행하는데, 한 달쯤 돌려보니 구멍이 보였다. 뉴스는 요약만 되고 우리 포트폴리오와 연결되지 않았고, 제안은 아무도 따져 묻지 않은 채 장부로 들어갔다. 사람 회사라면 회의에서 걸러질 것들이다.
그래서 오늘, 이미 돌고 있던 아침 뉴스 수집과 저녁 자가 진단 사이에 조간회의를 완성하기로 했다. 핵심은 반대 심문관 — 제안하는 Claude와 공격하는 Claude를 분리하는 것이다.
하루 스케줄에 역할별로 박았다
08:30 뉴스 수집. claude -p에 --allowedTools WebSearch만 붙여 호출한다. 미국·한국 증시, 금리·환율, 리스크 요인을 총 10문장 이내로, 출처 병기, 투자 조언 금지. 실패하면 요약 자리에 “(수집 실패 — 정보 없음. 보수적으로 판단할 것)“이 그대로 들어간다 — 조용한 빈칸은 다음 단계를 낙관하게 만든다.
08:50 조간회의. 성과·리스크 분석은 LLM 없이 순수 계산이다 — CLI 인증 만료 하나로 판단이 사흘 멈춘 전례가 있어, 판단 계층에 장애점을 늘리지 않는다. 시황 분석가(헤드리스 Claude)는 밤사이 뉴스를 “우리가 실제로 들고 있는 종목” 기준으로만 해석하고 마지막 줄에 HEADLINE: 한 문장을 강제받는다. 이어서 전략가가 목표 비중을 JSON으로 제안하고, 그 제안이 오늘 새로 붙인 반대 심문관에게 넘어간다.
너는 투자위원회의 반대 심문관이다. 이 제안을 공격하는 것이 유일한 임무다. 대안을 제시하지 마라. 동의할 근거를 찾지 마라. 약점만 찾아라.
심문관의 출력도 JSON이다 — 판정(PASS/OBJECT)과 심각도 0~3. 심각도 2 이상의 반대면 텔레그램 승인 요청이 오고, 09:05 집행 전까지 승인 명령이 없으면 그날 Claude 방식은 매매하지 않는다. 기본값이 “안 한다”인 게이트다.
17:00 자가 진단. 그날 운영 기록 전부 — 잡 실행, 경고 이벤트, 주문, 가상 매매, 손익, 장부 대사 — 를 DB에서 긁어 프롬프트에 통째로 넣는다.
이 기록만 근거로 진단하라. 과장 금지, 기록에 없는 건 추측하지 말 것. 코드·설정 변경은 제안만 하고 절대 실행을 지시하지 말 것.
모든 호출이 같은 틀이다. 역할 선언(“너는 ~다”) + 데이터 전문 삽입 + 코드가 강제하는 제약 명시 + JSON 스키마 강제.
막힌 곳: 프롬프트 금지는 강제가 아니다
두 가지가 걸렸다.
첫째, 프롬프트에 “하지 마라”라고 쓰는 건 부탁이지 강제가 아니다. 그래서 전략가 프롬프트에는 “시스템이 코드로 강제하므로 위반 제안은 폐기된다”라고 명시하고, 실제로 코드가 그렇게 한다. 비중 합이 1을 넘거나 음수면 보정 없이 통째로 폐기한다. 매매 시그널을 심사하는 심사관은 더 엄격하다 — 권한이 승인/거부/축소 셋뿐이고, 축소 비율이 1을 넘으면 1로 깎아주는 게 아니라 거부한다. 범위 밖 값은 고쳐 쓸 노이즈가 아니라 수량을 늘리려 한 증거라서다.
둘째, 실패의 기본값. 헤드리스 호출은 타임아웃·파싱 실패로 곧잘 죽는다. 전부 “실패 시 거부”로 하면 CLI 장애 하나로 전체가 멈추고, 전부 “실패 시 통과”로 하면 돈 앞의 심사가 장식이 된다.
기준: 돈이 지나가는 길목인가
결론은 역할마다 기본값을 다르게 두는 것이었다. 주문 수량을 쥐는 심사관은 실패하면 무조건 REJECT — 재시도 한 번 뒤엔 전부 거부다. 전략가는 실패하면 시그널 0건이다. 반면 심문관과 시황 분석가는 실패해도 매매를 막지 않는다 — 분석은 보조고 강제는 가드레일 코드가 한다. 대신 실패 자체를 활동 기록에 남긴다.
저녁 자가 진단은 이 구조의 마지막 조각이다. 지난주 실행분에서는 잡 실행 내역과 두 방식의 손익, 장부 대사를 근거로 “이상 징후 없음”이라 판정했는데, 자기가 도는 중이라 자기 잡만 RUNNING인 것까지 짚으며 “진행 중으로 정상 범위”라고 스스로를 진단했다. Claude가 Claude의 매매 기록을 감사하는 그림이 실제로 돌고 있다. 다만 진단은 읽기 전용이다 — 적용은 내가 세션에서 승인해야 한다. 오늘 붙인 심문관이 쓸 만한 반대를 내는지는 다음 주부터 지켜볼 일이다.
배운 점
- 프롬프트의 금지는 부탁이고, 강제는 코드다. “위반 제안은 폐기된다”를 프롬프트에 쓰는 것과 실제로 폐기하는 코드를 두는 것, 둘 다 필요했다.
- 실패의 기본값은 역할마다 달라야 한다. 돈이 지나가는 길목은 실패=거부, 보조 분석은 실패=통과+기록. 하나의 정책으로 통일하면 어느 쪽이든 사고가 난다.
- 범위 밖 출력은 보정 대신 거부 — clamp는 위반의 증거를 지운다.
- 제안하는 AI와 공격하는 AI를 분리하되, 심문관에게 대안 제시를 금지한 게 핵심이었다 — 대안을 허용하면 공격자가 제2의 제안자가 된다.
- 무인 감사의 마지노선은 읽기 전용이다. 진단·제안까지만 시키고, 실행은 사람 승인 뒤에 둔다.