Harness Tools

Harness Tools

Harness에는 세 가지 tool 표면이 있어요:

  • 기본 harness 런타임이 노출하는 내장 tools(파일 읽기, 편집, 셸 명령, 웹 검색 등).
  • tools 설정으로 HarnessAgent 에 전달하는 AI SDK tools.
  • harness 어댑터의 mcpServers 설정으로 구성된 외부 MCP tools.

이 페이지는 harness 특화 동작을 다룹니다. 일반 AI SDK tool 개념, 스키마, tool 결과, tool() 사용법은 Tools 를 보세요.

출처: 문서

본문

내장 Tool (Built-in Tools)

각 어댑터는 런타임이 네이티브하게 호출할 수 있는 내장 tools를 선언해요. HarnessAgent 는 그 내장 기능들을 여러분의 호스트 정의 tools와 병합하고 agent.tools 를 통해 결합된 tool 세트를 노출해요.

const agent = new HarnessAgent({
  harness: claudeCode,
});

agent.tools.bash;
agent.tools.read;
agent.tools.write;

내장 호출은 애플리케이션 프로세스가 아니라 harness 런타임이 실행해요. 런타임이 이미 호출을 수행한 경우 스트림 파트는 providerExecuted: true 를 사용해요.

어댑터는 가능하면 공통 이름을 사용해요:

  • read
  • write
  • edit
  • bash
  • grep
  • glob
  • webSearch

일부 런타임은 공통 크로스-harness 이름이 없는 네이티브 tools도 노출해요. 그것들은 네이티브 이름으로 나타나요.

호스트 실행 Tool (Host-Executed Tools)

ToolLoopAgent 에서와 같은 방식으로 HarnessAgent 에 AI SDK tools를 전달하세요:

import { HarnessAgent } from '@ai-sdk/harness/agent';
import { claudeCode } from '@ai-sdk/harness-claude-code';
import { tool } from 'ai';
import { z } from 'zod';

const weather = tool({
  description: 'Get the current temperature for a city.',
  inputSchema: z.object({
    city: z.string(),
  }),
  execute: async ({ city }) => {
    const temperatures: Record<string, number> = {
      Paris: 12,
      Tokyo: 18,
      Reykjavik: 3,
    };

    return { city, celsius: temperatures[city] ?? 20 };
  },
});

const agent = new HarnessAgent({
  harness: claudeCode,
  tools: { weather },
});

harness가 weather 를 호출하면 HarnessAgent 는 호스트 프로세스에서 tool을 실행한 다음 결과를 harness 런타임에 제출해요.

호스트 실행 tools는 contextSchema 를 선언하고 toolsContext 를 통해 턴 범위 컨텍스트를 받을 수 있어요:

const lookupAccount = tool({
  inputSchema: z.object({}),
  contextSchema: z.object({ userId: z.string() }),
  execute: async (_, { context }) => {
    return loadAccount(context.userId);
  },
});

const agent = new HarnessAgent({
  harness: claudeCode,
  tools: { lookupAccount },
  toolsContext: {
    lookupAccount: { userId: 'user-123' },
  },
});

값이 커스텀 호출 옵션에 의존할 때 prepareCall 을 사용해 toolsContext 를 교체하세요. toolsContext 의 타입은 tool 세트를 따릅니다. 어떤 tool도 context 스키마를 선언하지 않으면 거부되고, tool이 context 객체를 요구하면 필수이며, 모든 context 객체가 선택적이면 선택적이에요. HarnessAgent 는 실행 전에 각 항목을 tool의 contextSchema 에 대해 검증하고 설정된 맵을 단계 결과 및 수명 주기 콜백에 노출해요.

tool 컨텍스트는 호스트 전용으로 유지되며 일시 중단된 턴 상태로 직렬화되지 않아요. 미완료 턴을 위해 세션을 다시 만들 때 명시적으로 다시 바인딩하세요:

const session = await agent.createSession({
  sessionId,
  continueFrom,
  sandboxSession,
  toolsContext: {
    lookupAccount: { userId: 'user-123' },
  },
});

누락되거나 유효하지 않은 컨텍스트는 호스트 tool이 실행되기 전에 검증을 실패해요. harness 런타임에 반환된 검증 오류는 의도적으로 일반적이며, 호스트 전용 컨텍스트 값과 스키마 세부사항이 모델에 공개되지 않도록 해요.

클라이언트 측 Tool (Client-Side Tools)

브라우저, 사용자 상호작용, 다른 외부 프로세스가 tool 결과를 제공할 때는 execute 를 생략하세요:

const weather = tool({
  description: 'Get the current temperature for a city.',
  inputSchema: z.object({ city: z.string() }),
});

harness가 execute 없는 tool을 호출하면 반환된 결과 조각은 tool 호출 단계 후 끝나고 기본 턴은 결과를 기다려요. session.hasUnfinishedTurn() 은 true 로 유지되고, session.suspendTurn() 은 보류 중인 tool 호출을 직렬화 가능한 연속 상태에 포함해요.

UI 흐름에서 addToolOutput 이후 생성된 모델 메시지를 다음 stream() 또는 generate() 호출에 전달하세요. HarnessAgent 는 끝의 tool 결과를 추출하고 일시 중단된 턴을 자동으로 계속해요.

직접 에이전트 호출의 경우 원시 결과를 continueStream() 또는 continueGenerate() 에 제공하세요:

const continued = await agent.continueStream({
  session,
  toolResultContinuations: [
    {
      toolCallId,
      output: { city: 'Paris', celsius: 12 },
    },
  ],
});

외부 tool이 실패하면 isError: true 를 설정하세요. 다른 프로세스에서 계속하려면 suspendTurn() 을 호출하고 continueFrom 으로 세션을 다시 만든 다음 결과를 continueStream() 또는 continueGenerate() 에 전달하세요.

Tool 필터링 (Tool Filtering)

HarnessAgent 에서 activeTools 또는 inactiveTools 를 사용해 harness가 호출할 수 있는 tools를 제어하세요. 두 설정 모두 결합된 tool 세트(harness 어댑터가 선언한 내장 tools와 tools 로 전달한 AI SDK tools)의 tool 이름을 받아요.

activeTools 는 허용 목록이에요:

const agent = new HarnessAgent({
  harness: claudeCode,
  tools: { weather },
  activeTools: ['weather'],
});

inactiveTools 는 거부 목록이에요:

const agent = new HarnessAgent({
  harness: claudeCode,
  tools: { weather },
  inactiveTools: ['bash', 'write'],
});

activeTools 또는 inactiveTools 중 하나만 전달하세요. 둘 다가 아니에요. TypeScript 설정 타입은 결합을 방지하며, HarnessAgent 는 둘 다 지정되면 런타임에도 throw해요.

호스트 실행 tools의 경우 비활성 tools는 기본 harness 런타임에 전달되지 않아요. 런타임이 여전히 호출하려 하면 HarnessAgent 는 실행 거부된 tool 결과를 반환해요.

내장 tools의 경우 지원은 harness 어댑터에 달려 있어요. 일부 어댑터는 내장 기능을 네이티브하게 필터링할 수 있어요. 다른 것들은 승인 요청이나 응답 스트림 파트를 내보내지 않고 비활성 내장 호출을 실행 전에 거부함으로써 내장 tool 승인 메커니즘을 통해 필터링을 강제해요. 두 메커니즘 모두 지원하지 않는 어댑터는 내장 tools를 필터링하면 throw해요.

Tool 실행에서의 Sandbox (Sandbox in Tool Execution)

호스트 실행 tools는 다른 곳에서 AI SDK tools가 사용하는 것과 동일한 experimental_sandbox 실행 옵션을 통해 세션 sandbox를 받아요. 값은 제한된 sandbox 세션이므로 tools는 네트워크 sandbox를 중지하거나 네트워크 정책을 바꾸지 않고 읽고, 쓰고, 명령을 실행할 수 있어요.

const inspectFile = tool({
  description: 'Read a file from the harness workspace.',
  inputSchema: z.object({
    path: z.string(),
  }),
  execute: async ({ path }, { experimental_sandbox }) => {
    return {
      content: await experimental_sandbox?.readTextFile({ path }),
    };
  },
});

Tool 승인 (Tool Approvals)

Harness는 내장 tool 권한과 호스트 실행 tool 승인을 구분해요.

어댑터 네이티브 내장 기능에는 permissionMode 를 사용하세요:

const agent = new HarnessAgent({
  harness: pi,
  permissionMode: 'allow-edits',
});

사용 가능한 값:

  • allow-all: 내장 읽기, 편집, 셸 명령 허용. 기본값.
  • allow-edits: 읽기와 편집 허용, 하지만 어댑터가 내장 승인을 지원하면 셸 명령에 승인 요청.
  • allow-reads: 읽기 허용, 하지만 어댑터가 내장 승인을 지원하면 편집과 셸 명령에 승인 요청.

호스트 실행 tools에는 toolApproval 을 사용하세요:

const agent = new HarnessAgent({
  harness: claudeCode,
  tools: { weather },
  toolApproval: {
    weather: 'user-approval',
  },
});

toolApproval 은 AI SDK tool 승인 상태 객체와 동일한 상태 값을 받아요: not-applicable, approved, user-approval, denied.

승인이 필요하면 스트림은 tool-approval-request 후에 일시 중지돼요. tool 승인 응답 메시지를 보내 같은 세션을 계속하세요. UI 흐름에서 useChat 는 승인 결과를 추가할 때 그 메시지를 대신 보내요. 직접 에이전트 코드에서 승인 응답을 다음 stream() 또는 generate() 호출의 messages 로 전달하세요.

내장 승인 지원 (Built-in Approval Support)

대부분의 어댑터는 내장 tool 호출을 승인을 위해 일시 중지할 수 있어요. 지원하지 않는 어댑터는 지원되지 않는 tool 승인 모드가 지정되면 오류를 내요.

호스트 실행 tool 승인은 HarnessAgent 가 처리하므로 어댑터 전반에서 동작해요.

파일 변경과 압축 (File Changes and Compaction)

일부 harness 이벤트는 일반 tool 호출이 아니에요. UI 호환을 위해 HarnessAgent 는 이것들을 동적 프로바이더 실행 tool 파트로 투영해요:

  • fileChange: 불투명한 워크스페이스 파일 변형에 대해 내보내짐.
  • compaction: 런타임이 컨텍스트를 압축할 때 내보내짐.

tool 파트가 여러분의 타입화된 tool 세트에 속한다고 가정하기 전에 part.dynamic 을 확인하세요.

더 알아보기 (Learn more)

전체 사이트맵