포스트

GenericAgent는 30K 컨텍스트로 충분할까: Skill 결정화의 효과와 오염 위험

GenericAgent의 핵심은 컨텍스트를 무작정 늘리는 것이 아니라, 한 번 검증한 작업을 실행 가능한 Skill로 저장해 다음 요청의 추론량을 줄이는 데 있습니다.

긴 컨텍스트보다 중요한 것은 정보 밀도다

대화 기록, 검색 문서, 도구 설명을 계속 붙이면 모델이 참고할 정보는 늘지만 핵심과 잡음도 함께 섞입니다. GenericAgent가 택한 방향은 반대입니다. 원문 기준 코어는 약 3.3K 라인, 에이전트 루프는 약 100라인이며 브라우저, 터미널, 파일 시스템을 다루는 9개의 원자적 도구에서 출발합니다.

차이는 성공한 도구 호출 기록을 텍스트로 계속 보관하지 않는 데서 생깁니다. 반복할 가치가 있는 절차를 파이썬 함수 형태의 Skill로 추출해 Skill Tree에 넣고, 비슷한 문제가 오면 해당 함수를 다시 호출합니다. 원문은 이 방식으로 컨텍스트를 30K 토큰 아래에 유지하고 토큰 사용량을 다른 방식의 최대 6분의 1 수준으로 줄였다고 설명합니다. 다만 이 수치는 모든 모델, 저장소, 업무에 그대로 적용되는 보장이 아니라 프로젝트가 제시한 결과로 읽어야 합니다.

Skill 결정화는 무엇을 남기는가

원문이 제시한 다음 코드는 Spring Boot 로그에서 누락된 Bean 후보를 찾는 개념용 핵심 조각입니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
@skill(
    name="parse_and_fix_spring_boot_500",
    description="Analyzes Spring Boot 500 error logs and suggests the fix for missing Bean dependencies.",
    requires_tools=["read_file", "search_codebase"]
)
def parse_and_fix_spring_boot_500(log_path: str) -> dict:
    import re
    from tools import read_file, search_codebase

    log_content = read_file(log_path)
    match = re.search(r"NoSuchBeanDefinitionException: No qualifying bean of type \'(.*?)\'", log_content)

    if not match:
        return {"status": "failed", "reason": "Not a missing Bean error."}

    bean_type = match.group(1)
    implementations = search_codebase(f"implements {bean_type.split('.')[-1]}")

    return {
        "status": "success",
        "missing_bean": bean_type,
        "action": f"Add @Component or @Service to {implementations[0]}."
    }

이 조각만으로는 실행할 수 없습니다. skill 데코레이터와 tools 모듈 구현, 빈 검색 결과 처리, Spring 설정 방식 확인, 실행 환경과 권한 정책이 빠져 있습니다. 특히 첫 번째 구현체에 곧바로 @Component 또는 @Service를 붙이라는 결론은 조건부 후보일 뿐입니다. Skill은 정답 저장소가 아니라 검토 가능한 자동화 초안이어야 합니다.

반복 업무에는 유리하지만 첫 판단을 대신하지 않는다

효과가 큰 대상은 입력과 성공 조건이 비교적 일정한 반복 업무입니다. 같은 형식의 로그 분류, 저장소 검사, 정해진 보고서 생성처럼 이전 절차를 다시 실행할 수 있는 일이라면 매번 긴 추론을 재현할 이유가 없습니다.

반대로 원인이 매번 달라지는 장애 조사나 운영 서버 변경처럼 오판 비용이 큰 업무는 그대로 결정화하면 위험합니다. 첫 해결이 우연히 성공했거나 잘못된 가정을 포함하면 오류도 Skill Tree에 영구 보존됩니다. Skill이 많아질수록 어떤 버전이 언제 검증됐는지, 현재 코드와 여전히 맞는지도 관리해야 합니다. 비어 있는 Skill Tree에서 시작하는 콜드 스타트 비용 역시 사라지지 않습니다.

도입 전에는 재사용률보다 폐기 절차부터 정한다

작게 시험하려면 다음 순서가 현실적입니다.

  1. 읽기 전용이며 성공 여부를 자동 판정할 수 있는 업무 하나를 고릅니다.
  2. 새 Skill마다 입력, 출력, 필요 도구, 검증 날짜를 기록합니다.
  3. 생성 즉시 재사용하지 않고 테스트와 사람의 리뷰를 통과시킵니다.
  4. 실패율과 토큰 사용량을 기존 방식과 같은 요청 묶음으로 비교합니다.
  5. 코드나 외부 시스템이 바뀌면 Skill을 비활성화하거나 다시 검증합니다.

터미널과 파일 시스템을 쓰는 Skill은 샌드박스와 최소 권한이 전제입니다. 반복률이 낮거나 검증 비용이 절감액보다 크다면 긴 컨텍스트를 Skill 저장소로 바꾸는 것만으로 이득이 생기지 않습니다. GenericAgent의 실용적 교훈은 “30K면 충분하다”가 아니라, 재사용할 지식을 짧고 검증 가능한 실행 단위로 바꾸라는 데 있습니다.

원문과 버전 확인

함께 읽으면 이해가 이어지는 글

Skill 후보는 어떤 성공에서 추출해야 하는가?

한 번 성공했다는 사실만으로 재사용 절차가 되지는 않습니다. 입력 형태가 반복되고, 성공 조건을 자동으로 확인할 수 있으며, 실패했을 때 피해가 제한된 작업부터 후보로 삼습니다. 로그 분류나 읽기 전용 저장소 검사는 적합하지만 운영 설정 변경처럼 환경 의존성과 피해 범위가 큰 일은 매번 계획과 승인을 유지하는 편이 낫습니다.

결정화 전에 실행 기록에서 우연한 값과 일반 규칙을 분리합니다. 특정 파일 경로, 브랜치 이름과 첫 번째 검색 결과를 그대로 함수에 박아 넣으면 다른 저장소에서 잘못 작동합니다. 입력 파라미터, 필요한 도구, 전제 조건, 출력 스키마와 실패 유형을 명시하고, 원래 성공 사례뿐 아니라 빈 결과, 여러 후보, 권한 거부를 테스트합니다.

원문의 Spring 예시라면 implementations[0]이 존재한다는 가정과 첫 구현체가 정답이라는 가정을 제거해야 합니다. 후보가 없으면 진단 정보를, 여러 개면 결정에 필요한 설정과 annotation을 보여 주고 멈춥니다. Skill은 특정 수정안을 강제로 적용하기보다 검증 가능한 증거와 다음 선택을 반환하는 편이 재사용 범위가 넓습니다.

Skill Tree에서 올바른 버전을 어떻게 찾는가?

Skill이 늘어나면 이름만으로 선택하기 어렵습니다. 설명, 입력, 출력 스키마, 대상 언어와 프레임워크, 필요한 권한, 소유자, 근거 코드, 도구 버전과 마지막 검증 시각을 색인합니다. 사용자 요청과 현재 환경에 맞는 소수 후보만 검색하고, 전제가 맞지 않는 Skill은 점수가 높아도 제외합니다.

비슷한 Skill 두 개가 경쟁하면 자동으로 첫 번째를 실행하지 마세요. 최신 버전, 더 좁은 부작용, 검증 성공률과 필요한 권한을 비교하고 차이가 작으면 확인 질문이나 안전한 분석 단계만 실행합니다. 과거에 자주 사용됐다는 이유로 오래된 Skill이 계속 선택되는 인기 편향도 모니터링해야 합니다.

검색 실패 시 전체 Skill Tree를 프롬프트에 넣으면 원래의 컨텍스트 문제가 돌아옵니다. 읽기 전용 원자 도구로 새 계획을 만들거나 사용자에게 지원하지 않는 작업임을 알리는 fallback을 둡니다. 새로 성공한 절차는 즉시 전역 공개하지 말고 후보 상태에서 회귀 테스트와 소유자 승인을 거칩니다.

실행 권한과 샌드박스는 어디에 적용하는가?

Skill 선언의 requires_tools는 필요한 능력을 설명할 뿐 실제 접근 통제가 아닙니다. 런타임이 사용자와 업무별 allowlist를 계산하고 파일 경로, 네트워크 대상과 명령을 제한해야 합니다. 읽기 전용 분석 Skill이 쓰기 도구를 호출하려 하면 코드가 그렇게 요청해도 거부합니다.

외부 입력에서 생성된 Skill 코드는 신뢰할 수 없는 코드로 취급합니다. 격리된 프로세스나 컨테이너, CPU, 메모리, 시간 제한과 제한된 파일 시스템에서 실행하고 비밀은 필요한 호출에만 짧게 주입합니다. 서브프로세스, 동적 import와 네트워크처럼 권한을 넓힐 수 있는 동작은 정적 검사와 런타임 정책에서 모두 막거나 승인 대상으로 둡니다.

상태 변경 Skill은 계획과 실행을 분리합니다. 먼저 바뀔 파일, 자원과 예상 결과를 출력하고 사람 또는 정책 엔진이 승인한 해시만 실행합니다. 재시도 때 같은 변경이 중복되지 않도록 idempotency key를 쓰고, 부분 성공과 롤백 결과는 대화가 아니라 별도 실행 장부에 기록합니다.

스킬 오염과 오래된 지식을 어떻게 발견하는가?

코드베이스, 도구 API와 조직 정책이 바뀌면 어제의 성공 절차가 오늘의 오류가 됩니다. Skill에 생성 근거 커밋, 의존 도구 버전과 계약 해시를 붙이고 해당 입력이 바뀌면 자동으로 비활성화하거나 재검증 대기 상태로 보냅니다. 버전 정보가 없는 Skill은 운영 자동 실행 대상에서 제외하는 편이 안전합니다.

오염은 악의적 입력뿐 아니라 잘못된 성공 판정에서도 생깁니다. 테스트가 약해 실패를 성공으로 기록하거나 모델이 로그의 ‘success’ 문자열만 보고 통과할 수 있습니다. 결과 스키마, 독립 테스트와 부작용 검사를 사용하고, 사람이 나중에 수정한 실행은 해당 Skill의 성공률에서 실패로 반영해야 합니다.

canary 실행에서는 기존 절차와 새 Skill을 같은 입력에 읽기 전용으로 비교합니다. 출력 차이, 실패 유형, 토큰, 지연과 사람이 수정한 비율이 기준을 통과할 때 트래픽을 늘립니다. 오류율이 상승하면 최신 버전을 닫고 검증된 이전 버전이나 원자 도구 계획으로 되돌릴 수 있어야 합니다.

컨텍스트 절감 효과는 어떻게 측정하는가?

Skill 사용 전후에 같은 요청 묶음을 실행해 입력, 출력 토큰, 도구 호출 수, 성공률, 평균과 p95 시간, 사람이 개입한 횟수를 비교합니다. 토큰이 줄었지만 잘못된 Skill 선택으로 재시도가 늘면 총비용은 개선되지 않습니다. 콜드 스타트에서 새 계획을 만드는 비용과 반복 실행에서 얻는 절감도 따로 기록합니다.

재사용률만 높이는 목표는 위험합니다. 넓은 범용 Skill 하나가 많은 요청에 호출돼도 매번 예외 처리가 필요하면 가치가 낮습니다. 좁지만 검증이 쉬운 Skill 여러 개와 상위 상태 머신을 조합하는 편이 오류 위치와 권한을 설명하기 쉽습니다. 단, Skill 수가 늘어 검색 오류와 유지보수 비용이 증가하므로 사용 빈도와 검증 비용을 함께 봅니다.

합격 조건은 ‘30K 아래’ 같은 단일 문맥 수치가 아닙니다. 반복 업무의 성공률을 유지하면서 총 토큰과 시간은 줄고, 오래된 Skill을 발견, 폐기할 수 있으며, 고위험 실행이 승인 경계를 넘지 않아야 합니다. 이 조건을 충족하지 못하면 긴 컨텍스트를 줄인 대신 보이지 않는 코드 부채를 만든 것입니다.

자주 묻는 질문

성공한 에이전트 실행은 모두 Skill로 저장해야 하나요?

아닙니다. 입력과 성공 조건이 반복되고 자동 검증 가능한 절차만 후보로 삼아야 합니다. 우연한 성공이나 고위험 변경은 사람 검토 없이 재사용하면 안 됩니다.

Skill을 쓰면 긴 컨텍스트가 필요 없어지나요?

반복 절차의 토큰은 줄일 수 있지만 현재 코드, 사용자 요청, 실행 결과 문맥은 여전히 필요합니다. 관련 Skill만 검색하고 입력 전제와 버전을 다시 확인해야 합니다.

오래된 Skill은 어떻게 찾아서 중단하나요?

소유자, 근거 버전, 마지막 검증 시각, 실패율을 기록하고 코드나 도구 계약이 바뀌면 비활성화합니다. 회귀 테스트와 canary 실행을 통과한 버전만 다시 노출합니다.

THE END / OPSOAI

여기까지 읽었습니다

핵심 장면을 한 번 더 떠올려 보세요. 이해가 남았다면 이 책은 제 역할을 다했습니다.

다른 책 고르기
표지 1 —

←→ 키와 좌우 스와이프를 지원합니다. 읽던 페이지는 이 기기에 저장됩니다.

CONTENTS

이 책의 목차

    13개 장 20 분읽는 시간