CodeGym /행동 /ChatGPT Apps /다단계 프로세스: 모델에 의한 자동 오케스트레이션과 루프 제어

다단계 프로세스: 모델에 의한 자동 오케스트레이션과 루프 제어

ChatGPT Apps
레벨 12 , 레슨 3
사용 가능

1. 다단계 run이란 무엇이며 “단발성” 요청과 무엇이 다른가

ChatGPT App과 MCP tools만 사용할 때의 익숙한 그림은 꽤 선형적이었습니다: 사용자 요청이 들어옴 → GPT가 하나 이상의 도구 호출을 결정 → 사용자가 답변을 받음. 도구 내부에서 조금 더 복잡한 일을 하더라도, 이는 여전히 “하나의 논리적 단계”로 볼 수 있습니다.

에이전트의 run목표 + 일련의 단계입니다. 더는 “하나의 프롬프트 — 하나의 답변” 관점이 아니라, 에이전트가 처음부터 끝까지 이끄는 미니 프로젝트로 과제를 바라봅니다.

차이를 다음처럼 생각해 볼 수 있습니다:

상호작용 유형 모델이 하는 일 로직이 있는 곳
ChatGPT App에서의 일반적인 도구 호출 도구를 호출할지 판단하고, 인자를 채워 넣으며, 결과를 바탕으로 응답을 생성 주요 비즈니스 로직과 단계의 순서는 하나의 도구 또는 backend에 존재
에이전트 run (Agents SDK) 여러 단계를 계획하고, 언제 어떤 tool을 호출할지 결정하며, 중간 결과를 분석하고 필요하면 계획을 재검토 “목표에 도달하는 방법” 로직은 일부는 에이전트의 system 지시문에, 일부는 모델의 내부 추론에 의해 형성

여기서 중요한 점: 계획을 전부 모델에게 맡길 필요는 없다는 것입니다. 보통은 하이브리드로 갑니다. 예를 들어 큰 시나리오 단계를 코드로 단단히 고정(“먼저 요구사항 수집, 다음 선물 후보 탐색, 그다음 카드 준비”)하고, 각 단계 내부에서는 에이전트가 자신의 도구를 비교적 자유롭게 쓰도록 하는 식입니다.

작은 비유

단발성 도구 호출은 이렇게 부를 수 있습니다: “택배 기사를 불러 한 문서를 픽업해 사무실로 가져오게 한다”.

다단계 에이전트 run은 개인 비서와 같습니다: “동료의 생일 선물을 준비해줘. 그 사람이 무엇을 좋아하는지 알아보고, 몇 가지 옵션을 고르고, 배송 가능 여부를 확인한 뒤, 보기 좋은 프레젠테이션으로 정리해줘.” 비서는 그 과정에서 어떤 행동을 할지 스스로 결정합니다.

이 강의의 뒤에서, 이런 다단계 run들이 어떻게 기존에 익숙한 Apps SDK → MCP → backend 스택에 녹아들어, ChatGPT와 위젯 입장에서는 깔끔한 MCP 도구처럼 보이게 되는지 또한 살펴보겠습니다.

2. 모델이 스스로 단계를 계획하는 방식: 개략적 관점

Agents SDK 용어로 말하면, 각 run은 다음의 삼중항으로 보는 것이 편합니다:

  1. Goal(목표): 에이전트의 system/user 지시문에 들어가는 과제의 텍스트 설명.
  2. Tools: 좋은 설명과 JSON Schema를 갖춘 사용 가능한 도구 집합.
  3. State: 단계 기록과, 외부(DB, Redis 등)에 저장하는 구조화된 상태.

그다음 익숙한 run 사이클이 작동합니다. 모델은 목표와 사용 가능한 도구를 보고 매 단계마다 다음을 결정합니다:

  • “지금 정보가 충분하니 — 사용자에게 최종 결과를 내보내도 된다”;
  • 혹은 “도구 X를 이러한 인자와 함께 호출해야 한다”;
  • 혹은 “도구의 결과를 받았으니, 이를 해석/필터링하고, 필요하면 다른 도구를 호출해야 한다”.

의사코드 수준에서는 다음과 같습니다(이는 멘탈 모델일 뿐 실제 API가 아닙니다):

while (!done && steps < MAX_STEPS) {
  const modelResponse = await callModel({
    system: agentPolicy,
    messages: history,
    tools,
  });

  if (modelResponse.type === "tool_call") {
    const toolResult = await callTool(modelResponse.toolName, modelResponse.args);
    history.push({ role: "tool", content: toolResult });
  } else {
    // 최종 응답
    done = true;
    return modelResponse.content;
  }

  steps++;
}

실제 Agents SDK에서는 이 전체 사이클이 이미 라이브러리 내부에 구현되어 “숨겨져” 있습니다. 여러분은 에이전트를 선언적으로 기술하고, SDK가 모델과 도구를 반복 실행하여 최종 응답을 얻거나 단계/시간 제한에 도달할 때까지 돌립니다.

아키텍트의 과제는 다음과 같습니다:

  • 모델이 합리적인 단계를 계획하도록 goal과 system 지시문을 작성하기;
  • 의미가 겹치지 않도록 도구 집합 구성하기;
  • 단계/시간 제한 설정하기;
  • 어떤 단계들이 병렬 가능할지 고민하기.

목표, 도구, 상태에 대한 관점이 생겼다면, 다음 질문은 그 목표로 어떤 단계들로 나아갈 것인가입니다. 모든 단계가 동일하지는 않습니다. 어떤 것은 엄격히 순차적이고, 어떤 것은 병렬화할 수 있습니다.

3. 순차 단계와 병렬 단계

이제 run 사이클의 기본을 이해했으니, 그 과정 안의 단계들이 어떤 유형이 있는지 살펴보는 것이 중요합니다. 에이전트 workflow에는 크게 두 종류가 있습니다: 순차와 병렬.

순차 단계

단계 A의 결과가 단계 B에 반드시 필요한 경우입니다. 예를 들어 우리의 학습용 GiftGenius에서는:

  1. 먼저 선물의 수신자가 누구인지 파악합니다: 동료인지 가족인지, 나이, 관심사 등.
  2. 그다음 tool search_gifts로 후보를 모읍니다.
  3. 이후 예산과 제약에 맞게 필터링합니다.
  4. 그다음 위젯에 쓸 카드들을 보기 좋게 구성합니다.
  5. 그리고 마지막으로 필요하면 checkout으로의 전환을 제안합니다.

각 다음 단계가 이전 단계의 데이터에 의존하므로, 실행은 엄격히 순차적입니다.

에이전트의 행동을 의사코드로 표현하면 모델의 “내부 계획”은 다음과 같을 수 있습니다:

1. 사용자에게 수신자와 예산을 질문한다
2. tool search_gifts(profile, budget) 호출
3. tool filter_by_constraints(gifts, constraints) 호출
4. 최종 목록과 설명을 생성

모델이 이런 목록을 코드로 직접 작성하는 것은 아니지만, 우리는 system 지시문, 대화 예시, 도구 설명을 통해 모델을 이와 같은 구조로 유도할 수 있습니다.

병렬 단계

때로는 단계를 독립적으로 수행할 수 있습니다. 예를 들어, 세 개의 상점에서 선물 제안을 동시에 비교하고 싶을 때:

  • search_gifts_amazon
  • search_gifts_etsy
  • search_gifts_local_store

에이전트의 관점에서 이는 서로 독립적인 도구 호출 세 개이며, 전체 응답 시간을 줄이기 위해 병렬로 실행할 수 있습니다.

Agents SDK(및 최신 에이전트 프레임워크 전반)에는, 모델이 한 단계에서 여러 호출을 제안하는 경우 도구의 병렬 호출을 지원하는 기능이 종종 내장되어 있습니다. 전형적인 시나리오: 모델이 응답에서 호출 목록을 기술하면, SDK가 그것들을 경쟁적으로 호출하고 결과를 수집한 뒤, 다음 단계 모델에게 하나의 tool 메시지 묶음으로 제공하는 방식입니다.

계획 관점에서는 대략 이렇게 보입니다:

// 에이전트 단계: 모델이 세 개의 도구 호출을 결정
const calls = [
  { name: "search_gifts_amazon", args: {...} },
  { name: "search_gifts_etsy", args: {...} },
  { name: "search_gifts_local_store", args: {...} },
];

const results = await Promise.all(
  calls.map(c => callTool(c.name, c.args))
);

// 이후 모든 결과를 다음 단계 모델 앞에 놓일 컨텍스트에 추가

JS/TS로 프런트엔드를 작성해 본 분이라면 이미 병렬 요청 개념에 익숙할 것입니다. 예를 들어 Promise.all로 여러 fetch()를 동시에 실행할 때 말이죠. 이제 동일한 아이디어가 에이전트의 run 사이클 내부에도 등장합니다. 다만 무엇을 병렬로 수행할 수 있는지의 결정은 상당 부분 모델이 내립니다.

4. GiftGenius를 위한 workflow 예시: 단계, 목표, 도구

순차 단계에서 GiftGenius의 행동을 이미 직관적으로 단계로 나눴습니다. 이제 같은 다단계 시나리오를 에이전트 workflow로 형식화해 봅시다. 목표와 단계를 기술하고, 이를 도구와 에이전트 구성에 연결합니다. 아직 특정 Agents SDK API에 묶지 않고, 구조를 설명하며 약간의 가상 TypeScript 코드를 곁들이겠습니다.

목표(goal)

목표를 다음과 같이 정의합시다:

구체적인 수신자를 위한 3–5개의 선물 옵션을, 예산·이벤트·배송 제약을 고려해 추천하고, GiftGenius 위젯을 위한 구조화된 선물 카드 목록을 제공한다.

주요 단계

최소 4단계를 다음처럼 기술합니다:

  1. 수신자 컨텍스트 구체화
    목표: 선물을 받는 사람이 누구인지(나이, 성별, 관심사, 증정자와의 관계), 예산, 이벤트 날짜 등의 정보를 모읍니다.
    도구: 도구 없이 모델 ↔ 사용자 대화만으로도 가능.
  2. 선물 탐색 및 1차 선별
    목표: “원시” 선물 후보군을 확보합니다.
    도구: search_gifts(profile, budget) — 우리 카탈로그/검색 시스템을 조회해 후보 목록을 반환하는 tool.
  3. 필터링과 정렬
    목표: 부적합한 항목(배송 불가 지역, 예산 초과, 맞지 않는 제약)을 제거하고, 관련도에 따라 정렬합니다.
    도구: filter_and_score_gifts(candidates, constraints) — 순수하고, 멱등(idempotent)적인 도구.
  4. 위젯용 결과 포맷팅
    목표: UI에 편한 형식으로 데이터를 정리: 제목, 짧은 설명, 이미지, 가격, CTA 등.
    도구: format_gift_cards(gifts) — 구조 생성(코드형) 또는 미적 텍스트 생성(LLM형) 도구가 될 수 있음.

에이전트 구성에서의 모습

가상의 에이전트 생성기가 있다고 가정해 봅시다(의사코드):

import { createAgent } from "@acme/agents-sdk";
import { tools } from "./gift-tools";

export const giftAgent = createAgent({
  name: "gift-guru",
  system: `
    너는 GiftGenius 에이전트로서 선물 고르기를 돕는다.
    목표: 수신자 프로필, 예산, 배송 제약을 고려해 실제로 구매 가능한
    3–5개의 옵션을 제안한다.
    먼저 중요한 세부정보를 확인한 뒤, 검색과 필터링 도구를 사용하라.
    예산이나 핵심 관심사를 아직 모른다면 도구를 호출하지 마라.
    선물 카드의 명확한 목록을 갖추면 작업을 종료하라.
  `,
  tools, // 여기에는 search_gifts, filter_and_score_gifts, format_gift_cards 가 포함됩니다
  maxSteps: 12,
  timeoutMs: 15000,
});

몇 가지 포인트를 눈여겨보세요:

  • system 지시문에서 에이전트가 먼저 세부정보를 묻고 이후에 검색 도구를 사용하라고 명시했습니다. 이렇게 하면 모델이 컨텍스트가 너무 모호한 상태에서 도구를 성급히 호출하는 위험이 줄어듭니다.
  • maxSteps를 제한해 에이전트가 무한 루프에 빠지지 않도록 했습니다.
  • timeoutMs는 전체 run이 사용자의 반영구적인 대기 시간이 되지 않도록 하기 위한 값입니다.

5. 모델 자동 오케스트레이션: 무엇을 모델에 맡기고 무엇을 엄격히 고정할 것인가

에이전트는 모델의 자유와 여러분이 설계한 엄격한 구조 사이의 균형입니다.

경계를 전혀 주지 않고 모델에게 너무 많은 자유를 주면 “창의적 혼란”을 얻게 됩니다. 불필요한 tool 호출, 반복 단계, 눈에 띄지 않는 루프가 생깁니다. 반대로 모든 것을 backend의 유한 상태 기계처럼 하드코딩하면, 모델은 똑똑한 실행자라기보다 텍스트 데코레이터로 전락합니다.

보통 모델에게 맡기는 것

GiftGenius 및 유사 시나리오에서 모델에게 맡기기 합리적인 일은 다음과 같습니다:

  • 사용자 질문의 문구화(관심사를 어떻게 묻을지, 예산을 어떻게 정중히 물을지);
  • 언제 정보가 충분해져서 검색을 시작할지 결정;
  • 하나의 단계 내에서 어떤 도구를 사용할지 선택(예: 상점 검색 도구가 여럿이라면 그중 무엇을 쓸지);
  • 설명/비교/해설 등의 텍스트 생성.

엄격히 고정하는 것이 좋은 것

다음은 사전에 고정해 두는 편이 좋습니다:

  • 큰 시나리오 단계(“정보 수집” → “검색” → “필터링” → “포맷팅” → “완료”);
  • 단계와 시간 제한;
  • 에이전트가 반드시 “중단”하고 과제가 불가함을 정직하게 알려야 하는 조건(예: 예산이 5달러인데 내일 배송해야 하는 고가 전자기기를 원하는 경우);
  • 도구의 멱등성 정책과 재시도 전략.

하이브리드 예: 단계는 상태로, 세부는 모델에

에이전트의 state에 phase 필드를 두어 "collect_profile" | "search" | "filter" | "format" | "done" 값을 갖게 할 수 있습니다. 그러면 backend(또는 사용자 정의 상태 기계를 지원하는 Agents SDK 자체)가 현재 단계에서 어떤 도구가 사용 가능한지 제어할 수 있습니다.

의사코드:

type Phase = "collect_profile" | "search" | "filter" | "format" | "done";

interface GiftAgentState {
  phase: Phase;
  profile?: UserProfile;
  candidates?: GiftCandidate[];
  finalGifts?: GiftCard[];
}

에이전트의 system 지시문에 각 단계를 간략히 설명하게 하고, 코드에서는 현재 단계에 따라 모델에 노출할 도구 목록을 제한하세요. 이것이 tool gating의 예이며, 자세한 내용은 workflow 모듈에서 더 다룹니다.

6. 무한 루프와 무의미한 반복 제어

에이전트의 run 사이클을 방치하면, 마감 앞둔 학생처럼 무한히 “수정/다듬기”만 하며 제출을 미루기 시작합니다. 우리의 과제는 그가 멈추지 못하고 매달리지 않도록 하는 것입니다.

무한 루프의 전형적 원인은 세 가지입니다:

  1. 모델이 답에 확신이 없어, 의미 없는 미세 수정과 함께 동일한 도구 요청을 계속 재포뮬레이션한다.
  2. 도구가 일관되게 오류 또는 빈 결과를 반환하는데, 에이전트가 고집스럽게 “다시 시도”한다.
  3. 에이전트가 두 도구 사이에서 오가며 한 번은 이것, 한 번은 저것을 호출하되, 최종 답으로 전진하지 못한다.

단계 제한(maxSteps)

가장 간단하고 필수적인 장치가 단계 수 제한입니다. 대부분의 Agents SDK 구현에서 maxStepsrun 시작 시 또는 에이전트 구성에서 지정할 수 있습니다. 한계에 도달하면, SDK는 run을 특수 상태(예: aborted_by_max_steps)로 종료합니다. 이후 이를 사용자에게 어떻게 보여줄지는 여러분의 몫입니다.

GiftGenius에서는 합리적인 선물 추천이 대략 10단계 내에 들어온다고 볼 수 있습니다(몇 번의 확인, 몇 번의 검색, 필터링, 포맷팅). 여유를 두고 12–15단계를 설정하고, 한계 도달 시를 세심히 처리합시다:

const run = await giftAgent.run({
  input: userGoal,
  maxSteps: 12, // 기본값을 덮어씀
});

if (run.status === "max_steps_exceeded") {
  // 사용자에게 솔직한 메시지를 표시
}

시간 제한(timeout)

문제가 단계 수가 아니라 총 소요 시간인 경우도 있습니다. 도구가 느릴 수 있고, 네트워크가 불안정할 수 있습니다. 따라서 timeoutMs를 개별 tool 호출 레벨과 전체 run 레벨에서 지정하는 것이 유용합니다.

예를 들면 다음처럼 정할 수 있습니다:

  • 외부 API 호출(파트너의 선물 검색)은 3–5초를 넘기지 않도록 한다;
  • 전체 선물 추천 run은 15초 내에 완료되도록 한다.

timeout이 발동되면, run을 정돈되게 종료하고, 일부 결과만 먼저 보여주며 “일부 소스가 제시간에 응답하지 않았다”는 정직한 설명을 덧붙일 수 있습니다.

반복 감지

한 단계 더 고급(하지만 유용한) 패턴은 동일한 인자로 반복되는 도구 호출을 감지하는 것입니다. 에이전트가 search_gifts(profile, budget)를 같은 파라미터로 연속 세 번 호출했다면, 그가 갇혔다는 신호입니다.

state에 (toolName, argsHash) 키의 호출 카운터를 추가하고 임계값을 넘으면, 다음 중 하나를 수행하세요:

  • run을 중단하고 이해 가능한 오류를 사용자에게 반환;
  • 혹은 모델에 추가 지시문을 주입: “같은 파라미터로 이 도구를 세 번 시도했다. 전략을 바꾸거나 사용자에게 질문하라”.

의사코드:

function shouldAbortToolCall(toolName: string, args: unknown, state: GiftAgentState) {
  const key = `${toolName}:${hashArgs(args)}`;
  const count = state.toolCallCounts[key] ?? 0;

  if (count >= 3) return true;

  state.toolCallCounts[key] = count + 1;
  return false;
}

여기서 hashArgs는 인자를 직렬화하는 임의의 결정적 함수입니다(예: 키 정렬을 곁들인 JSON.stringify).

7. 명확한 과제 종료 기준

“장난감” 에이전트와 프로덕션 에이전트의 큰 차이는 명확한 종료 기준의 존재입니다. 이 기준이 없으면, 모델은 너무 이른 시점에 과제를 던져버리거나(“대충 몇 개 추천했으니 나머지는 알아서”), 반대로 무한 개선에 빠질 수 있습니다.

GiftGenius에서는 간단한 규칙을 만들 수 있습니다:

  • 다음 필드가 채워진 3~5개의 선물이 있으면 에이전트를 종료한다: id, title, shortDescription, price, imageUrl, purchaseUrl, 그리고 이 선물들이 예산과 배송 제약 필터를 통과했을 것.
  • 검색과 필터링을 최대 N번 시도했음에도 적합한 선물이 3개 미만이면, 좋은 후보를 찾지 못했음을 정직하게 알리고 예산을 늘리거나 제약을 완화하도록 제안한다.

이 기준은 에이전트의 system 지시문에 직접 코딩하거나, run 이후 결과 검사에서 구현할 수 있습니다.

run 이후 결과 검사의 예:

if (run.status === "completed") {
  const gifts = run.output.gifts; // 가령, 에이전트가 구조화된 JSON을 반환한다고 하자

  if (!gifts || gifts.length < 3) {
    // 에이전트가 "완료"되었지만 결과가 약함 — 다음 중 하나를 수행:
    // 1) 정직한 설명을 보여준다,
    // 2) 사용자의 조건 변경을 제안한다.
  } else {
    // 괜찮음 — 선물 위젯을 표시
  }
}

모델이 비즈니스 성공을 마법처럼 이해하리라 기대하지 마세요. 개발자인 여러분이 “만족스러운” 결과의 조건을 명시적으로 정하고 이를 검사해야 합니다.

8. 오케스트레이션은 정확히 어디에서 구현되는가: 에이전트, backend, 위젯

앞서 오케스트레이션은 다양한 레벨(에이전트, backend, 위젯)에 위치할 수 있다고 말했습니다.

다단계 프로세스 관점에서의 대략적인 역할은 다음과 같습니다.

에이전트(Agents SDK)는 “사고의” workflow를 담당합니다:

  • 목표를 어떻게 단계로 나눌지;
  • 어떤 도구를 어떤 순서로 호출할지;
  • 사용자에게 어떤 추가 질문을 할지.

Backend는 보통 다음을 담당합니다:

  • 도구 구현(검색, 필터, 커머스 등);
  • 상태와 체크포인트 저장;
  • 엄격한 비즈니스 제약(budget caps, 권한, 지역 가용성).

위젯(Apps SDK)은 다음을 관리합니다:

  • 진행 상태 표시(스텝퍼, 진행 바, “4단계 중 2단계”);
  • 입력 폼;
  • UX 디테일(필수 데이터가 채워지지 않았을 때 버튼 비활성화 등).

좋은 실천은 이렇게 생각하는 것입니다: 에이전트는 도구와 대화를 연출하고, UI 위젯은 사용자의 시각적 경험을 연출한다. 이들은 구조화된 데이터(ToolOutput, agent run output)로 합의합니다.

9. 미니 코드 예시: MCP 도구에서 다단계 에이전트 GiftGenius 실행하기

이제 강의 초반 약속대로, 새로운 개념을 이미 익숙한 Apps SDK → MCP → backend 스택과 연결해, MCP 도구가 에이전트 run을 호출하는 작은 예시를 보겠습니다.

여러분의 app/mcp/route.tsrun_gift_workflow라는 tool이 있다고 상상해 봅시다. 이 도구는:

  • 사용자 텍스트 요청(목표)을 입력으로 받고;
  • giftAgent를 실행하며;
  • 위젯을 위한 구조화된 결과를 반환합니다.

코드는 단순화된 가상 예시이지만, 연결 방식을 이해하는 데 도움이 됩니다:

// app/mcp/route.ts
import { server } from "@modelcontextprotocol/sdk/server";
import { z } from "zod";
import { giftAgent } from "@/agents/giftAgent";

server.registerTool(
  "run_gift_workflow",
  {
    title: "선물 고르기",
    description: "다단계 선물 추천 에이전트를 실행합니다",
    inputSchema: {
      userGoal: z
        .string()
        .describe("사용자의 과제, 예: 동료를 위한 $50 이하의 선물을 원함"),
    },
  },
  async ({ userGoal }) => { 		
    const run = await giftAgent.run({		// 여기에서 에이전트를 12단계, 15초 타임아웃으로 실행합니다
      input: userGoal,
      maxSteps: 12,
      timeoutMs: 15000,
    });

    return {
      status: run.status,
      gifts: run.output?.gifts ?? [],
      debug: run.debugInfo, // 나중에 제거해도 됨
    };
  }
);

이후 ChatGPT App은 다른 MCP 도구와 마찬가지로 이 MCP-tool을 호출할 수 있고, 여러분의 GiftGenius 위젯은 gifts를 바탕으로 UI를 구성할 수 있습니다. 겉보기에는 ChatGPT에 하나의 깔끔한 tool처럼 보이면서도, 내부에는 다단계 workflow가 “숨겨진” 셈입니다.

10. 다단계 프로세스 설계 시 흔한 오류

오류 №1: “모델이 알아서 하게 두자. 도구만 다 주면 되겠지”.
서로 의미가 겹치는 도구가 한 뭉치 있고, 명확한 system 지시문과 단계가 없다면, 모델은 갈팡질팡합니다. 같은 일을 다른 방식으로 호출하고, 요청을 중복하며, 루프에 빠집니다. 시나리오를 단계로 나누고, 각 단계에서의 사용 가능 도구를 제한하며, 전략을 system 프롬프트에 명시하는 데 시간을 쓰는 편이 낫습니다.

오류 №2: 단계/시간 제한의 부재.
maxStepstimeout을 지정하지 않으면, 프로덕션에서 곧 “헤매는” run들이 자원을 소모하는데 사용자에게는 아무것도 보이지 않는 상황을 마주합니다. 제한은 “선택”이 아니라 기본 위생입니다. 아울러 한계 초과 상황을 의미 있게 처리하고, 말 없는 500으로 떨어지지 않게 하세요.

오류 №3: 명시적 종료 기준의 부재.
모델은 스스로 “이제 충분하다”고 느끼면 run을 끝냅니다. 하지만 그 “충분함”이 비즈니스 요구와 동떨어져 있을 수 있습니다. 성공 기준(선물 개수, 필요한 필드, 통과해야 할 필터)을 형식화하고 검증하지 않으면 UX가 불안정해집니다. 오늘은 훌륭한 다섯 가지, 내일은 “그저 그런” 하나와 중복 세 개가 나올 수도 있습니다.

오류 №4: 반복 도구 호출을 추적하지 않음.
에이전트는 “오류 발생 → 요청을 두어 단어만 바꿔 재작성 → 동일 도구 재호출” 패턴에 갇힐 수 있습니다. (toolName, args) 기준으로 반복 호출을 추적하지 않으면, 로그를 보기 전까지 이 루프는 눈에 띄지 않습니다. 단순 카운터와 인자 hash가 큰 도움이 됩니다.

오류 №5: 오케스트레이션과 비즈니스 로직 구현을 하나의 도구에 뒤섞음.
가끔 전체 workflow를 하나의 MCP 도구나 에이전트 함수 내부에 숨기려는 시도를 합니다: 검색, 필터, 포맷팅, 의사결정까지 모두요. 그러면 에이전트의 의미가 사라집니다 — 모델은 단계별로 과정을 제어할 수 없고, 투명성과 재사용성도 잃습니다. 단계를 독립된 tools로 분리하고, 그 합성은 에이전트에게 맡기는 편이 좋습니다.

오류 №6: 상태와 체크포인트의 부재.
중간 상태와 체크포인트 저장이 없는 다단계 프로세스는 깨지기 쉬운 모놀리스로 변합니다. 중간에 뭔가 실패하면, 사용자는 모든 과정을 처음부터 다시 시작해야 합니다. 특히 사용자가 단계 사이를 오가거나 시간이 지난 뒤 돌아오는 시나리오에서 치명적입니다. state store를 사용하고, 단계/프로필/후보를 저장하며, 에이전트가 적절한 지점에서 계속할 수 있게 하세요.

오류 №7: UX 레이어를 무시함.
개발자는 에이전트의 내부 workflow에 열중하다가, 사용자가 보는 것은 위젯과 채팅 메시지뿐이라는 사실을 잊곤 합니다. UI에 명확한 진행 상태, “선물을 찾는 중…”, “옵션을 필터링하는 중…” 같은 표시가 없다면, 사용자는 App이 “멈췄다”, “아무것도 안 한다”고 느낄 것입니다. 다단계 run을 설계할 때, 그것이 인터페이스에 어떻게 반영될지도 함께 생각하세요.

코멘트
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION