메뉴
HN
Hacker News • 58일 전

AI 에이전트 프로덕션 인프라 패턴

IMP
8/10
핵심 요약

AI 에이전트를 단순한 웹 API 요청처럼 취급하면 실제 프로덕션 환경에서 치명적인 오류를 겪게 됩니다. 에이전트의 장기 실행, 상태 유지, 비결정성이라는 특징을 고려하여 작업을 비동기 큐로 분리해야 합니다. 안정적인 서비스를 위해 웹-큐-워커(Web-Queue-Worker) 아키텍처 도입과 안전한 재시도 로직 구현이 필수적입니다.

번역된 본문

클라우드를 전환하시나요? 최대 1만 달러의 크레딧과 실무 지원을 제공해 드립니다. 지금 신청하세요.

회사 / 2026년 7월 20일

에이전트 애플리케이션을 위한 인프라 패턴 (Infrastructure Patterns for Agentic Applications) Jacob Prall / 2026년 7월 20일

대부분의 팀은 에이전트를 구축할 때 일반적인 웹 기능을 만들 때와 같은 방식을 사용합니다. 모델을 라우트 핸들러로 감싸고, 요청을 파싱한 다음, 응답을 기다리는 방식입니다. 데모 수준에서는 이 방식이 괜찮습니다. 하지만 프로덕션 환경에서는 가장 먼저 망가지는 부분이기도 합니다.

에이전트는 오래 실행되고(long-running), 상태를 유지하며(stateful), 비결정적(non-deterministic)입니다. 이들은 도구를 호출하고, 외부 API를 기다리며, 하위 작업으로 분기하고, 속도 제한에 걸리고, 다단계 시퀀스 도중에 충돌이 발생하기도 합니다. 에이전트가 단일 HTTP 요청에 묶여 있다면, 애플리케이션의 신뢰성을 비결정적인 루프의 실제 경과 시간(wall-clock time)에 의존하게 만드는 것과 같습니다. 데모 수준을 넘어서려면 이러한 결합을 끊어내야 합니다.

이 글에서는 팀들이 불안정한 에이전트 스크립트를 확장 가능하고 탄력적인 프로덕션 시스템으로 전환하기 위해 사용하는 세 가지 핵심 패턴을 살펴봅니다.

에이전트의 본질

에이전트의 핵심은 '루프(loop)'입니다. 목표를 받고, 다음에 할 일을 결정하고, 모델이나 도구를 호출하고, 결과를 관찰하고, 상태를 업데이트한 뒤, 완료될 때까지 반복합니다. 이 루프는 단순한 웹 아키텍처에 적용하기 매우 까다로운 몇 가지 특징을 가지고 있습니다.

에이전트는 오래 실행됩니다. 일반적인 API 요청은 빨리 끝나야 하지만, 에이전트는 종종 완료하는 데 몇 시간 심지어 며칠이 걸리기도 합니다.

에이전트는 상태를 유지합니다. 실행(run)은 단일 함수 호출이 아닙니다. 여기에는 목표, 계획, 도구 호출 및 출력, 재시도, 에러, 결정, 그리고 최종 결과물이 포함됩니다. 프로세스가 중단되면 이미 무슨 일이 일어났는지 알아야 합니다. 그렇지 않으면 진행 상황을 잃거나 맹목적으로 작업을 다시 실행하게 됩니다. 특히 오래 실행되는 에이전트의 경우 이는 좋은 상황이 아닙니다.

에이전트는 비결정적입니다. 전통적인 워크플로우 코드는 명시된 절차를 따르지만, 에이전트 코드는 런타임에 모델이 다음 행동을 선택합니다. 이로 인해 복구, 재실행, 디버깅이 훨씬 어려워집니다. 하나의 실행이 3단계로 끝날 수도 있고 30단계가 걸릴 수도 있습니다. 여러 도구에 걸쳐 작업이 분산되거나, 사람의 응답을 기다리거나, 대용량의 중간 결과물을 생성하거나, 중간에 멈출 수도 있습니다. 인프라는 타임아웃, 예산, 체크포인트, 승인 및 명시적인 종료 조건을 통해 이러한 예측 불가능성에 경계를 설정해야 합니다.

종합해 보면, 이러한 특성들은 에이전트가 단순히 애플리케이션 코드로 감싼 모델 호출 그 이상을 필요로 한다는 것을 의미합니다. 실행을 요청에서 분리하는 아키텍처와 진행 상황을 유지하고 결정을 기록하며, 부작용을 제어하고, 모델의 컨텍스트와 분리하여 결과물을 관리하는 인프라가 필요합니다.

패턴: 웹-큐-워커 (Web-Queue-Worker)

첫 번째 프로덕션 패턴은 에이전트 전체를 웹 요청 내부에서 실행하는 것을 멈추는 것입니다. HTTP 요청의 수명은 에이전트 실행의 수명으로 적합하지 않습니다. 대신 영구적인 실행 기록을 생성하고, 작업을 큐에 넣은 다음, 즉시 반환해야 합니다. 이를 통해 애플리케이션에는 다음과 같은 명확한 경계가 생깁니다:

  • API는 작업을 큐에 넣습니다.
  • 큐는 작업을 안정적으로 저장합니다.
  • 워커(Worker)가 작업을 실행합니다.
  • 데이터베이스는 진행 상황을 기록합니다.
  • 클라이언트는 실행 ID를 즉시 받습니다.
  • 에이전트는 다른 곳에서 실행됩니다.
  • 사용자는 상태를 확인하거나, 업데이트를 구독하거나, 실행이 완료되면 콜백을 받습니다.

큐는 작업을 생성하는 주체와 수행하는 주체 사이의 튼튼한 버퍼입니다. 실행이 일반적인 요청보다 오래 걸리고, 작업이 대부분 독립적이며, 워커 확장, 재시도 또는 트래픽 폭주를 흡수해야 할 때 이 패턴이 기본 시작점이 됩니다.

하지만 함정이 있습니다. 큐는 작업이 존재한다는 것은 알지만, 그 작업이 속한 논리적 프로세스는 알지 못합니다. 단일 백그라운드 작업이라면 문제가 없습니다. 하지만 20개의 종속적 단계, 3번의 재시도, 2개의 분기, 그리고 사람의 승인을 기다리는 일시 정지 등은 큐가 대신 관리해 주지 않습니다. 이러한 로직은 결국 직접 구축해야 합니다. 앞으로 살펴보겠지만, 이때 바로 워크플로우 엔진이 필요해지는 지점입니다.

신뢰성: 안전한 재시도와 부분적 실패

작업을 큐로 이동시키는 것은 실행 시간의 수명 문제를 해결할 뿐입니다. 실행의 내구성(durability) 문제를 해결하지는 못합니다. 대부분의 프로덕션 큐는 '최소 한 번 이상 실행(at-least-once)' 방식입니다. 즉, 작업이 두 번 이상 실행될 수 있습니다. 이는 작업 손실을 막기 위한 의도적인 트레이드오프이며, 여러분의 코드는 이 상황에서도 살아남아야(견뎌내야) 합니다. 에이전트가 도구를 호출하고 쓰기를 실행할 수 있게 되면...

원문 보기
원문 보기 (영어)
Switching clouds? Get up to $10K in credits + hands-on help. Apply now Company July 20, 2026 Company Infrastructure Patterns for Agentic Applications Jacob Prall July 20, 2026 Jacob Prall Most teams start building agents the same way they build any other web feature: wrap the model in a route handler, parse the request, and wait for the response. This is fine for a demo. It's also the first thing to break in production. Agents are long-running, stateful, and non-deterministic. They call tools, wait for external APIs, branch into subtasks, hit rate limits, and crash halfway through multi-step sequences. If your agent is tied to a single HTTP request, you've coupled your application's reliability to the wall-clock time of a non-deterministic loop. Moving past the demo means breaking that coupling. This post walks through the three core patterns teams use to turn fragile agent scripts into scalable, resilient production systems. The Nature of Agents At the core of an agent is a loop: receive a goal, decide what to do next , call a model or tool, observe the result, update state, repeat until done. That loop has a few properties that make it hostile to naive web architectures. Agents are long-running. A normal API request should finish quickly. Agents often don't, somtimes taking hours or even days to complete. Agents are stateful. A run isn't one function call. It's a goal, a plan, tool calls and outputs, retries, errors, decisions, and a final output. If the process crashes, you need to know what already happened. If not, you either lose progress or rerun work blindly. Neither is great, especially for long-running agents. Agents are non-deterministic. Traditional workflow code says: Agent code says: The model chooses the next action at runtime, which makes recovery, replay, and debugging much harder. A run may take three steps or thirty. It may fan out across several tools, wait for a human, produce large intermediate artifacts, or stop early. Infrastructure has to set boundaries around that unpredictability with timeouts, budgets, checkpoints, approvals, and explicit termination conditions. Taken together, these properties mean agents need more than model calls wrapped in application code. They need architecture that decouples runs from requests, and infrastructure that preserves progress, records decisions, controls side effects, and manages artifacts separately from model context. Pattern: Web-Queue-Worker The first production pattern is to stop running the whole agent inside the web request. A request is the wrong lifetime for an agent run. It should create a durable run record, enqueue the work, and return immediately. That gives the application a simple boundary: The API enqueues the job. The queue stores the job durably. The worker executes the job. The database records progress. The client gets a run ID immediately. The agent runs somewhere else. The user checks status, subscribes to updates, or receives a callback when the run completes. A queue is a durable buffer between the thing that creates work and the thing that performs it. This is the default starting point when runs are longer than a normal request, tasks are mostly independent, and you need worker scaling, retries, or burst absorption. The trap: a queue knows a job exists, but it doesn't know the logical process that job belongs to. One background job is fine. Twenty dependent steps, three retries, two branches, and a human approval pause is not something a queue manages for you. You'll build that logic yourself. As we'll see later, that's where workflow engines come in. Reliability: Safe Retries and Partial Failure Moving work to a queue solves the lifetime problem. It does not solve for durability of execution. Most production queues are at-least-once : a job may run more than once. That's a deliberate tradeoff to avoid losing work, and your code has to survive it. Once an agent can call tools, write records, send messages, or provisions resources, retry behavior becomes part of the application’s correctness model. Two disciplines matter most. Idempotency answers what happens when a single step runs twice. Compensation answers what happens when a run stops partway through a sequence of steps. Retries make the first a requirement. Permanent failures make the second necessary for production. Agents that touch remote services needs both. Idempotency: Surviving a Step That Runs Twice Bad worker code assumes no crash between steps: Better code creates an idempotency boundary : For agents, every side-effecting tool call needs the same treatment: check for a completed record before calling the tool, upsert a "running" record, call the tool, mark it complete. Retry is not a recovery strategy unless the retried operation is safe. Compensation: Surviving a Run That Stops Halfway Consider an agent that completes three of five steps: it charges a card, provisions a resource, and sends a confirmation email. Then step four then fails permanently. None of the first three steps can be rolled back with a database transaction, since a charge is not undone by deleting a database row; the money has already moved. Restarting the run from step one would recharge the card and resend the email, recreating the exact duplicate-side-effect problem idempotency was meant to prevent. Distributed systems have a standard answer to this: the saga pattern . For every side-effecting action an agent can take, define a compensating action that reverses the effect. A charge is reversed with a refund. An email is reversed with a correction message. When a run fails permanently, the orchestrator walks the completed steps in reverse order and runs their compensations. Compensations must be idempotent in the same way forward actions are. Compensations can also fail on their own; a refund API can be unavailable just as easily as a charge API. A compensation chain needs a bounded retry, a dead-letter path for compensations that will not complete, and a manual escape hatch. Without these, a failed run can end up half-undone instead of half-done, which is not an improvement. Compensation is not always the right response to a partial failure. If four of five parallel sub-orders succeeded and one failed, completing the four and dropping the fifth is often the better outcome. This avoids unwinding work that succeeded. Compensation is worth building when partial success is unacceptable, not as a default response to any failure. Idempotency covers a step that runs twice. Compensation covers a run that stops halfway through. Both are required whether the run is executed by a simple worker or by a workflow engine. A queue distributes work, but it does not remember the shape of a run. It knows that a job exists. It does not know that step three depends on step two, that a human approval is pending, that two branches need to join before synthesis, or that compensation should run if the final step fails. Pattern: Workflows Once the hard part is no longer where should this job run? but what should happen next, given what already happened? , you have moved from queueing into orchestration. A workflow engine provides that orchestration layer. It stores the history of a run: which steps started, completed, failed, retried, timed out, or waited for external input. In a workflow, a crash doesn't mean starting over. Every workflow system divides the code into the same two roles: a coordinator that decides what happens next, and steps that do the actual work — model calls, tool executions, record writes. The names vary from engine to engine, but the division of responsibility is the concept that matters: decisions live in one layer, effects live in the other. The coordinator has one hard rule: given the same history, it must always make the same decisions. This is because of how recovery works. After a crash, the engine rebuilds a run by re-executing the decision logic from the top,