에이전트 가이드
이 가이드에서는 문서 버킷(bucket)과 커스텀 툴(tool)을 기반으로 질문에 답하는 에이전트(agent)를 만드는 방법을 설명합니다. 가이드를 마치면 문서를 검색하고 툴을 호출하며, 관찰할 수 있는 이벤트(event)를 발생시키는 TypeScript 에이전트를 완성할 수 있습니다.
사전 준비 사항
섹션 제목: “사전 준비 사항”- Node.js 18 이상
- Schift 워크스페이스(workspace) API 키(API key) (
sch_...) - 워크스페이스에 구성된 API origin
- Schift CLI 설치 (버킷(bucket) 생성 및 데이터 채우기에만 필요)
참고: 아직 버킷(bucket)을 만들고 검색이 정상 작동하는지 확인하지 않았다면 먼저 퀵스타트를 따라 하세요. 에이전트를 추가하기 전에 검색 경로가 올바른지 확인하면 디버깅이 훨씬 수월해집니다.
1단계: SDK 설치
섹션 제목: “1단계: SDK 설치”npm install @schift-io/sdk2단계: 지식 버킷 준비
섹션 제목: “2단계: 지식 버킷 준비”버킷(bucket)을 생성하고 최소한 하나의 문서(document)를 업로드합니다:
export SCHIFT_API_KEY=sch_...export SCHIFT_API_URL=https://api.example.com/v1
schift db create support-docsschift upload ./handbook.pdf --bucket support-docsschift search "How do I reset my password?" --bucket support-docs --top-k 5검색 결과가 관련 있는 청크(chunk)를 반환하는지 확인하세요. 검색이 정상 작동하면 같은 버킷(bucket)을 에이전트(agent)에 연결할 수 있습니다.
3단계: 에이전트 생성
섹션 제목: “3단계: 에이전트 생성”agent.ts 파일을 생성합니다:
import { Schift, Agent, RAG } from "@schift-io/sdk";
const schift = new Schift({ apiKey: process.env.SCHIFT_API_KEY,});
const rag = new RAG({ bucket: "support-docs" }, schift.transport);
const agent = new Agent({ name: "Support Bot", instructions: "You are a support assistant. Answer questions using the knowledge base. " + "If the answer is not in the documents, say so clearly.", rag, model: "gpt-4o-mini", transport: schift.transport, maxSteps: 10,});RAG 인스턴스는 자동으로 rag_search라는 이름의 툴(tool)로 등록되므로, 질문에 문서 검색이 필요할 때 에이전트(agent)가 버킷(bucket)을 검색할 수 있습니다.
4단계: 에이전트 실행
섹션 제목: “4단계: 에이전트 실행”const result = await agent.run("How do I reset my password?");
console.log(result.output);console.log(`Completed in ${result.totalDurationMs}ms`);console.log(`Steps: ${result.steps.length}`);result.steps의 각 스텝(step)은 think, tool_call, tool_result, final_answer 같은 타입(type)을 가집니다. 스텝(step)을 살펴 보는 것이 에이전트(agent)가 특정 답변을 낸 이유를 파악하는 가장 빠른 방법입니다.
5단계: 커스텀 툴 추가
섹션 제목: “5단계: 커스텀 툴 추가”에이전트(agent)가 직접 만든 API를 호출할 수 있을 때 더 유용해집니다. 날씨 툴(tool)을 추가해 보겠습니다:
import type { AgentTool } from "@schift-io/sdk";
const getWeather: AgentTool = { name: "get_weather", description: "Get the current weather for a city", parameters: { type: "object", properties: { city: { type: "string", description: "City name, for example Seoul", }, }, required: ["city"], }, handler: async (args) => { const city = String(args.city); const temperature = await fetchWeatherAPI(city); // your implementation return { success: true, data: { city, temperature } }; },};
const agent = new Agent({ name: "Support Bot", instructions: "Answer support questions and report weather when asked.", rag, tools: [getWeather], transport: schift.transport,});툴(tool) 이름은 하나의 에이전트(agent) 안에서 고유해야 하며, snake_case를 사용하고 /^[a-zA-Z_][a-zA-Z0-9_]*$/ 패턴과 일치해야 합니다.
6단계: 이벤트 관찰
섹션 제목: “6단계: 이벤트 관찰”이벤트(event)를 구독하면 진행 상황을 표시하거나 실행 로그를 남길 수 있습니다:
agent.on("tool_call", (event) => { console.log(`Calling tool: ${event.toolName}`);});
agent.on("tool_result", (event) => { console.log(`Tool result:`, event.result);});
agent.on("agent_end", (event) => { console.log(`Run finished in ${event.totalDurationMs}ms`);});
const result = await agent.run("What is the weather in Seoul?");반환된 정리(cleanup) 함수는 더 이상 리스너가 필요 없을 때 구독을 해제합니다:
const unsub = agent.on("tool_call", handler);unsub();7단계: 오류 처리
섹션 제목: “7단계: 오류 처리”에이전트(agent) 수준의 오류를 처리하려면 실행을 try/catch로 감싸세요:
import { AgentError, MaxStepsError } from "@schift-io/sdk";
try { const result = await agent.run("A very complex question"); console.log(result.output);} catch (err) { if (err instanceof MaxStepsError) { console.log("The agent used too many steps. Try a simpler question or increase maxSteps."); } else if (err instanceof AgentError) { console.log(`Agent error: ${err.message}`); }}에이전트(agent)가 maxSteps에 도달하면 agent.run()은 정상적으로 반환되고, 마지막 스텝(step)의 타입(type)은 error가 됩니다. result.steps를 확인하면 루프가 어디서 끝났는지 알 수 있습니다.
다음 단계
섹션 제목: “다음 단계”- 최신 정보가 필요한 질문에는 웹 검색을 추가해 보세요.
- ReAct 루프와 설정 옵션에 대해 더 깊이 이해하려면 에이전트 개념을 읽어 보세요.
- 에이전트(agent)의 기능을 확장하려면 툴과 스킬을 살펴 보세요.
- 프로덕션 환경에 적합한 패턴은 오류 처리를 참고하세요.