장시간 실행되는 AI 에이전트에는 지속형 채널이 필요해요
OpenAI의 background mode 문서는 이제 일반적인 에이전트 문제를 설명해요. 추론 작업은 몇 분이 걸릴 수 있고, 개발자는 ID로 응답을 폴링하거나, 응답을 취소하거나, 기록된 sequence number부터 스트림을 다시 이어갈 수 있어요.1
핵심 요점은 무엇인가요?
- 장시간 실행되는 에이전트 작업에는 주소가 필요해요. 클라이언트는 같은 작업에 다시 연결하고, 알려진 커서부터 스트리밍하고, 방향 조정 명령을 보내고, 작업을 취소하고, 근거를 확인할 수 있어야 해요.
- 폴링만으로는 계약이 너무 빈약해요. 폴링은 상태를 알려줄 수 있지만, 본격적인 에이전트 작업에는 명령, 이벤트 이력, 재개 가능한 스트림, 산출물, 권한, 체크포인트도 필요해요.
- 지속 실행은 시스템의 일부만 해결해요. Temporal 방식의 작업 흐름은 실행 상태와 이벤트 이력을 보존하지만, 사용자는 실행 중인 작업을 둘러싼 지속적인 소통 표면도 필요해요.23
- WebSocket은 도움이 되지만, 소켓 자체가 전체 주소는 아니에요. 연결이 끊겨도 사용자가 에이전트 작업으로 돌아갈 경로가 사라져서는 안 돼요.
- 제품 표면이 중요해요. 사용자는 흩어진 로그와 낙관적인 상태 문구가 아니라, 근거와 결정, 다음 행동이 정리된 하나의 일관된 작업을 봐야 해요.
장시간 실행되는 AI 에이전트는 예전의 요청-응답 구조에 맞지 않아요. 일반적인 요청에는 엔드포인트, 응답, 제한 시간이 있어요. 하지만 본격적인 에이전트 작업에는 지속 시간, 이벤트 이력, 중간 산출물, 사용자 개입, 모델과 도구 상태, 취소 규칙, 그리고 떠났다가 돌아올 수 있는 사람이 함께 있어요.
빠진 객체는 또 하나의 채팅 메시지가 아니에요. 빠진 객체는 지속형 채널(durable channel), 즉 실행 중인 작업에 붙는 안정적인 주소예요.
저는 이미 관리형 에이전트가 실행 환경 인프라를 흡수하고 있다고 주장했고, 에이전트 실행 기록이 실행 환경 계약이 되고 있다고도 썼어요. 지속형 채널은 이 두 생각 사이에 놓여요. 실행 기록은 무슨 일이 있었는지 증명해요. 관리형 실행 환경은 작업을 계속 살려 둬요. 지속형 채널은 제품과 사용자가 작업이 살아 있는 동안 그 작업과 대화할 수 있게 해줘요.
예전 요청 모델에서는 무엇이 깨지나요?
예전 웹 모델은 계산이 요청 안에서 끝나거나 백그라운드 작업으로 넘어간다고 가정해요. 데이터베이스는 지속 상태를 저장해요. 애플리케이션 서버는 상태를 갖지 않도록 유지돼요. 클라이언트는 페이지를 새로고침하고, 다른 서버에 요청하고, 같은 데이터베이스 행을 읽을 수 있어요.
에이전트 작업은 이 모델에 3가지 방식으로 부담을 줘요. 몇 분이나 몇 시간 동안 실행될 수 있어요. 하나의 데이터베이스 기록으로 깔끔하게 줄이기 어려운 프로세스 상태를 지녀요. 그리고 보기, 중단, 승인, 방향 전환, 취소, 재개 같은 양방향 제어가 필요해요.
Zak Knill도 같은 압박을 라우팅 문제로 짚었어요. 그의 2026년 5월 글은 장시간 실행되고, 상태를 가지며, 상호작용하는 에이전트 작업에는 결과를 저장하는 데이터베이스만이 아니라 실제로 일을 하는 프로세스를 주소 지정할 수 있는 라우팅 가능한 기본 단위가 필요하다고 주장해요.4 이 관점에서 유용한 부분은 클라이언트가 원래의 소켓, 워커, 탭, 프로세스가 사라졌더라도 “작업 X에 명령 Y를 전달해”라고 말하고 싶어 한다는 점이에요.
백그라운드 작업은 여전히 단순한 작업에 적합할 수 있어요. 이미지 크기 조정, 송장 내보내기, 야간 동기화에는 대기 중, 실행 중, 성공, 실패 정도만 필요할 수 있어요. 하지만 사용자가 끝나기 전에 작업의 방향을 조정해야 하는 순간, 에이전트 작업은 선을 넘어가요.
폴링은 왜 부족한가요?
폴링은 클라이언트가 “아직 끝났나요?”라고 물을 방법을 줘요. 하지만 완전한 상호작용 계약을 주지는 않아요.
OpenAI의 background mode에 폴링이 포함된 이유는 폴링이 제한 시간 문제를 해결하기 때문이에요. 문서는 상태가 queued 또는 in_progress인 동안 background response를 가져오고, 종료 상태에 도달하면 멈추라고 안내해요.1 같은 페이지는 취소와 sequence_number 커서를 사용한 스트림 재개도 제공하는데, 이는 단순한 폴링을 넘어 더 풍부한 실행 작업 계약이 필요하다는 신호예요.1
폴링에서 멈춘 제품은 보통 에이전트 상태를 너무 많은 곳에 흩어 놓아요.
| 필요 | 얇은 폴링의 답 | 지속형 채널의 답 |
|---|---|---|
| 진행 상황 보기 | status = in_progress |
시간표시와 유형이 있는 추가 전용 이벤트 |
| 탭 연결이 끊긴 뒤 다시 연결 | 최신 행 폴링 | 커서 N 이후부터 스트림 재개 |
| 작업 방향 바꾸기 | 어딘가에 메모 쓰기 | 작업 X에 형식화된 신호 보내기 |
| 안전하게 취소 | 불리언 값 뒤집기 | 종료 이벤트가 기록되는 멱등 취소 명령 |
| 근거 검토 | 최종 텍스트 읽기 | 이벤트 이력, 산출물, 체크포인트 확인 |
| 제어 권한 부여 | 페이지 세션 신뢰 | 작업과 명령별 권한 확인 |
폴링은 하나의 접근 경로로 남을 수 있어요. 실수는 폴링을 제품 계약 자체로 취급하는 거예요.
지속형 채널에는 무엇이 들어가야 하나요?
지속형 채널은 하나의 실행 작업을 둘러싼 이름 있는 소통 계약이에요. 구현에는 작업 흐름 엔진, 큐, 이벤트 테이블, WebSocket, SSE 스트림, pub/sub 주제, 관리형 에이전트 세션 또는 이 조각들의 조합을 쓸 수 있어요. 중요한 것은 전송 방식보다 제품 계약이에요.
최소 계약에는 9가지가 필요해요.
| 필드 또는 엔드포인트 | 목적 |
|---|---|
run_id 또는 workflow_id |
작업의 안정적인 주소. |
GET /runs/{id} |
현재 상태, 소유자, 시간표시, 종료 상태, 요약. |
GET /runs/{id}/events?after=N |
재연결과 감사를 위한 순서 있는 이벤트 이력. |
GET /runs/{id}/stream?after=N |
알려진 커서부터 이어지는 재개 가능한 실시간 업데이트. |
POST /runs/{id}/signals |
approve, revise, pause, add context 같은 형식화된 방향 조정 명령. |
POST /runs/{id}/cancel |
종료 이벤트가 기록되는 멱등 취소. |
GET /runs/{id}/artifacts |
diff, 파일, 보고서, screenshot, 실행 기록, 그 밖의 증거. |
checkpoint events |
인수인계와 재개를 위한 사람이 읽을 수 있는 상태. |
| authorization checks | 작업별 읽기, 스트리밍, 신호, 산출물, 취소 권한. |
모든 이벤트에는 유형, sequence number, 시간표시, 행위자, payload 참조, 수정 정책이 필요해요. 이 구조가 없으면 이벤트 로그는 또 하나의 채팅 기록이 돼요.
채널에도 판단력이 필요해요. 사용자가 결정을 필요로 할 때 모든 token을 흘려보내지 마세요. 도구 실패를 친절한 spinner 뒤에 숨기지 마세요. 실행 중인 에이전트를 알림 폭풍으로 만들지 마세요. 좋은 채널은 사용자가 작업을 신뢰하고, 방향을 잡고, 멈추는 데 도움이 되는 몇 가지 이벤트만 보여줘요.
기존 시스템은 이 패턴을 어떻게 가리키고 있나요?
Temporal은 실행 측면에 성숙한 어휘를 제공해요. 작업 흐름 실행에는 이벤트 이력, 재실행, 결정론적인 작업 흐름 코드, 그리고 API 호출, 데이터베이스 질의, LLM 호출, 파일 I/O 같은 외부 작업을 위한 활동이 있어요.2 Temporal의 TypeScript message-passing 문서는 작업 흐름을 queries, signals, updates를 받는 상태 있는 서비스로 설명해요. 클라이언트는 작업 흐름 ID로 작업 흐름 핸들을 가져오고, 상태를 질의하고, 신호를 보내고, 업데이트를 실행할 수 있어요.3
이 모델은 에이전트 작업에 깔끔하게 대응돼요. 질의는 “이 실행 작업이 어떤 상태를 보고하나요?”에 답해요. 신호는 “방향을 바꿔 주세요”에 답해요. 업데이트는 “추적되는 변경을 수행하고 결과를 돌려주세요”에 답해요. 이벤트 이력은 “무슨 일이 있었나요?”에 답해요. 팀이 이 구조에서 배우기 위해 꼭 Temporal을 써야 하는 것은 아니지만, 이 구조는 에이전트 제품에 “백그라운드 작업 더하기 채팅”보다 나은 어휘를 줘요.
Cloudflare Durable Objects는 다른 조각, 즉 주소 지정 가능한 조율을 가리켜요. Cloudflare는 각 Durable Object를 storage가 있는 전역적으로 고유한 instance로 설명하며, 여러 클라이언트 사이의 stateful coordination에 유용하다고 말해요.5 WebSocket 문서는 오래 지속되는 양방향 연결과, object가 잠든 동안에도 클라이언트 연결을 유지하고 메시지가 도착하면 object를 깨우는 hibernation을 설명해요.6 이것이 Durable Objects를 범용 에이전트 실행 환경으로 만들어 주지는 않아요. 다만 실시간 에이전트 표면에 주소 지정 가능한 조율 객체가 왜 자연스럽게 느껴지는지 보여줘요.
Anthropic의 장시간 실행 에이전트 글은 사람의 작업 측면을 더해요. 그 글은 에이전트가 아직 많은 context window를 넘나드는 데 어려움을 겪는다고 말하며, 이후 작업 회차가 다음 작업 회차를 위해 명확한 산출물을 남기면서 점진적으로 진전하는 패턴을 설명해요.7 지속형 채널은 그런 산출물을 비공개 로그에 묻어 두지 말고 제품 표면으로 가져와야 해요.
무엇부터 만들면 좋을까요?
저라면 거대한 오케스트레이션 플랫폼이 아니라 작은 실행 작업 서비스부터 만들겠어요.
소유권, 상태, 시간표시, 현재 요약을 담는 runs table을 만드세요. 단조 증가하는 sequence number를 가진 run_events table 또는 stream을 만드세요. 큰 payload와 산출물은 별도로 저장한 뒤 이벤트에서 참조하세요. 재개 가능한 stream endpoint 하나와 형식화된 signal endpoint 하나를 추가하세요. 취소는 멱등으로 만드세요. 모든 상태 전환을 이벤트 로그에 넣으세요.
그다음 이벤트 어휘를 제한하세요.
| Event type | 의미 |
|---|---|
run.started |
시스템이 작업을 받아들이고 안정적인 ID를 할당했어요. |
agent.plan.updated |
에이전트가 현재 계획 또는 체크포인트를 바꿨어요. |
tool.started |
도구 또는 명령이 수정된 인수와 함께 시작됐어요. |
tool.finished |
도구 또는 명령이 상태, 지속 시간, 증거 참조와 함께 끝났어요. |
artifact.created |
diff, 파일, screenshot, 보고서 또는 실행 기록을 사용할 수 있게 됐어요. |
human.signal.received |
사용자가 형식화된 방향 조정 명령을 보냈어요. |
run.blocked |
작업에 권한, 입력 또는 외부 상태가 필요해요. |
run.cancelled |
시스템이 취소를 받아들이고 작업을 멈췄어요. |
run.completed |
작업이 근거를 갖춘 종료 성공 상태에 도달했어요. |
run.failed |
작업이 근거를 갖춘 종료 실패 상태에 도달했어요. |
이제 UI는 하나의 일관된 작업을 보여줄 수 있어요. 사용자는 떠났다가 돌아오고, 이벤트를 검토하고, 산출물을 확인하고, 같은 주소에서 방향을 조정할 수 있어요. 에이전트는 성공했다고 글로 주장하는 대신 상태 전환에 근거를 붙이기 시작할 수 있어요.
팀은 무엇을 피해야 하나요?
3가지 지름길을 피하세요.
첫째, 순수한 채팅 기록만 두지 마세요. 채팅은 작업을 시작하고 확인 질문을 모으는 데 쓸 수 있어요. 하지만 장시간 실행되는 작업의 유일한 실행 객체가 되어서는 안 돼요.
둘째, 원시 토큰 스트리밍을 주요 진행 표면으로 삼지 마세요. 토큰 스트림은 개발자가 지연 시간을 디버깅하는 데 도움이 되지만, 대부분의 사용자는 이정표, 차단 요소, 산출물, 결정을 필요로 해요. 지속형 채널은 전문가 검토용 원시 이벤트를 여전히 노출할 수 있어요.
셋째, 비공개 프로세스가 새어 나오지 않게 하세요. 공개 제품 표면은 근거를 보여줘야지, 비공개 프롬프트, 후크 본문, 로컬 파일 경로, 내부 채점 장치를 보여줘서는 안 돼요. 사용자는 작업을 신뢰할 만큼의 정보가 필요해요. 작업을 가능하게 만든 모든 내부 기법까지 알 필요는 없어요.
이 개인정보 경계는 에이전트 시스템에 관한 공개 글쓰기에도 적용돼요. 계약은 공유하세요. 비공개 장치는 비공개로 두세요.
지속형 채널은 평가를 어떻게 바꾸나요?
지속형 채널은 평가를 덜 연극적으로 만들어요.
최종 답변이 그럴듯하게 들리는지 묻는 대신, 평가자는 실행 작업을 확인할 수 있어요.
- 작업이 올바른 소유자, 권한, 범위로 시작했나요?
- 에이전트가 행동하기 전에 계획을 내보냈나요?
- 주장된 모든 산출물이 기록된 이벤트에서 나왔나요?
- 실패가 유용한 체크포인트를 만들었나요?
- 사용자 신호가 예상한 방식으로 작업을 바꿨나요?
- 취소가 하나의 종료 상태로 끝났나요?
- 최종 보고서가 이벤트 로그의 근거를 인용했나요?
이 목록은 증거 관문을 실행 환경이 직접 지원할 수 있는 것으로 바꿔요. 또한 정리 계층과도 연결돼요. 많은 에이전트 제품은 지저분한 작업을 이해 가능하고, 재개 가능하고, 검토 가능하게 만들어 승리할 거예요.
빠른 요약
장시간 실행되는 AI 에이전트에는 지속형 채널이 필요해요. 사용자가 작업으로 돌아갈 안정적인 경로가 필요하기 때문이에요. 폴링은 상태를 알려줄 수 있지만, 전체 계약을 혼자 담을 수는 없어요. 좋은 에이전트 작업에는 작업 흐름 ID, 순서 있는 이벤트, 재개 가능한 스트림, 형식화된 신호, 멱등 취소, 산출물 참조, 권한, 사람이 읽을 수 있는 체크포인트가 필요해요. 지속 실행은 작업을 계속 살려 두고, 지속형 채널은 사용자와 제품이 그 작업과 상호작용하게 해줘요.
FAQ: 장시간 실행되는 AI 에이전트와 지속형 채널
장시간 실행되는 AI 에이전트에는 Temporal이 필요한가요?
아니요. Temporal은 팀에 강력한 작업 흐름 어휘와 성숙한 실행 모델을 제공하지만, 지속형 채널 계약은 더 단순한 인프라에서도 실행할 수 있어요. 안정적인 실행 작업 ID, 순서 있는 이벤트, 재개 가능한 스트림, 형식화된 명령, 산출물부터 시작하세요. 재시도, 재실행, 타이머, 운영 규모가 이를 정당화할 때 작업 흐름 엔진으로 옮기면 돼요.
WebSocket만 있으면 에이전트 진행 상황에 충분한가요?
아니요. WebSocket은 실시간 양방향 연결을 제공해요. 제품에는 여전히 지속적인 주소, 이벤트 이력, 재연결 커서, 권한, 종료 상태가 필요해요. 소켓은 채널을 운반할 수 있지만, 소켓이 전체 채널을 정의해서는 안 돼요.
폴링은 항상 나쁜가요?
아니요. 폴링은 단순한 상태 확인에 적합하고 예비 경로로 남을 수 있어요. 문제는 폴링이 장시간 실행되는 에이전트 작업을 관찰하고, 방향을 조정하고, 복구하는 유일한 방법이 될 때 시작돼요.
작은 팀은 무엇을 먼저 만들어야 하나요?
runs resource와 추가 전용 run_events log를 만드세요. 이벤트 로그에 sequence number가 생기면 재개 가능한 stream을 추가하세요. 형식화된 signal은 제품이 안전하게 이행할 수 있는 명령에만 추가하세요. approve, pause, revise, add context, cancel 같은 명령이에요.
에이전트 작업 이벤트에는 무엇이 들어가야 하나요?
상태 전환, 계획, 도구 시작과 종료, 산출물 생성, 사람의 신호, 차단 요소, 취소, 실패, 완료를 기록하세요. 민감한 payload는 inline event text에 넣지 마세요. 비공개 세부 사항은 수정된 참조와 접근 확인 뒤에 저장하세요.
References
-
OpenAI, “Background mode,” OpenAI API 문서, 2026년 5월 18일 접속. 비동기 background Responses, response ID로 하는 polling, terminal statuses, cancellation,
sequence_numbercursors,starting_after를 사용한 stream resumption의 출처. ↩↩↩ -
Temporal, “Temporal Workflow,” Temporal 문서, 2026년 5월 18일 접속. Temporal의 작업 흐름 실행, 이벤트 이력, 재실행, 결정론적인 작업 흐름 코드, 그리고 API calls, database queries, LLM invocations, file I/O를 위한 활동의 출처. ↩↩
-
Temporal, “Workflow message passing - TypeScript SDK,” Temporal 문서, 2026년 5월 18일 접속. 상태 있는 서비스로 작동하는 작업 흐름, queries, signals, updates, 작업 흐름 핸들, 작업 흐름 ID의 출처. ↩↩
-
Zak Knill, “LLMs are breaking 20 year old system design,” /dev/knill, 2026년 5월 13일. 라우팅 기본 단위 관점, 폴링 비판, 연결로서의 WebSocket 구분, 지속형 채널 주장의 출처. ↩
-
Cloudflare, “Durable Objects,” Cloudflare Developers 문서, 2026년 5월 18일 접속. Durable Objects를 storage가 있는 전역적으로 고유한 stateful coordination objects로 설명한 출처. ↩
-
Cloudflare, “Use WebSockets,” Cloudflare Developers 문서, 2026년 5월 18일 접속. WebSocket endpoints로서의 Durable Objects, long-lived bidirectional connections, WebSocket Hibernation behavior의 출처. ↩
-
Anthropic, “Effective harnesses for long-running agents,” Anthropic Engineering, 2025년 11월 26일. 많은 context window를 가로지르는 장시간 실행 에이전트, 작업 회차를 넘는 점진적 진전, 이후 작업 회차를 위한 명확한 산출물의 출처. ↩