에이전트란 무엇인가? 🤔
에이전트란 무엇인가? 🤔
에이전트 시스템에 대한 입문입니다. 효율적인 AI 시스템은 LLM에게 현실 세계에 접근할 방법을 줘야 합니다. 예를 들어 외부 정보를 얻기 위한 검색 도구를 호출하거나, 특정 작업을 해결하기 위해 프로그램에 작용하는 식이죠. 다시 말해, LLM에는 **에이전시(agency, 작용 능력)**가 필요해요.
에이전시의 스펙트럼
이 정의에서 "에이전트"는 0 또는 1로 나뉘는 불연속 개념이 아닙니다. 워크플로에서 LLM에 더 많은 권한을 줄수록 에이전시는 연속적인 스펙트럼 위에서 진화해요. 아래 표를 보면 시스템마다 에이전시가 어떻게 달라지는지 알 수 있어요.
| 에이전시 수준 | 설명 | 짧은 이름 | 예시 코드 |
| ☆☆☆ | LLM 출력이 프로그램 흐름에 영향 없음 | 단순 처리기 | process_llm_output(llm_response) |
| ★★☆ | LLM 출력이 함수 실행을 제어 | 도구 호출 | run_function(llm_chosen_tool, llm_chosen_args) |
| ★★☆ | LLM 출력이 반복·프로그램 지속을 제어 | 다단계 에이전트 | while llm_should_continue(): execute_next_step() |
| ★★★ | 한 에이전틱 워크플로가 다른 워크플로를 시작 | 멀티 에이전트 | if llm_trigger(): execute_agent() |
| ★★★ | LLM이 코드로 작동, 자신의 도구 정의/다른 에이전트 시작 | 코드 에이전트 | def custom_tool(args): ... |
✅ 에이전트를 쓸 때 / ⛔ 피할 때
고객 요청을 처리하는 서핑 여행 사이트 앱을 만든다고 해볼게요. 날씨 API, 이동 거리를 계산하는 Google Maps API, 직원 가용성 대시보드, 지식 베이스 RAG 시스템에 접근할 수 있는 다단계 에이전트로 만들 수 있어요.
하지만 실제 대부분의 일상 작업(위 여행 예시처럼)은 미리 정해진 워크플로에 들어맞지 않아요. 에이전틱 시스템은 프로그램에 실제 세계 작업이라는 광대한 세계를 열어줍니다.
왜 smolagents인가?
체인이나 라우터 같은 저수준 에이전틱 사용 사례는 코드를 직접 다 쓸 수 있어요. 그게 시스템을 더 잘 제어·이해하게 해주니 훨씬 나아요. 하지만 LLM이 함수를 호출("도구 호출")하게 하거나 while 루프를 실행("다단계 에이전트")하게 하는 복잡한 동작으로 넘어가면, 몇 가지 추상화가 필요해집니다.
- 도구 호출: 에이전트 출력을 파싱해야 하니, "Thought: I should call tool 'get_weather'. Action: get_weather(Paris)." 같은 미리 정의된 형식과 그걸 파싱하는 함수, 그리고 이 형식을 알려주는 시스템 프롬프트가 필요해요.
- 다단계 에이전트: 마지막 루프 반복에서 무슨 일이 있었는지에 따라 LLM에 다른 프롬프트를 줘야 하니 메모리가 필요해요.
이 두 예시만 봐도 다음 항목들이 필요하다는 걸 알 수 있어요.
- 시스템을 구동하는 엔진인 LLM
- 에이전트가 접근할 수 있는 도구 목록
- ReAct 루프(Reflection → Action → Observation), 가용 도구, 사용할 도구 호출 형식을 LLM에 안내하는 시스템 프롬프트
- 시스템 프롬프트가 지시한 형식으로 LLM 출력에서 도구 호출을 추출하는 파서
- 메모리
그리고 LLM에게 결정권을 주면 실수도 하게 마련이니 오류 로깅과 재시도 메커니즘도 필요해요. 이 모든 요소가 잘 맞물려야 제대로 작동하는 시스템이 됩니다. 그래서 이것들을 함께 동작하게 만드는 기본 빌딩 블록이 필요했던 거예요.
코드 에이전트
Anthropic, OpenAI 등이 쓰는 일반적인 형식은 "도구 이름과 인자의 JSON으로 동작을 작성하고, 어떤 도구를 어떤 인자로 실행할지 파싱하는" 방식이에요.