Multi-agent AI newsletter pipeline: scouts news, research, tools, video, jobs, and events; runs analysis and prompt engineering; then compiles a Markdown issue with Jinja2. Built with LangGraph and AWS Bedrock (langchain-aws).
main.py runs a LangGraph workflow with a live Rich status table (per-agent phases and timing). The final Markdown is written under outputs/ as newsletter_issue_{N}_{YYYY-MM-DD}.md, using templates/newsletter.j2.
| Phase | Mode | Agents |
|---|---|---|
| 1 | Parallel from START |
news_agent, research_agent, tools_agent, youtube_agent, jobs_agent, events_agent |
| 2 | Sequential | analysis_agent → prompt_agent (waits until all Phase 1 nodes finish) |
| 3 | Compile | compiler_agent → END (editor’s note, closing thoughts, Jinja render, file save) |
Shared state is defined in state.py (NewsletterState): collected sections (news, papers, tools, YouTube, jobs, events, quotes, etc.), LLM-written fields (deep dive, prompt of the week, sentiment), and final_markdown / errors.
- Python
>=3.13(see.python-versionfor the repo default). - AWS credentials and a Bedrock model ID the account can invoke.
- Tavily API key (web search / news-style gathering in agents).
- YouTube Data API key (video curation).
-
Clone the repo and create a
.envin the project root (same directory asconfig.py). -
Set required variables (startup fails fast if any are empty):
Variable Purpose BEDROCK_MODEL_IDBedrock chat model ID AWS_ACCESS_KEY_IDAWS access key AWS_SECRET_ACCESS_KEYAWS secret key AWS_DEFAULT_REGIONRegion (default in code: us-east-1)TAVILY_API_KEYTavily YOUTUBE_API_KEYYouTube Data API -
Optional newsletter metadata:
Variable Default NEWSLETTER_NAMETHE AI PULSENEWSLETTER_AUTHORAI Pulse TeamNEWSLETTER_ISSUE_NUMBER1 -
Install dependencies (e.g. with uv —
uv.lockis present):uv sync
Or use your preferred tool against
pyproject.toml.
python main.pyOn Windows, the entry point forces UTF-8 I/O so Rich output (including emoji) is less likely to break the console.
main.py— CLI entry, state init, graph stream, live statusgraph.py—StateGraphwiringconfig.py—.envloading, validation,get_llm()(ChatBedrock)state.py—NewsletterStateanddefault_state()agents/— one module per graph nodetools/— Tavily, arXiv, YouTube helpers used by collectorstemplates/newsletter.j2— issue templateoutputs/— generated.mdfiles
LangChain / LangGraph, langchain-aws, Tavily, arXiv, Google API client, boto3, python-dotenv, Rich, Jinja2.