Wzorzec odpytywania czatu
Jak odpytywać o wiadomości od człowieka między wywołaniami narzędzi bez blokowania przepływu pracy.
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
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
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
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:
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:
@app.post("/webhook")
async def handle(request):
payload = await request.json()
if payload["event"] == "chat.message_received":
# Przebudzenie agenta
await agent.wake_up()
return 200Wzorce obsługi wiadomości
Wzorzec: potwierdzenie, a następnie przetworzenie
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
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
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 |
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:
# 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
Częste problemy
Utrata wiadomości
/chat/pollautomatycznie 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