An intelligent blog writing agent built with LangGraph and LangChain that automates the entire blog creation process from research to publication.
- 🔍 Competitor Research: Automatically scrape and analyze competitor blogs
- 🔑 Keyword Research: Generate SEO-optimized keywords based on your site and competitors
- 📝 Title Generation: Create multiple compelling blog title options
- 🎯 Smart Selection: AI-powered title selection based on SEO and engagement potential
- 📋 Outline Generation: Structured content outlines for better organization
- ✍️ Content Writing: Generate high-quality, SEO-optimized blog posts (1500-2500 words)
- 🖼️ Image Generation: Create featured images using AI (DALL-E)
Built with LangGraph for orchestrating a multi-step agent workflow:
START → Competitor Research → Keyword Research → Title Generation
→ Title Selection → Outline Generation → Content Generation
→ Image Generation → END
- State Management: TypedDict-based state tracking across all nodes
- Conditional Routing: Smart workflow decisions (skip competitor research if no URLs provided)
- Checkpointing: SQLite-based persistence for pause/resume capability
- Error Handling: Robust error recovery and logging
- Visual Debugging: Full LangGraph Studio integration
# Clone the repository
git clone <your-repo-url>
cd blog-writing-agent
# Run setup script
chmod +x setup.sh
./setup.sh
# Or manual setup
python -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
pip install -r requirements.txtCreate a .env file:
# Google AI (Gemini)
GOOGLE_API_KEY=your_google_api_key_here
# Or OpenAI
OPENAI_API_KEY=your_openai_api_key_here# Install LangGraph CLI
pip install langgraph-cli
# Start the studio
langgraph devOpen your browser at http://localhost:8123 and start creating blogs!
See LANGGRAPH_STUDIO.md for detailed Studio usage.
python main.pyblog-writing-agent/
├── graphs/
│ ├── __init__.py
│ └── blog_writer.py # Main workflow graph
├── nodes/
│ ├── __init__.py
│ ├── competitor_research.py
│ ├── keyword_research.py
│ ├── title_generation.py
│ ├── title_selection.py
│ ├── outline_generation.py
│ ├── content_generation.py
│ └── image_generation.py
├── states/
│ ├── __init__.py
│ └── BlogState.py # State schema
├── tools/
│ └── ... # Utility functions
├── config/
│ └── ... # LLM configuration
├── langgraph.json # Studio configuration
├── requirements.txt
├── main.py # CLI entry point
└── README.md
- Open LangGraph Studio
- Load the project
- Use this input:
{
"site_url": "https://yoursite.com",
"site_title": "Your Blog Title",
"site_description": "A blog about...",
"existing_blogs": [
{"title": "Previous Blog 1", "url": "https://..."}
],
"competitors_urls": [
"https://competitor1.com",
"https://competitor2.com"
],
"messages": []
}import asyncio
from graphs.blog_writer import graph
async def generate_blog():
config = {"configurable": {"thread_id": "test_run"}}
initial_state = {
"site_url": "https://yoursite.com",
"site_title": "Your Blog",
"site_description": "A blog about tech",
"existing_blogs": [],
"competitors_urls": ["https://competitor.com"],
"messages": []
}
result = await graph.ainvoke(initial_state, config)
print(result['blog_content'])
asyncio.run(generate_blog())The agent maintains this state across all nodes:
class BlogState(MessagesState):
# Input
site_url: str
site_title: str
site_description: str
existing_blogs: List[Dict[str, str]]
competitors_urls: List[str]
# Research
competitors_blogs: List[Dict[str, str]]
competitor_summary: str
keywords: List[str]
# Generation
titles: List[str]
selected_title: str
blog_outline: str
blog_content: str
featured_image_prompt: str
featured_image: str
# Metadata
current_step: str
error: Optional[str]- Scrapes competitor websites
- Extracts blog articles
- Generates summaries and insights
- Analyzes site description
- Incorporates competitor insights
- Generates 15-20 SEO keywords
- Creates 10 title options
- Ensures no duplicates with existing blogs
- Various formats (how-to, listicles, guides)
- AI-powered selection
- Based on SEO potential and engagement
- Structured blog outline
- 4-6 main sections
- Word count suggestions
- 1500-2500 word blog posts
- SEO-optimized
- Markdown formatted
- Engaging and valuable
- Creates featured images
- DALL-E integration
- Professional and relevant
Automatically skips competitor research if no competitors are provided.
All progress is saved to checkpoints.db. You can pause and resume runs.
Robust error handling with detailed logging at each step.
With LangGraph Studio, watch each node execute in real-time.
LangGraph Studio provides:
- 📊 Visual Graph: See your workflow structure
▶️ Step-by-Step Execution: Run one node at a time- 🔍 State Inspector: View state changes at each step
- 📝 Logs: Detailed execution logs
- ⏸️ Pause/Resume: Checkpoint-based persistence
- 🐛 Error Debugging: See exactly where and why failures occur
{
"dependencies": ["."],
"graphs": {
"blog_writer": "./graphs/blog_writer.py:graph"
},
"env": ".env"
}GOOGLE_API_KEY=your_key_here
OPENAI_API_KEY=your_key_here
LOG_LEVEL=INFO- Python 3.9+
- LangGraph
- LangChain
- Google AI or OpenAI API key
- Check
langgraph.jsonis in project root - Verify all imports in
graphs/blog_writer.py - Ensure dependencies are installed
- Verify
.envfile has correct API keys - Check API key permissions
- Review rate limits
- Check logs in Studio console
- Inspect state before failed node
- Verify input data format
Contributions welcome! Please:
- Fork the repository
- Create a feature branch
- Add tests if applicable
- Submit a pull request
MIT License - see LICENSE file for details
For issues or questions:
- Open a GitHub issue
- Check LANGGRAPH_STUDIO.md for Studio-specific help
Built with ❤️ using LangGraph and LangChain