Skip to main content
Summary

예측 가능성은 좋은 답변이 아니라 계약에서 나온다

AI 시스템을 만들 때 흔한 실수는 모델에게 "정확하게 답해줘", "반드시 JSON으로 답해줘", "위험한 행동은 하지 마"라고만 지시하는 것이다. 이 방식은 데모에서는 잘 보일 수 있다. 하지만 운영에서는 곧 깨진다. 사용자의 말은 매번 다르고, 모델의 출력도 조금씩 흔들리며, 후처리 코드는 예상하지 못한 형식 앞에서 실패한다.

하네스 엔지니어링에서는 이 문제를 프롬프트만으로 풀지 않는다. 모델 호출 전에는 입력 계약(Input Contract)을 검증하고, 모델 호출 후에는 출력 계약(Output Contract)을 검증한다. 계약은 "모델이 이렇게 해주면 좋겠다"가 아니라 "이 조건을 만족하지 않으면 다음 단계로 넘기지 않는다"는 실행 규칙이다.

운영 가능한 AI 시스템은 자연어 재주가 아니라 깨지지 않는 계약에서 시작된다. 자연어는 사용자를 위한 인터페이스일 수 있다. 그러나 시스템 내부에서는 타입, 필드, 권한, 근거, 승인 상태처럼 검증 가능한 값으로 바뀌어야 한다.

입출력 계약으로 예측 가능성 만들기

입력 계약: 모델에게 넘기기 전에 정규화한다

입력 계약은 모델이 받을 수 있는 요청의 모양을 정한다. 여기에는 최소한 다음 항목이 포함되어야 한다.

  • 필수 필드

  • 필드 타입

  • 허용값

  • 문자열 길이 제한

  • 실행 환경

  • 참조 가능한 데이터 소스

  • 민감정보 포함 여부

  • 허용된 도구와 액션

  • 사람 승인 필요 여부

예를 들어 사용자가 "배포 실패 원인 좀 찾아서 고쳐줘"라고 말했을 때, 이 문장을 그대로 모델에 넘기면 범위가 넓다. 모델은 로그를 읽어도 되는지, 코드를 수정해도 되는지, 배포를 다시 실행해도 되는지, 사람 승인이 필요한지 추측해야 한다. 운영 시스템에서 추측은 장애의 시작이다.

따라서 하네스는 자연어 요청을 내부 파라미터로 정규화해야 한다.

{
  "task_type": "deployment_triage",
  "target_resource": "service:payment-api",
  "allowed_actions": ["read_logs", "read_pipeline", "suggest_fix"],
  "approval_required": true,
  "evidence_required": true,
  "data_sources": ["ci_logs", "deployment_history", "error_tracker"],
  "contains_sensitive_data": false
}

이 구조에서는 모델이 무엇을 할 수 있는지 분명하다. 로그와 파이프라인은 읽을 수 있지만, 직접 배포하거나 고객 데이터를 조회할 수는 없다. 수정안은 제안할 수 있지만 실행은 승인 뒤에만 가능하다. evidence_required가 true라면 결론마다 근거를 요구할 수 있다.

Harness의 Worker Agent도 비슷한 관점에서 이해할 수 있다. Worker Agent는 지시문, 모델 커넥터, 선택적 MCP 서버, 런타임 입력을 하나의 재사용 가능한 governed step으로 묶어 파이프라인 단계에서 실행할 수 있게 한다.1 중요한 점은 "프롬프트 하나"가 아니라 실행 단위 전체가 계약의 대상이라는 것이다. 어떤 모델을 쓰는지, 어떤 MCP 데이터 소스에 접근하는지, 어떤 입력을 받을 수 있는지가 함께 정의되어야 한다.

자연어 요청과 실행 파라미터를 분리한다

사용자 요청은 의도를 담고 있다. 하지만 파이프라인과 자동화 시스템은 의도만으로 움직일 수 없다. 실행 가능한 파라미터가 필요하다.

예를 들어 PR 리뷰 에이전트를 만든다고 하자. 나쁜 입력은 다음과 같다.

"이 PR 좀 잘 봐줘."

좋은 입력 계약은 다음과 같이 바뀐다.

{
  "task_type": "pr_review",
  "target_resource": "github://org/repo/pull/128",
  "review_focus": ["security", "schema_change", "test_coverage"],
  "allowed_actions": ["read_diff", "read_files", "comment_suggestion"],
  "forbidden_actions": ["push_commit", "merge_pr"],
  "approval_required": false,
  "evidence_required": true,
  "max_files": 30
}

이렇게 설계하면 모델의 자유도가 줄어든다. 하지만 이것은 단점이 아니다. 운영에서 자유도는 비용이다. 모델이 할 수 있는 범위를 줄이면 검증 가능성이 높아지고, 후속 자동화가 쉬워진다.

입력 계약은 특히 권한과 연결되어야 한다. allowed_actions에 없는 행동은 프롬프트에서 "하지 말라"고 말하는 수준이 아니라 런타임에서 차단해야 한다. 모델이 실수로 merge_pr을 요청하더라도 도구 제어 계층이 실행하지 않아야 한다.

출력 계약: 좋은 문장이 아니라 파싱 가능한 구조

출력 계약은 모델이 돌려줘야 하는 결과의 모양을 정한다. 자유 텍스트는 사람이 읽기에는 좋지만 시스템이 처리하기에는 불안정하다. 후속 단계가 CI/CD, 티켓 생성, 알림, 승인 워크플로우와 연결된다면 출력은 반드시 파싱 가능해야 한다.

출력 계약에는 보통 다음 필드가 필요하다.

  • status: 성공, 실패, 추가 정보 필요 등 상태

  • result: 핵심 결과

  • evidence: 판단 근거

  • confidence: 신뢰도

  • actions_performed: 수행한 액션

  • requested_actions: 앞으로 필요한 액션

  • approval_required: 사람 승인 필요 여부

  • next_steps: 다음 단계

  • risk_level: 위험도

예시는 다음과 같다.

{
  "status": "needs_approval",
  "result": {
    "summary": "배포 실패 원인은 DB 마이그레이션 순서 불일치로 추정됩니다.",
    "root_cause": "migration_20260520_add_index가 애플리케이션 배포보다 늦게 실행됨"
  },
  "evidence": [
    {
      "source": "ci_logs",
      "quote": "column user_status does not exist",
      "confidence": 0.86
    }
  ],
  "actions_performed": ["read_logs", "read_deployment_history"],
  "requested_actions": ["run_migration", "rerun_deployment"],
  "approval_required": true,
  "risk_level": "medium",
  "next_steps": ["DB 마이그레이션 실행 승인 요청", "승인 후 배포 재시도"]
}

이런 출력은 사람이 읽을 수도 있고, 시스템이 처리할 수도 있다. 승인 필요 작업은 승인 큐로 보낼 수 있다. 근거가 없는 판단은 차단할 수 있다. 위험도가 높으면 슬랙 알림 대신 온콜 호출로 바꿀 수 있다.

출력 계약을 강제하는 방법은 여러 가지다. JSON Schema, 함수 호출, 타입 정의, 명시적 마크업을 사용할 수 있다. 중요한 것은 "JSON으로 답해"라는 문장이 아니라, 실제 파서와 검증기가 뒤에 있어야 한다는 점이다. 하네스 관점에서 출력 파서는 대표적인 피드백 장치다. 출력이 계약을 어기면 그 결과는 업무 로직으로 들어가지 못해야 한다.

검증기는 파싱보다 더 많은 일을 해야 한다

검증기를 단순히 "JSON 파싱 성공 여부"로만 만들면 부족하다. 운영 검증기는 다음 문제를 찾아야 한다.

  • 필드 누락

  • 타입 불일치

  • 허용값 위반

  • 길이 제한 초과

  • 금지된 액션 요청

  • 근거 없는 판단

  • 민감정보 노출

  • 승인 없이 실행하려는 변경

  • 입력 계약과 출력의 불일치

예를 들어 입력 계약의 allowed_actions가 read_logs, suggest_fix뿐인데 출력의 actions_performed에 rerun_deployment가 들어 있다면 이는 계약 위반이다. 모델이 실제로 실행하지 않았더라도 "실행했다"고 주장하는 순간 감사 로그와 운영 판단이 오염된다.

또 evidence_required가 true인데 evidence가 비어 있다면 결과는 실패로 처리해야 한다. "그럴듯한 결론"은 운영 근거가 아니다. 특히 장애 분석, 보안 판단, 비용 최적화, 고객 응대처럼 책임이 따르는 작업에서는 근거 필드가 필수다.

민감정보 검증도 중요하다. 모델 출력에 API 키, 주민등록번호, 계정 토큰, 고객 이메일 원문이 포함되면 후속 로그나 알림 시스템으로 퍼질 수 있다. 따라서 출력 검증기는 보안 필터와도 연결되어야 한다.

AI Adapter 계층을 둔다

입출력 계약은 모델 호출 코드 안에 흩어져 있으면 안 된다. 비즈니스 로직이 프롬프트 문자열, 모델명, 재시도 횟수, 스키마 검증 코드를 직접 알고 있으면 변경 비용이 커진다. 모델을 바꾸거나 출력 필드를 하나 추가할 때 업무 코드 전체가 흔들린다.

이를 막기 위해 모델 호출 코드와 비즈니스 로직 사이에 AI Adapter 계층을 둔다. 이 계층은 다음 책임을 가진다.

  • 프롬프트 버전 관리

  • 모델 커넥터 선택

  • 입력 스키마 검증

  • 출력 스키마 검증

  • MCP 연결 관리

  • 재시도와 백오프 정책

  • 폴백 모델 선택

  • 감사 로그 기록

  • 계약 위반 분류

상위 애플리케이션은 "PR 리뷰를 실행한다", "배포 실패 원인을 분석한다" 같은 기능 계약만 호출한다. 내부에서 어떤 모델을 쓰는지, 프롬프트가 몇 번째 버전인지, MCP 서버가 어디에 연결되는지는 Adapter가 감춘다.

이 구조는 Harness Worker Agent의 재사용 가능한 governed step 개념과도 맞닿아 있다. 지시문, 모델 커넥터, 입력, MCP 연결을 한 단위로 묶으면 같은 작업을 여러 파이프라인에서 반복 사용할 수 있고, 정책 변경도 한 곳에서 관리할 수 있다.1

계약 위반은 예외가 아니라 운영 플로우다

계약 위반을 단순히 에러로 던지고 끝내면 운영성이 낮다. 하네스는 위반 유형에 따라 다음 경로를 선택해야 한다.

위반 유형처리 경로
출력 파싱 실패더 엄격한 형식으로 재요청
필수 필드 누락누락 필드를 명시해 재시도
허용값 위반실패 처리 후 감사 로그 기록
근거 없는 판단근거 수집 단계로 되돌림
금지 액션 요청즉시 차단하고 보안 이벤트 기록
민감정보 노출출력 폐기, 마스킹, 사고 로그 기록
승인 없는 변경 요청사람 승인 단계로 전환
반복 실패폴백 모델 또는 규칙 기반 처리

예를 들어 출력 형식만 조금 틀렸다면 재요청이 적절하다. 하지만 승인 없이 배포를 실행하려는 요청이 나왔다면 재시도보다 차단과 감사가 먼저다. 민감정보가 노출되었다면 해당 응답을 저장할지 말지도 별도로 판단해야 한다.

계약 위반을 운영 플로우로 다루면 AI 시스템은 더 예측 가능해진다. 실패가 사라지는 것이 아니라, 실패가 갈 곳을 갖게 된다. 이것이 운영 시스템과 데모의 차이다.

작은 계약부터 시작하라

처음부터 완벽한 계약을 만들 필요는 없다. 가장 자주 실행되고, 실패 비용이 있는 작업 하나를 고르면 된다. 그 작업에 대해 입력 필드 5개와 출력 필드 5개만 정의해도 효과가 있다.

시작 순서는 단순하다.

  1. 자연어 요청을 내부 파라미터로 바꾼다.

  2. 필수 필드와 허용값을 정한다.

  3. 모델이 사용할 수 있는 데이터 소스와 액션을 제한한다.

  4. 출력 스키마를 정한다.

  5. 검증기를 만든다.

  6. 위반 유형별 운영 경로를 만든다.

  7. 실행 로그에 계약 버전을 남긴다.

여기서 가장 중요한 습관은 계약에 버전을 붙이는 것이다. 프롬프트만 버전 관리할 것이 아니라 입력 스키마, 출력 스키마, 검증 규칙도 함께 관리해야 한다. 그래야 특정 날짜 이후 실패율이 왜 증가했는지 추적할 수 있다.

입출력 계약은 모델을 답답하게 만드는 장치가 아니다. 오히려 모델이 안전하게 일할 수 있는 작업면을 만들어 준다. 사용자는 자연어로 요청하되, 하네스는 그 요청을 검증 가능한 구조로 바꾼다. 모델은 그 구조 안에서 판단하고, 검증기는 결과를 확인한다. 그리고 계약을 어긴 결과는 다음 단계로 넘어가지 못한다.

AI를 운영 컴포넌트로 다룬다는 것은 바로 이런 뜻이다. 자유 응답 생성기를 업무 시스템에 붙이는 것이 아니라, 가이드와 센서와 구조화된 제약 안에서 움직이는 실행 단위를 설계하는 것이다. 예측 가능성은 모델의 성격에서 나오지 않는다. 계약에서 나온다.

참고

1Worker Agents | Harness Developer Hub

책 목록

AI 하네스 엔지니어링: 신뢰 가능한 에이전트를 만드는 실행 구조

전체 목차 보기

이 노트는 보도·비평·교육·연구 목적으로 작성되었습니다. 저작권 문의가 있으시면 에서 알려주세요.

틸노트는 사용자가 AI를 활용해 노트를 쉽게 작성하거나 편집할 수 있는 서비스입니다.

AI 스퀘어 단톡방에 함께해요

AI 활용과 틸노트 사용 팁을 나누는 오픈채팅방입니다. 입장 비밀번호는 tilnote입니다.

참여하기