tool()
tool()은 모델 없이 동작하는 Step을 만들어요. agent()가 호출하는 평범하고 결정적인 능력일 수도 있고, workflow()의 노드로 단독으로 쓰일 수도 있어요.
시그니처
섹션 제목: “시그니처”export interface Tool<Name, In, Out, Deps> extends Step<Name, In, Out, Deps> { readonly "~kind": "tool"; readonly description: string; readonly run: (input: InferOut<In>, ctx: ToolCtx<Deps>) => Promise<InferOut<Out>>; /** 최소 1회(at-least-once) 지속성 계약: 툴 실행 도중 크래시가 나면 재실행되므로 멱등성이 필요해요. */ readonly idempotencyKey?: (input: InferOut<In>) => string;}
export function tool< const Name extends string, In extends IO<any, any>, Out extends IO<any, any>, const D extends readonly (keyof LoopyDeps)[] = [],>(def: { name: Name; description: string; input: In; output: Out; deps?: D; idempotencyKey?: (input: InferOut<In>) => string; run: (input: InferOut<In>, ctx: ToolCtx<D[number]>) => Promise<InferOut<Out>>;}): Tool<Name, In, Out, D[number]>;name— 문자열 리터럴이에요. 타입에 그대로 보존돼서(string으로 넓혀지지 않아요) 툴이 쓰이는 모든 곳에 이 이름 그대로 나타나요. 예를 들면agent()의ToolMap에서 키로 쓰여요.description— 툴이 하는 일을 평범한 말로 설명한 거예요. 여러분이 아니라 모델이 읽는 텍스트예요.input/output—io<...>()(또는 Standard Schema 형태의 검증기라면 무엇이든)로 만든IO<...>스키마예요.deps—LoopyDeps의 키를 문자열 리터럴로 나열한 배열이에요. 기본값은[]이고,run안에서ctx.deps가 정확히 무엇을 노출할지 결정해요.idempotencyKey— 선택 사항이에요. loopy의 지속성 모델은 최소 1회(at-least-once) 실행을 보장해요. 프로세스가 툴 호출 도중 크래시 나면 런타임이 복구 시점에 호출을 다시 내보내요. 효과가 자연히 멱등적이지 않은 툴(예: “파일 생성”, “PR 열기”)이라면idempotencyKey를 제공하세요. 런타임이 이를 구현하고 나면, 재실행된 호출을 인식해서 중복을 제거할 수 있어요.run— 툴의 본문이에요. 검증된 입력과ToolCtx<Deps>를 받아요. 평범한 툴이라면 그냥{ deps }예요 —team()이 쓰는interrupt확장은 휴먼 인 더 루프를 보세요.
import { tool, io } from "@loopyjs/core";import type { GitRepo } from "./deps";
export const editFile = tool({ name: "editFile", description: "Apply a find/replace edit to a file.", input: io<{ path: string; find: string; replace: string }>(), output: io<{ applied: boolean }>(), deps: ["repo"], idempotencyKey: (i) => `edit:${i.path}:${i.find}`, run: async (i, { deps }) => { const cur = await deps.repo.read(i.path); await deps.repo.write(i.path, cur.replace(i.find, i.replace)); return { applied: true }; },});(examples/tools.ts에서 가져왔어요)
다음 단계
섹션 제목: “다음 단계”- agent() — 에이전트의
tools배열에 이 툴을 넘겨보세요. - 가이드 → 툴 작성하기