도구 추가
레지스트리에 새 도구를 추가하는 방법
도구는 JSON-Schema 파라미터를 갖는 타입이 지정된 TypeScript 함수입니다. apps/agent/src/tools/<name>.ts에 위치하며, ToolEntry[]를 반환하는 팩토리 함수를 내보냅니다.
최소 예제
apps/agent/src/tools/my-provider.ts를 생성합니다:
import { PermissionTier, type ToolEntry } from "../core/tool-registry.js";
import { ok, err, errFromThrow } from "./_shared/result.js";
export function createMyProviderTools(): ToolEntry[] {
const apiKey = process.env.MY_PROVIDER_API_KEY;
if (!apiKey) return []; // feature-gate: registry hides missing tools
return [
{
name: "my_provider_search",
toolSet: "research",
permissionTier: PermissionTier.READ_ONLY,
isAsync: true,
description: "Search My Provider for a query",
schema: {
name: "my_provider_search",
description: "Search My Provider for a query",
parameters: {
type: "object",
properties: {
query: { type: "string", description: "The search query" },
limit: { type: "number", description: "Max results", default: 10 },
},
required: ["query"],
},
},
handler: async ({ query, limit }) => {
try {
const res = await fetch(
`https://api.myprovider.com/search?q=${encodeURIComponent(query)}&limit=${limit ?? 10}`,
{ headers: { Authorization: `Bearer ${apiKey}` } },
);
if (!res.ok) return err(`HTTP ${res.status}`);
return ok(await res.json());
} catch (e) {
return errFromThrow(e);
}
},
},
];
}가장 가까운 기능 옆에서 팩토리를 등록합니다. 배선 도메인에 속한 도구는 apps/agent/src/app/ 아래의 해당 Builder, 예를 들어 messaging.ts, institution.ts, artifacts.ts에 둡니다. 해당 Builder가 없는 기능은 apps/agent/src/app.ts의 관련 등록 옆에 둡니다.
import { createMyProviderTools } from "./tools/my-provider.js";
// ...
for (const tool of createMyProviderTools()) toolRegistry.register(tool);apps/agent/src/core/tool-registry.ts 내 BUILTIN_TOOL_SETS에 툴 세트 항목을 추가합니다:
research: {
description: "Market and social research tools",
tools: [
// ... existing
"my_provider_search",
],
},Agent가 스킬을 통해 도구를 발견해야 한다면 정확한 이름을 해당 스킬의 metadata.minara.tool_names에 추가합니다. 지연 도구는 tool_search로 발견되므로 설명은 구체적이고 충돌하지 않아야 합니다.
권한 등급
권한 등급은 apps/agent/src/core/tool-registry.ts에 정의되어 있습니다:
| 등급 | 이름 | 사용 시점 |
|---|---|---|
| 1 | READ_ONLY | 시세 조회, 잔고 조회, 검색, read_file |
| 2 | CONFIRM_ONCE | 분석, 리서치, 소규모 스왑 |
| 3 | ALWAYS_CONFIRM | write_file, patch, 자금 이동, 문서 생성 |
| 4 | MANUAL_ONLY | 출금, 외부 주소 송금, 비상 정지 |
어느 등급을 선택할지 불확실하면 가장 가까운 기존 도구를 따릅니다. 자금을 이동하는 도구는 isFundMoving: true와 controlPolicy.confirm도 선언합니다. 공통 권한 게이트가 미리보기를 표시하고 핸들러 실행 전에 정확한 요청을 확인합니다.
결과 봉투
모든 핸들러는 apps/agent/src/tools/_shared/result.ts의 ok({...}) 또는 err("...")를 통해 문자열을 반환합니다. 핸들러 내부에서 예외를 직접 던져서는 안 됩니다. 포착된 오류는 errFromThrow(e)로 변환합니다. 에이전트 루프는 이 봉투를 파싱하여 LLM에 구조화된 오류를 전달합니다.
샌드박스 기반 파일 도구
파일 시스템에 접근하는 도구는 반드시 apps/agent/src/tools/_security/sandbox.ts의 resolveInSandbox()를 통해 모든 경로를 처리해야 합니다. 이 규칙은 예외가 없습니다. 자세한 내용은 샌드박스 및 권한을 참고하세요.
검증하고 문서화하기
apps/agent/tests/unit/tools/에 집중된 테스트를 추가해 성공 결과, 공급자 오류, 자격 증명 누락, 선언한 안전 정책을 검증합니다.
pnpm --filter @minara/agent exec vitest run tests/unit/tools/my-provider.test.ts
pnpm --filter @minara/agent typecheck
pnpm --filter @minara/docs generate공개 흐름이 바뀌면 직접 작성한 문서를 네 언어로 수정합니다. 생성된 도구 참조 문서는 BUILTIN_TOOL_SETS에서 나오므로 직접 편집하지 마세요.