AGENTS.md · AI 코딩 · 코딩 에이전트 · Agent Skill
AGENTS.md 작성법: AI 코딩을 위한 프로젝트 문서 설계
AGENTS.md에 프로젝트 구조, 금지 경계, 검증 명령을 어떻게 써야 하는지 설명합니다. README·Skill·Hook·CI의 역할 차이와 적용 순서를 공개 자료로 분석합니다.
1. AGENTS.md가 필요한 이유
AGENTS.md를 길게 쓰기만 하면 AI 코딩 품질이 좋아질까요? 같은 코딩 에이전트도 어떤 저장소에서는 기존 컴포넌트를 재사용하지만, 다른 저장소에서는 중복 유틸리티를 만들거나 아키텍처 경계를 넘습니다. 문법 지식만으로는 현재 저장소의 책임 분배와 완료 조건을 판단할 수 없기 때문입니다.
이 글은 성격이 다른 세 저장소를 비교해 README·CONTRIBUTING.md·AGENTS.md·Skill·Hook·CI가 각각 어떤 문제를 맡아야 하는지 설명합니다. 글을 읽고 나면 프로젝트 규칙을 어디에 배치하고 어떤 명령으로 검증할지 판단할 수 있습니다.
본문에서는 분석 대상을 특정 오픈소스 A, 특정 오픈소스 B, 특정 오픈소스 C라는 가명으로 부르고 인용의 고유 식별자는 일반 placeholder로 치환했습니다. 실제 프로젝트명과 원문 링크, 분석 기준은 마지막 출처 섹션에서만 공개합니다.
2. README·CONTRIBUTING.md·AGENTS.md의 차이
README는 대개 “이 프로젝트는 무엇이며 어떻게 실행하는가”에 답합니다. 하지만 코드를 바꾸는 AI에게는 다른 정보가 더 필요합니다. 어느 패키지가 해당 기능을 소유하는지, 기존 구현 중 무엇을 재사용해야 하는지, 어떤 계층을 건너뛰면 안 되는지, 완료 전에 어떤 명령을 실행해야 하는지를 알아야 합니다. 제품 소개와 설치 방법만으로는 이 판단을 내리기 어렵습니다.
그래서 세 문서는 서로 다른 질문을 맡습니다. README는 제품과 빠른 시작을 설명하고, CONTRIBUTING.md는 이슈 등록·PR 작성·리뷰처럼 사람이 변경을 제출하는 절차를 정합니다. AGENTS.md는 AI가 저장소 안에서 작업할 때 지켜야 할 실행 계약입니다. 수정 범위, 아키텍처 경계, 금지 패턴, 재사용 대상과 검증 명령이 여기에 들어갑니다.
특정 오픈소스 B에서는 루트 AGENTS.md가 모노레포의 전체 지도를 제공한 뒤 “현재 수정 파일과 가장 가까운 AGENTS.md를 따르라”고 안내합니다. 예를 들어 웹 코드를 바꾸는 AI는 루트 문서에서 저장소 구조를 파악하고, web/AGENTS.md로 이동해 프론트엔드에만 적용되는 API·UI·테스트 규칙을 읽습니다. 변경을 제출할 때는 다시 CONTRIBUTING.md의 이슈·테스트·PR 요구사항을 확인합니다.
정리하면 흐름은 루트에서 위치 파악 → 가까운 AGENTS.md에서 구현 규칙 확인 → CONTRIBUTING.md에서 제출 조건 확인입니다. 역할을 나누면 AI가 거대한 README에서 모든 규칙을 추측하거나, 백엔드 규칙을 프론트엔드에 잘못 적용하는 일을 줄일 수 있습니다.
3. 좋은 프로젝트 지침은 디렉터리보다 경계를 설명한다
디렉터리 목록은 지도를 주지만, 경계는 “어디로 가면 안 되는지”까지 알려줍니다. 특정 오픈소스 A의 프론트엔드 지침은 이 차이를 직접 드러냅니다.
편집 발췌 A-1: 특정 오픈소스 A,
frontend/src/AGENTS.md, L1-L14. 프로젝트 식별자를 치환했습니다.
# Frontend agent guide (`frontend/src`)Applies to any change under `frontend/src`. This is a **discovery + cadence** guide: the rules below exist because agents tend to generate before they look. The root `AGENTS.md` and the [compact-ui] package guides remain authoritative — this file does not repeat them, it points at them.## Rule 1 — Reuse before you create**Before building any UI element, search for an existing one.** [프로젝트명] already has a badge, a label, a table, a tag, a card, a modal. Hand-rolling one with raw `<div>`/`<table>` + Tailwind is the single most common agent mistake here, and it produces unbounded, off-design output.Where to look, in order:1. `frontend/src/lib/[main-ui]/` — the main-app default (~50 `[MainUI*]` components). Grep here first, and in most cases stop here.2. `frontend/src/lib/ui/` and `frontend/src/lib/components/` — older / app-specific shared pieces.`@[project]/[compact-ui]` is **not** for this tree. It targets MCP apps and the desktop app, it's deliberately more compact than [MainUI], and the main app isn't being migrated onto it, so those components read as out of place here. A handful of files already import it; treat those as exceptions rather than a pattern to copy.이 문서는 frontend/src의 탐색 순서와 UI 경계를 소유합니다. AI는 주 UI 라이브러리를 먼저 찾고 일부 예외 import를 표준으로 오해하지 말아야 함을 압니다. 실제 공용 table 구현과 생성 API를 쓰는 로그인 세션 로직이 규칙을 뒷받침합니다. 중복은 줄지만 기존 컴포넌트가 요구에 맞는지는 사람이 판단해야 합니다.
특정 오픈소스 B의 백엔드 지침은 폴더보다 의존성 방향을 더 분명히 씁니다.
편집 발췌 B-1: 특정 오픈소스 B,
api/AGENTS.md, L7-L25. 프로젝트 식별자를 치환했습니다.
Run backend checks from the repository root:- Format and lint: `make lint`- Type check: `make type-check`- Unit tests: `make test`- Targeted tests: `make test TARGET_TESTS=./api/tests/<path>`Run direct Python commands through `uv run --project api`. Docker-backed integration suites are normally CI-owned. Do not start long-running services as part of routine agent work.## Architecture And Boundaries- Keep transport parsing and serialization in controllers, orchestration in services, and domain policy in `core/` or its domain owner. Keep `libs/` business-agnostic and reuse existing owners before adding abstractions.- Before changing controller schemas, generated API contracts, or `SystemFeatureModel`, read `controllers/API_SCHEMA_GUIDE.md`. Treat `/system-features` as a minimal unauthenticated bootstrap allowlist, not a general configuration registry.- Scope tenant-owned reads and writes by the complete owner chain, and propagate `tenant_id` across every affected layer. Reconstruct trusted internal references from validated database state after payload or async boundaries.- Keep write transactions explicit and bounded. Do not perform external I/O inside an open transaction unless a documented consistency contract requires it.- Read configuration through `configs.[project_config]`, access storage through `extensions.ext_storage.storage`, and route outbound HTTP through the existing SSRF-safe owner in `core.helper.ssrf_proxy`.- Use Pydantic v2 for request and response models. Reuse domain-specific exceptions and translate them at the controller boundary.- Use existing Celery task and queue owners for asynchronous work; do not route unrelated jobs through workflow-specific services.- Celery tasks that may be retried or redelivered must keep side effects idempotent and log affected resource identifiers.이 파일은 api/의 명령과 계층 경계를 소유합니다. AI는 controller·service·core의 책임, 테넌트와 트랜잭션 경계를 얻습니다. 명령은 Makefile, 테스트는 api-tests.yml에 실제로 이어집니다. 계층 배치는 자동 테스트만으로 완전히 증명할 수 없어 설계 리뷰가 남습니다.
특정 오픈소스 C는 Python 라이브러리의 핵심 자료형을 경계로 삼습니다.
편집 발췌 C-1: 특정 오픈소스 C,
AGENTS.md, L39-L45. 프로젝트 식별자를 치환했습니다.
### Key design patterns- **`Detections` is the lingua franca** — every connector, tracker, and annotator speaks `Detections`. New connector = `@classmethod from_<framework>(cls, result) -> Detections`.- **Annotators are composable** — receive `scene` (BGR `np.ndarray`) + `detections`, return annotated copy.- **`data` dict extensibility** — per-detection metadata in `detections.data` as `np.ndarray` aligned with `xyxy`. Keys are constants from `config.py`.- **Vectorized throughout** — NumPy arrays, no Python loops in hot paths. Never write `for det in detections`.- **Lazy-import heavy deps** — `torch`, `transformers`, `ultralytics` must be imported inside the function that needs them, never at module top level.이 지침은 connector의 공통 타입과 성능 경계를 소유합니다. AI는 결과를 Detections로 정규화하고 metadata 정렬과 지연 import를 지켜야 함을 압니다. 실제 Detections 클래스가 패턴을 구현하지만, hot path와 메모리 비용은 사람이 입력 특성을 보고 판단해야 합니다.
4. 검증 명령은 실제 실행 경로와 연결해야 한다
“테스트를 충분히 작성한다”는 완료 조건이 아닙니다. 특정 오픈소스 A의 AGENTS.md는 저장소 CLI를 통한 경로별 테스트, Ruff, 타입 검사와 빌드를 지정하고, 이는 frontend/package.json의 Jest·tsgo·Oxlint·Oxfmt와 일치합니다.
특정 오픈소스 B는 로컬 단위 테스트와 CI 소유 통합 테스트를 구분하고, web/package.json은 test·type-check·build를 제공합니다. 특정 오픈소스 C도 pytest와 pre-commit 명령을 명시합니다. 실행하지 못한 E2E는 성공으로 꾸미지 않고 검증 공백으로 남기며, 사라진 명령은 현재 설정에 맞춰 문서를 고쳐야 합니다.
5. 루트와 하위 AGENTS.md를 나누는 기준
루트는 공통 규칙을, 하위 문서는 지역 책임과 예외를 맡습니다. 특정 오픈소스 A와 B는 프론트·백엔드·서비스별로 나누지만, C는 루트 AGENTS.md와 이를 불러오는 CLAUDE.md를 씁니다. 규모가 달라 문서 수 자체가 품질 지표는 아닙니다.
특정 오픈소스 A
A는 프론트엔드·제품·서비스별로 AGENTS.md를 나누고, 별도의 AI_POLICY.md에서 AI 사용 공개와 인간 책임을 설명합니다. 개발·운영 작업별 Skill도 여러 개 둡니다. 자동 검증은 Husky Hook과 GitHub Actions가 맡고, 저장소 CLI·Jest·Playwright 같은 명령으로 변경을 확인합니다. 에이전트가 만든 PR도 사람이 검토해야 한다는 조건이 명시되어 있습니다.
특정 오픈소스 B
B는 web, api, e2e, CLI처럼 모노레포의 주요 영역마다 지침을 나눕니다. controller·service·core의 책임과 테넌트 경계처럼 구현 중 넘지 말아야 할 선도 하위 문서에 적습니다. 프론트·백엔드 리뷰, 테스트와 E2E는 작업별 Skill로 분리하고, Claude PreToolUse Hook과 Actions가 자동 검증을 보완합니다. 테스트는 make test, vp test, Cucumber/Playwright로 이어집니다. PR 템플릿은 자동화 도구의 이름을 요구하지만, 공개 파일만으로 최종 승인 규칙 전체를 확인할 수는 없습니다.
특정 오픈소스 C
C는 루트 AGENTS.md에 핵심 규칙을 모으고, CLAUDE.md와 Copilot 지침이 이를 연결하거나 보완합니다. Detections, annotator, NumPy 벡터화처럼 라이브러리 전체가 공유하는 설계 패턴이 중심입니다. 개발용 Skill은 확인되지 않았고, pre-commit 설정과 Actions를 사용합니다. 다만 일부 CI 연동은 공개 저장소만으로 확정하기 어렵습니다. 테스트는 uv run pytest --cov=[package]로 실행하며, 모든 PR을 maintainer가 검토한다고 명시합니다.
범위 분리는 관계없는 규칙을 줄이지만 우선순위가 필요합니다. 특정 오픈소스 A는 루트 문서를 authoritative로, C는 충돌 시 CONTRIBUTING.md를 우선으로 둡니다. 우선순위가 없으면 문서가 늘수록 충돌도 늘어납니다.
6. AGENTS.md·Skill·Hook·CI의 역할 차이
Skill은 요청에 따라 선택하는 재사용 절차입니다. 특정 오픈소스 B의 프론트엔드 리뷰 Skill은 언제 열고 어디까지 읽을지를 다음처럼 제한합니다.
프론트엔드 리뷰 Skill이 finding을 행동 테스트로 전환하는 상세 과정은 AI 프론트엔드 코드 리뷰 Skill: 결함을 행동 테스트로 연결하는 법에서 이어집니다. 여기서는 Skill과 자동 검증의 활성화 조건 차이에 집중합니다.
편집 발췌 B-2: 특정 오픈소스 B,
.agents/skills/frontend-code-review/SKILL.md, L1-L15. 프로젝트 식별자를 치환했습니다.
---name: frontend-code-reviewdescription: Use only when the user explicitly requests a review or audit of frontend code under `web/` or `packages/[project-ui]/`. Supports pending-change, file-focused, and pasted-diff reviews. Do not use for implementation-only requests, diagnosis without review intent, or backend-only code.---Review the requested scope for concrete, reproducible regressions. This skill owns the review phase and routes directly to its bundled rule packs. For a combined review-and-fix request, establish findings before applying implementation or testing guidance.이 Skill은 명시적 리뷰를 증거 중심 절차로 바꿉니다. AI는 범위, 주변 코드로 확장할 조건, 결함으로 인정할 기준을 얻고, web/AGENTS.md는 테스트 작성을 다른 Skill로 보냅니다. 탐색 낭비는 줄지만 브라우저·운영 장애를 문서만으로 재현할 수는 없습니다.
Hook은 요청 여부와 관계없이 특정 이벤트에 자동으로 끼어듭니다. 특정 오픈소스 B의 Claude 설정은 Bash 도구가 실행되기 전에 명령 하나를 호출합니다.
편집 발췌 B-3: 특정 오픈소스 B,
.claude/settings.json, L1-L15.
{ "hooks": { "PreToolUse": [ { "matcher": "Bash", "hooks": [ { "type": "command", "command": "npx -y block-no-verify@1.1.1" } ] } ] }}이 Hook은 Bash 전에 block-no-verify를 자동 호출합니다. AI가 선택하는 Skill과 달리 이벤트 경로를 강제하며, 특정 오픈소스 A의 pre-push Hook도 preflight 실패 시 push를 막습니다. 다만 B의 Hook 구현은 외부 npm 패키지라 저장소만으로 내부 동작 전체를 검증할 수 없습니다.
7. 문서도 코드와 테스트로 검증해야 한다
특정 오픈소스 C의 AGENTS.md는 공개 API를 제거하기 전 최소 세 번의 minor release를 유지하고, 예전 모듈 이름에는 경고를 남기라고 요구합니다. 실제 호환 코드도 남아 있습니다.
편집 발췌 C-2: 특정 오픈소스 C,
src/[project_package]/keypoint/__init__.py, L1-L13. 프로젝트 식별자를 치환했습니다.
from project_package.utils.internal import warn_deprecatedwarn_deprecated( "The 'project_package.keypoint' module is deprecated in `0.27.0` and will be removed " "in `0.31.0`. Please use 'project_package.key_points' instead.")from project_package.key_points.annotators import ( EdgeAnnotator, VertexAnnotator, VertexLabelAnnotator,)from project_package.key_points.core import KeyPoints이 모듈은 예전 import를 새 구현으로 연결하며 경고합니다. AI는 공개 API를 즉시 삭제하지 않고 alias와 제거 버전을 유지해야 함을 알며, warn_deprecated 구현과 테스트도 이 규칙에 연결됩니다.
그런데 AGENTS.md와 코드는 제거 버전을 0.31.0, 우선 문서인 CONTRIBUTING.md는 0.30.0으로 적습니다. 현재 0.31.0.dev0에도 alias가 남아 있습니다. 어느 쪽이 옳다고 단정할 수 없으므로 AI는 충돌을 사람에게 넘겨야 합니다. 문서도 코드·테스트와 대조해야 하는 이유입니다.
8. 자동화가 끝나는 곳에서 인간 검토가 시작된다
특정 오픈소스 C의 CI는 한 개발자의 환경에서 통과했다는 말보다 더 넓은 증거를 만듭니다.
편집 발췌 C-3: 특정 오픈소스 C,
.github/workflows/ci-tests.yml, L24-L77. 프로젝트 식별자를 치환했습니다.
run-tests: name: Pytest Run # needs: build # todo: consider using this build package for testing timeout-minutes: 10 strategy: fail-fast: false matrix: os: ["ubuntu-latest", "windows-latest", "macos-latest"] python-version: ["3.10", "3.11", "3.12", "3.13"]# ... 중간 설정 생략 ... - name: 📦 Run the Import test run: python -c "import project_package; from project_package import assets; from project_package import metrics; print(project_package.__version__)" - name: 📋 Print installed packages run: uv pip list - name: 🧪 Run the Test run: pytest src/ tests/ --cov=project_package --cov-report=xml# ... 중간 설정 생략 ...은 작성자가 넣은 표시입니다. 이 CI는 여러 OS·Python에서 import와 pytest를 실행해 플랫폼 회귀를 찾습니다. AI는 로컬 통과가 전부가 아님을 알지만, CI도 사용성·설계 의도는 판정하지 못합니다.
검증은 formatter→lint→typecheck→unit·integration→build→E2E→자동 리뷰→인간 검토로 넓어집니다. 특정 오픈소스 B는 경로별 CI와 Cucumber/Playwright, A는 pre-push preflight를 둡니다. 한편 C의 문서는 pre-commit GitHub Action 강제를 말하지만 워크플로에서 호출을 찾지 못했습니다. 외부 pre-commit.ci 앱 상태는 공개 저장소만으로 알 수 없으므로 강제를 단정할 수 없습니다.
마지막 경계는 사람입니다. 특정 오픈소스 A는 이 책임을 별도 정책으로 명시합니다.
편집 발췌 A-2: 특정 오픈소스 A,
AI_POLICY.md, L8-L23.
**You own what you submit.**Understand your code, test it, and be ready to explain why it's correct and how it interacts with the rest of the system (without re-prompting an LLM).This is no different from what we'd expect of any contribution; AI makes it easier to skip the work – please don't skip the work.**Prove it works.**Before submitting, please verify the change actually works end-to-end — don't rely on "it compiles" or "tests pass" alone.- **Frontend changes:** include a short demo (screenshot, screen recording, or GIF) of the feature working in the PR description. Ideally you demo more than just the happy path.- **Backend changes:** add tests for new behavior, and describe your test strategy in the PR description: what you tested, how you tested it, and what edge cases you considered.PRs that clearly weren't run or tested will be closed under this policy.**Disclose AI usage.**Our [PR template](.github/pull_request_template.md) includes an Agent context section — please use it (most agents will pick it up automatically).If an agent co-authored or authored your PR, say so and leave context about the tools and session.This helps reviewers calibrate.이 정책은 코드 소유자, 증명 수준, AI 사용 공개를 정합니다. AI는 데모·테스트 전략·Agent context를 남기고, PR 템플릿은 실행한 테스트만 쓰도록 하며 인간 검토를 요구합니다. 책임을 사람에게 돌려놓지만 공개만으로 이해를 보장하지는 못합니다.
AI 문서는 무오류 보장이 아니라 작업 절차와 실패 발견 경로를 정의합니다.
9. Next.js·NestJS 프로젝트에 적용하는 순서
Next.js App Router와 NestJS 모노레포라면 실제 명령과 경계부터 고정합니다.
아래 예시는 앞서 분석한 패턴을 바탕으로 재구성한 적용 예시이며, 특정 오픈소스 프로젝트의 원본은 아니다.
AGENTS.md 공통: pnpm lint && pnpm typecheck && pnpm test && pnpm build 구조: apps/web, apps/api, packages/contractsapps/web/AGENTS.md 서버 데이터는 생성 client로만 접근, DB import 금지 App Router 경계와 사용자 행동 테스트 명령 명시apps/api/AGENTS.md controller=검증, service=조정, domain=정책, repository=저장 공개 DTO 변경 시 migration·계약 테스트 필수.agents/skills/add-endpoint/SKILL.md DTO → service → generated client → 계약 테스트 절차.husky/pre-push 변경 범위 lint·typecheck·test 실행적용 순서는 다음과 같습니다.
- 루트 AGENTS.md에 모노레포 지도와 공통 명령을 적습니다.
apps/web,apps/api에 해당 영역에서만 유효한 지침을 둡니다.- lint·typecheck·test·build를 복사해 실행할 수 있는 명령으로 씁니다.
- 웹은 생성 API client만 사용하고, API는 controller→service→domain→repository 방향을 지키도록 경계를 적습니다.
- 생성 파일 직접 수정, 웹의 DB 접근, migration 없는 공개 DTO 파괴 같은 금지 패턴을 명시합니다.
- endpoint 추가, migration, 컴포넌트 리뷰처럼 반복되는 다단계 작업만 Skill로 분리합니다.
- formatter와 빠른 정적 검사는 Git Hook으로, 전체 test·build·E2E는 CI로 강제합니다.
- 분기마다 문서의 명령을 CI에서 실제 실행해 문서와 설정의 불일치를 찾습니다.
최근 반복된 수동 DTO나 잘못된 계층 접근 하나부터 문서·검사·테스트로 연결하면 충분합니다.
10. 결론: AI 코딩 문서는 연결 구조를 설계한다
좋은 AI 개발 문서의 차이는 길이가 아니라 연결 방식입니다. README는 제품, CONTRIBUTING.md는 사람의 기여, AGENTS.md는 지역 책임과 금지 경계를 맡습니다. Skill은 판단 순서를 재사용하고 Hook과 CI는 자동 규칙을 실행합니다.
결국 핵심은 긴 프롬프트가 아니라 구조·아키텍처 경계·절차·금지 규칙·검증 명령을 실행 가능한 형태로 잇는 것입니다. 문서도 충돌하거나 낡을 수 있으므로 공개 API, 보안, 라이선스, 데이터 보호와 병합의 최종 책임은 인간에게 남습니다. 좋은 문서는 인간을 없애는 설명서가 아니라 AI와 인간이 같은 근거를 보게 하는 작업 인터페이스입니다.
분석한 오픈소스와 원문 출처
본문의 A/B/C가 가리키는 실제 프로젝트와 분석 기준은 다음과 같습니다. 각 저장소의 전체 이력을 보존한 partial clone에서 기본 브랜치 커밋을 고정해 분석했습니다. 인용은 설명에 필요한 최소 범위만 사용했으며, 프로젝트 식별자만 가명으로 치환했습니다. 이 글은 각 프로젝트의 공식 문서나 공식 입장이 아닙니다.
- 특정 오픈소스 A = PostHog — 공식 저장소,
master, commitd13528e2a2c45dc770a5d8b36679021a7baf6646, 2026-08-05. Python/Django, TypeScript/React·kea, ClickHouse/PostgreSQL, Rust 서비스가 함께 있는 모노레포입니다. 라이선스는 루트 LICENSE 기준ee/밖은 MIT Expat,ee/는 별도 Enterprise License입니다. 본문 근거: 루트 지침, A-1 · 프론트 지침, 공용 table 구현, 생성 API 사용, 프론트 스크립트, pre-push Hook, A-2 · AI 정책, PR 템플릿. - 특정 오픈소스 B = Dify — 공식 저장소,
main, commit4213e6b150a17055f3bca6fe8e4a4f29670453fd, 2026-08-05. Python/Flask·Celery API, Next.js/React 웹, TypeScript 패키지, Docker와 Cucumber/Playwright E2E로 구성됩니다. 라이선스는 수정 Apache 2.0 기반 Dify Open Source License입니다. 본문 근거: 루트 지침, 기여 지침, B-1 · API 지침, Makefile, API 테스트 CI, 웹 스크립트, B-2 · 리뷰 Skill, 프론트 지침, B-3 · Claude Hook. - 특정 오픈소스 C = Roboflow Supervision — 공식 저장소,
develop, commite82349fabfa9a11b874b8add77e66a49a40c8751, 2026-08-05. Python 3.10+·NumPy 기반 컴퓨터 비전 라이브러리이며 MIT License를 사용합니다. 본문 근거: C-1 · 설계 패턴, Detections 구현, C-2 · 호환 모듈, deprecated 경고 테스트, 기여 지침, C-3 · 테스트 CI.
함께 읽을 글