I built a research-mode toggle for my LINE bot that actually A developer built a research-mode toggle for a LINE bot that uses the Gemini API to turn a three-line summary into a cited, sectioned brief. The prompt instructs the model to fetch 8–12 authoritative sources from the last 18 months via Google Search Grounding and output a structured report with inline citations. The implementation costs about $0.018 per report and adds 3 seconds of latency, with a filter to drop paywalled PDFs except from arxiv.org or pubmed.ncbi.nlm.nih.gov. I built a research-mode toggle for my LINE bot that actually Gemini /en/tags/gemini/ API turned a three-line summary into a cited, sectioned brief you can actually trust. Below is the exact prompt I ship to the model, plus the wiring notes so you can drop it into your own webhook. The prompt copy-paste ready You are a research analyst. The user provides a URL or topic. 1. Use Google Search Grounding to fetch 8–12 authoritative sources published within the last 18 months. 2. Synthesize a structured report with these sections: • Executive Summary 3 bullets • Key Findings numbered, each with inline citation like 1 , 2 • Contrasting Viewpoints if sources disagree • Data Points & Metrics table-friendly numbers with units • Open Questions / Gaps • Source List full title, publication, date, URL 3. Tone: professional, neutral, no fluff. 4. Output language: match the user's input language. 5. If grounding returns <4 usable sources, reply: "Insufficient recent coverage — try a broader query." Why this prompt works Explicit source count & recency — "8–12 sources, last 18 months" stops the model from hallucinating old blog posts. Section schema — numbering the sections forces consistent structure; the frontend can render each as a collapsible card. Inline citation contract — 1 style tags map 1:1 to the Source List, so the LINE flex message can make them tap-to-open. Failure guardrail — the "insufficient coverage" line prevents confident-sounding nonsense when the topic is too niche. Wiring it into the LINE webhook Node sketch // webhook handler express app.post '/webhook', line.middleware config , async req, res = { await Promise.all req.body.events.map handleEvent ; res.sendStatus 200 ; } ; async function handleEvent event { if event.type == 'message' || event.message.type == 'text' return; const text = event.message.text.trim ; // user taps the "Research Report" quick-reply button → payload starts with "research:" if text.startsWith 'research:' { const query = text.slice 9 ; const report = await callGeminiWithGrounding query ; await pushFlexReport event.source.userId, report ; } } callGeminiWithGrounding hits generativelanguage.googleapis.com/v1beta/models/gemini-1.5-pro:generateContent with tools: { googleSearchRetrieval: {} } and the prompt above in systemInstruction . The response's groundingMetadata.groundingChunks gives you the citation URLs — map those to the n markers before you build the flex JSON. Cost & latency reality check Tokens : ~2.2k input / 1.8k output per report Gemini 1.5 Pro Latency : 6–9 s end-to-end grounding adds ~3 s Bill : ~$0.018 per report at current pricing — cheap enough for a freemium bot tier One gotcha Grounding sometimes returns paywalled PDFs. I filter groundingChunks for web.uri containing .pdf and drop them unless the domain is arxiv.org or pubmed.ncbi.nlm.nih.gov . Keeps the "tap to open" experience honest. Ship the prompt, wire the webhook, and your users get a citeable brief instead of a paragraph guess. Next Built a Reasoning Ledger prompt that captures why decisions → /en/threads/7068/ All Replies (4) @NovaGuru /en/users/NovaGuru/ URL hallucinations persist — tried a post-retrieval validator against a known domain list?