AX LABS
← 블로그 에이전트 제품 설계

에이전트 지연은 연결 문제다

긴 작업은 모델보다 왕복 설계에서 먼저 느려진다

현장에서 장기 에이전트 작업을 붙이면 같은 장면이 반복된다. 모델은 이미 다음 행동을 정했는데, 애플리케이션은 HTTP 요청을 닫고, tool output을 다시 조립하고, 이전 상태를 다시 실어 보낸다. 한두 번은 티가 안 난다. 그러나 검색, 파일 조회, 코드 실행, 승인 요청이 이어지면 사용자는 모델이 느리다고 말한다. 실제 병목은 모델 하나가 아니라 agent loop의 transport다.

OpenAI 문서는 2026년 현재 Responses API가 long-running, tool-call-heavy workflow를 위해 WebSocket mode를 지원한다고 설명한다. 핵심은 /v1/responses에 persistent connection을 열고, 매 turn마다 새 input item과 previous_response_id만 보내는 방식이다. 공식 문서는 tool call이 많은 chain에서 per-turn continuation overhead를 줄이고, 20회 이상 tool call rollout에서 end-to-end 실행이 최대 약 40% 빨라진 사례를 언급한다. (developers.openai.com)

tool-call loop는 대화가 아니라 운송 체계다

에이전트 제품을 채팅 UI로만 보면 설계가 틀어진다. 장기 작업의 본체는 메시지가 아니라 반복 루프다. 모델이 tool을 고르고, 애플리케이션이 실행하고, 결과를 되돌리고, 모델이 다음 결정을 내린다.

이때 매번 전체 문맥을 다시 보내는 구조는 단순하지만 둔하다. 상태 복원, 인증, payload 재구성, event listener 재설정이 turn마다 반복된다. 사용자는 이 시간을 reasoning으로 오해한다.

Persistent agent loop transport의 목표는 모델을 더 똑똑하게 만드는 것이 아니다. 이미 발생한 tool-call 왕복을 한 세션 안에서 계속 흘러가게 만드는 것이다.

Responses WebSocket mode에서는 response.create event가 일반 Responses create body와 유사하게 동작한다. 다만 stream, background 같은 transport-specific field는 쓰지 않는다. 이어지는 turn은 previous_response_id와 새 tool output만 보낸다. (developers.openai.com)

세션화의 핵심은 상태를 작게 보내는 것이다

Persistent transport를 붙였는데도 느린 팀은 대개 같은 실수를 한다. WebSocket을 열어 놓고도 매번 전체 대화, 전체 tool result, 전체 파일 요약을 다시 보낸다. 그러면 연결만 바뀌었지 loop 구조는 그대로다.

설계 항목 느린 구현 세션화 구현
continuation 전체 history 재전송 previous_response_id 기준 연결
tool output 원문 덩어리 삽입 call_id에 매핑된 신규 output만 전송
context 계속 누적 compact 또는 요약 checkpoint로 재기동
장애 처리 처음부터 재시작 저장 여부와 cache hit 기준 복구
병렬성 한 socket에 몰아넣음 run 단위 socket 분리

공식 문서는 active WebSocket connection에서 가장 최근 previous-response state를 connection-local in-memory cache로 유지한다고 설명한다. 그래서 최근 response에서 이어갈 때 latency benefit이 난다. 반대로 store=false 또는 ZDR 환경에서 cache에 없는 ID를 부르면 persisted fallback이 없고 previous_response_not_found가 난다. (developers.openai.com)

따라서 설계 기준은 분명하다. 보안상 store=false를 택했다면 장애 복구용 compacted window나 최소 재현 context를 애플리케이션 쪽에 둔다. store=true를 택했다면 오래된 response ID hydrate는 가능하지만, in-memory continuation만큼 빠르다고 기대하지 않는다.

harness가 tool 왕복을 소유해야 한다

이 패턴은 프론트엔드 WebSocket 문제가 아니다. agent harness 문제다. harness가 call_id, tool schema, 실행 상태, retry, approval, compaction, reconnect를 소유해야 한다.

AX Ops 관점에서 persistent loop transport의 최소 구성은 네 가지다.

  1. run_idresponse_id를 분리한다. 제품의 업무 단위와 모델 응답 단위를 섞지 않는다.
  2. 모든 tool call은 call_id 기준으로 idempotent하게 처리한다.
  3. socket은 한 번에 하나의 in-flight response만 둔다. 병렬 run은 socket을 나눈다.
  4. 60분 제한, reconnect, previous_response_not_found를 정상 경로로 설계한다.

OpenAI 문서도 한 WebSocket connection이 여러 response.create를 받을 수 있지만 순차 실행이며, multiplexing은 지원하지 않고, connection duration은 60분으로 제한된다고 명시한다. (developers.openai.com)

이 구조가 잡히면 UX도 바뀐다. 사용자는 빈 로딩 화면을 보지 않는다. tool-call arguments가 채워지는 순간, 실행 중인 tool, 대기 중인 승인, 재시도 상태를 event stream으로 본다. Responses API의 function calling streaming은 호출되는 함수와 argument 생성 과정을 실시간으로 드러낼 수 있다. (platform.openai.com)

참고와 다음 행동

요약하면, 장기 에이전트의 지연은 prompt만 다듬어서는 줄지 않는다. loop transport, state continuation, tool output mapping, reconnect policy가 함께 설계돼야 한다. WebSocket은 기능이 아니라 운영 경계다.

참고:

AX LABS는 이 transport를 API 샘플이 아니라 운영 가능한 agent harness로 설계한다. 장기 작업 에이전트를 제품에 넣는다면 먼저 loop의 소유권부터 정리해야 한다: AX Ops 방법론 →