툴을 쓰는 에이전트
이 가이드는 examples/agents.ts의 codeGen 에이전트를 만들어요. 작은 툴셋 위에서 think→act→observe 루프를 직접 도는 에이전트인데, 그 툴셋 안에는 툴처럼 쓰이는 다른 에이전트도 하나 들어 있어요.
1. 필요한 툴부터 준비하기
섹션 제목: “1. 필요한 툴부터 준비하기”editFile, createFile, readFile이 이미 있다고 가정할게요. 셋 다 deps: ["repo"]를 선언하는 평범한 tool()이에요(자세한 내용은 가이드: 툴 만들기 참고).
2. 먼저 평범한 에이전트 정의하기
섹션 제목: “2. 먼저 평범한 에이전트 정의하기”import { agent, io } from "@loopyjs/core";
export const fileAnalyzer = agent({ name: "fileAnalyzer", model: "haiku", instructions: "Identify the files relevant to a goal.", input: io<{ goal: string }>(), output: io<{ paths: readonly string[] }>(), deps: ["repo"],});fileAnalyzer에는 자체 tools가 없어요. “목표가 주어지면 어떤 파일이 중요한지 판단한다”는 게 이 작고 집중된 에이전트의 유일한 일이에요. 그래도 deps: ["repo"]는 선언하는데, instructions가 리포지토리를 들여다보라고 지시할 걸로 보이기 때문이에요. 이 타입 시그니처만 보면 툴 호출이 전혀 드러나지 않지만, 실제로 그 조회를 수행하는 건 나중에 구현될 모델 루프예요.
3. 그걸 툴로 쓰는 에이전트 만들기
섹션 제목: “3. 그걸 툴로 쓰는 에이전트 만들기”export const codeGen = agent({ name: "codeGen", model: "sonnet", instructions: "Generate code changes in a think→act→observe loop.", input: io<{ task: string }>(), output: io<{ applied: readonly string[]; failed: readonly string[] }>(), // edit/create/read tools + a sub-agent passed where a tool is expected. tools: [editFile, createFile, readFile, fileAnalyzer], deps: ["repo"],});fileAnalyzer는 별도 래퍼나 어댑터 없이, 다른 진짜 툴들과 나란히 tools 배열에 그대로 들어가요. Agent와 Tool이 구조적으로 둘 다 Step이기 때문에 가능한 일이에요. 타입 시스템이 정확히 왜 이걸 허용하는지는 Step 구조에서 볼 수 있어요. 개념적으로 codeGen은 다른 툴을 부르듯 “어떤 파일이 관련 있는가?“라는 질문을 fileAnalyzer에 위임할 수 있어요. 그러면 fileAnalyzer 자신의 모델 루프가 돌면서 답을 내놓아요.
4. 추론된 타입 확인하기
섹션 제목: “4. 추론된 타입 확인하기”import type { ToolDepKeys } from "@loopyjs/core";
type CodeGenToolDeps = ToolDepKeys<typeof codeGen.tools>;// = "repo" — editFile, createFile, readFile, fileAnalyzer로부터 누적됐어요.// fileAnalyzer가 Tool이 아니라 Agent인데도 마찬가지예요.이건 examples/consumer.ts에서 실제 컴파일 어서션으로 검사돼요. ToolDepKeys<typeof codeGen.tools>는 정말로 정확히 "repo"로 해석되고, unknown도 아니고 앱에 있는 모든 의존성의 유니온도 아니에요.
5. 호출 지점에서 걸러지는 중복 이름
섹션 제목: “5. 호출 지점에서 걸러지는 중복 이름”agent({ name: "codeGen", // ... tools: [editFile, editFile], // ❌ compile error — NoDuplicateTools brands this call // ...});이름이 같은 툴 두 개는 원래대로라면 에이전트 내부의 툴 맵 안에서 조용히 충돌해요. NoDuplicateTools가 이걸 컴파일 타임 거부로 바꿔줘요.
다음 단계
섹션 제목: “다음 단계”- 결정적 워크플로우 —
codeGen을 재시도 사이클이 있는 명시적 그래프의 노드 하나로 써 보세요. - API 레퍼런스 → agent()