Sequential Agent (실습 : 코드 생성 에이전트 만들기)
(참고) 유튜브 영상으로 시청하고 싶으신분은 글 맨 하단 [강의 자료 URL]을 확인해주세요^^
지난 시간에 구글 ADK에서 제공하는 에이전트 3가지 유형 중 에이전트의 '두뇌'를 담당하는 LLM 에이전트를 배웠습니다. 이번 시간은 에이전트들의 작업 흐름을 제어하고 견고한 에이전트 파이프라인을 구축할 수 있도록 돕는 워크플로우(Workflow)에이전트에 대해 이번 시간부터 차근차근 배워보도록 하겠습니다.
워크플로우 에이전트는 사전에 정의된 작업 절차(Workflow)에 따라 동작하는 에이전트입니다.
순차적, 반복적, 병렬적인 작업 흐름을 구성할 수 있으며, 복잡한 프로세스를 체계적으로 실행할 때 유용합니다.
모든 일에는 작업 절차와 순서가 존재합니다. 그리고 모든 작업이 동일한 흐름으로 흘러가진 않습니다.
정해진 순서대로 처리되는일도 있고, 작업의 퀄리티를 위해 고객이 만족할 때까지 반복해서 수정해야할 일도 있고 때로는 일의 시간 단축을 위해 여러 작업을 동시에 처리해야할 때도 있습니다.
이처럼 다양한 작업 유형과 흐름을 쉽게 구성하고 제어할 수 있도록 돕는 것이 바로 '워크플로우 에이전트' 입니다.
Google ADK에서는 다음과 같은 세 가지 워크플로우 에이전트를 제공합니다
1. SequentialAgent : 하위 에이전트를 순서대로 하나씩 실행합니다.
2. LoopAgent : 하위 에이전트를 반복적으로 실행합니다.
3. ParallelAgent : 하위 에이전트를 동시에 병렬로 실행합니다.
위 3가지 워크플로우 에이전트를 잘 숙지하신다면 나중에 복잡한 에이전트를 구현할 때 작업 흐름에 따라 적절한 워크플로우 에이전트를 선택하여 체계적인 프로세스를 구축하는데 많은 도움이 될 것입니다.
일반 에이전트와 워크플로우 에이전트의 가장 큰 차이는 결정론적 방식이냐 비결정론적 방식이냐의 차이입니다.
저희가 이전 시간에 처음으로 학습하고 구현했던 LLM 에이전트는 상황에 따라 언어 모델을 활용해 동적으로 추론하고 결정을 내립니다. 반면, 워크플로우 에이전트는 고정된 로직을 따르며, 오케스트레이션 단계에서 LLM의 개입 없이 결정론적 방식으로 실행됩니다.
각각의 장단점은 분명히 존재하지만 결정론적 방식의 워크플로우 구조는 다음과 같은 장점을 제공합니다.
1. 예측 가능성: 실행 흐름이 명확하고 재현 가능합니다.
2. 신뢰성: 중요한 순서나 조건에 따라 작업이 일관되게 수행됩니다.
3. 구조화된 제어: 복잡한 작업도 단계별로 설계하여 관리할 수 있습니다.
워크플로우 에이전트는 다음과 같은 상황에서 특히 유용합니다
1. 작업 순서를 명확히 제어해야 할 때
2. 일관된 실행 결과가 중요한 경우
3. 여러 에이전트를 조직적으로 조합해야 하는 복합 프로세스가 필요할 때
이처럼 정해진 워크플로우와 고정된 로직을 따르며 오케스트레이션 단계에서 LLM의 개입 없이 결정론적인 방식으로 작업을 처리할 수 있도록 제어하는 에이전트가 바로 '워크플로우 에이전트'입니다.
또한, 워크플로우 내에서 사용하는 하위 에이전트는 반드시 고정형일 필요는 없습니다.
지능형 LLM 에이전트도 하위 에이전트로 포함시킬 수 있어, 정형화된 제어와 유연한 추론 능력을 동시에 활용할 수 있습니다.
이제 본격적으로 3가지 워크플로우 에이전트를 각 유형별로 이론과 실습을 통해 배워보도록 하겠습니다.
첫번째로 배울 워크플로우 에이전트는 SequentialAgent입니다.
Sequential Agent의 'Sequential'이라는 단어는 '순차적인', '잇달이 일어나는' 이라는 뜻에서 알 수 있듯이
어떤 작업들을 정해진 순서대로 제어하는 에이전트입니다.
SequentialAgent 는 하위 에이전트들을 정해진 순서대로 차례로 실행하며 파이프라인처럼 각 단계의 출력을 다음 단계로 전달하며 처리합니다.
예를 들어 코드를 작성하는 AI 에이전트를 개발한다는 가정하에 간단한 AI 에이전트 작업 파이프라인을 크게 3가지로 나눌 수 있겠습니다.
첫번째로 사용자가 원하는 기능을 사양에 따라 초기 코드로 작성해주는 코드 작성자 에이전트입니다.
두번째로 코드 작성자 에이전트로부터 생성된 코드의 오류, 스타일, 문법 및 모범 준수 여부를 검토하는 코드 검토자 에이전트입니다.
세번째로 코드 검토자 에이전트로부터 검토된 코드(및 검토자의 의견)를 가져와 품질을 개선하고 문제를 해결하기 위해 코드를 리팩터링 하는 코드 리팩터러 에이전트 입니다.
위 흐름은 코드 작성자 에이전트부터~코드리팩터러 에이전트까지 순서대로 작업이 진행되어야합니다.
코드가 작성되지도 않았는데 코드를 검토하고 리팩터링할 수는 없는 노릇이니까요.
이런 경우에 SequentialAgent를 메인 에이전트 즉, 루트 에이전트로 두고 위 3가지 에이전트를 하위 에이전트로 순서에 맞게 추가해주시면 사용자가 요청할 때마다 정해진 순서대로 위 에이전트들이 작업을 진행하게 되고 각 하위 에이전트의 작업 결과는 출력 키를 통해 상태에 저장되어 다음 에이전트로 전달됩니다.
SequentialAgent( sub_agents=[ 코드 작성자, 코드 검토자, 코드 리팩터 ] )
결론적으로 실행 순서가 중요한 결정론적 단계별 워크플로가 필요한 경우 SequentialAgent를 사용하면 됩니다. 그럼 위 예시에서 설명드린 코드 작성 에이전트를 SequentialAgent로 구현하는 방법을 실습을 통해 배워보도록하겠습니다.
이제 실습 화면으로 넘어가서 코드를 작성하면서 설명하도록 하겠습니다.
지난 LLM Agent챕터에 이어서 새로운 챕터 폴더를 만들어주겠습니다.
폴더 이름은 02-workflow-agnet라 짓겠습니다.
이 폴더 아래 바로 에이전트 폴더를 생성해도 되지만 workflow-agnet 강의는 3가지 워크플로우를 배울 예정이기 때문에 구분하기 위해 하위 챕터 폴더도 생성해주도록 하겠습니다.
02-workflow-agnet/ 폴더 아래 이번에 배울 sequential_agent 폴더도 만들어주겠습니다.
상위 챕터와 하위챕터를 구분하기 위해 하위 챕터는 앞에 '0'자를 빼고 바로 순번을 입력하겠습니다.
이름을 '1-sequential-agent' 폴더를 만들어줍니다.
방금 전에 예시로 들었던 에이전트 구현을 위해 에이전트 폴더를 만들어주겠습니다.
이름은.. 음.. 코드를 생성해준다는 의미로 'code-generation-agent'라는 이름으로 폴더를 생성해주겠습니다.
이전 배운 LLM Agent 시간에 ADK에서 에이전트 폴더 생성 규칙대로 동일하게 폴더를 구성해주겠습니다.
1) __init__.py 파일
2) .env 파일
3) agent.py 파일
__init__.py 파일과 .env는 전과 동일하기 때문에 LLM Agent에 있는 파일내 코드를 그대로 복사해서 붙여넣겠습니다. 이제 agent만 구현하면 됩니다.
from . import agent
GOOGLE_GENAI_USE_VERTEXAI=FALSE
GOOGLE_API_KEY=구글 AI 스튜디오에서 받은 API 키
현재까지는 LLM Agent를 구현할때와 동일합니다.
루트 에이전트는 에이전트 폴더 아래 agent.py에 구현을합니다.
여기에서 루트에이전트는 전체 작업 흐름을 순차적으로 제어하는 SequentialAgent가 될 겁니다.
하지만 SequentialAgent를 활용한 코드작성 파이프라인을 구현하려면 추가되어야할 부분이 있습니다.
코드 작성에 필요한 3가지 하위 에이전트는 어디에 구현하는 것이 좋을까요?
물론 에이전트 폴더 아래 agent.py에 모든 에이전트를 정의해도 되지만 코드 가독성과 추후 복잡한 에이전트 개발할때, 관리 효율을 높이기 위해 항상 역할별, 쓰임새별로 폴더와 파일 구조를 정리하고 분리하는 습관을 가지는 것이 좋습니다.
그래서 3가지 하위 에이전트들은 에이전트 폴더아래 따로 관리하기 위한 폴더를 생성하고 그 안에 에이전트를 구현하도록 하겠습니다.
에이전트 폴더아래 sub_agents 폴더를 생성합니다.
하위 에이전트들을 순차적으로 작업 흐름을 조율할 SequentialAgent를 구현하기 이전에 하위 에이전트 3개를 먼저 구현하겠습니다.
먼저 사용자가 요청에 따라 초기 코드를 작성해주는 코드 작성자 에이전트를 구현하겠습니다.
sub_agents 아래 작성자라는 뜻의 writer 폴더를 만들어줍니다.
그리고 하위 에이전트도 루트 에이전트와 마찬가지로, __init__.py 파일과 agent.py 파일을 추가합니다.
루트에이전트와 다른점은 에이전트 변수를 root_agent로 할필요가 없다는 점과 .env 파일이 필요 없다는 점입니다.
먼저 writer/ 아래 __init__.py을 열고 아래와 같이 작성하겠습니다.
그리고 /writer 아래 agent.py 파일을 열고 코드작성자 에이전트를 구현해보도록 하겠습니다.
하위 에이전트들은 모두 LLM Agent로 구현할 예정이므로 LlmAgent 클래스를 임포트 하겠습니다.
from google.adk.agents import LlmAgent
다음으로 코드 작성자 에이전트를 간단하게 정의하겠습니다.
변수명은 code_writer_agent로 짓고 LlmAgent를 할당합니다.
그리고 LlmAgent의 정체성과 목적을 부여하기 위한 설정값을 입력하겠습니다.
- name은 변수명과 동일한 code_writer_agent라고 입력합니다.
- model은 "gemini-2.0-flash" 모델을 사용하겠습니다.
- description은 "사용자의 요청에 따라 초기 파이썬 코드를 작성합니다." 라고 입력하겠습니다.
- instruction은 조금 길기 때문에 미리 준비해둔 프롬프트를 복사 붙여넣기 하겠습니다.
인스트럭션은 간단하게 설명드리자면 파이썬 코드를 작성하고 결과물 출력 지침을 설명합니다.
그리고 이전에 배우지 않았던 ouput_key를 설정하겠습니다.
output_key는 에이전트의 응답, 즉 결과물을 저장하기 위한 변수명을 설정한다고 생각하시면 됩니다.
코드 작성자 에이전트가 작업을 마치면 코드 검토자 에이전트가 이어서 작업을 시작하는데, 이 에이전트는 코드 작성자 에이전트가 작성한 코드의 결과물을 가지고 작업을 진행해야하기 때문입니다. output_key를 통해 작업 결과물을 저장하면, 다른 에이전트들이 output_key로 저장된 정보를 가져올 수 있게됩니다.
코드 작성자의 결과물은 "generated_code"에 저장하도록 하겠습니다.
https://gist.github.com/SoonCoding/f2227b16c71fcd72638a491a52da0ea3
이로써 코드 작성자 에이전트를 구현했습니다.
그럼 다음 작업을 처리할 코드 검토자 에이전트를 구현해보겠습니다.
하위 에이전트의 코드 구조는 비슷하기 때문에 빠른 진행을 위해 작성자 에이전트 폴더를 복사해서 같은 폴더 위치에 그대로 붙여넣어주겠습니다.
복사된 writer/ 폴더 이름을 검토자라는 뜻의 reviewer/라고 수정해줍니다.
복사된 __init__.py는 import 변수를 기존 코드 작성자 변수(code_writer_agent) -> 코드 검토자 변수(
code_reviewer_agent)로 수정해줍니다.
그 다음 agent.py 파일을 열어서 코드 작성자 코드내용을 코드 검토자 코드 내용으로 수정해주겠습니다.
변수명은 code_writer_agent에서 코드 검토자 에이전트라는 뜻의 code_reviewer_agent로 변경해주겠습니다.
- name은 변수명과 동일한 code_reviewer_agent라고 수정합니다.
- model은 동일하게 "gemini-2.0-flash" 모델을 사용할 것이기에 그대로 두겠습니다.
- description은 "코드를 리뷰하고 피드백을 제공합니다." 라고 수정해줍니다.
- instruction은 또한 미리 준비해둔 프롬프트를 복사 붙여넣기 하겠습니다.
코드 검토자의 경우 인스트럭션 내용이 조금 기네요.
인스트럭션 내용을 간단히 설명드리자면,
처음에 검토자 에이전트의 역할을 말해주고 검토자 에이전트가 수행해야할 각 작업 항목을 지정했습니다.
첫번째로 리뷰대상 코드를 알려줍니다. 리뷰대상코드는 이전 작업을 수행한 코드 작성자 에이전트의 결과물인 generated_code를 참조합니다.
두번째로 리뷰 기준을 설명합니다. 그리고 마지막으로 결과물 출력 방법 및 유의사항을 설명합니다.
코드 검토자는 작성된 코드를 리뷰하고 최종적으로 검토 피드백을 응답합니다. 만약 코드에 이상이 없다면 "큰 문제 없음"이라고 출력합니다.
- 그리고 코드 검토자 에이전트의 결과물은을 저장하기 위한 output_key는 "review_comments" 저장되도록하고 다음 작업 에이전트가 참조할 수 있도록 합니다.
https://gist.github.com/SoonCoding/b42ad803bc3ba5230534a5f6be7c450b
다음으로 마지막 하위 에이전트인 코드 리펙터 에이전트를 구현하겠습니다.
코드 리펙터러 에이전트 또한 이전과 동일하게 빠른진행을 위해 코드 검토자 에이전트 폴더를 복사해서 같은 폴더 위치에 붙여넣겠습니다.
복사된 reviewer/ 폴더 이름을 refactorer라고 수정해줍니다.
복사된 __init__.py 파일은 import 변수를 기존 코드 검토자 변수(code_reviewer_agent) -> 코드 리펙터 변수(code_refactorer_agent)로 수정해줍니다.
그리고 agent.py 파일을 열어서 코드 검토자 코드 내용을 코드 리펙터러 코드 내용으로 수정해주겠습니다.
변수명은 code_reviewer_agent에서 code_refactorer_agent로 변경해주겠습니다.
- name은 변수명과 동일한 code_refactorer_agent라고 수정합니다.
- model은 동일하게 그대로 두겠습니다.
- description은 "리뷰 코멘트를 기반으로 코드를 리팩토링합니다." 라고 수정해줍니다.
- instruction은 미리 준비해둔 프롬프트를 복사 붙여넣기 하겠습니다.
코드 리펙터러 에이전트의 작업 지침을 살펴보면
제공된 코드와 리뷰 코멘트를 바탕으로 코드를 개선하는 역할입니다.
항목을 코드 작성자가 작성한 코드 결과물과 코드 검토자의 리뷰 코멘트 결과물 모두 참조합니다.
리뷰 코멘트 내용에 따라 코드를 개선하여 최종 파이썬 코드 결과물을 출력합니다.
그리고 최종 결과물 저장을 위해 output_key에 "refactored_code"라고 입력합니다.
https://gist.github.com/SoonCoding/04176693eda4abbbbb9c3e517912ff9c
이로써 코드 생성을 위해 필요한 하위 에이전트 구현이 끝났습니다.
이제 마지막으로 이번 장의 주제인 시퀀셜 에이전트를 구현해보겠습니다.
시퀀셜 에이전트는 앞서 설명드린것 처럼 위 3가지 하위 에이전트들이 순차적으로 작업을 진행할 수 있도록 제어하는 에이전트 입니다.
121212
이말인 즉슨, code_generation_agent의 루트 에이전트로 지정되어야 한다는 뜻입니다.
에이전트 루트 폴더인 code_generation_agent 폴더 아래 agent.py 파일을 열고 SequentialAgent를 구현해주겠습니다.
SequentialAgent 구현은 생각보다 간단합니다.
지금까지 에이전트 구현을 위해 LLM Agent 만 임포트 했는데 이번에는 LLM Agent가 아닌 Sequential Agent를 임포트 해줍니다.
그리고 변수명을 직관적으로 code_pipeline_agent라고 짓겠습니다.
그 다음 SequentialAgent를 할당해줍니다.
SequentialAgent를 설정하기 위해 필요한 설정값은 3개면 충분합니다.
LLM Base의 LLM Agent와 달리 이미 SequentialAgent 클래스가 처리되는 로직이 고정되어 있는 결정론적 에이전트이기 때문에 llm 모델과 인스트럭션이 없습니다.
그대신 추후 복잡한 에이전트 시스템에서 SequentialAgent를 정의할때 다른 LLM 등의 에이전트가 이 에이전트를 식별하고 참조할 수 있도록 이름과 설명은 동일하게 작성해줍니다.
- name은 변수명과 동일한 code_pipeline_agent라고 입력합니다.
- description은 "코드 작성 → 리뷰 → 리팩토링의 순서로 작업을 수행하는 Sequential 에이전트입니다."라고 입력하겠습니다.
그리고 마지막으로 제일 중요한 설정이 남아있습니다.
SequentialAgent의 핵심은 하위 에이전트를 순차적으로 실행하는 것입니다.
그래서 sub_agents=[] 설정값에 실행할 하위 에이전트를 순서대로 입력해줍니다.
sub_agents 설정에 하위 에이전트를 지정하기 위해서는 구현한 하위 에이전트를 임포트 해야합니다.
참고로 하위 에이전트는 현재 저희가 작업중인 파일을 기준으로 sub_agents 폴더 아래에 위치하고 있습니다.
코드 작성자, 코드 검토자, 코드 리펙터러 하위 에이전트들을 임포트해주겠습니다.
from .sub_agents.writer import code_writer_agent
from .sub_agents.reviewer import code_reviewer_agent
from .sub_agents.refactorer import code_refactorer_agent
임포트한 하위 에이전트들은 SequentialAgent의 sub_agents설정값에 순서에 맞게 할당해줍니다.
그리고 끝으로 이전에 강조드린대로 SequentialAgent가 루트 에이전트가 되었기 때문에 ADK가 일르 식별할 수 있도록 변수명을 root_agent로 할당해줍니다.
https://gist.github.com/SoonCoding/6ffcfcfa06e98bab0ce90821a9c982d5
이로써 SequentialAgent를 활용한 코드 생성 에이전트 구현이 완료되었습니다!
이제 adk web ui에 접속해서 코드 생성 에이전트가 잘 동작하는지 테스트를 진행하겠습니다.
커서 터미널에서 지금 학습중인 02-workflow-agent/1-sequential-agent 상위 폴더에 진입하고
adk web 명령어를 입력한 이후, TEST WEB UI에 접속해주겠습니다.
그리고 대화 인터페이스를 통해 에이전트에게 간단한 계산기 코드를 요청해보겠습니다.
"계산기 기능이 있는 코드를 작성해주세요"
대화를 시작하는 순간 코드 생성 에이전트가 실행되고, 순차적으로 하위 에이전트들이 작업을 실행하는 것을 확인 할 수 있습니다.
첫번째로 코드 작성자 에이전트가 계산기 기능이 있는 파이썬 코드를 생성한 내용입니다.
그다음 코드 작성자 에이전트가 생성한 코드를 코드 검토자 에이전트가 검토 후 피드백하는 내용이 보입니다.
코드 검토 피드백을 보면
- 연산 로직을 함수로 분리하여 가독성을 높일 수 있습니다 (예: add(x, y), subtract(x, y) 등).
- choice 값에 따라 연산을 수행하는 부분을 딕셔너리나 함수 매핑을 사용하여 더 간결하게 만들 수 있습니다.
- 사용자 인터페이스 메시지를 별도의 변수로 관리하여 국제화/지역화에 대비할 수 있습니다.
- 입력 프롬프트에 공백을 추가하여 가독성을 향상시킬 수 있습니다 (예: input("첫 번째 숫자를 입력하세요: ")을 input("첫 번째 숫자를 입력하세요: ")로 변경).
- 전체적인 try...except 블록 대신, 개별적인 float() 변환에 try...except 블록을 사용하는 것이 좋습니다. (오류 발생 지점 명확화)
뭐 이런 내용이구요.
마지막으로 작성된 코드와 검토 피드백을 반영하여 최종적으로 개선된 코드를 반환하는 모습입니다.
몇분만에 뚝딱 만든 에이전트인데 이정도라니 굉장하지 않습니까?
그리고 코드 생성 에이전트와 상호작용 했던 내용을 확인해보기 위해 Trace 탭을 확인해보겠습니다.
trace 탭을 확인하시면 Invocations 아래 저희가 에이전트에게 요청했던 대화 내용이 있고, 해당 요청에 따라 처리된 에이전트 작업 처리 히스토리와 데이터를 확인할 수 있습니다.
대화가 시작되고, 루트 에이전트이자 시퀀셜 에이전트로 구현된 code_pipleline_agent가 실행 되었고,
그 이후 순차적으로 코드 작성자, 코드 검토자, 코드 리팩터러 에이전트가 순서대로 호출되어 실행된 것을 확인할 수 있습니다.
그리고 각 에이전트의 호출 상세 내역을 확인해보겠습니다.
제일 먼저 호출된 코드 작성자 에이전트의 call_llm 내역을 클릭하면 이벤트, 리퀘스트, 리스폰스 등의 상세 정보를 확인할 수 있습니다.
이벤트 탭에서 에이전트 이름, 응답내용, 세션 정보 등 지금 생성된 대화 내에서 에이전트와의 상호작용 과정에서 발생한 모든 정보를 시간순으로 담고 있습니다.
그리고 리퀘스트 탭을 확인해보시면 우리가 요청한 내용과 저희가 에이전트에 입력한 인스트럭션, 즉 프롬프트 정보를 확인할 수 있습니다.
리스폰스 탭은 사용자의 요청에 의해 호출된 에이전트가 작업을 처리하고 최종적으로 반환한 응답 정보를 담고 있습니다. 코드 생성 에이전트니까 최종 개선된 코드가 되겠죠.
그리고 마지막으로 그래프 탭을 확인해보시면 에이전트 파이프라인 구조와 현재 확인 중인 에이전트가 무엇인지 확인할 수 있습니다. 저희는 코드 생성 에이전트의 전체 순차적 파이프라인에서 현재 코드 작성자 에이전트 정보를 확인할 수 있습니다.
코드 검토자 에이전트와 코드 리펙터러 에이전트도 이런 식으로 상호작용 이력을 확인해보시면 됩니다.
에이전트와 상호작용한 전체 이력을 한눈에 보시려면 이벤트 탭을 확인하셔도 되는데
여러분이 보기 편하신 것을 선택해서 확인하시면 됩니다.
저는 Trace 탭으로 보는 것이 조금 더 직관적인것 같아서 trace로 보는 것을 조금 더 선호하는 편입니다.
앞으로 이 강의에서는 Trace 탭을 위주로 에이전트와의 상호작용 이력을 확인하겠습니다.
이것으로 작업 흐름을 제어하는 워크플로우 에이전트 유형중 순차적으로 작업을 처리하는 '시퀀셜 에이전트' 강의를 마무리하도록 하겠습니다.
다음 강의는 워크플로우 에이전트 유형중 작업을 원하는 결과를 얻을 때까지 반복적으로 처리하는 '루프 에이전트' 강의를 진행하도록 하겠습니다.
https://brunch.co.kr/@sooncoding/61/write