AGENTS.md로 Claude Code · 코딩 에이전트 행동 제어하기: Always / Ask first / Never 3계층 컨텍스트 엔지니어링 실전 가이드
Claude Code, Cursor, OpenAI Codex 같은 AI 코딩 에이전트를 써본 분이라면 비슷한 경험이 있을 겁니다. 분명히 "테스트만 고쳐줘"라고 했는데 에이전트가 갑자기 package.json을 건드리거나, .env 파일까지 슬쩍 열어보는 상황. 저도 처음엔 "어, 잠깐만..." 하면서 Ctrl+Z를 연타하곤 했습니다. 그런데 그 정도면 다행인 겁니다. 실제로 에이전트가 의도치 않게 의존성을 추가하거나 패키지 빌드를 터뜨리거나, 심한 경우 프로덕션 브랜치에 직접 커밋을 밀어 넣는 사고도 드물지 않게 일어납니다.
문제는 에이전트가 "멍청해서"가 아닙니다. 오히려 너무 열심히, 너무 자율적으로 일한다는 게 문제입니다. 경계를 알려준 적이 없으니까요. 마치 "알아서 잘 해줘"라고만 하고 온보딩 문서 하나 없이 신입 팀원을 바로 프로덕션 환경에 던져넣은 것과 같습니다.
이 글에서는 그 경계를 파일 하나로 정의하는 방법을 다룹니다. AGENTS.md에 "항상 해도 되는 것 / 먼저 물어볼 것 / 절대 하면 안 되는 것"을 명문화하면, 에이전트는 훨씬 예측 가능하게 행동하고 팀은 더 안심하고 자율성을 위임할 수 있습니다. 규칙 작성 원칙부터 계층적 오버라이드 패턴, 그리고 "이게 정말 효과가 있어?"라는 솔직한 이야기까지 실무 경험을 토대로 풀어보겠습니다.
핵심 개념
세 개의 버킷 — 에이전트 행동의 지도
AGENTS.md의 아이디어는 단순합니다. 에이전트가 할 수 있는 행동을 딱 세 영역으로 나누는 것입니다.
| 버킷 | 의미 | 대표 키워드 |
|---|---|---|
| Always (항상 해도 됨) | 승인 없이 즉시 실행 가능한 행동 | Allow, Always, Use |
| Ask first (먼저 물어볼 것) | 실행 전 사용자 승인이 필요한 행동 | Prompt, Ask before, Confirm |
| Never (절대 금지) | 어떤 상황에서도 실행 불가인 행동 | Forbidden, Never, Avoid |
우선순위는 forbidden > prompt > allow 순입니다. 더 제한적인 규칙이 항상 이깁니다. 이게 설계적인 선택인 이유가 있습니다. "허용"과 "금지"가 충돌할 때 허용이 이기면 규칙 하나를 빠뜨린 순간 에이전트가 예측 불가한 행동을 할 수 있습니다. 반대로 금지가 이기면 최악의 경우 에이전트가 지나치게 신중할 뿐이고, 그게 훨씬 안전합니다. 예측 가능성과 안전을 최우선으로 설계된 원칙입니다.
컨텍스트 엔지니어링 — 프롬프트 엔지니어링의 다음 단계
AGENTS.md를 단순히 "지시사항을 파일에 적는 것"으로 이해하면 절반밖에 못 본 겁니다.
컨텍스트 엔지니어링(Context Engineering): Anthropic이 정의한 개념으로, "LLM 추론 중 토큰의 최적 집합을 선별하고 유지하는 전략의 집합"입니다. 프롬프트 엔지니어링이 "무엇을 말하는가"에 집중한다면, 컨텍스트 엔지니어링은 "어떤 정보를 어떤 순서로 제공하는가"를 설계하는 시스템 엔지니어링입니다.
에이전트에게 규칙 파일을 제공하는 건 신입 팀원에게 온보딩 문서를 주는 것과 비슷합니다. "우리 팀은 이렇게 일해"라는 맥락을 미리 심어두는 거죠. 단, 에이전트는 문서를 읽고 기억하는 게 아니라 매 요청마다 규칙을 컨텍스트로 받아 처리한다는 점이 다릅니다. 그리고 에이전트가 한 번에 처리할 수 있는 정보량에는 한계가 있어서(토큰 한도), 규칙이 길어질수록 실제 작업에 쓸 수 있는 공간이 줄어든다는 트레이드오프도 있습니다.
좋은 규칙 작성의 4가지 원칙
실무에서 써보면서 정리한 기준입니다.
- 행동 동사로 시작 —
Use,Avoid,Prefer,Always,Never같은 명령형 동사가 첫 단어여야 합니다. "클린 코드를 추구할 것"보다 "Use named exports only"가 훨씬 명확합니다. - 25단어 이하로 짧게 — 길고 모호한 지시보다 짧고 구체적인 규칙이 일관된 결과를 냅니다.
- 긍정문과 부정문 분리 — "하라"와 "하지 마라"를 섞으면 에이전트도 헷갈립니다. 버킷을 명시적으로 나누어 적는 것이 효과적입니다.
- 추상보다 구체 — "타입 안전하게 써라" 대신 "TypeScript strict mode, no
anytypes, named exports only"가 실제로 일관된 결과를 만들어냅니다.
실전 적용
개념을 이해했다면 실제 파일이 어떻게 생겼는지 살펴보겠습니다.
예시 1: 3계층 권한 모델 (팀 단위 기본 구성)
아래는 여러 팀의 공개 사례와 실무 경험을 토대로 재구성한 권한 모델 구성입니다. 파일 읽기·포맷·단일 파일 검사는 자유롭게 허용하면서, 외부 영향(패키지 설치, git push)은 확인 단계를 두고, 보안·배포 관련 행동은 완전히 차단하는 논리입니다.
## Permissions
### Allowed without prompt
- Read files, list files
- TypeScript single-file type check (tsc --noEmit specific-file.ts)
- Prettier, ESLint
- Vitest single test
### Ask first
- Package installs (pnpm add)
- Git push
- Deleting files, chmod
- Running full build or end-to-end test suites
### Never
- Rotate API keys or secrets
- Modify CI/CD pipeline configuration
- Push directly to main branch"어떤 작업을 어느 버킷에 넣을지" 합의하는 것 자체가 팀에게 유익한 대화입니다. 에이전트에게 무엇을 맡길 준비가 됐는지 명시적으로 논의하는 기회가 되기도 하거든요.
복잡한 구성을 갖추기 전에 아래 세 줄부터 시작해보시면 좋습니다. 이것만으로도 에이전트 행동이 달라지는 걸 바로 느낄 수 있습니다.
Always: Run pnpm type-check before finishing
Ask before: Installing dependencies
Never: Commit .env files예시 2: 코딩 컨벤션 중심 AGENTS.md
권한 모델만이 아니라 코드 스타일 규칙도 같은 방식으로 표현할 수 있습니다. TypeScript 프로젝트에서 바로 사용해볼 수 있는 형태입니다.
## Coding Conventions
Always:
- Use async/await instead of .then()
- Prefer named exports over default exports
- Run `pnpm type-check` before marking a task complete
Ask before:
- Installing new production dependencies
- Modifying shared configuration files (tsconfig.json, vite.config.ts)
- Creating new top-level directories
Never:
- Use `any` type in TypeScript
- Commit .env files or secrets
- Bypass pre-commit hooks with --no-verify각 규칙에는 이유가 있습니다.
| 규칙 | 이유 |
|---|---|
async/await 강제 |
콜백 지옥과 .then() 체이닝 혼용 방지 |
pnpm type-check 먼저 |
에이전트가 "완료"라고 표시하기 전 타입 오류 사전 차단 |
any 금지 |
TypeScript strict mode의 핵심, 런타임 오류 예방 |
--no-verify 금지 |
pre-commit 훅 우회로 인한 품질 기준 저하 방지 |
예시 3: 계층적 오버라이드 패턴
팀 프로젝트라면 전역 설정과 프로젝트별 설정, 패키지별 설정을 분리해서 관리할 수 있습니다. 더 구체적인(디렉토리 깊이가 깊은) 파일이 우선순위를 가집니다.
~/.codex/AGENTS.md # 전역 개인 기본값 (내 개발 습관)
/repo/AGENTS.md # 팀 공유 표준 (모든 기여자에게 적용)
/repo/packages/api/AGENTS.md # 패키지별 국소 규칙 (API 서버 전용)충돌이 생기면 어떻게 작동하는지 구체적으로 보겠습니다. 전역 파일에서 Prettier 실행을 Always로 정의했는데, 특정 패키지에서 포맷터가 자동 생성 파일과 충돌한다면 이렇게 덮어쓸 수 있습니다.
# ~/.codex/AGENTS.md (전역)
Always: Run Prettier before committing
# /repo/packages/api/AGENTS.md (패키지별 오버라이드)
Ask before: Running Prettier on generated/* directories팀의 공통 기준을 깔면서도 개별 컨텍스트를 존중하는 구조입니다.
예시 4: OpenAI Codex .rules — Markdown을 넘어선 프로그래머블 권한
Markdown 파일에 텍스트로 규칙을 쓰는 방식은 에이전트가 규칙을 "참고"하는 형태입니다. 컨텍스트에 따라 규칙을 다르게 해석하거나 간과할 여지가 있죠. 저도 "더 강한 보장이 필요한 경우는?" 이라는 질문에 한동안 마땅한 답을 찾지 못했습니다.
OpenAI Codex의 .rules 파일은 여기에 한 단계 더 나아갑니다. Starlark 문법으로 도구 호출 자체를 가로채서 allow / prompt / forbidden 중 하나를 반환하는 방식입니다.
# .rules — Starlark 문법
def rule(event, config):
# 마이그레이션 관련 bash 명령은 항상 확인 요청
if event.tool == "bash" and "migration" in event.input:
return "prompt"
# rm -rf는 절대 허용 안 함
if event.tool == "bash" and "rm -rf" in event.input:
return "forbidden"
return "allow"Starlark: Google이 개발한 Python 유사 스크립트 언어로, Bazel 빌드 시스템에서 파생됐습니다. 결정론적 실행이 보장되어 권한 모델처럼 예측 가능성이 중요한 영역에 적합합니다.
Markdown AGENTS.md가 "이렇게 행동해줘"라는 부탁이라면, .rules는 "이 행동이 감지되면 무조건 이렇게 처리해"에 가깝습니다. 텍스트 기반 규칙으로 충분한 경우가 훨씬 많지만, 보안·데이터 관련 금지 규칙은 이런 코드 레벨 차단이 훨씬 믿음직스럽습니다.
장단점 분석
장점
솔직히 이 중에서 가장 크게 와닿았던 건 두 번째 항목이었습니다. PR 리뷰에서 "왜 any 썼어요?" 같은 스타일 지적이 사라지는 효과는 직접 써보기 전엔 얼마나 좋은지 잘 모릅니다.
| 항목 | 내용 |
|---|---|
| 행동 예측 가능성 | Forbidden 규칙은 "제안"이 아닌 "차단"으로 작동합니다. 도구 권한 설정과 결합하면 강한 보장을 얻을 수 있습니다. |
| 팀 컨텍스트 외부화 | 코드 컨벤션, 커밋 방식, 금지 패턴을 파일 하나에 모아 온보딩 비용을 줄이고 PR 리뷰에서 스타일 논쟁이 사라집니다. |
| 점진적 정제 가능 | AGENTS.md는 살아있는 문서입니다. 에이전트가 같은 실수를 두 번 반복하면 그 교정 내용을 파일에 추가하는 방식으로 팀 경험이 규칙으로 축적됩니다. |
| 도구 중립적 확장성 | AGENTS.md 오픈 포맷이 표준화되면서 Claude Code, Codex, Cursor 등 여러 도구를 파일 하나로 제어하는 "One AGENTS.md to Rule Them All" 패러다임이 현실화되고 있습니다. |
단점 및 주의사항
장점만 있는 건 아닙니다. 써보면서 느낀 함정들을 솔직하게 정리했습니다.
실제 효과에 대해서는 냉정하게 볼 필요가 있습니다. AGENTS.md 컨텍스트 파일의 효과를 측정한 2025년 연구를 처음 봤을 때 솔직히 당황했습니다. 개발자가 직접 작성한 컨텍스트 파일이 에이전트 성능을 평균 4% 향상시키는 데 그쳤고, LLM이 자동 생성한 파일은 오히려 3% 하락을 초래했다는 내용이었거든요. "고작 4%?"라는 생각이 들었지만, 이 수치는 코딩 성능 벤치마크에 관한 것이고, 팀 커뮤니케이션 비용 절감이나 스타일 일관성 같은 부분은 측정에 포함되지 않았습니다. 에이전트가 더 나은 코드를 쓴다는 기대보다는 팀이 예측 가능한 방식으로 협업한다는 가치로 접근하는 편이 현실적입니다.
또 하나 주의할 점은 에이전트가 규칙을 프로그램처럼 실행하지 않는다는 사실입니다. 규칙은 확률적 결과에 영향을 주는 신호 중 하나일 뿐입니다. Never 버킷에 적었다고 에이전트가 반드시 그 행동을 안 한다는 보장은 없습니다. 정말 중요한 금지 사항은 도구 권한 설정으로 이중 보호하는 것이 필요합니다. 도구 권한 설정이란 에이전트가 사용할 수 있는 도구 목록 자체를 제한하는 것입니다. 예를 들어 Claude Code에서 Write 도구를 허용 목록에서 제거하면 에이전트가 파일 수정 자체를 할 수 없게 됩니다. "규칙을 안 지키면 어쩌지" 걱정보다 "아예 못 하게 막는" 방식이 훨씬 믿음직합니다.
파일 비대화 문제도 있습니다. 온갖 규칙을 다 넣다 보면 파일이 거대해지는데, 이게 역효과를 낳습니다. 에이전트가 한 번에 처리할 수 있는 정보량에는 한계가 있어서 규칙 파일이 길어질수록 실제 작업 공간이 줄어듭니다. 짧고 정확한 규칙 20개가 길고 모호한 규칙 100개보다 낫습니다.
| 항목 | 내용 | 대응 방안 |
|---|---|---|
| 효과가 생각보다 작다 | 컨텍스트 파일은 평균 4% 향상에 그쳤습니다. | 팀 커뮤니케이션 비용 절감 도구로 활용합니다. |
| 규칙은 명령이 아닌 제안 | 에이전트는 규칙을 확률적으로 반영합니다. | 하드 가드레일은 도구 권한 설정으로 구현합니다. |
| 파일 비대화 | 규칙이 토큰을 소모해 실제 작업 공간을 빼앗습니다. | 짧고 핵심적인 규칙만 유지합니다. |
| 도구 간 호환성 불완전 | 각 에이전트가 파일을 해석하는 방식이 아직 다릅니다. | 공통 교집합 규칙만 공유하고, 도구별 특화 규칙은 별도로 관리합니다. |
실무에서 가장 흔한 실수
이 부분은 직접 당해보거나 팀에서 실제로 문제가 됐던 경우들입니다.
-
LLM에게 AGENTS.md를 자동 생성시키기 — 처음에 "GPT한테 우리 프로젝트 코드 보여주고 AGENTS.md 써달라고 하면 편하지 않을까?" 생각해서 직접 해봤습니다. 그럴듯해 보이지만 실제 팀 맥락과 동떨어진 규칙들이 나왔습니다. 앞서 언급한 연구 결과도 이를 뒷받침합니다. 자동 생성 파일은 오히려 성능이 하락했으니까요. 에이전트가 작성한 규칙은 팀이 실제로 겪은 아픔에서 나온 것이 아닙니다. 직접 작성하는 것을 권장합니다.
-
"항상 해도 됨" 버킷을 너무 크게 잡기 — 편의를 위해 너무 많은 작업을 Always에 넣으면 에이전트가 예상치 못한 타이밍에 큰 작업을 자율적으로 실행합니다. 처음엔 보수적으로 설정하고 점차 넓혀가는 것을 권장합니다. "이게 되면 좋겠다"는 바람보다 "이게 잘못되면 얼마나 아프지"를 기준으로 버킷을 나눠보시면 좋습니다.
-
규칙 파일만 믿고 도구 권한 설정을 생략하기 — Never 버킷에 적어도 에이전트가 절대 실행하지 않는다는 보장은 없습니다. 정말 위험한 행동(프로덕션 DB 수정, 시크릿 로테이션 등)은 도구 권한 자체를 제거하거나 미들웨어로 하드 차단하는 것이 안전합니다.
HumanLayer: "먼저 물어봐" 계층의 자동화를 돕는 미들웨어 도구입니다. 규칙 기반으로 특정 도구 호출(예: 마이그레이션이 포함된 Bash 명령)을 자동 감지해 차단하고 사용자에게 에스컬레이션하는 방식으로, 소프트 규칙과 하드 차단의 중간 지점을 제공합니다.
마치며
행동의 경계를 명문화하면 에이전트는 더 예측 가능해집니다. 에이전트에게 "눈치껏 알아서"를 기대하는 대신, AGENTS.md 한 파일로 경계를 선언하면 팀 전체가 더 안심하고 자율성을 위임할 수 있게 됩니다. 규칙 파일이 쌓일수록 온보딩 문서가 되고, PR 리뷰의 스타일 논쟁이 사라지고, 팀의 경험이 코드가 아닌 컨텍스트로 축적됩니다. 에이전트가 "알아서 잘"하는 게 아니라, 팀이 설계한 방식대로 움직이는 것 — 그게 에이전트와 사람이 더 잘 협업하는 팀의 모습이라고 생각합니다.
지금 바로 시작해볼 수 있는 3단계입니다.
-
프로젝트 루트에
AGENTS.md파일을 만들어보세요. 처음엔 세 줄만으로 충분합니다.Always: Run pnpm type-check before finishing/Ask before: Installing dependencies/Never: Commit .env files. 이것만으로도 에이전트 행동이 달라지는 걸 느낄 수 있습니다. -
팀과 함께 "에이전트에게 가장 당황했던 순간"을 모아보세요. 그 목록이 곧 Never 버킷의 초안이 됩니다. 실제 사고에서 나온 규칙이 가장 유효합니다.
-
정말 중요한 금지 사항은 도구 권한 설정으로 이중 보호하는 것을 권장합니다. 사용 중인 에이전트 도구의 권한 설정에서 특정 도구를 비활성화하거나, HumanLayer 같은 미들웨어로 특정 명령 패턴을 자동 차단하는 것도 검토해볼 만합니다.
다음 글: 멀티 에이전트 오케스트레이션에서 AGENTS.md를 어떻게 설계할까 — 오케스트레이터와 서브에이전트 간 컨텍스트 분리 전략과 역할별 권한 위임 패턴
참고 자료
- AGENTS.md — a simple, open format for guiding coding agents | GitHub
- Custom instructions with AGENTS.md – OpenAI Codex Developers
- Improve your AI code output with AGENTS.md | Builder.io Blog
- Writing a good CLAUDE.md | HumanLayer Blog
- Advanced Context Engineering for Coding Agents | HumanLayer GitHub
- Context Engineering for Coding Agents | Martin Fowler
- Effective context engineering for AI agents | Anthropic Engineering
- Harness engineering for coding agent users | Martin Fowler
- Evaluating AGENTS.md: Are Context Files Helpful for Coding Agents?
- AGENTS.md Best Practices | agentsmd.io