Repo Context

Repo Context

이 문서에서는 RepoContext capability를 소개해요. 저장소에 축적된 코딩 어시스턴트 컨텍스트 엔지니어링(CE)을 발견하고 로드해요. 트리 전반에 흩어진 지침 파일(CLAUDE.md/AGENTS.md)과 .claude/.agents/.codex/.grok 아래의 자산(skills, sub-agents, hooks)을 다룹니다.

출처: 문서

본문

RepoContext는 저장소에 축적된 코딩 어시스턴트 컨텍스트 엔지니어링(CE)을 발견하고 로드해요. 트리 전반에 흩어진 지침 파일(CLAUDE.md/AGENTS.md)과 .claude/.agents/.codex/.grok 아래의 자산(skills, sub-agents, hooks)을 다룹니다.

소스

Pydantic AI Harness가 0.x 릴리스인 동안에는 minor 릴리스 사이에 API가 바뀔 수 있어요. 그럴 때는 deprecation 경고와 릴리스 노트 마이그레이션 안내가 (당신이나 당신의 에이전트에게) 정확히 업그레이드 방법을 알려줘요. 버전 정책을 참고하세요.

The problem

저장소는 그 안에서 일했던 모든 코딩 어시스턴트를 위해 CE를 축적해요. 트리 전반에 흩어진 지침 파일(CLAUDE.md/AGENTS.md)과 .claude/.agents/.codex/.grok 아래의 자산(skills, sub-agents, hooks)이 그것이에요. 최상위 지침 파일만 로드하는 에이전트는 조상 컨텍스트를 놓치고 나머지 설정이 존재한다는 것을 전혀 모르므로, 그것을 존중할 수도 번역할 수도 없어요.

The solution

RepoContext는 세 가지 전략을 한데 묶으며, 각각 독립적으로 토글할 수 있어요. Agentcapabilities에서 RepoContext(...)로 구성하며, 에이전트가 작업하는 가장 깊은 디렉터리에 앵커링해요:

from pathlib import Path

from pydantic_ai import Agent
from pydantic_ai_harness import RepoContext

agent = Agent(
    'anthropic:claude-sonnet-4-6',
    capabilities=[RepoContext(workspace_dir=Path('.'), home_dir=Path.home())],
)

result = agent.run_sync('Summarize the coding-assistant setup in this repo.')
print(result.output)

1. Walk-up instruction autoload (on by default)

workspace_dir에서 home_dir까지(포함)의 모든 조상에서 CLAUDE.md/AGENTS.md를 로드해요. 우선순위는 조상-먼저, 워크스페이스-마지막이에요. 가장 넓은 컨텍스트 먼저, 가장 구체적인 것 마지막. 파일은 해석된 실제 경로와 콘텐츠 해시로 중복 제거되므로, 심볼릭 링크된 AGENTS.md -> CLAUDE.md나 동일한 콘텐츠를 공유하는 두 조상이 한 번만 로드돼요.

home_dirNone(기본값)이면 workspace_dir만 스캔돼요 — walk-up 없음. home_dir=Path.home()을 전달하면 홈 디렉터리까지 올라가요.

2. Asset inventory (on by default)

inventory_agent_context()라는 하나의 도구를 노출하며, 저장소의 CE 자산이 어디에 있는지 보고해요 — .claude/.agents/.codex/.grok 루트와, 각각 안에 포함된 skills/(SKILL.md), agents/(.md), settings.json(hooks). 구조화된 AgentContextInventory를 반환해요. 자산을 찾지만 파싱하지는 않으며, 번역은 오케스트레이터의 몫으로 남겨둬요.

inventory_tool_name으로 도구 이름을 바꾸거나 asset_roots로 스캔할 루트를 범위 지정할 수 있어요.

3. Nested-on-traversal (off by default)

모델이 디렉터리를 나열하거나 읽으면 해당 디렉터리의 CLAUDE.md/AGENTS.md를 노출해요. 이 전략은 FileReadEventDirectoryListedEvent를 구독하므로, 원시 도구 인자를 조사하는 대신 정규화되고 containment 검사된 경로를 받아요. 여전히 옵트인 방식이에요:

from pathlib import Path

from pydantic_ai import Agent
from pydantic_ai_harness import FileSystem, RepoContext

agent = Agent(
    'anthropic:claude-sonnet-4-6',
    capabilities=[
        FileSystem(root_dir='.'),
        RepoContext(
            workspace_dir=Path('.'),
            nested_traversal=True,
            nested_inject='pointer',  # or 'contents'
        )
    ],
)

nested_inject='pointer'(기본값)는 파일을 가리키는 한 줄 메모를 큐에 넣고, 'contents'는 파일 본문을 큐에 넣어요. 메모는 다음 모델 요청 전에 메시지 히스토리에 도달해요. 각 디렉터리는 실행당 최대 한 번 노출돼요.

FileSystem은 이러한 이벤트를 직접 발생시켜요. 다른 파일 도구를 가진 호스트는 pydantic_ai_harness.filesystem에서 FileReadEventDirectoryListedEvent를 import해 같은 타입을 발생시킬 수 있어요. root_dir을 이벤트의 path가 상대적인 디렉터리로 설정하세요.

순회 위치는 root_dir / path이므로, workspace_dir의 하위 디렉터리에 루팅된 FileSystem도 올바른 디렉터리를 노출해요. workspace_dir 밖으로 해석되는 순회는 무시돼요. 워크스페이스에 중첩되지 않으므로 노출할 중첩 컨텍스트가 없어요.

traversal_tool_namestraversal_path_arg는 deprecate됐어요. 둘 중 하나를 기본값이 아닌 값으로 설정하면 HarnessDeprecationWarning을 발생시키고, 이벤트를 발생시키지 않는 호스트를 위해 이전 도구 이름·인자 감지 경로를 유지해요. 기본값에서는 감지가 비활성화되므로 FileSystem 이벤트가 같은 메모를 두 번 전달할 수 없어요.

Cache cost

파일 콘텐츠를 시스템 프롬프트에 주입하는 것은 프롬프트 캐시 안정성을 대가로 해요. 변경된 접두사는 캐시된 전체 영역을 재청구해요. RepoContext는 두 캐시 관련 경로를 분리해서 유지해요:

  • 전략 1은 실행 시작 시 파일을 한 번 읽고 이를 정적 시스템 지침으로 주입하므로, 캐시된 접두사가 턴 사이에 바이트 동일하게 유지돼요.
  • 전략 3은 휘발성이에요(방금 건드린 디렉터리에 의존). 그래서 메모는 시스템 프롬프트가 아니라 메시지 꼬리에 큐에 들어가며, 캐시된 접두사를 무효화할 수 없어요.

Configuration

RepoContext(
    workspace_dir,                  # Path -- the deepest dir the agent works in (required)
    home_dir=None,                  # Path | None -- shallowest dir to stop walk-up at, inclusive
    filenames=('CLAUDE.md', 'AGENTS.md'),
    autoload_instructions=True,     # Strategy 1
    expose_inventory_tool=True,     # Strategy 2
    inventory_tool_name='inventory_agent_context',
    nested_traversal=False,         # Strategy 3
    nested_inject='pointer',        # 'pointer' | 'contents'
    traversal_tool_names=frozenset({'list_directory', 'read_file'}),  # deprecated fallback
    traversal_path_arg='path',                                       # deprecated fallback
    asset_roots=('.claude', '.agents', '.codex', '.grok'),
)

Scope

RepoContext는 CE를 찾고 로드해요. skill/sub-agent frontmatter나 hook 본문을 파싱하지 않고, 자산을 다시 쓰거나 번역하지도 않아요. 전략 1은 실행당 한 번 파일을 읽으므로, 실행 중간에 그 파일을 편집해도 다시 로드되지 않아요.

Further reading

API reference

RepoContext

Bases: AbstractCapability[AgentDepsT]

저장소의 축적된 코딩 어시스턴트 컨텍스트 엔지니어링을 발견하고 로드.

세 가지 전략, 각각 독립적으로 토글 가능:

  1. Walk-up instruction autoload (autoload_instructions, 기본 켜짐): workspace_dir에서 home_dir까지의 모든 조상에서 CLAUDE.md/AGENTS.md를 로드. 중복 제거, 조상-먼저. 이것들은 실행 시작 시 한 번 읽히고 get_instructions를 통해 정적 시스템 지침으로 주입되므로 캐시 접두사에 남고 턴마다 다시 읽히지 않아요.

  2. Asset inventory (expose_inventory_tool, 기본 켜짐): 저장소의 CE 자산이 어디에 있는지 보고하는 도구(.claude/.agents/.codex/ .grok 및 그 skills/, agents/, settings.json). 자산을 찾지만 파싱하지는 않아요.

  3. Nested-on-traversal (nested_traversal, 기본 꺼짐): 모델이 파일시스템 capability 이벤트를 통해 디렉터리를 나열하거나 읽으면 그 디렉터리의 CLAUDE.md/AGENTS.md를 노출. 메모는 시스템 지침이 아니라 메시지 꼬리에 큐에 들어가므로 캐시 접두사를 무효화하지 않아요. nested_inject='pointer'(기본값)는 한 줄 포인터를 큐에 넣고, 'contents'는 파일 본문을 인라인해요.

캐시 메모: 시스템 프롬프트에 파일 콘텐츠를 주입하는 것은 프롬프트 캐시 안정성을 대가로 해요. 전략 1은 파일이 정적이라 안전하고, 휘발성 전략 3 콘텐츠는 대신 메시지 꼬리에 실려요.

from pathlib import Path

from pydantic_ai import Agent
from pydantic_ai_harness.repo_context import RepoContext

agent = Agent(
    'anthropic:claude-sonnet-4-6',
    capabilities=[RepoContext(workspace_dir=Path('.'), home_dir=Path.home())],
)

Attributes

workspace_dir

에이전트가 작업하는 가장 깊은 디렉터리. walk-up과 자산 스캔이 여기에 앵커링돼요.

Type: Path

home_dir

walk-up을 멈출 가장 얕은 디렉터리(포함). None(기본값)은 workspace_dir만 스캔 — walk-up 없음.

Type: Path | None Default: None

filenames

찾을 지침 파일 이름. 디렉터리 내 우선순위 순서.

Type: Sequence[str] Default: ('CLAUDE.md', 'AGENTS.md')

autoload_instructions

전략 1: 지침 파일을 시스템 프롬프트로 로드.

Type: bool Default: True

expose_inventory_tool

전략 2: 자산 인벤토리 도구 노출.

Type: bool Default: True

inventory_tool_name

모델에 노출된 인벤토리 도구의 이름.

Type: str Default: 'inventory_agent_context'

nested_traversal

전략 3: 모델이 해당 디렉터리를 나열하거나 읽으면 디렉터리의 지침 파일을 노출. 기본 꺼짐 — list/read 도구에 결합되기 때문.

Type: bool Default: False

nested_inject

전략 3용: 한 줄 pointer를 추가하거나 파일 contents를 인라인.

Type: Literal['pointer', 'contents'] Default: 'pointer'

traversal_tool_names

호환성 순회 감지기가 사용하는 deprecate된 도구 이름.

Type: frozenset[str] Default: _DEFAULT_TRAVERSAL_TOOL_NAMES

traversal_path_arg

호환성 순회 감지기가 사용하는 deprecate된 경로 인자.

Type: str Default: _DEFAULT_TRAVERSAL_PATH_ARG

asset_roots

인벤토리 도구가 스캔하는 루트 디렉터리. workspace_dir에 상대적.

Type: Sequence[str] Default: ('.claude', '.agents', '.codex', '.grok')

Methods

for_run

@async

def for_run(ctx: RunContext[AgentDepsT]) -> RepoContext[AgentDepsT]

고립된 순회/캐시 상태를 가진 새 실행별 인스턴스를 반환.

Returns

RepoContext[AgentDepsT]

get_instructions
def get_instructions() -> AgentInstructions[AgentDepsT] | None

정적이고 캐시 안정적인 지침: 로드된 파일에 인벤토리 힌트를 더한 것.

Returns

AgentInstructions[AgentDepsT] | None

get_toolset
def get_toolset() -> AgentToolset[AgentDepsT] | None

자산 인벤토리 툴셋, 또는 도구가 비활성화되었으면 None.

Returns

AgentToolset[AgentDepsT] | None

after_tool_execute

@async

def after_tool_execute(
    ctx: RunContext[AgentDepsT],
    *,
    call: ToolCallPart,
    tool_def: ToolDefinition,
    args: dict[str, Any],
    result: Any,
) -> Any

커스터마이즈된 레거시 순회 도구·인자 이름을 지원.

Returns

Any

get_serialization_name

@classmethod

def get_serialization_name(cls) -> str | None

agent-spec 지원용 직렬화 이름.

Returns

str | None

AgentContextInventory

Bases: BaseModel

저장소의 CE 자산이 어디에 있는지의 맵. 오케스트레이터가 읽거나 번역하기 위한 것.

AssetRoot

Bases: BaseModel

단일 루트 디렉터리(예: .claude) 아래 CE 자산이 어디에 있는지.

더 알아보기 (Learn more)