당신의 AI 에이전트와 당신 사이에 있는 누락된 레이어

발행: (2026년 3월 8일 AM 03:14 GMT+9)
10 분 소요
원문: Dev.to

Source: Dev.to

위 링크에 포함된 전체 텍스트를 제공해 주시면, 해당 내용을 한국어로 번역해 드리겠습니다.

개발자들이 선택하는 세 가지 패턴

패턴 1: 터미널 베이비시팅

python my_agent.py >> agent.log 2>&1 &
tail -f agent.log

에이전트를 실행하고 로그를 확인하며, 충돌 시 재시작합니다.

  • 한 번 실행되는 배치 작업 (스크래핑, 처리, 작업이 완료될 때까지 실행되고 출력 파일을 작성하는 경우)에는 잘 동작합니다.
  • 에이전트가 비행 중에 인간의 결정을 필요로 하거나, 여러 에이전트를 동시에 실행하면서 전역 상태를 파악해야 할 순간 문제가 발생합니다.

패턴 2: 폴링 (REST API)

# Check status
curl http://localhost:8000/status
# {"status": "running", "task": "scraping page 42/100", "errors": 0}

# Ask it something
curl -X POST http://localhost:8000/query \
  -d '{"question": "what have you found so far?"}'

더 나은 점은 프로그래밍 방식의 대화가 가능하다는 것입니다.
하지만 파워 다이나믹은 일방적입니다: 에이전트는 요청에만 응답할 수 있습니다. 2 AM에 속도 제한에 걸리거나 예상치 못한 이상 현상을 만나면, 에이전트는 이를 알려줄 수 없으며, 별도의 스크립트를 사용해 확인해야 합니다.

  • 동기식 도구에는 적합하지만 흥미로운 에이전트는 장시간 실행되며 연락을 취할 수 있는 능력이 필요합니다.

패턴 3: 양방향 메시징

에이전트는 상태 변화가 있거나 도움이 필요할 때 WebSocket이나 Server‑Sent Events (SSE)를 통해 메시지를 푸시합니다. 사용자는 비동기적으로 응답합니다. 채널이 히스토리를 추적하므로 컨테이너가 재시작되더라도 컨텍스트를 잃지 않습니다.

# Agent sends you a message when it hits an edge case
import requests

headers = {
    "Authorization": f"Bearer {API_KEY}",
    "Content-Type": "application/json"
}

# The agent encountered a decision point and escalates
requests.post(
    f"{API}/channels/{CHANNEL_ID}/messages",
    headers=headers,
    json={
        "content": (
            "Found 3 candidates matching the criteria. "
            "Should I contact all three, or just the top one? @human"
        )
    },
)

푸시 알림을 받고 답변하면 에이전트가 워크플로를 재개합니다.

이것이 인간이 함께 일하는 방식입니다. 기본적으로 에이전트 오케스트레이션을 이렇게 구축하지 않는 것은 이상합니다.

에이전트 통신을 위한 아키텍처 요구사항

양방향 pub/sub 레이어를 에이전트에 구축하려면 몇 가지 비‑트리비얼한 인프라 요구사항에 직면하게 됩니다:

  1. 지속적인 대화 기록 – 에이전트의 유일한 메모리가 토큰 윈도우라면, 프로세스가 재시작될 때 기록이 사라집니다. 채널 히스토리를 추적할 수 있는 빠르고 내구성 있는 데이터스토어(Postgres, Redis 등)가 필요합니다.
  2. 통합 인증 – 에이전트는 API 키를 사용하고, 사람은 세션 쿠키나 OAuth를 사용합니다. 대부분의 웹 프레임워크는 하나는 잘 처리하고 다른 하나는 별도로 붙입니다. 올바른 통신 레이어는 두 가지를 동일한 채팅 방에서 일급 시민으로 다뤄야 합니다.
  3. 실시간 전송 – 몇 초마다 REST 엔드포인트를 폴링하는 방식은 깨지기 쉽고 비효율적입니다. WebSockets 또는 SSE를 사용하면 상호작용이 실제 터미널 세션처럼 느껴집니다.
  4. 낮은 진입 장벽 – 통신 레이어 설정이 에이전트 자체를 작성하는 것보다 더 어려우면, 개발자는 print() 문으로 되돌아가게 됩니다.

최소 작업 예제

아래는 전체 흐름을 보여줍니다 – 에이전트가 자체 워크스페이스를 부트스트랩하고, 자격 증명을 얻은 뒤 메시지를 주고받습니다.

단계 1: 부트스트랩

curl -X POST http://localhost:8080/api/v1/bootstrap \
  -H "Content-Type: application/json" \
  -d '{
        "owner_email": "admin@local",
        "owner_password": "changeme",
        "agent_name": "research-bot",
        "agent_description": "Handles research tasks"
      }'

응답

{
  "api_key":    "au_abc123...",
  "channel_id": "ch_xyz789...",
  "invite_url": "http://localhost:3001/invite/TOKEN"
}

invite_url을 브라우저에서 엽니다. 이제 여러분과 에이전트가 같은 채널을 공유하게 됩니다.

단계 2: 에이전트가 메시지 전송

import json, requests, websocket

API      = "http://localhost:8080/api/v1"
KEY      = "au_abc123..."
CHANNEL  = "ch_xyz789..."
headers  = {
    "Authorization": f"Bearer {KEY}",
    "Content-Type": "application/json"
}

# REST: fire‑and‑forget
requests.post(
    f"{API}/channels/{CHANNEL}/messages",
    headers=headers,
    json={"content": "Started research run. Will update with findings."}
)

# WebSocket: real‑time back‑and‑forth
ws = websocket.create_connection(f"ws://localhost:8080/ws?token={KEY}")

# 인간의 답변을 듣기
while True:
    msg = json.loads(ws.recv())
    if msg["type"] == "new_message":
        sender  = msg["message"]["author_name"]
        content = msg["message"]["content"]
        if sender != "research-bot":          # 인간이 보낸 메시지
            handle_human_reply(content)

SDK도, 프레임워크에 대한 락인도 없습니다. 코드가 HTTP 호출을 하거나 WebSocket을 열 수 있다면—Python, Node, Go, Bash 등 어떤 환경에서도 동작합니다.

멀티‑에이전트 패턴

메시징 레이어가 구축되면 멀티‑에이전트 조정이 자연스럽게 따라옵니다.

  • 오케스트레이터는 작업을 생성하고, 이를 전문가에게 라우팅하며, 결과를 집계합니다. 각 에이전트는 자체 API 키를 가지고; 오케스트레이터는 모든 채널을 읽고 에스컬레이션을 처리합니다.
  • 에이전트는 공유 채널에 게시하고, 다른 에이전트는 이를 읽고 반응합니다. 이러한 느슨한 결합은 병목이 되는 단일 중앙 디스패처를 피합니다.
# Agent 1 posts result to shared channel
ws.send(json.dumps({
    "type":       "send_message",
    "channel_id": SHARED_CHANNEL,
    "content":    "Research complete: found 3 key findings. See attached."
}))

# Agent 2 is subscribed to the same channel
msg = json.loads(ws.recv())
if msg["type"] == "new_message":
    if "Research complete" in msg["message"]["content"]:
        trigger_analysis_pipeline(msg["message"]["content"])

간단한 pub/sub 채널을 사용하면 에이전트가 긴밀한 오케스트레이션 없이도 협업하고, 에스컬레이션하며, 실패로부터 복구할 수 있습니다.

그냥 pub/sub

차이점은 인간이 같은 채널에 참여할 수 있다는 것입니다 — 에이전트가 협업하는 모습을 보고, 질문을 하며, 그들을 재지시할 수 있습니다. 협업이 눈에 보입니다.

사고 방식의 전환

에이전트를 불투명한 백엔드 작업처럼 대하는 것을 멈추세요.

그 전환은 필요한 오케스트레이션 레이어를 완전히 바꿉니다. 무거운 텔레메트리 대시보드가 필요하지 않습니다. 에이전트가 정확히 무엇을 하고 있는지 보고, 흐트러질 때 개입할 수 있는 빠르고 투명한 메시징 버스가 필요합니다.

Agent United

나는 이 마찰 지점을 계속 겪었기 때문에 **Agent United**를 만들었습니다. 이것은 오픈소스이며 자체 호스팅 가능한 채팅 플랫폼으로, WebSocket 연결, 인증 분리, 지속적인 상태 관리를 모두 처리해 주어 에이전트 로직에만 집중할 수 있습니다. 단일 명령으로 실행됩니다:

docker-compose up

인간 감독이 필요한 시스템을 구축하고 있다면 GitHub에서 코드를 가져오거나 **docs.agentunited.ai/docs/agent‑guide**에서 API 패턴을 확인할 수 있습니다.

결론

하지만 궁극적으로 구현은 중요하지 않다. 패턴이 중요하다. 반응하는 시스템을 구축하라.


단어 수: ~1,050 단어

대상: Dev.to (전체 포스트) + HN 링크 포스트 3월 9일 + r/MachineLearning 패턴 섹션만

0 조회
Back to Blog

관련 글

더 보기 »

게시물 테스트 dev.to — Trust Layer 소개 (v3)

왜 당신의 AI 에이전트는 암호학적 증명이 필요한가 AI 에이전트는 결정을 내리고, 계약에 서명하고, APIs를 호출하며, 돈을 이동시킵니다. 하지만 문제는 이렇습니다: 아무도 p...