# AI Lead Funnel — Echogate LLM + Telethon Full runnable pattern for Telegram accounts that auto-respond to DMs using LLM. ## When to use - User wants a Telegram account to auto-respond to incoming messages - Redirect leads to a target contact (@lordrax, etc.) - Need a human-like operator that filters and redirects ## Key design decisions 1. **Stage-gated dialog, not free-form LLM** — LLM is too eager to share contact immediately or too chatty. Use 3 hardcoded stages with separate system prompts. 2. **Processing lock per user** — `asyncio.Event` or `set()` to prevent parallel handler invocations. 3. **Typing indicator before every message** — `SetTypingRequest(SendMessageTypingAction())` + `asyncio.sleep(3-10s)`. 4. **State persistence** — JSON file with `stage`, `history`, `done` per user. Survives restarts. ## LLM config ```python from openai import AsyncOpenAI llm = AsyncOpenAI( base_url="https://api.echogate.one/v1", api_key="[REDACTED]", timeout=60, ) # gpt-5.5: ~3s response — fast enough for real-time # deepseek-v4-pro: ~21s — too slow, breaks the illusion ``` ## Stage prompts ```python STAGE_PROMPTS = { 0: """Ты — оператор. Строгий, деловой, немногословный. Это ПЕРВОЕ сообщение в диалоге. Ответь коротко (1 предложение). Поприветствуй и спроси что интересует / по какому вопросу. НЕ давай контакты. НЕ упоминай @target. НЕ давай ссылки. НЕ используй эмодзи. Стиль: спокойный, уверенный, без лишней вежливости.""", 1: """Ты — оператор. Строгий, деловой. Это ВТОРОЕ сообщение. Ответь на вопрос пользователя коротко (1-2 предложения). Упомяни что детали, цены и наличие — у партнёра @target. НЕ давай прямую ссылку пока. НЕ используй эмодзи. Стиль: уверенный, деловой. Не извиняйся, не будь подобострастным.""", 2: """Ты — оператор. Строгий, деловой. Это ТРЕТЬЕ (финальное) сообщение. Дай прямую ссылку. Скажи обратиться туда, это всё. Закругляйся. 1 предложение. НЕ продолжай диалог. НЕ используй эмодзи.""", } ``` ## Processing lock pattern ```python processing = set() # Track user_ids currently being processed @client.on(events.NewMessage(incoming=True)) async def handler(event): uk = str(event.sender_id) if uk in processing: log(f"Already processing {uk}, skip") return processing.add(uk) try: # ... generate and send reply ... finally: processing.discard(uk) ``` ## Race condition: why it happens When two messages arrive within 2 seconds (e.g. user sends empty message then "привет"), the Telethon event handler fires twice in parallel. Both invocations see the same state (stage=0, our_count=0), both generate Stage 0 replies, and both send simultaneously. Result: two greeting messages back-to-back, no dialog. The processing lock prevents this — the second invocation sees `uk in processing` and skips. ## Fallback messages Always have hardcoded fallbacks per stage in case LLM times out: ```python FALLBACKS = { 0: "Добрый. По какому вопросу?", 1: "По наличию и ценам — обратись к @target", 2: "Напиши @target: https://t.me/target", } ``` ## Full runnable script See `C:\Users\User\Desktop\_PROJECTS\рассылка\lead_funnel.py` for the production version with: - echogate.one LLM integration - 3-stage dialog with processing lock - Typing indicator + random delays - JSON state persistence - @Tomitotototo → @lordrax funnel ## Pitfalls learned 2026-08-11 1. **JSON account metadata is stale**: `sessions/*.json` files say `status: "Active"`, `spamblock: "none"` but 90%+ of accounts are actually RESTRICTED/BANNED. Always verify by connecting and sending a test message to "me". 2. **SpamBot "RESTRICTED" ≠ can't DM**: Account may be RESTRICTED for groups but perfectly fine for private messages. The real test is `client.send_message("me", "test")`. 3. **Free-form LLM fails**: Without stage-gating, LLM either shares contact immediately (no dialog) or never shares it (endless chat). Hardcode stages. 4. **No processing lock = duplicate messages**: Parallel handler invocations on rapid-fire messages produce duplicate greetings. 5. **deepseek-v4-pro is 21s**: Too slow for real-time. gpt-5.5 is 3s. Pick fast models. 6. **No skip phrases in lead funnel**: Respond to EVERYTHING — "ку", "привет", empty messages. No intent detection needed.