VibecoderMcSwaggins commited on
Commit
2763672
Β·
1 Parent(s): 53bf395

feat(phase8): implement Report Agent for structured scientific report generation

Browse files

- Introduced `ReportAgent` to generate comprehensive research reports from evidence and hypotheses.
- Added `ResearchReport` model with sections for executive summary, methodology, findings, limitations, and references.
- Updated MagenticOrchestrator to include ReportAgent as the final synthesis step in the workflow.
- Implemented report generation flow and markdown rendering for output.
- Added unit tests to ensure functionality of ReportAgent and report generation process.

docs/implementation/08_phase_report.md ADDED
@@ -0,0 +1,630 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Phase 8 Implementation Spec: Report Agent
2
+
3
+ **Goal**: Generate structured scientific reports with proper citations and methodology.
4
+ **Philosophy**: "Research isn't complete until it's communicated clearly."
5
+ **Prerequisite**: Phase 7 complete (Hypothesis Agent working)
6
+
7
+ ---
8
+
9
+ ## 1. Why Report Agent?
10
+
11
+ Current limitation: **Synthesis is basic markdown, not a scientific report.**
12
+
13
+ Current output:
14
+ ```
15
+ ## Drug Repurposing Analysis
16
+ ### Drug Candidates
17
+ - Metformin
18
+ ### Key Findings
19
+ - Some findings
20
+ ### Citations
21
+ 1. [Paper 1](url)
22
+ ```
23
+
24
+ With Report Agent:
25
+ ```
26
+ ## Executive Summary
27
+ One-paragraph summary for busy readers...
28
+
29
+ ## Research Question
30
+ Clear statement of what was investigated...
31
+
32
+ ## Methodology
33
+ - Sources searched: PubMed, DuckDuckGo
34
+ - Date range: ...
35
+ - Inclusion criteria: ...
36
+
37
+ ## Hypotheses Tested
38
+ 1. Metformin β†’ AMPK β†’ neuroprotection (Supported: 7 papers, Contradicted: 2)
39
+
40
+ ## Findings
41
+ ### Mechanistic Evidence
42
+ ...
43
+ ### Clinical Evidence
44
+ ...
45
+
46
+ ## Limitations
47
+ - Only English language papers
48
+ - Abstract-level analysis only
49
+
50
+ ## Conclusion
51
+ ...
52
+
53
+ ## References
54
+ Properly formatted citations...
55
+ ```
56
+
57
+ ---
58
+
59
+ ## 2. Architecture
60
+
61
+ ### Phase 8 Addition
62
+ ```
63
+ Evidence + Hypotheses + Assessment
64
+ ↓
65
+ Report Agent
66
+ ↓
67
+ Structured Scientific Report
68
+ ```
69
+
70
+ ### Report Generation Flow
71
+ ```
72
+ 1. JudgeAgent says "synthesize"
73
+ 2. Magentic Manager selects ReportAgent
74
+ 3. ReportAgent gathers:
75
+ - All evidence from shared context
76
+ - All hypotheses (supported/contradicted)
77
+ - Assessment scores
78
+ 4. ReportAgent generates structured report
79
+ 5. Final output to user
80
+ ```
81
+
82
+ ---
83
+
84
+ ## 3. Report Model
85
+
86
+ ### 3.1 Data Model (`src/utils/models.py`)
87
+
88
+ ```python
89
+ class ReportSection(BaseModel):
90
+ """A section of the research report."""
91
+ title: str
92
+ content: str
93
+ citations: list[str] = Field(default_factory=list)
94
+
95
+
96
+ class ResearchReport(BaseModel):
97
+ """Structured scientific report."""
98
+
99
+ title: str = Field(description="Report title")
100
+ executive_summary: str = Field(
101
+ description="One-paragraph summary for quick reading",
102
+ min_length=100,
103
+ max_length=500
104
+ )
105
+ research_question: str = Field(description="Clear statement of what was investigated")
106
+
107
+ methodology: ReportSection = Field(description="How the research was conducted")
108
+ hypotheses_tested: list[dict] = Field(
109
+ description="Hypotheses with supporting/contradicting evidence counts"
110
+ )
111
+
112
+ mechanistic_findings: ReportSection = Field(
113
+ description="Findings about drug mechanisms"
114
+ )
115
+ clinical_findings: ReportSection = Field(
116
+ description="Findings from clinical/preclinical studies"
117
+ )
118
+
119
+ drug_candidates: list[str] = Field(description="Identified drug candidates")
120
+ limitations: list[str] = Field(description="Study limitations")
121
+ conclusion: str = Field(description="Overall conclusion")
122
+
123
+ references: list[dict] = Field(
124
+ description="Formatted references with title, authors, source, URL"
125
+ )
126
+
127
+ # Metadata
128
+ sources_searched: list[str] = Field(default_factory=list)
129
+ total_papers_reviewed: int = 0
130
+ search_iterations: int = 0
131
+ confidence_score: float = Field(ge=0, le=1)
132
+
133
+ def to_markdown(self) -> str:
134
+ """Render report as markdown."""
135
+ sections = [
136
+ f"# {self.title}\n",
137
+ f"## Executive Summary\n{self.executive_summary}\n",
138
+ f"## Research Question\n{self.research_question}\n",
139
+ f"## Methodology\n{self.methodology.content}\n",
140
+ ]
141
+
142
+ # Hypotheses
143
+ sections.append("## Hypotheses Tested\n")
144
+ for h in self.hypotheses_tested:
145
+ status = "βœ… Supported" if h.get("supported", 0) > h.get("contradicted", 0) else "⚠️ Mixed"
146
+ sections.append(
147
+ f"- **{h['mechanism']}** ({status}): "
148
+ f"{h.get('supported', 0)} supporting, {h.get('contradicted', 0)} contradicting\n"
149
+ )
150
+
151
+ # Findings
152
+ sections.append(f"## Mechanistic Findings\n{self.mechanistic_findings.content}\n")
153
+ sections.append(f"## Clinical Findings\n{self.clinical_findings.content}\n")
154
+
155
+ # Drug candidates
156
+ sections.append("## Drug Candidates\n")
157
+ for drug in self.drug_candidates:
158
+ sections.append(f"- **{drug}**\n")
159
+
160
+ # Limitations
161
+ sections.append("## Limitations\n")
162
+ for lim in self.limitations:
163
+ sections.append(f"- {lim}\n")
164
+
165
+ # Conclusion
166
+ sections.append(f"## Conclusion\n{self.conclusion}\n")
167
+
168
+ # References
169
+ sections.append("## References\n")
170
+ for i, ref in enumerate(self.references, 1):
171
+ sections.append(
172
+ f"{i}. {ref.get('authors', 'Unknown')}. "
173
+ f"*{ref.get('title', 'Untitled')}*. "
174
+ f"{ref.get('source', '')} ({ref.get('date', '')}). "
175
+ f"[Link]({ref.get('url', '#')})\n"
176
+ )
177
+
178
+ # Metadata footer
179
+ sections.append("\n---\n")
180
+ sections.append(
181
+ f"*Report generated from {self.total_papers_reviewed} papers "
182
+ f"across {self.search_iterations} search iterations. "
183
+ f"Confidence: {self.confidence_score:.0%}*"
184
+ )
185
+
186
+ return "\n".join(sections)
187
+ ```
188
+
189
+ ---
190
+
191
+ ## 4. Implementation
192
+
193
+ ### 4.1 Report Prompts (`src/prompts/report.py`)
194
+
195
+ ```python
196
+ """Prompts for Report Agent."""
197
+
198
+ SYSTEM_PROMPT = """You are a scientific writer specializing in drug repurposing research reports.
199
+
200
+ Your role is to synthesize evidence and hypotheses into a clear, structured report.
201
+
202
+ A good report:
203
+ 1. Has a clear EXECUTIVE SUMMARY (one paragraph, key takeaways)
204
+ 2. States the RESEARCH QUESTION clearly
205
+ 3. Describes METHODOLOGY (what was searched, how)
206
+ 4. Evaluates HYPOTHESES with evidence counts
207
+ 5. Separates MECHANISTIC and CLINICAL findings
208
+ 6. Lists specific DRUG CANDIDATES
209
+ 7. Acknowledges LIMITATIONS honestly
210
+ 8. Provides a balanced CONCLUSION
211
+ 9. Includes properly formatted REFERENCES
212
+
213
+ Write in scientific but accessible language. Be specific about evidence strength."""
214
+
215
+
216
+ def format_report_prompt(
217
+ query: str,
218
+ evidence: list,
219
+ hypotheses: list,
220
+ assessment: dict,
221
+ metadata: dict
222
+ ) -> str:
223
+ """Format prompt for report generation."""
224
+
225
+ evidence_summary = "\n".join([
226
+ f"- [{e.citation.title}]({e.citation.url}): {e.content[:200]}..."
227
+ for e in evidence[:15]
228
+ ])
229
+
230
+ hypotheses_summary = "\n".join([
231
+ f"- {h.drug} β†’ {h.target} β†’ {h.pathway} β†’ {h.effect} (Confidence: {h.confidence:.0%})"
232
+ for h in hypotheses
233
+ ])
234
+
235
+ return f"""Generate a structured research report for the following query.
236
+
237
+ ## Original Query
238
+ {query}
239
+
240
+ ## Evidence Collected ({len(evidence)} papers)
241
+ {evidence_summary}
242
+
243
+ ## Hypotheses Generated
244
+ {hypotheses_summary}
245
+
246
+ ## Assessment Scores
247
+ - Mechanism Score: {assessment.get('mechanism_score', 'N/A')}/10
248
+ - Clinical Evidence Score: {assessment.get('clinical_score', 'N/A')}/10
249
+ - Overall Confidence: {assessment.get('confidence', 0):.0%}
250
+
251
+ ## Metadata
252
+ - Sources Searched: {', '.join(metadata.get('sources', []))}
253
+ - Search Iterations: {metadata.get('iterations', 0)}
254
+
255
+ Generate a complete ResearchReport with all sections filled in."""
256
+ ```
257
+
258
+ ### 4.2 Report Agent (`src/agents/report_agent.py`)
259
+
260
+ ```python
261
+ """Report agent for generating structured research reports."""
262
+ from collections.abc import AsyncIterable
263
+ from typing import Any
264
+
265
+ from agent_framework import (
266
+ AgentRunResponse,
267
+ AgentRunResponseUpdate,
268
+ AgentThread,
269
+ BaseAgent,
270
+ ChatMessage,
271
+ Role,
272
+ )
273
+ from pydantic_ai import Agent
274
+
275
+ from src.prompts.report import SYSTEM_PROMPT, format_report_prompt
276
+ from src.utils.config import settings
277
+ from src.utils.models import Evidence, MechanismHypothesis, ResearchReport
278
+
279
+
280
+ class ReportAgent(BaseAgent):
281
+ """Generates structured scientific reports from evidence and hypotheses."""
282
+
283
+ def __init__(
284
+ self,
285
+ evidence_store: dict[str, list[Evidence]],
286
+ ) -> None:
287
+ super().__init__(
288
+ name="ReportAgent",
289
+ description="Generates structured scientific research reports with citations",
290
+ )
291
+ self._evidence_store = evidence_store
292
+ self._agent = Agent(
293
+ model=settings.llm_provider,
294
+ output_type=ResearchReport,
295
+ system_prompt=SYSTEM_PROMPT,
296
+ )
297
+
298
+ async def run(
299
+ self,
300
+ messages: str | ChatMessage | list[str] | list[ChatMessage] | None = None,
301
+ *,
302
+ thread: AgentThread | None = None,
303
+ **kwargs: Any,
304
+ ) -> AgentRunResponse:
305
+ """Generate research report."""
306
+ query = self._extract_query(messages)
307
+
308
+ # Gather all context
309
+ evidence = self._evidence_store.get("current", [])
310
+ hypotheses = self._evidence_store.get("hypotheses", [])
311
+ assessment = self._evidence_store.get("last_assessment", {})
312
+
313
+ if not evidence:
314
+ return AgentRunResponse(
315
+ messages=[ChatMessage(
316
+ role=Role.ASSISTANT,
317
+ text="Cannot generate report: No evidence collected."
318
+ )],
319
+ response_id="report-no-evidence",
320
+ )
321
+
322
+ # Build metadata
323
+ metadata = {
324
+ "sources": list(set(e.citation.source for e in evidence)),
325
+ "iterations": self._evidence_store.get("iteration_count", 0),
326
+ }
327
+
328
+ # Generate report
329
+ prompt = format_report_prompt(
330
+ query=query,
331
+ evidence=evidence,
332
+ hypotheses=hypotheses,
333
+ assessment=assessment,
334
+ metadata=metadata
335
+ )
336
+
337
+ result = await self._agent.run(prompt)
338
+ report = result.output
339
+
340
+ # Store report
341
+ self._evidence_store["final_report"] = report
342
+
343
+ # Return markdown version
344
+ return AgentRunResponse(
345
+ messages=[ChatMessage(role=Role.ASSISTANT, text=report.to_markdown())],
346
+ response_id="report-complete",
347
+ additional_properties={"report": report.model_dump()},
348
+ )
349
+
350
+ def _extract_query(self, messages) -> str:
351
+ """Extract query from messages."""
352
+ if isinstance(messages, str):
353
+ return messages
354
+ elif isinstance(messages, ChatMessage):
355
+ return messages.text or ""
356
+ elif isinstance(messages, list):
357
+ for msg in reversed(messages):
358
+ if isinstance(msg, ChatMessage) and msg.role == Role.USER:
359
+ return msg.text or ""
360
+ elif isinstance(msg, str):
361
+ return msg
362
+ return ""
363
+
364
+ async def run_stream(
365
+ self,
366
+ messages: str | ChatMessage | list[str] | list[ChatMessage] | None = None,
367
+ *,
368
+ thread: AgentThread | None = None,
369
+ **kwargs: Any,
370
+ ) -> AsyncIterable[AgentRunResponseUpdate]:
371
+ """Streaming wrapper."""
372
+ result = await self.run(messages, thread=thread, **kwargs)
373
+ yield AgentRunResponseUpdate(
374
+ messages=result.messages,
375
+ response_id=result.response_id
376
+ )
377
+ ```
378
+
379
+ ### 4.3 Update MagenticOrchestrator
380
+
381
+ Add ReportAgent as the final synthesis step:
382
+
383
+ ```python
384
+ # In MagenticOrchestrator.__init__
385
+ self._report_agent = ReportAgent(self._evidence_store)
386
+
387
+ # In workflow building
388
+ workflow = (
389
+ MagenticBuilder()
390
+ .participants(
391
+ searcher=search_agent,
392
+ hypothesizer=hypothesis_agent,
393
+ judge=judge_agent,
394
+ reporter=self._report_agent, # NEW
395
+ )
396
+ .with_standard_manager(...)
397
+ .build()
398
+ )
399
+
400
+ # Update task instruction
401
+ task = f"""Research drug repurposing opportunities for: {query}
402
+
403
+ Workflow:
404
+ 1. SearchAgent: Find evidence from PubMed and web
405
+ 2. HypothesisAgent: Generate mechanistic hypotheses
406
+ 3. SearchAgent: Targeted search based on hypotheses
407
+ 4. JudgeAgent: Evaluate evidence sufficiency
408
+ 5. If sufficient β†’ ReportAgent: Generate structured research report
409
+ 6. If not sufficient β†’ Repeat from step 1 with refined queries
410
+
411
+ The final output should be a complete research report with:
412
+ - Executive summary
413
+ - Methodology
414
+ - Hypotheses tested
415
+ - Mechanistic and clinical findings
416
+ - Drug candidates
417
+ - Limitations
418
+ - Conclusion with references
419
+ """
420
+ ```
421
+
422
+ ---
423
+
424
+ ## 5. Directory Structure After Phase 8
425
+
426
+ ```
427
+ src/
428
+ β”œβ”€β”€ agents/
429
+ β”‚ β”œβ”€β”€ search_agent.py
430
+ β”‚ β”œβ”€β”€ judge_agent.py
431
+ β”‚ β”œβ”€β”€ hypothesis_agent.py
432
+ β”‚ └── report_agent.py # NEW
433
+ β”œβ”€β”€ prompts/
434
+ β”‚ β”œβ”€β”€ judge.py
435
+ β”‚ β”œβ”€β”€ hypothesis.py
436
+ β”‚ └── report.py # NEW
437
+ β”œβ”€β”€ services/
438
+ β”‚ └── embeddings.py
439
+ └── utils/
440
+ └── models.py # Updated with report models
441
+ ```
442
+
443
+ ---
444
+
445
+ ## 6. Tests
446
+
447
+ ### 6.1 Unit Tests (`tests/unit/agents/test_report_agent.py`)
448
+
449
+ ```python
450
+ """Unit tests for ReportAgent."""
451
+ import pytest
452
+ from unittest.mock import AsyncMock, MagicMock, patch
453
+
454
+ from src.agents.report_agent import ReportAgent
455
+ from src.utils.models import (
456
+ Citation, Evidence, MechanismHypothesis,
457
+ ResearchReport, ReportSection
458
+ )
459
+
460
+
461
+ @pytest.fixture
462
+ def sample_evidence():
463
+ return [
464
+ Evidence(
465
+ content="Metformin activates AMPK...",
466
+ citation=Citation(
467
+ source="pubmed",
468
+ title="Metformin mechanisms",
469
+ url="https://pubmed.ncbi.nlm.nih.gov/12345/",
470
+ date="2023",
471
+ authors=["Smith J", "Jones A"]
472
+ )
473
+ )
474
+ ]
475
+
476
+
477
+ @pytest.fixture
478
+ def sample_hypotheses():
479
+ return [
480
+ MechanismHypothesis(
481
+ drug="Metformin",
482
+ target="AMPK",
483
+ pathway="mTOR inhibition",
484
+ effect="Neuroprotection",
485
+ confidence=0.8,
486
+ search_suggestions=[]
487
+ )
488
+ ]
489
+
490
+
491
+ @pytest.fixture
492
+ def mock_report():
493
+ return ResearchReport(
494
+ title="Drug Repurposing Analysis: Metformin for Alzheimer's",
495
+ executive_summary="This report analyzes metformin as a potential...",
496
+ research_question="Can metformin be repurposed for Alzheimer's disease?",
497
+ methodology=ReportSection(
498
+ title="Methodology",
499
+ content="Searched PubMed and web sources..."
500
+ ),
501
+ hypotheses_tested=[
502
+ {"mechanism": "Metformin β†’ AMPK β†’ neuroprotection", "supported": 5, "contradicted": 1}
503
+ ],
504
+ mechanistic_findings=ReportSection(
505
+ title="Mechanistic Findings",
506
+ content="Evidence suggests AMPK activation..."
507
+ ),
508
+ clinical_findings=ReportSection(
509
+ title="Clinical Findings",
510
+ content="Limited clinical data available..."
511
+ ),
512
+ drug_candidates=["Metformin"],
513
+ limitations=["Abstract-level analysis only"],
514
+ conclusion="Metformin shows promise...",
515
+ references=[],
516
+ sources_searched=["pubmed", "web"],
517
+ total_papers_reviewed=10,
518
+ search_iterations=3,
519
+ confidence_score=0.75
520
+ )
521
+
522
+
523
+ @pytest.mark.asyncio
524
+ async def test_report_agent_generates_report(
525
+ sample_evidence, sample_hypotheses, mock_report
526
+ ):
527
+ """ReportAgent should generate structured report."""
528
+ store = {
529
+ "current": sample_evidence,
530
+ "hypotheses": sample_hypotheses,
531
+ "last_assessment": {"mechanism_score": 8, "clinical_score": 6}
532
+ }
533
+
534
+ with patch("src.agents.report_agent.Agent") as MockAgent:
535
+ mock_result = MagicMock()
536
+ mock_result.output = mock_report
537
+ MockAgent.return_value.run = AsyncMock(return_value=mock_result)
538
+
539
+ agent = ReportAgent(store)
540
+ response = await agent.run("metformin alzheimer")
541
+
542
+ assert "Executive Summary" in response.messages[0].text
543
+ assert "Methodology" in response.messages[0].text
544
+ assert "References" in response.messages[0].text
545
+
546
+
547
+ @pytest.mark.asyncio
548
+ async def test_report_agent_no_evidence():
549
+ """ReportAgent should handle empty evidence gracefully."""
550
+ store = {"current": [], "hypotheses": []}
551
+ agent = ReportAgent(store)
552
+
553
+ response = await agent.run("test query")
554
+
555
+ assert "Cannot generate report" in response.messages[0].text
556
+ ```
557
+
558
+ ---
559
+
560
+ ## 7. Definition of Done
561
+
562
+ Phase 8 is **COMPLETE** when:
563
+
564
+ 1. `ResearchReport` model implemented with all sections
565
+ 2. `ReportAgent` generates structured reports
566
+ 3. Reports include proper citations and methodology
567
+ 4. Magentic workflow uses ReportAgent for final synthesis
568
+ 5. Report renders as clean markdown
569
+ 6. All unit tests pass
570
+
571
+ ---
572
+
573
+ ## 8. Value Delivered
574
+
575
+ | Before (Phase 7) | After (Phase 8) |
576
+ |------------------|-----------------|
577
+ | Basic synthesis | Structured scientific report |
578
+ | Simple bullet points | Executive summary + methodology |
579
+ | List of citations | Formatted references |
580
+ | No methodology | Clear research process |
581
+ | No limitations | Honest limitations section |
582
+
583
+ **Sample output comparison:**
584
+
585
+ Before:
586
+ ```
587
+ ## Analysis
588
+ - Metformin might help
589
+ - Found 5 papers
590
+ [Link 1] [Link 2]
591
+ ```
592
+
593
+ After:
594
+ ```
595
+ # Drug Repurposing Analysis: Metformin for Alzheimer's Disease
596
+
597
+ ## Executive Summary
598
+ Analysis of 15 papers suggests metformin may provide neuroprotection
599
+ through AMPK activation. Mechanistic evidence is strong (8/10),
600
+ while clinical evidence is moderate (6/10)...
601
+
602
+ ## Methodology
603
+ Systematic search of PubMed and web sources using queries...
604
+
605
+ ## Hypotheses Tested
606
+ - βœ… Metformin β†’ AMPK β†’ neuroprotection (7 supporting, 2 contradicting)
607
+
608
+ ## References
609
+ 1. Smith J, Jones A. *Metformin mechanisms*. Nature (2023). [Link](...)
610
+ ```
611
+
612
+ ---
613
+
614
+ ## 9. Complete Magentic Architecture (Phases 5-8)
615
+
616
+ ```
617
+ User Query
618
+ ↓
619
+ Gradio UI
620
+ ↓
621
+ Magentic Manager (LLM Coordinator)
622
+ β”œβ”€β”€ SearchAgent ←→ PubMed + Web + VectorDB
623
+ β”œβ”€β”€ HypothesisAgent ←→ Mechanistic Reasoning
624
+ β”œβ”€β”€ JudgeAgent ←→ Evidence Assessment
625
+ └── ReportAgent ←→ Final Synthesis
626
+ ↓
627
+ Structured Research Report
628
+ ```
629
+
630
+ **This matches Mario's diagram** with the practical agents that add real value for drug repurposing research.