AI 에이전트로 CS 환불 문의 자동화하기: Agentica 활용기

seunghwa17·2025년 3월 19일
22
post-thumbnail

개요


최근 사내에서 고객 서비스(CS) 팀의 환불 문의를 자동화 하기 위해 AI 에이전트를 개발 했습니다.

이 에이전트는 저희 팀이 개발한 Agentica 라이브러리를 활용해 만들어졌으며, 현재 CS 담당자를 대신해 환불 문의를 처리하면서 업무 효율성을 크게 향상시키고 있습니다.

이 글에서는 개발 과정, 주요 코드 예시, 적용 전후 생산성 비교, 그리고 시행착오와 해결 방법을 공유하고자 합니다.


개발 배경 및 목표


CS 팀은 하루 수십 건의 환불 문의를 수동으로 처리하며 많은 시간을 소비하고 있었습니다. 환불 문의는 반복적인 질문과 단순 작업으로 이루어져 있어 자동화의 필요성이 꾸준히 제기되어 왔습니다. 이에 AI 에이전트를 통해 이를 해결할 수 있을 것으로 판단했습니다.

프로젝트의 목표는 다음과 같습니다:

  • 환불 문의 처리 시간을 80% 이상 단축
  • CS 팀이 보다 복잡한 문제 해결에 집중할 수 있도록 지원


개발 과정과 코드 예시


Agentica 라이브러리 소개

저희 팀은 Agentica라는 오픈소스 라이브러리를 개발해 공개했습니다. 이 라이브러리를 사용하면 누구나 간단히 클래스 인스턴스를 생성해 즉시 채팅 가능한 에이전트를 만들 수 있습니다. TypeScript 클래스나 Swagger 문서만 있으면 LLM이 자동으로 필요한 기능을 Function Call(Tool Call)로 호출할 수 있도록 설계되었습니다.

간단한 예시로 Gmail 기능을 지원하는 에이전트를 만들어 보겠습니다.

import { Agentica } from "@agentica/core";
import { GmailService } from "@wrtnlabs/connector-gmail";
import dotenv from "dotenv";
import OpenAI from "openai";
import typia from "typia";
 
dotenv.config();
 
const openai = new OpenAI({ apiKey: process.env.OPENAI_KEY });

class GmailService {
	sendMail(auth: OAuth2Client, to: string, from: string, subject: string, message: string) {
		const gmail = google.gmail({ version: 'v1', auth });
	  const raw = createEmail(to, from, subject, message);
	
	  try {
	    const response = await gmail.users.messages.send({
	      userId: 'me',
	      requestBody: {
	        raw,
	      },
	    });
	    console.log('이메일이 성공적으로 전송되었습니다:', response.data);
	    return response.data;
	  } catch (error) {
	    console.error('이메일 전송 중 오류 발생:', error);
	    throw error;
	  }
	}
}
 
export const GmailAgent = new Agentica({
  model: "chatgpt",
  vendor: {
    api: openai,
    model: "gpt-4o-mini",
  },
  controllers: [
    {
      name: "Gmail Connector",
      protocol: "class",
      application: typia.llm.application<GmailService, "chatgpt">(),
      execute: new GmailService({
        clientId: process.env.GMAIL_CLIENT_ID!,
        clientSecret: process.env.GMAIL_CLIENT_SECRET!,
        secret: process.env.GMAIL_REFRESH_TOKEN!,
      }),
    },
  ],
});

예시 코드를 봤을 때 상당히 간단하게 Agent 하나를 만들 수 있는 것을 보실 수 있습니다.

위와 같이 구현하게 되면 application에 정의된 함수 목록들을 LLM이 tool로 호출이 가능하고, 실제 호출은 execute로 되게 됩니다.

만약, Gmail 외에 다른 기능을 함께 쓰고 싶다면 마찬가지로 기능을 Class를 통해 구현해서 넣거나 해당 기능을 Swagger 문서로 만들어서 넣을 수도 있습니다.

import { Agentica } from "@agentica/core";
import { GmailService } from "@wrtnlabs/connector-gmail";
import dotenv from "dotenv";
import OpenAI from "openai";
import typia from "typia";
 
dotenv.config();
 
const openai = new OpenAI({ apiKey: process.env.OPENAI_KEY });

class GmailService {
	sendMail(auth: OAuth2Client, to: string, from: string, subject: string, message: string) {
		const gmail = google.gmail({ version: 'v1', auth });
	  const raw = createEmail(to, from, subject, message);
	
	  try {
	    const response = await gmail.users.messages.send({
	      userId: 'me',
	      requestBody: {
	        raw,
	      },
	    });
	    console.log('이메일이 성공적으로 전송되었습니다:', response.data);
	    return response.data;
	  } catch (error) {
	    console.error('이메일 전송 중 오류 발생:', error);
	    throw error;
	  }
	}
}

class GoogleCalenderService {
	createEvent(auth: OAuth2Client){
		const calendar = google.calendar({ version: 'v3', auth });
	
	  const event = {
	    summary: '테스트 이벤트',
	    location: '온라인',
	    description: 'Google Calendar API로 생성된 테스트 이벤트입니다.',
	    start: {
	      dateTime: '2025-03-20T10:00:00+09:00', 
	      timeZone: 'Asia/Seoul',
	    },
	    end: {
	      dateTime: '2025-03-20T11:00:00+09:00',
	      timeZone: 'Asia/Seoul',
	    },
	    attendees: [
	      { email: 'attendee@example.com' }, 
	    ],
	    reminders: {
	      useDefault: false,
	      overrides: [
	        { method: 'email', minutes: 24 * 60 }, 
	        { method: 'popup', minutes: 10 },
	      ],
	    },
	  };
	
	  try {
	    const response = await calendar.events.insert({
	      calendarId: 'primary',
	      requestBody: event,
	      sendUpdates: 'all',
	    });
	    console.log('이벤트가 성공적으로 생성되었습니다:', response.data);
	    console.log('이벤트 링크:', response.data.htmlLink);
	    return response.data;
	  } catch (error) {
	    console.error('이벤트 생성 중 오류 발생:', error);
	    throw error;
	  }
	}
}
 
export const ExampleAgent = new Agentica({
  model: "chatgpt",
  vendor: {
    api: openai,
    model: "gpt-4o-mini",
  },
  controllers: [
    {
      protocol: "http",
      name: "shopping",
      application: HttpLlm.application({
        model: "chatgpt",
        document: OpenApi.convert(
          await fetch(
            "https://shopping-be.wrtn.ai/editor/swagger.json",
          ).then(r => r.json()),
        ),
      }),
      connection: {
        host: "https://shopping-be.wrtn.ai",
        headers: {
          Authorization: "Bearer *****",
        },
      },
    },
    {
      name: "Gmail Connector",
      protocol: "class",
      application: typia.llm.application<GmailService, "chatgpt">(),
      execute: new GmailService({
        clientId: process.env.GMAIL_CLIENT_ID!,
        clientSecret: process.env.GMAIL_CLIENT_SECRET!,
        secret: process.env.GMAIL_REFRESH_TOKEN!,
      }),
    },
    {
      name: "Google Calendar Connector",
      protocol: "class",
      application: typia.llm.application<GoogleCalenderService, "chatgpt">(),
      execute: new GmailService({
        clientId: process.env.GOOGLE_CALENDAR_CLIENT_ID!,
        clientSecret: process.env.GOOGLE_CALENDAR_CLIENT_SECRET!,
        secret: process.env.GOOGLE_CALENDAR_REFRESH_TOKEN!,
      }),
    },
  ],
});

다양한 기능들을 편하게 사용하실 수 있도록 connector 라이브러리 형태로 만들어놓았으니 여기서 확인해보시고 써 보시면 좋을 것 같습니다.

Agentica에 대해 더 궁금하신 점이 있거나 자세한 사항은 Agentica Docs를 참고해 주시면 됩니다.

이제 실제 제가 환불 CS AI Agent를 어떻게 구현 했는지 살펴보겠습니다.

환불의 과정은 매우 단순합니다.
7일이내 결제 이력을 조회하고 환불이 가능한 결제 이력에 대해 환불을 진행합니다.

환불에 필요한 기능을 API로 만들고 해당 API의 Swagger 문서로 Function call이 가능한 tool의 형태로 제공했습니다. 그리고 Agentica 라이브러리를 사용해서 환불 CS AI Agent를 만들었습니다.

export function RefundCsAgent(histories: Primitive<IAgenticaPrompt[]>) {
  const openai = new OpenAI({
    apiKey: isNotNull(
      process.env.CHATGPT_API_KEY,
      "Environment variable CHATGPT_API_KEY is not set or empty. Please define it in your environment configuration",
    ),
  });
  return new Agentica({
    provider: {
      type: "chatgpt",
      api: openai,
      model: "gpt-4o-2024-11-20",
    },
    histories: histories,
    controllers: [
      {
        protocol: "http",
        name: "Refund Connector",
        connection,
        application,
      },
    ],
  });
}

const application = HttpLlm.application({
  model: "chatgpt",
  document: OpenApi.convert(
    await fetch(
      isNotNull(
        process.env.SWAGGER_URL,
        "Environment variable SWAGGER_URL is not set or empty. Please define it in your environment configuration",
      ),
      {
        cache: "no-store",
      },
    ).then((r) => r.json()),
  ),
});

const connection: IHttpConnection = {
  host: isNotNull(
    process.env.CONNECTION_HOST,
    "Environment variable CONNECTION_HOST is not set or empty. Please define it in your environment configuration",
  ),
};



시행착오와 해결 과정


개발 과정에서 LLM의 tool 호출 오류가 빈번하게 발생했습니다. 함수 구조에는 문제가 없다고 판단하여 프롬프트를 개선하려 했지만 효과가 미미했습니다. 결국 함수 구조를 단순화하고 함수 설명을 명확하게 개선하여 문제를 해결했습니다.

  • 처리 방식 개선: 3단계 처리 방식에서 2단계로 축소하여 LLM의 tool 선택 오류 가능성을 줄였습니다.

  • API 엔드포인트 및 함수명 변경: LLM 친화적인 엔드포인트 및 함수명으로 변경했습니다.

  • 함수 설명 단순화: 기존의 복잡하고 긴 설명에서 핵심만 간결하게 전달하는 방식으로 변경했습니다.


적용 전 후 생산성 비교


도입 전 CS 팀은 환불 문의로 하루에 평균 건당 30분 이상이 소요되었습니다.

사용자에게 계정 정보를 받고 수동으로 환불 조건에 부합 하는지 확인하고 실제 환불 요청까지 수동으로 진행하며, 매우 많은 시간을 소비하고 있었습니다.

환불 AI Agent 도입 후 환불 문의는 24시간 즉시 처리 되며 기존에는 영업시간에만 가능했던 환불 상담을 실시간으로 처리할 수 있게 되었습니다. 즉, 우리는 언제 어디서든 시간과 장소에 구애받지않는 환불 시스템을 구축하였다고 이야기 할 수 있습니다.

이는 약 5배 가량의 생산성 향상을 기록 했고, CS 팀은 더 많고 복잡한 문의를 처리하며 고객 상담 품질 개선에 집중할 수 있게 되었습니다.


결론 및 교훈


이번 프로젝트는 목표 했던 바를 성공적으로 달성 했습니다. 환불 문의 처리 소요 시간이 기존 대비 80% 이상 감소되었습니다.

이는 CS 팀의 업무 부담을 크게 덜어주었고 더 복잡하고 가치 있는 문제 해결에 집중할 수 있게 되었으며, 24시간 실시간 처리를 통해 고객 만족도 또한 향상되었습니다 .

Agentica 라이브러리를 활용한 빠르고 효율적인 개발은 프로젝트 기간을 단축 시켰고 기존 수동 작업 대비 5배의 생산성 향상을 기록했습니다.

이 프로젝트를 진행하며 얻은 교훈으로는 LLM의 tool 호출 성공 여부는 함수 설계와 설명의 명확성과 단순성에 따라 크게 좌우된다는 점입니다.

복잡하고 장황한 함수 구조와 긴 설명은 LLM의 잦은 오작동을 유발했습니다. 이를 단순화하며 퀄리티가 개선된 경험은 추후 AI와 상호작용하는 인터페이스를 설계할 때 큰 도움을 줄 것 같습니다.

제가 경험했던 시행착오를 다른 분들이 겪지 않도록 하고 더 효율적이고 다양한 기능을 지원하기 위해 팀 내에서 라이브러리 발전을 시키는데 많은 공을 들이고 있습니다. 앞으로 발전되는 Agentica 라이브러리를 관심 있게 지켜봐주시면 감사할 것 같습니다.

질문은 언제나 환영입니다. 긴 글 읽어주셔서 감사합니다!

1개의 댓글

comment-user-thumbnail
2025년 3월 20일

좋은 정보 감사합니다!

답글 달기