harness는 LLM 호출을 감싼 모델 바깥의 코드 전체입니다 — 무엇을 보여 주고(컨텍스트), 어떻게 시키고(지시문), 어떤 설정으로 부르고(모델), 받은 답을 어떻게 믿을지(검증). 같은 모델이라도 harness가 다르면 결과가 달라집니다.
루프 + 도구. 모델이 다음 행동을 정하고 도구를 불러 스스로 반복합니다. 코딩 도우미처럼 열린 문제에 맞습니다.
한 번 묻고 한 번 답받기. 순서는 코드가 정하고 모델에게 도구를 주지 않습니다(tool use 0건). AI 호출 16곳이 같은 틀을 지납니다. 현장 안전에서 AI의 일은 판단을 돕는 것이지 행동하는 것이 아니기 때문입니다.
기능을 고르면 그 기능의 AI 호출이 harness를 지나가는 길이 차례로 켜집니다. 단계를 눌러 멈춰 볼 수도 있습니다.
파란 단계는 harness 코드, 주황 단계는 모델입니다. 같은 모델이라도 앞뒤 여섯 단계가 결과의 품질과 안전을 정합니다.
위험분석 한 번에 코드가 날씨·팀원 컨디션 추이·회사 위험성평가·규칙으로 거른 사고사례(최대 60건)·동료의 아찔순간을 골라 넣습니다. AI는 이 밖의 것을 모릅니다.
개발 팁무엇을 빼는지도 설계입니다. 사람 입력은 지시와 섞이지 않게 as_data()로 '자료' 구획에 감쌉니다.
위험은 최대 3개, 항목마다 정확히 2문장, 읽어서 1분 이내, 강조어 대신 오늘의 숫자 — 현장 피드백으로 정한 출력 규칙입니다.
개발 팁규칙이 지시문에서 빠지면 테스트가 먼저 실패하게 합니다. 지시문 버전을 캐시 키에 넣어 예전 답이 다시 나오지 않게 합니다.
모델 이름은 DEFAULT_MODEL 한 줄. 생각(thinking)은 판단이 품질을 좌우하는 3개 기능만 켜고, 번호만 답하는 호출은 끈 채 응답 상한도 짧게 둡니다.
개발 팁thinking은 응답 한도를 함께 씁니다. 상한을 1200→600으로 줄였다가 답이 255자에서 잘려 JSON이 깨진 일이 있었습니다 — 설정도 테스트 대상입니다.
준비가 끝나면, 요청은 단 하나의 함수를 지나 나갑니다. ↓
# backend/ai_guard.py — 실제 코드를 줄여 옮김
def claude(feature, content, names=None, think=False):
if not ai_enabled(): _blocked(feature) ①
if len(content) > MAX_INPUT: raise ... ②
safe, alias = scrub(content, names) ③
safe = defuse(safe) ③
assert_egress("https://api.anthropic.com/…") ④
msg = client.messages.create( ⑤
model=DEFAULT_MODEL, system=SAFETY_SYSTEM,
thinking=think, messages=[safe])
text, flags = guard_output(msg.text) ⑥
audit(feature, 길이, 해시, flags) # 본문 X ⑦
return restore(text, alias) # 가명 → 실명
AI_ENABLED=false 한 줄로 전면 차단. 앱은 죽지 않고 503으로 물러섭니다.답이 돌아오면, 믿어도 되는지 확인합니다. ↓
폴백(fallback) — 원래 방법이 실패했을 때 대신 작동하는 예비 경로입니다. 엘리베이터가 멈추면 계단으로 가듯, AI가 답하지 못하면 규칙이나 사람이 이어 받습니다.
코드 펜스를 걷어 내고 요청한 형식(JSON)인지 확인합니다. 깨진 답은 캐시에 남기지 않습니다.
사고매칭에서 AI가 고른 번호가 후보 목록에 있는지 확인합니다. 없거나 호출이 실패하면 규칙으로 고른 후보 안에서 대신 고릅니다.
아찔순간 정리가 깨지면 받아쓴 원문을 그대로 넘겨 작업자가 직접 고칩니다. 위험분석을 못 받으면 막지 않고 스스로 한 번 더 확인하라고 안내합니다.
정리하면, 직접 만들 때도 같은 질문을 던지면 됩니다. ↓