ADK Go 2.0 멀티 에이전트 설계: 그래프 워크플로우로 운영 안정성 높이기
요약: ADK Go 2.0의 핵심은 “에이전트를 더 자유롭게 만들자”가 아닙니다. 오히려 반대입니다. 모델에게 맡기면 안 되는 순서, 승인, 재시도, 병렬 실행을 그래프 워크플로우로 고정하고, 언어 모델은 애매한 판단이 필요한 지점에만 배치하는 방식입니다. 프로덕션 멀티 에이전트를 만들려는 Go 팀이라면 이 관점을 먼저 잡아야 합니다.
문제가 되는 기존 패턴
많은 팀이 처음 에이전트를 만들 때 하나의 LLM agent에 모든 도구를 붙입니다. 프롬프트에는 “1단계로 구매 이력을 확인하고, 2단계로 정책을 읽고, 3단계로 환불 가능 여부를 판단하고…” 같은 순서를 적습니다. 데모에서는 잘 됩니다. 하지만 운영에서는 흔들립니다.
문제는 모델이 실행 오케스트레이션에 적합하지 않다는 점입니다. 모델은 문장을 이해하고 애매한 정보를 해석하는 데 강합니다. 그러나 “A 다음에는 반드시 B”, “실패하면 최대 5번 재시도”, “승인 없이는 환불 실행 금지” 같은 규칙은 전통적인 코드가 더 잘합니다.
Google Developers Blog의 ADK 2.0 설명도 같은 문제를 짚습니다. agent가 100번 중 95번은 잘해도, 5번은 context 혼잡이나 hallucination 때문에 단계를 건너뛸 수 있습니다. 비즈니스 프로세스에서는 이 5번이 장애입니다.
ADK Go 2.0의 핵심 구조
ADK for Go 2.0은 agent workflow를 graph로 표현합니다. 노드는 작업 단위이고, edge는 실행 흐름입니다. 노드는 function node, emitting function node, agent node, tool node, join node, dynamic node, workflow node 등으로 나뉩니다.
실무적으로 중요한 것은 다음 5가지입니다.
- Function node: 일반 Go 함수를 노드로 감쌉니다. 타입과 스키마를 명확히 잡기 좋습니다.
- Agent node: LLM agent를 그래프 안의 특정 판단 지점에 배치합니다.
- Tool node: 외부 API 호출이나 DB 조회를 독립 단계로 둡니다.
- Join node: 병렬 작업 결과를 모으는 fan-in barrier 역할을 합니다.
- Dynamic node: 런타임 데이터에 따라 반복, 조건, fan-out을 Go 코드로 제어합니다.
이 구조의 장점은 모델과 제어 흐름을 분리하는 것입니다. “정책 해석”은 LLM이 하고, “환불 API 호출 전 승인 필요”는 graph가 강제합니다.
환불 처리 예시로 보는 설계
고객 환불 처리를 예로 들어보겠습니다. 자율 에이전트 방식은 모든 도구를 agent에 넣고 프롬프트로 순서를 지시합니다. 반면 graph workflow 방식은 다음처럼 나눕니다.
- 구매 이력 조회: DB 또는 결제 API를 호출하는 tool node.
- 정책 예외 판단: 고객 메시지와 정책을 해석하는 LLM agent node.
- 조건 분기: eligible이면 환불, 아니면 티켓 종료.
- 환불 실행: Stripe 같은 결제 API를 호출하는 tool node.
- 확인 메일 작성: LLM이 문안을 만들되, 발송은 별도 tool node가 수행.
- CRM 업데이트: ticket status를 닫는 tool node.
여기서 LLM은 “정책 예외 판단”과 “고객에게 보낼 자연어 문안”에 집중합니다. 순서, 분기, 실행, 재시도는 Go 코드와 ADK runtime이 담당합니다.
운영 안정성을 높이는 기능
ADK Go 2.0에는 production agent에 필요한 장치가 꽤 많이 들어 있습니다.
첫째, human-in-the-loop가 built-in primitive입니다. 노드가 중간에 멈추고 사람에게 승인이나 입력을 요청할 수 있습니다. 이후 답변이 들어오면 handoff 또는 re-entry 방식으로 재개합니다. 중요한 점은 resume이 durable하다는 것입니다. 프로세스가 재시작되어도 session history를 바탕으로 paused workflow를 복원할 수 있습니다.
둘째, retry policy가 노드 단위로 붙습니다. 기본 retry config는 5회 시도, 1초 초기 지연, 60초 cap, 2배 backoff, jitter를 포함합니다. API 장애나 일시적 네트워크 오류를 prompt로 해결하려 하지 않아도 됩니다.
셋째, graph-wide concurrency 제한과 branch isolation이 있습니다. 병렬 branch가 서로의 LLM prompt history를 오염시키지 않도록 격리할 수 있습니다. 멀티 에이전트 시스템에서 이 부분은 매우 중요합니다. 한 branch의 잡음이 다른 branch의 판단을 바꾸면 재현이 어려워집니다.
언제 ADK Go 2.0을 써야 하나
모든 챗봇에 graph workflow가 필요한 것은 아닙니다. 단순 Q&A나 내부 문서 검색이라면 과할 수 있습니다. 하지만 다음 조건 중 2개 이상이면 검토할 만합니다.
- 업무 순서가 명확하고, 일부 단계는 반드시 실행되어야 한다.
- 결제, 계정, 권한, 데이터 변경처럼 실패 비용이 큰 tool call이 있다.
- 중간 승인이나 사람 입력이 필요하다.
- 병렬 조사 후 결과를 합치는 구조가 반복된다.
- 장애 발생 시 어느 노드에서 실패했는지 추적해야 한다.
- Go 서비스 안에 agent runtime을 자연스럽게 넣고 싶다.
특히 기존 Go 백엔드 팀에게는 장점이 큽니다. 새로운 orchestration 서버를 따로 두지 않고, 익숙한 Go 코드와 타입 시스템 안에서 agent workflow를 구성할 수 있기 때문입니다.
설계 체크리스트
- 먼저 전체 업무를 노드와 edge로 그린다.
- LLM이 필요한 단계와 deterministic code로 충분한 단계를 분리한다.
- 외부 API 호출은 tool node로 격리한다.
- 사람 승인이 필요한 지점은 HITL interrupt로 명시한다.
- 실패 가능성이 있는 노드에는 retry와 timeout을 설정한다.
- 병렬 branch는 isolation scope를 확인한다.
- 테스트에서는 “정상 경로”뿐 아니라 거절, 재시도, resume, timeout을 검증한다.
- session event 저장소가 새 node metadata를 제대로 보존하는지 확인한다.
ADK Go 2.0은 멀티 에이전트를 더 복잡하게 만들기 위한 도구가 아닙니다. 반대로 복잡해진 agent application을 다시 소프트웨어 엔지니어링의 기본 원칙 안으로 가져오는 도구입니다. 모델은 판단에 쓰고, 흐름은 코드로 고정하세요. 그 선을 지키면 운영 장애가 줄어듭니다.