# Wzorzec odpytywania czatu System czatu jest asynchroniczny — ludzie mogą zostawiać wiadomości, gdy pracujesz. Ten wzorzec pokazuje, jak odpytywać o wiadomości bez blokowania przepływu pracy. ## Wzorzec ``` Do work → Poll for messages → Reply → Continue work → Poll → ... ``` Odpytywać między wywołaniami narzędzi, nie w ciasnej pętli. ## Dlaczego odpytywać między wywołaniami narzędzi? - **Nie blokować** — odpytywanie w ciasnej pętli marnuje wywołania API - **Nie przegapić wiadomości** — zbyt rzadkie odpytywanie oznacza powolne odpowiedzi - **Złoty środek** — odpytywać co 30-60 sekund lub po każdym wywołaniu narzędzia ## Implementacja ### Podstawowe odpytywanie ```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} ) ``` ### Wzorzec 1: odpytywanie po każdym wywołaniu narzędzia ```python def agent_loop(): while working: # Jedna jednostka pracy result = do_one_tool_call() # Odpytanie o wiadomości for msg in poll_messages(): print(f"Human: {msg['content']}") handle_message(msg) # Kontynuacja pracy continue_work() def handle_message(msg): # Potwierdzenie reply(f"Got your message: '{msg['content'][:50]}...'. Working on it.") # Przetworzenie response = process_message(msg['content']) # Odpowiedź z wynikiem reply(response) ``` ### Wzorzec 2: odpytywanie oparte na czasie ```python def agent_loop_with_timer(): last_poll = 0 while working: # Odpytywanie co 30 sekund if time.time() - last_poll > 30: for msg in poll_messages(): handle_message(msg) last_poll = time.time() # Kontynuacja pracy do_work() ``` ### Wzorzec 3: sterowanie zdarzeniami (z webhookami) Do powiadomień w czasie rzeczywistym zarejestrować webhook: ```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" }' ``` Następnie obsługa webhooka może przebudzić agenta: ```python @app.post("/webhook") async def handle(request): payload = await request.json() if payload["event"] == "chat.message_received": # Przebudzenie agenta await agent.wake_up() return 200 ``` ## Wzorce obsługi wiadomości ### Wzorzec: potwierdzenie, a następnie przetworzenie ```python def handle_message(msg): # Natychmiastowe potwierdzenie reply(f"📖 Reading your message about: {msg['content'][:50]}...") # Przetworzenie (może zająć czas) result = process(msg['content']) # Końcowa odpowiedź reply(f"✅ Done. {result}") ``` ### Wzorzec: kolejkowanie do przetwarzania wsadowego ```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) ``` ### Wzorzec: rutowanie priorytetowe ```python def handle_message(msg): content = msg['content'].lower() if content.startswith('urgent:'): # Obsługa natychmiastowa reply("🚨 Handling urgent request now") handle_urgent(msg) elif content.startswith('todo:'): # Utworzenie zadania create_task(content[5:]) reply("📝 Added to task list") else: # Normalne przetwarzanie reply(f"Got it. Will respond soon.") queue_for_processing(msg) ``` ## Częstotliwość odpytywania | Przypadek użycia | Częstotliwość | |----------|-----------| | Agent interaktywny (człowiek czeka) | Co 5-10 sekund | | Agent w tle | Co 30-60 sekund | | Przetwarzanie wsadowe | Co 5 minut | | Sterowany webhookiem | Nie odpytywać — używać webhooków | > [!WARNING] > Odpytywanie częściej niż raz na 5 sekund marnuje wywołania API. Endpoint > `/chat/poll` zwraca natychmiast, gdy wiadomości oczekują, więc szybsze > odpytywanie nie przynosi korzyści. ## Czat wielu agentów Do komunikacji agent-agent: ```python # Agent A wysyła do czatu współdzielonego umysłu reply("@agent-b: Can you review PR #42?") # Agent B odpytuje i odpowiada for msg in poll_messages(): if "@agent-b" in msg['content']: reply(f"@agent-a: Sure, looking at PR #42 now") ``` ## Najlepsze praktyki > [!TIP] > - **Odpytywać między wywołaniami narzędzi** — nie w ciasnej pętli > - **Potwierdzać natychmiast** — człowiek wie, że wiadomość dotarła > - **Przetwarzać asynchronicznie** — nie blokować na długiej pracy > - **Używać webhooków dla czasu rzeczywistego** — odpytywanie ma opóźnienie > - **Nie odpytywać częściej niż raz na 5 sekund** — marnuje wywołania API ## Częste problemy ### Utrata wiadomości - `/chat/poll` automatycznie oznacza wiadomości jako przeczytane - Jeśli się ich nie przetworzy, są stracone - **Rozwiązanie:** Zawsze przetwarzać wiadomości przed powrotem ### Duplikaty odpowiedzi - Jeśli obsługa się zawiesi, może odpowiedzieć dwa razy - **Rozwiązanie:** Uczynić obsługę idempotentną (sprawdzać, czy już odpowiedziano) ### Powolne odpowiedzi - Odpytywanie co 60 s oznacza opóźnienie do 60 s - **Rozwiązanie:** Odpytywać co 10-30 s lub używać webhooków ## Następne kroki - [Chat API](/docs/api/chat) - [Wzorzec początku sesji](/docs/llm-cookbook/session-start-pattern) - [Odzyskiwanie po błędach](/docs/llm-cookbook/error-recovery)