실제로 사용하는 AI 에이전트 명령어는 무엇인가요? 감사해 보세요
사용자 지정 에이전트 명령어는 사용 중단하는 속도보다 더 빠르게 쌓입니다. 세션 로그에서 실제 사용량을 집계한 다음, 사용하지 않는 명령어는 삭제하지 않고 비활성화하세요.
코딩 에이전트를 위해 작성하는 모든 사용자 지정 명령어는 좋은 아이디어로 시작됩니다. 스물네 개쯤 만들고 나면 그 폴더는 박물관이 되어 있습니다. 수천 개의 세션 기록에서 실제 호출 횟수를 세어 보니, 제 명령어의 절반이 두 달 동안 한 번도 호출되지 않았다는 것을 알게 되었습니다. 정리 작업은 쉬웠습니다. 숫자를 올바르게 해석하는 것은 쉽지 않았습니다.
명령은 축적되지만, 사용은 그렇지 않다
에이전트 명령은 패키지화된 명령어 집합으로, 슬래시 이름을 입력할 때 에이전트가 로드하는 정의 파일이 담긴 폴더입니다. 하나를 작성하는 데는 오후 한나절이 걸립니다. 하나를 폐기하는 데는 아무 비용도 들지 않지만, 그래서 아무도 하지 않습니다.
이렇게 쌓인 것이 단순히 어수선한 것만은 아닙니다. 각 정의는 매 세션마다 에이전트의 컨텍스트에 자신의 이름과 설명을 제공하며, 붐비는 네임스페이스는 모델이 잘못된 도구를 선택하게 만듭니다. 하지만 진짜 비용은 다른 형태로 나타났습니다. 제 26개의 명령은 모두 같은 종류의 것이 아니었습니다. 그것들은 하나의 플랫 폴더에 들어 있는 세 가지 다른 종류의 객체였습니다.
메모리가 아닌 세션 로그에서 집계하기
에이전트는 대화 기록을 디스크에 쓰는데, 보통 세션당 하나의 JSON-per-line 파일 형식으로 저장합니다. 모델이 수행한 모든 도구 호출은 그 안에 구조화된 블록으로 들어 있습니다. 그 파일 트리는 아무도 쿼리할 생각을 하지 않는 사용량 데이터베이스입니다.
명령어 호출은 입력값에 명령어 이름을 포함한 tool-use 블록으로 나타납니다. 전체 트리에 대해 grep을 한 번 실행하면 순위가 매겨진 목록을 얻을 수 있습니다:
# adjust the JSON shape to match your agent's transcript format
rg -o -I '"name":"<ToolName>","input":\{"<field>":"([^"]+)"' -r '$1' \
--glob '*.jsonl' "$TRANSCRIPT_DIR" | sort | uniq -c | sort -rn
단순한 이름이 아닌 블록을 일치시키세요. 명령어 문자열을 느슨하게 grep하면 설명하는 글에서 단순히 이름이 언급될 때마다 이를 포착하게 되어, 거의 사용되지 않는 명령어의 수를 가장 많이 부풀립니다. 이는 원하던 결과와는 정반대입니다.
가장 중요한 단일 단계는 시간별로 횟수를 나누는 것입니다. 전체를 대상으로 한 번, 그리고 지난 60일 동안 수정된 파일을 대상으로 또 한 번, 이렇게 두 번 실행하세요.
find "$TRANSCRIPT_DIR" -name '*.jsonl' -mtime -60 > recent.txt
rg -o -I '"name":"<ToolName>","input":\{"<field>":"([^"]+)"' -r '$1' $(cat recent.txt) \
| sort | uniq -c | sort -rn
누적 총계는 거짓말을 합니다. 누적 총계는 지난봄에 많이 사용하다가 6월에 사용을 중단한 명령어와 오늘 아침에 실행한 명령어를 같은 범주로 뭉뚱그립니다. 제 데이터에서는 목록의 약 3분의 1에 대해 두 열의 내용이 일치하지 않았습니다. 한 명령어는 평생 호출 횟수가 수백 번이었지만 최근 호출은 0번이었습니다. 또 다른 명령어는 평생 호출 횟수가 겨우 12번 남짓이었지만 여전히 매주 사용되고 있었습니다.
호출 0회가 항상 사용되지 않음을 의미하지는 않습니다
제가 만든 명령어 중 세 개는 호출 횟수가 거의 0에 가까웠지만, 전체 세트에서 가장 많은 부하를 견디는 파일이었습니다.
이들은 더 큰 파이프라인 명령어의 본문이었습니다. 해당 파이프라인은 이들을 도구로 호출하지 않습니다. 대신 디스크에서 정의 파일을 읽고 그 안의 단계를 따릅니다. 로그상으로는 이 세 파일이 사용되지 않는 것처럼 보입니다. 이들을 삭제하면 파이프라인이 실행 도중에 중단됩니다.
이는 일반적인 함정입니다. 사용량 원격 측정(telemetry)은 계측(instrumentation)이 알고 있는 진입점만 볼 수 있습니다. 파일 읽기, 셸 실행(shell-out) 또는 문서 참조를 통한 구성은 보이지 않습니다. 호출 횟수가 0인 것에 대해 조치를 취하기 전에, 명령어 이름뿐만 아니라 파일 경로에 대해서도 나머지 도구 전체를 grep으로 검색해 보세요:
# does anything else read the definition file directly?
rg -n '<commands-dir>/[a-z-]+/<definition-file>' .
그 명령어 하나가 삭제 목록을 유지 목록으로 바꿔버렸습니다. "작년에는 수백 건의 직접 호출, 이번 분기에는 0건"이라는 내용을 올바르게 해석하면 명령어가 더 이상 사용되지 않는다는 뜻이 아니었습니다. 더 새로운 파이프라인이 그 명령어를 진입점으로 흡수했고, 그 하위 단계들은 부모가 호출될 때마다 여전히 실행되고 있었다는 뜻이었습니다.
그래서 그 플랫 폴더에 있는 세 종류는 제가 직접 호출하는 것, 파이프라인이 읽는 것, 그리고 아무도 건드리지 않는 것이었습니다. 세 번째 그룹만이 정리 대상입니다. 두 번째 그룹에 대해서는 파이프라인이 의도된 진입점이라는 내용으로 설명을 변경하고, 파이프라인이 해당 경로를 하드코딩하기 때문에 파일들은 원래 있던 위치에 그대로 두었습니다.
삭제 대신 깊이로 비활성화하기
휴면 상태인 13개를 삭제하는 것은 꺼림칙했습니다. 그것들은 정상적으로 작동하고 문서화도 되어 있습니다. 6개월 뒤에 다시 사용하고 싶어질 수도 있습니다.
대부분의 에이전트는 정확히 한 단계 깊이의 디렉터리를 스캔하여 명령을 찾습니다. 즉, 각 하위 디렉터리에서 정의 파일을 확인합니다. 재귀는 없습니다. 문서를 믿기보다는 사용 중인 에이전트의 로더를 직접 읽어보세요. 제가 확인한 에이전트의 경우 동작이 명확했습니다. 디렉터리에 자체 정의 파일이 없으면 그 하위 디렉터리는 절대 검사되지 않습니다.
이를 통해 비활성화 메커니즘을 공짜로 얻을 수 있습니다. 폴더를 한 단계 더 깊이 이동하세요:
mkdir -p commands/_attic
git mv commands/old-command commands/_attic/old-command
이제 정의는 깊이 2에 위치합니다. 스캐너는 여기에 도달하지 않습니다. 명령은 메뉴에서 사라지고 컨텍스트를 소비하지 않게 되며, 모든 바이트는 여전히 디스크와 버전 관리에 남아 있습니다. 복원은 git mv 한 번으로 되돌릴 수 있습니다.
여기서 실제로 어떤 것이 작동하는지 주목하세요. 폴더 이름의 밑줄도 아니고, 도구가 준수하겠다고 약속한 이름 지정 규칙도 아닙니다. 바로 깊이의 변화입니다. 정의 파일을 재귀적으로 글로빙(globbing)하는 로더는 보관된 모든 명령을 조용히 활성 상태로 유지하므로, 이 방법을 사용하기 전에 자신의 에이전트에 대한 스캔 동작을 확인하세요. 두 명의 리뷰어가 저에게 바로 그 위험을 지적했고, 로더를 읽어보고 나서야 문제가 해결되었습니다.
그 코드를 읽으면서 한 가지 더 발견한 것이 있습니다. 스캐너는 심볼릭 링크(symlinks)도 명령으로 받아들입니다. 저는 언어 별칭으로 다른 명령 폴더를 가리키는 심볼릭 링크를 가지고 있었는데, 이는 해당 명령이 매 세션마다 두 번씩 등록되고 있었다는 의미입니다. 별칭은 이미 설명 텍스트에서 처리되고 있었습니다. 심볼릭 링크는 순수한 중복이었고, 탐색(discovery)이 어떻게 작동하는지 읽어보기 전까지는 보이지 않았습니다.
정리 작업 중 발생한 문제점
이동 자체는 간단했습니다. 문제가 발생한 곳은 문서였고, 동일한 결함이 서로 다른 파일에서 세 번이나 나타났습니다.
편집하면 줄 번호가 바뀝니다. 제 계획에는 편집할 내용을 위에서 아래로 절대적인 줄 범위로 나열했습니다. 496번 줄을 삭제하면 그 이후의 모든 범위가 한 줄씩 밀립니다. 한 파일에서는 대상 섹션 헤더가 계획에서 시작하라고 한 위치보다 한 줄 위에 있게 되어, 삭제 작업이 본문만 제거하고 헤더는 수평선 아래에 고아처럼 남겨두었습니다. 그 후 동일한 버그가 두 번째 파일에서 나타났고, 아홉 개의 범위가 있는 세 번째 파일에서도 나타났습니다. 해결책은 지루하고 절대적입니다. 파일의 맨 아래에서 위로 편집하거나, 숫자 대신 문자열을 기준으로 삼는 것입니다.
검증 범위는 편집 범위와 일치해야 합니다. 저는 리포지토리 전체에 오래된 참조가 없는지 확인하는 검사를 작성한 다음, 편집할 파일로 네 개만 나열했습니다. 다섯 번째 파일에 참조가 있었습니다. 그 검사는 실행하기도 전에 실패가 보장되어 있었습니다. 만약 수용 기준이 특정 디렉터리를 훑는다면, 그 디렉터리의 모든 파일이 범위에 포함되거나, 기준에 명시적인 제외 목록이 필요합니다.
아카이브된 항목 내부의 경로는 업데이트하지 마십시오. 아카이브된 정의에는 자체의 이전 경로가 포함되어 있습니다. 이 경로들을 새로운 아카이브 위치로 다시 작성하는 것은 깔끔해 보이지만 잘못된 것입니다. 폴더를 복원하면 원래 경로로 다시 이동하게 되고, 다시 작성된 참조는 아무것도 가리키지 않게 됩니다. 아카이브 내부에 있는 오래돼 보이는 경로는 아카이브가 복원될 것으로 예상하는 상태에 대한 올바른 경로입니다.
기록할 만한 결정이 하나 더 있었습니다. 저는 설정 파일에서 두 개의 섹션 전체를 삭제할 계획이었는데, 그중 하나가 여전히 실행 중인 인프라를 문서화하고 있다는 것이 밝혀졌습니다. 거기에 언급된 명령어들은 폐기되었지만, 그 아래의 훅과 스크립트들은 그렇지 않았습니다. 그 섹션을 삭제했다면 작동 중인 장치에 대한 유일한 설명을 제거하는 셈이었습니다. 저는 명령어에 대한 두 줄을 잘라내고 나머지는 남겨두었습니다.
자주 묻는 질문
숫자에 의미가 생기려면 세션을 몇 번이나 사용해야 하나요? 최근 기간에 평소의 작업량이 골고루 포함될 만큼 충분히 사용해야 합니다. 제 경우에는 매일 두 달 정도 사용하니 충분했습니다. 최근 열의 총 호출 횟수가 몇백 회 미만이라면, 낮은 횟수는 증거라기보다는 노이즈로 취급하세요.
아카이브 대신 삭제해야 하나요? 리포지토리에 히스토리가 있다면 삭제는 복구할 수 있으며 가장 깔끔한 트리를 남깁니다. 콘텐츠를 다시 활성화하지 않고 참조할 것으로 예상될 때 아카이브하는 것이 더 좋습니다. 이는 수동으로 단계를 따를 수 있는 명령어의 일반적인 경우입니다. 두 방법 모두 되돌릴 수 있습니다. 하나를 선택하고 일관성을 유지하세요.
명령어는 휴면 상태인데 문서에서는 여전히 사용하라고 안내한다면 어떻게 해야 하나요? 동일한 변경 사항 내에서 문서를 수정하고, 눈에 띄는 파일뿐만 아니라 전체 리포지토리를 확인하세요. 스크립트, 하위 프로젝트의 README, 워크플로 가이드 모두에 참조가 쌓입니다. 제 경우에는 5개의 파일에 흩어져 있었고, 그중 하나는 독자에게 제가 아카이브하려던 명령어를 호출하라고 안내하고 있었습니다.
목록을 줄이는 것이 실제로 측정 가능한 개선 효과가 있나요? 컨텍스트 절약 효과는 실재하지만 작습니다. 더 큰 효과는 선택 정확도입니다. 거의 중복되는 설명이 적을수록 잘못된 선택이 줄어듭니다. 단지 토큰 수 때문에 이 작업을 하지는 않을 것입니다. 세 가지 다른 종류의 객체가 동일하게 보이는 폴더는 결국 사용자를 오도할 것이기 때문에 이 작업을 할 것입니다.
관련 글
AI 에이전트가 무언가를 망가뜨리기 전에 중지시키는 가드레일 훅
AI 에이전트는 실제 도구를 실행하며, 때로는 잘못된 도구를 실행하기도 합니다. 다음은 파괴적인 작업을 사후가 아닌 실행 계층에서 포착하는 방법입니다.
AI 에이전트는 Sudo를 실행할 수 없으며, 그것이 바로 여러분을 위한 경계선입니다
AI 에이전트가 프로덕션 서버를 정리하도록 하는 것은 `sudo`를 실행할 수 없다는 것을 알아차리기 전까지는 위험하게 들립니다. 권한 경계는 작업을 에이전트에게 안전한 작업과 사람만 할 수 있는 작업으로 저절로 나눕니다.
AI 작업 계획을 Markdown 폴더가 아닌 SQLite에 인덱싱하세요
AI 협업은 당신을 기획 문서 더미에 파묻히게 합니다. markdown을 신뢰할 수 있는 단일 출처로 유지하고, FTS5로 SQLite 인덱스를 추가하여 전체 기록을 빠르게 쿼리하세요.
신뢰할 수 없는 텍스트를 읽는 에이전트를 위한 프롬프트 인젝션 방어
웹 페이지와 파일을 읽는 에이전트는 그 안에 숨겨진 지시에 의해 하이재킹될 수 있습니다. 여기에 프롬프트 인젝션을 막는 아키텍처가 있습니다.
더 많은 별칭 대신, AI 에이전트를 셸 프런트엔드로 사용하기
잊혀진 셸 스크립트의 무덤에는 대안이 있습니다. 작업을 평이한 말로 설명하고 AI가 당신을 위해 grep, awk, jq를 조합하도록 하세요.