from crewai import Task from crewai import Agent def build_tasks(agents: dict[str, Agent], query: str, depth: str, session_id: str) -> list[Task]: max_sources = {"quick": 5, "standard": 10, "deep": 15}.get(depth, 10) is_fast_moving = depth != "deep" search_task = Task( description=f""" Search for high-quality sources on the following research topic: RESEARCH TOPIC: {query} SEARCH DEPTH: {depth} (quick=5 sources, standard=10, deep=15) Instructions: 1. Use Tavily Web Search for general/news sources — request raw_content=True 2. Use arXiv Academic Search if the topic is scientific or technical 3. Use Semantic Scholar Search for academic papers with citation counts 4. Search with 2-3 different query variations to cover multiple angles 5. Collect up to {max_sources * 2} raw results (they will be filtered next) 6. Return ALL results as a single JSON list under the key "results" Each result must have: url, title, content, published_date, source """, expected_output=( "A JSON object with key 'results' containing a list of source dicts. " "Each dict has: url (str), title (str), content (str, full text), " "published_date (str or null), source (str). Minimum 8 results." ), agent=agents["researcher"], ) credibility_task = Task( description=f""" Score and filter the sources collected by the Research Specialist. Instructions: 1. Take the full results list from the previous task output 2. Call the Source Credibility Scorer tool with: - sources_json: the JSON string of all results - fast_moving_topic: {str(is_fast_moving).lower()} 3. The tool will return accepted sources (score >= 0.35) and a dropped count 4. Return the accepted sources list as-is — do not modify scores Topic context: {query} """, expected_output=( "A JSON object with key 'accepted' containing scored source dicts. " "Each dict has: url, title, content, credibility_score (float 0-1), " "confidence ('high' or 'low'), published_date. Sorted by credibility_score desc." ), agent=agents["credibility_analyst"], context=[search_task], ) rag_task = Task( description=f""" Embed the accepted sources and retrieve the most relevant chunks. SESSION_ID: {session_id} RESEARCH QUESTION: {query} Instructions: 1. Take the accepted sources list from the previous task 2. Call Embed Sources into Vector Store with: - sources_json: JSON string of the accepted sources list - session_id: "{session_id}" 3. After embedding completes, call Retrieve Relevant Chunks with: - query: "{query}" - session_id: "{session_id}" - n_results: 12 4. Return the retrieved chunks with their metadata """, expected_output=( "A JSON object with key 'chunks'. Each chunk has: text (str), " "url (str), title (str), credibility_score (float), confidence (str). " "Also include 'accepted_sources' list for the reference section." ), agent=agents["rag_engineer"], context=[credibility_task], ) synthesis_task = Task( description=f""" Write a comprehensive, fully cited research report on: RESEARCH QUESTION: {query} Use ONLY the retrieved chunks provided by the RAG Pipeline Engineer. STRICT RULES: 1. Every factual claim MUST be followed by an inline citation [N] matching a source 2. ONLY cite sources whose chunks appear in the context — never invent a citation 3. If you cannot find evidence for a claim in the chunks, write "INSUFFICIENT EVIDENCE" instead 4. Do not use any prior knowledge — only what appears in the retrieved chunks OUTPUT FORMAT (use exactly these headers): ## Research Question {query} ## Key Findings [Bullet points with inline citations [N]] ## Detailed Analysis [Multiple paragraphs with inline citations [N]] ## Points of Uncertainty or Disagreement [What the sources disagree on, or gaps in evidence] ## Synthesis [Your integrated conclusion from the evidence] ## References [Numbered list: [1] Title — URL (credibility: X.XX)] ## Confidence Assessment [HIGH / MEDIUM / LOW / INSUFFICIENT — one paragraph explaining why] Criteria: - HIGH: 5+ high-credibility sources (score > 0.75), consistent findings - MEDIUM: 3+ sources with score > 0.55, or minor source disagreement - LOW: Fewer than 3 reliable sources, or significant disagreement - INSUFFICIENT: Could not find adequate evidence to answer reliably """, expected_output=( "A complete Markdown research report with inline [N] citations, " "a numbered reference list, and a confidence assessment label. " "No fabricated facts. Every claim is backed by a chunk from the retrieved context." ), agent=agents["synthesis_analyst"], context=[rag_task], ) return [search_task, credibility_task, rag_task, synthesis_task]