Google이 Genkit Agents API preview를 공개했습니다. Genkit은 TypeScript, Go, Dart, Python을 지원하는 오픈소스 AI 애플리케이션 프레임워크이고, 이번 Agents API는 대화형 AI 앱에서 반복되는 배관 작업을 하나의 인터페이스로 묶는 데 초점을 둡니다. message history, tool loop, streaming, persistence, frontend protocol을 매번 직접 붙이던 문제를 줄이려는 시도입니다.
이 글은 Genkit Agents API, conversational AI app, AI agent state management, human in the loop, streaming agent UI를 검색하는 개발자를 위한 구현 가이드입니다. 핵심은 “에이전트가 답한다”가 아니라, 상태가 남고 중간 결과가 보이며 위험한 작업은 멈춰 승인받는 구조를 어떻게 만들지입니다.
많은 AI 기능은 처음에는 generate() 한 번으로 시작합니다. 사용자가 질문하면 모델이 답합니다. 하지만 제품이 조금만 복잡해지면 바로 한계가 옵니다. 이전 대화를 기억해야 하고, tool을 여러 번 호출해야 하고, 긴 작업은 streaming으로 보여줘야 하고, 사용자가 브라우저를 닫아도 작업이 이어져야 합니다.
또한 frontend와 backend 사이의 protocol도 필요합니다. 텍스트 chunk만 스트리밍하면 충분하지 않습니다. 상태 변경, artifact 생성, tool approval 요청, abort, resume 같은 이벤트가 오갑니다. 이걸 프로젝트마다 새로 만들면 비슷한 버그가 반복됩니다.
Genkit Agents API는 agent를 서버에서 정의하고, local agent든 HTTP endpoint 뒤 agent든 같은 chat() 인터페이스로 다루게 합니다. 개발자는 agent의 기능에 집중하고, 반복되는 session/store/streaming plumbing은 프레임워크에 맡기는 방향입니다.
대화형 AI에서 가장 먼저 결정할 것은 상태의 소유권입니다. Genkit은 session store를 붙이면 server-managed 방식으로 동작합니다. 서버가 messages, custom state, artifacts를 snapshot으로 저장하고, client는 session ID로 이어갑니다. persistent chat, shared device, multi-instance server처럼 client가 전체 대화 상태를 들고 있으면 곤란한 경우에 맞습니다.
반대로 store를 붙이지 않으면 client-managed에 가깝습니다. 서버가 state를 반환하고 client가 다음 turn에 다시 보냅니다. 이미 앱이 자체 persistence를 갖고 있거나, stateless server deployment를 원할 때 선택할 수 있습니다.
실무 기준은 명확합니다. 고객 지원, 문서 작성, 리포트 생성처럼 작업 이력이 제품 데이터인 경우 server-managed가 낫습니다. 간단한 위젯이나 임시 대화처럼 저장 가치가 낮고 backend를 가볍게 유지하려면 client-managed가 낫습니다. 중요한 것은 중간에 바꾸기 어렵다는 점입니다. 처음 설계할 때 개인정보, 보존 기간, 삭제 요청, multi-device 요구사항을 같이 봐야 합니다.
Genkit 문서에서 흥미로운 부분은 snapshot ID로 특정 시점에서 branch할 수 있다는 점입니다. 사용자가 기존 여행 계획을 유지한 채 “예산을 줄인 버전도 보여줘”라고 할 수 있고, 보고서 초안에서 “이 버전은 보존하고 다른 톤으로 다시 써줘”라고 할 수 있습니다.
이 기능은 단순 편의 기능이 아니라 UX 패턴입니다. 기존 chatbot은 마지막 상태만 앞으로 굴러갑니다. 하지만 실제 작업은 여러 대안을 비교합니다. snapshot branching이 있으면 AI 앱을 대화창이 아니라 작업 공간으로 만들 수 있습니다.
개발팀은 snapshot을 저장할 때 비용과 보안도 생각해야 합니다. 모든 turn마다 전체 state를 저장하면 저장 비용이 커집니다. 반대로 너무 성긴 checkpoint는 복구와 branch가 어렵습니다. Genkit은 checkpoint interval을 설정할 수 있으므로, artifact가 큰 앱은 메시지와 산출물을 분리해 저장하는 구조가 필요합니다.
Genkit Agents API의 streaming은 text chunk뿐 아니라 custom state와 artifact update도 다룹니다. 예를 들어 리포트 작성 agent가 “자료 수집 중”, “표 생성 중”, “초안 작성 중” 같은 상태를 보내고, 중간에 생성된 CSV나 markdown artifact를 UI에 표시할 수 있습니다.
이 차이는 사용자 신뢰와 직접 연결됩니다. 2분 동안 spinner만 보이는 앱은 사용자가 실패했다고 느낍니다. 반면 단계별 진행 상황과 부분 산출물이 보이면 오래 걸리는 작업도 기다릴 이유가 생깁니다. 특히 agent가 tool을 여러 번 호출하는 제품에서는 progress event가 필수입니다.
구현할 때는 이벤트 타입을 UI 상태와 분리하세요. backend event를 그대로 component state로 박으면 버전 변경 때 깨집니다. agent_status, artifact_patch, approval_required, error_recoverable처럼 앱 내부 event model로 한 번 매핑하는 편이 안전합니다.
Genkit은 interruptible tool을 통해 위험한 tool 실행 전에 agent를 멈추고 사용자 승인을 받을 수 있습니다. 예시에서는 run_shell tool이 위험한 command를 감지하면 interrupt를 반환하고, client가 승인 또는 거절을 보낸 뒤 실행을 이어갑니다.
이 구조는 결제, 배포, 파일 삭제, 이메일 발송, 권한 변경 같은 작업에 필요합니다. 모델에게 “위험하면 물어봐”라고 prompt에 쓰는 것만으로는 부족합니다. tool 자체가 승인 없이는 실행되지 않도록 코드 레벨에서 막아야 합니다.
승인 UI에는 최소한 네 가지가 있어야 합니다. 실행하려는 작업, 왜 승인이 필요한지, 예상 영향, 취소했을 때 대안입니다. “승인하시겠습니까?”만 보여주면 사용자는 판단할 수 없습니다. 승인 이벤트도 audit log로 남겨야 합니다.
AI agent 작업은 점점 길어지고 있습니다. 시장 조사, 코드 수정, 문서 리팩터링, QA 자동화는 요청 하나가 몇 분 이상 걸릴 수 있습니다. Genkit은 server-managed state에서 turn을 detach하고, client가 나중에 snapshot ID로 reconnect할 수 있는 흐름을 제공합니다.
이 패턴을 쓰면 사용자가 탭을 닫아도 작업이 계속됩니다. 모바일에서 시작하고 데스크톱에서 확인하는 UX도 가능합니다. 다만 운영 측면에서는 job timeout, cancel, retry, idempotency가 필요합니다. 사용자가 같은 요청을 두 번 눌렀을 때 중복 실행을 막아야 하고, 오래 걸리는 작업의 비용 상한도 있어야 합니다.
실무에서는 detached task마다 owner, status, started_at, last_heartbeat_at, cost_estimate, cancel_token을 저장하는 것이 좋습니다. agent framework가 state를 관리해도 제품 레벨의 작업 큐 메타데이터는 별도로 필요합니다.
Genkit Agents API의 가치는 모델 호출을 조금 편하게 만드는 데서 끝나지 않습니다. 대화형 AI 앱이 production 제품이 되기 위해 필요한 상태, 스트리밍, 승인, 재개 흐름을 표준화하려는 점이 핵심입니다. AI 앱을 오래 운영할 계획이라면 prompt보다 먼저 session architecture를 봐야 합니다.