A multi-agent framework for adversarial news bias navigation.
Five agents deconstruct news articles into interpretable framing maps, exposing ideological omissions, rhetorical manipulation, and the gap between competing political readings of the same event.
Paper: NewsLens: A Multi-Agent Framework for Adversarial News Bias Navigation — Joy Bose (preprint, 2026)
Most bias detection tools label an article as "left" or "right". NewsLens instead asks: where exactly do left and right framings diverge, what does each framing omit, and what do both framings jointly ignore?
The system runs five agents in sequence:
| Agent | Input | Output |
|---|---|---|
| Fact Verifier | Article text | Verified events, contested claims, structural omissions |
| Progressive Analyst | Article text | Progressive framing, linguistic markers, omissions |
| Conservative Analyst | Article text | Conservative framing, linguistic markers, omissions |
| Propaganda Detector | Article text | Manipulation index, technique attribution (span-level) |
| Neutral Summarizer | Article + all agent outputs | Omission map, de-biased summary, media literacy takeaway |
The Progressive and Conservative Analysts receive only the raw article text, not each other's outputs. This prevents anchoring and keeps the framing divergence genuine.
Two metrics come out of the pipeline:
- PDS (Perspective Divergence Score): Jaccard distance between left and right ideological framing word sets. 0 means identical framings, 1 means maximally divergent.
- MI (Manipulation Index): 0.0 to 1.0, assigned by the Propaganda Detector based on density and severity of detected rhetorical techniques.
No API key needed. Runs on a free Google Colab T4 GPU.
- Open
newslens_colab.ipynbin Google Colab - Runtime → Change runtime type → T4 GPU
- Run all cells top to bottom
- Results download automatically as
bias_results.jsonandmetrics_table1.csv
To run locally with Mistral via Ollama:
# Install Ollama and pull Mistral
ollama pull mistral
# Clone and install
git clone https://github.com/joyboseroy/newslens
cd newslens
pip install -r requirements.txt
# Run on sample data (no internet needed)
cd newsbiasagents
PYTHONPATH=. OLLAMA_MODEL=mistral python3 main.py --mode local --data_dir data/ --dry_run
# Run on a single URL
PYTHONPATH=. OLLAMA_MODEL=mistral python3 main.py --mode url --url "https://..."Local runs on laptop CPU take 45-60 minutes per article with Mistral 7B. Use Colab if you want reasonable speed.
newslens/
├── newslens_colab.ipynb # Main Colab notebook (Qwen2.5-3B, no API key)
├── stats.py # Statistical analysis (Mann-Whitney U tests)
├── requirements.txt
├── README.md
│
├── newsbiasagents/ # Local pipeline (Mistral via Ollama)
│ ├── main.py # Entry point
│ ├── agents/
│ │ ├── pipeline.py # LangGraph state machine
│ │ └── prompts.py # All 5 agent system prompts
│ ├── utils/
│ │ ├── gdelt_fetcher.py # GDELT same-event article clustering
│ │ ├── scraper.py # Full-text extraction
│ │ └── sample_data.py # Kashmir test cluster (no scraping needed)
│ ├── graph/
│ │ └── falkor_writer.py # FalkorDB Cypher writes (optional)
│ └── data/ # Cluster JSON files
│
├── figures/
│ ├── newslens_architecture.png # Figure 1: Pipeline diagram
│ └── newslens_message_flow.svg # Figure 2: Message-passing schema
│
└── results/
├── bias_results_kashmir_mistral.json # Mistral 7B, 4 articles
├── bias_results_all_qwen.json # Qwen 3B, 15 articles
└── metrics_summary.csv
| Model | Where | VRAM | Time per article |
|---|---|---|---|
| Qwen2.5-3B-Instruct (4-bit NF4) | Colab T4 (free) | ~2GB | 75-107s |
| Mistral 7B Instruct | Local CPU via Ollama | RAM only | 45-60 min |
The Colab notebook is the easiest starting point. The local pipeline is there for offline use and reproducibility.
Evaluated on 15 articles across four geopolitical clusters (Kashmir, Gaza, Climate Policy, Ukraine) using Qwen2.5-3B-Instruct, with cross-model validation using Mistral 7B on the Kashmir cluster.
| Framing group | n | PDS mean | MI mean |
|---|---|---|---|
| Conservative/right | 6 | 0.888 | 0.600 |
| Center | 4 | 0.907 | 0.300 |
| Progressive/left-center | 5 | 0.734 | 0.380 |
Center outlets show the highest PDS. Conservative outlets show the highest MI. Mann-Whitney U tests find no significant between-group differences at n=15, which we report as a sample-size limitation rather than a null finding.
All five prompts are in newsbiasagents/agents/prompts.py and reproduced in Appendix A of the paper. Each uses one worked example (few-shot). At 3B scale, zero-shot prompting tends to produce schema echo rather than substantive analysis.
- n=15 is not enough for statistical inference. The results are directionally interesting but need replication at larger scale.
- Qwen2.5-3B occasionally fails to parse JSON correctly (1 failure in 75 agent invocations in our run). Larger models are more reliable.
- Jaccard PDS ignores semantic similarity between paraphrased framings. A sentence-embedding alternative is noted in the paper but not yet implemented stably.
- Articles were manually collected. Automated ingestion via GDELT is implemented but requires scraping infrastructure.
@article{bose2026newslens,
title={NewsLens: A Multi-Agent Framework for Adversarial News Bias Navigation},
author={Bose, Joy},
year={2026},
note={Preprint}
}Will be updated with arXiv ID on submission.
Extends:
- Patankar & Bose (ICMLA 2017) — word-vector bias geometry
- Patankar, Bose & Khanna (ICSC 2019) — bias-aware news recommendation