강의

멘토링

커뮤니티

인프런 커뮤니티 질문&답변

유준모님의 프로필 이미지
유준모

작성한 질문수

LangGraph를 활용한 AI Agent 개발 (feat. MCP)

3.6 human-in-the-loop: 사람이 Agent와 소통하는 방법

3.6 human_in_the_loop 3rd case

해결된 질문

작성

·

20

·

수정됨

0

강의를 들으면서 문득 든 궁금증인데, ai메세지가 도구를 잘못 선택했을 때(3번케이스)를 구현할 때, 왜 tool message를 수정하셨나요? tool 노드 호출전에 interrupt 해서 ai_message의 tool_calls에서 툴네임을 변경해도 되지 않을까해서요

case2번 : 도구는 잘 선택했을 때 쿼리가 잘못된 경우에서는 ai_message의 쿼리를 변경했듯이 3번의 케이스에선 ai_message의 툴네임을 변경해도 되지 않을까 의문이 들었습니다.

답변 1

0

제이쓴님의 프로필 이미지
제이쓴
지식공유자

안녕하세요! 좋은 질문 감사합니다.

TL;DR

핵심부터 말씀드리면, case 3(update_tool)은 "도구 자체를 바꾸는 것"이 아니라 "도구 호출을 건너뛰고, 사람이 직접 도구 결과를 제공하는 것"입니다.

코드를 다시 보시면:

if review_action == 'update_tool':
    updated_tool_message = {
        'tool_call_id': tool_call['id'],
        'name': tool_call['name'],
        'role': 'tool',
        'content': review_data  # 사람이 직접 제공하는 "결과값"
    }
    return Command(goto='agent', update={'messages': [updated_tool_message]})

여기서 두 가지를 확인할 수 있는데요

  1. goto='agent'

    1. tools 노드가 아니라 바로 agent로 갑니다.

    2. 즉, 실제로 도구를 실행하지 않습니다.

  2. role: 'tool'인 메시지를 직접 만들어서 삽입을 하게 되는데, 마치 도구가 실행된 것처럼 LLM에게 결과를 전달하는 가짜 ToolMessage입니다.

이 패턴의 의도는 이렇습니다: AI가 잘못된 도구를 선택했을 때, 사람이 "이 도구 말고 웹에서 검색해줘"라고 자연어로 피드백을 주면, 그 피드백 자체가 ToolMessage의 content로 들어가서 agent가 다시 판단할 수 있게 되는 것입니다.

실제 예시에서도 확인할 수 있습니다:

Command(resume={"action": "update_tool", "data": "arxiv말고 web에서 검색해주세요"})

여기서 arxiv말고 web에서 검색해주세요 라는 문자열이 ToolMessage의 content가 되어 agent에게 전달되고, agent는 이를 보고 다음에 duckduckgo_search를 호출하게 됩니다.

 

그러면 질문하신 것처럼 ai_message의 tool_calls에서 tool name을 직접 바꾸면 안 되는 것인지 의문이 들 수 있는데요,

기술적으로 가능은 하지만, 실용적으로 문제가 있습니다:

  • tool_name을 바꾸면 args도 함께 바꿔야 합니다. 각 도구마다 파라미터 스키마가 다르기 때문입니다. 강의에서 진행한 케이스의 경우 arxiv 도구와 duckduckgo_search 도구의 인자 형식이 동일한데요(모두 query를 사용함), 만약 스키마가 다른 경우에는 에러가 발생합니다.

    • 사람이 도구 이름과 정확한 인자까지 알아서 지정해야 하므로 human-in-the-loop의 편의성이 크게 떨어집니다.

  • 반면 case 3 방식은 사람이 자연어로 피드백만 주면, agent(LLM)가 알아서 적절한 도구와 인자를 다시 선택하므로 훨씬 유연합니다.

유준모님의 프로필 이미지
유준모
질문자

자세하고 간결한 설명 감사합니다

유준모님의 프로필 이미지
유준모

작성한 질문수

질문하기