MINARA
기여하기

도구 추가

레지스트리에 새 도구를 추가하는 방법

도구는 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.tsBUILTIN_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에 정의되어 있습니다:

등급이름사용 시점
1READ_ONLY시세 조회, 잔고 조회, 검색, read_file
2CONFIRM_ONCE분석, 리서치, 소규모 스왑
3ALWAYS_CONFIRMwrite_file, patch, 자금 이동, 문서 생성
4MANUAL_ONLY출금, 외부 주소 송금, 비상 정지

어느 등급을 선택할지 불확실하면 가장 가까운 기존 도구를 따릅니다. 자금을 이동하는 도구는 isFundMoving: truecontrolPolicy.confirm도 선언합니다. 공통 권한 게이트가 미리보기를 표시하고 핸들러 실행 전에 정확한 요청을 확인합니다.

결과 봉투

모든 핸들러는 apps/agent/src/tools/_shared/result.tsok({...}) 또는 err("...")를 통해 문자열을 반환합니다. 핸들러 내부에서 예외를 직접 던져서는 안 됩니다. 포착된 오류는 errFromThrow(e)로 변환합니다. 에이전트 루프는 이 봉투를 파싱하여 LLM에 구조화된 오류를 전달합니다.

샌드박스 기반 파일 도구

파일 시스템에 접근하는 도구는 반드시 apps/agent/src/tools/_security/sandbox.tsresolveInSandbox()를 통해 모든 경로를 처리해야 합니다. 이 규칙은 예외가 없습니다. 자세한 내용은 샌드박스 및 권한을 참고하세요.

검증하고 문서화하기

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에서 나오므로 직접 편집하지 마세요.

목차