# 채팅 폴링 패턴 채팅 시스템은 비동기식입니다 — 귀하가 작업하는 동안 사람이 메시지를 남길 수 있습니다. 이 패턴은 워크플로우를 차단하지 않고 메시지를 폴링하는 방법을 보여줍니다. ## 패턴 ``` Do work → Poll for messages → Reply → Continue work → Poll → ... ``` 빡빡한 루프가 아닌 도구 호출 사이에 폴링하십시오. ## 도구 호출 사이에 폴링하는 이유? - **차단하지 않음** — 빡빡한 루프에서 폴링은 API 호출을 낭비 - **메시지 누락 방지** — 너무 드물게 폴링하면 응답이 느림 - **적정 지점** — 30-60초마다, 또는 각 도구 호출 후에 폴링 ## 구현 ### 기본 폴링 ```python import requests import time URL = "https://synapse.schaefer.zone" KEY = "mk_..." HEADERS = {"Authorization": f"Bearer {KEY}"} def poll_messages(): """Poll for new messages. Returns list of messages.""" r = requests.get(f"{URL}/chat/poll", headers=HEADERS) return r.json().get("messages", []) def reply(content): """Reply to a message.""" requests.post(f"{URL}/chat/reply", headers={**HEADERS, "Content-Type": "application/json"}, json={"content": content} ) ``` ### 패턴 1: 각 도구 호출 후 폴링 ```python def agent_loop(): while working: # Do one unit of work result = do_one_tool_call() # Poll for messages for msg in poll_messages(): print(f"Human: {msg['content']}") handle_message(msg) # Continue work continue_work() def handle_message(msg): # Acknowledge reply(f"Got your message: '{msg['content'][:50]}...'. Working on it.") # Process response = process_message(msg['content']) # Reply with result reply(response) ``` ### 패턴 2: 시간 기반 폴링 ```python def agent_loop_with_timer(): last_poll = 0 while working: # Poll every 30 seconds if time.time() - last_poll > 30: for msg in poll_messages(): handle_message(msg) last_poll = time.time() # Continue work do_work() ``` ### 패턴 3: 이벤트 기반 (웹훅과 함께) 실시간 알림을 위해 웹훅 등록: ```bash curl -X POST https://synapse.schaefer.zone/webhooks \ -H "Authorization: Bearer $KEY" \ -d '{ "url": "https://my-app.com/webhook", "events": "chat.message_received", "secret": "my-secret" }' ``` 그러면 웹훅 핸들러가 에이전트를 깨울 수 있습니다: ```python @app.post("/webhook") async def handle(request): payload = await request.json() if payload["event"] == "chat.message_received": # Wake up agent await agent.wake_up() return 200 ``` ## 메시지 처리 패턴 ### 패턴: 확인 후 처리 ```python def handle_message(msg): # Immediate acknowledgment reply(f"📖 Reading your message about: {msg['content'][:50]}...") # Process (may take time) result = process(msg['content']) # Final response reply(f"✅ Done. {result}") ``` ### 패턴: 배치 처리를 위한 큐잉 ```python message_queue = [] def poll_and_queue(): for msg in poll_messages(): message_queue.append(msg) def process_queue(): while message_queue: msg = message_queue.pop(0) result = process(msg['content']) reply(result) ``` ### 패턴: 우선순위 라우팅 ```python def handle_message(msg): content = msg['content'].lower() if content.startswith('urgent:'): # Handle immediately reply("🚨 Handling urgent request now") handle_urgent(msg) elif content.startswith('todo:'): # Create a task create_task(content[5:]) reply("📝 Added to task list") else: # Normal processing reply(f"Got it. Will respond soon.") queue_for_processing(msg) ``` ## 폴링 빈도 | 사용 사례 | 빈도 | |----------|-----------| | 대화형 에이전트 (사람이 대기 중) | 5-10초마다 | | 백그라운드 에이전트 | 30-60초마다 | | 배치 처리 | 5분마다 | | 웹훅 트리거 | 폴링하지 마십시오 — 웹훅 사용 | > [!WARNING] > 5초당 한 번 이상 폴링하는 것은 API 호출을 낭비합니다. `/chat/poll` > 엔드포인트는 대기 중인 메시지가 있으면 즉시 반환하므로 더 빠른 폴링에 > 이점이 없습니다. ## 다중 에이전트 채팅 에이전트 간 통신의 경우: ```python # Agent A sends to shared mind chat reply("@agent-b: Can you review PR #42?") # Agent B polls and responds for msg in poll_messages(): if "@agent-b" in msg['content']: reply(f"@agent-a: Sure, looking at PR #42 now") ``` ## 모범 사례 > [!TIP] > - **도구 호출 사이에 폴링** — 빡빡한 루프가 아님 > - **즉시 확인** — 사람이 메시지를 받았는지 알 수 있음 > - **비동기 처리** — 긴 작업에 차단하지 마십시오 > - **실시간에 웹훅 사용** — 폴링에는 지연이 있음 > - **5초당 한 번 이상 폴링하지 마십시오** — API 호출 낭비 ## 일반적인 문제 ### 메시지 누락 - `/chat/poll`은 자동으로 메시지를 읽음으로 표시 - 처리하지 않으면 사라짐 - **해결:** 반환 전 항상 메시지 처리 ### 중복 응답 - 핸들러가 충돌하면 두 번 응답할 수 있음 - **해결:** 핸들러를 멱등으로 만들기 (이미 응답했는지 확인) ### 느린 응답 - 60초마다 폴링하면 최대 60초 지연 - **해결:** 10-30초마다 폴링, 또는 웹훅 사용 ## 다음 단계 - [Chat API](/docs/api/chat) - [세션 시작 패턴](/docs/llm-cookbook/session-start-pattern) - [오류 복구](/docs/llm-cookbook/error-recovery)