Production-oriented multi-agent RAG pipeline that discovers technology trends, researches the web, embeds knowledge into Qdrant, plans and writes articles with Qwen (Ollama), and stores results in PostgreSQL. All agents communicate asynchronously through RabbitMQ events.
flowchart LR
subgraph Agents
TA[trend-agent]
RA[research-agent]
EA[embedding-agent]
PA[planner-agent]
WA[writer-agent]
SA[storage-agent]
end
subgraph Infra
RMQ[(RabbitMQ)]
QD[(Qdrant)]
PG[(PostgreSQL)]
OL[Ollama Qwen3]
end
TA -->|TrendFound| RMQ
RMQ --> RA
RA -->|ResearchCompleted| RMQ
RMQ --> EA
EA --> QD
EA -->|EmbeddingCompleted| RMQ
RMQ --> PA
PA --> QD
PA --> OL
PA -->|PlanCreated| RMQ
RMQ --> WA
WA --> QD
WA --> OL
WA -->|ArticleGenerated| RMQ
RMQ --> SA
SA --> PG
sequenceDiagram
participant T as trend-agent
participant R as research-agent
participant E as embedding-agent
participant P as planner-agent
participant W as writer-agent
participant S as storage-agent
participant Q as Qdrant
participant O as Ollama
T->>R: TrendFound
R->>E: ResearchCompleted
E->>Q: upsert chunks
E->>P: EmbeddingCompleted
P->>Q: RAG search
P->>O: outline JSON
P->>W: PlanCreated
W->>Q: RAG search
W->>O: markdown article
W->>S: ArticleGenerated
| Event | Routing Key | Queue | Producer | Consumer |
|---|---|---|---|---|
TrendFound |
trend.found |
trend-found |
trend-agent | research-agent |
ResearchCompleted |
research.completed |
research-completed |
research-agent | embedding-agent |
EmbeddingCompleted |
embedding.completed |
embedding-completed |
embedding-agent | planner-agent |
PlanCreated |
plan.created |
plan-created |
planner-agent | writer-agent |
ArticleGenerated |
article.generated |
article-generated |
writer-agent | storage-agent |
Exchange: content-pipeline (topic). Each queue has a dead-letter queue (<queue>.dlq).
- Docker and Docker Compose
- 16 GB+ RAM recommended (embedding model + Ollama)
cd ai-content-factory
docker compose up --build -dServices:
| Service | Port | Purpose |
|---|---|---|
| RabbitMQ | 5672, 15672 | Event bus (management UI) |
| Qdrant | 6333 | Vector store |
| PostgreSQL | 5432 | Article persistence |
| Ollama | 11434 | Local LLM (qwen3:8b) |
docker compose ps
docker compose logs -f trend-agentQuery stored articles:
docker exec -it acf-postgres psql -U content -d content_factory -c "SELECT title, slug, created_at FROM articles ORDER BY created_at DESC LIMIT 5;"topics.json— seed technology topics for trend discovery.env— copy from.env.exampleshared/config/pipeline.yaml— documented pipeline topology and defaultsshared/config/settings.py— Pydantic settings (env vars override YAML defaults)
| Variable | Default | Description |
|---|---|---|
OLLAMA_HOST |
http://ollama:11434 |
Ollama API endpoint |
OLLAMA_MODEL |
qwen3:8b |
Model for planner/writer |
EMBEDDING_MODEL |
BAAI/bge-m3 |
HuggingFace embeddings |
QDRANT_COLLECTION |
articles |
Qdrant collection name |
RABBITMQ_HOST |
rabbitmq |
Message broker host |
- Reads
topics.json - Uses
GoogleTrendsProvider(pluggableTrendProvider) - Publishes
TrendFoundevery 7 days - Deduplicates trends and skips topics processed in the last 30 days
- Consumes
TrendFound - Builds search queries (
tutorial,architecture,deployment,observability) - Collects 5–20 sources, extracts clean text (trafilatura/newspaper3k)
- Stores raw JSON locally, publishes
ResearchCompleted
- Chunks text (512 tokens, 50 overlap)
- Embeds with
BAAI/bge-m3(1024-dim, cosine) - Upserts into Qdrant collection
articles - Publishes
EmbeddingCompleted
- RAG: top 20 chunks from Qdrant
- Prompts Qwen for JSON outline (validated, retried)
- Publishes
PlanCreated
- RAG + outline → markdown article (1500–3000 words)
- Grounded in retrieved context with citations
- Publishes
ArticleGeneratedwith SEO metadata
- Persists articles and source URLs to PostgreSQL
- Name:
articles - Vector size:
1024 - Distance:
COSINE - Payload:
topic,url,title,chunk_text,created_at
articles: id, topic, title, slug, content, meta_description, created_at
sources: id, article_id, url, title
pip install -r requirements-dev.txt
pip install -r shared/requirements.txt
pytest -m "not integration"export RABBITMQ_HOST=localhost
export QDRANT_HOST=localhost
export OLLAMA_HOST=http://localhost:11434
pytest -m integrationgraph TD
EX[content-pipeline topic exchange]
EX --> Q1[trend-found]
EX --> Q2[research-completed]
EX --> Q3[embedding-completed]
EX --> Q4[plan-created]
EX --> Q5[article-generated]
Q1 --> D1[trend-found.dlq]
Q2 --> D2[research-completed.dlq]
Q3 --> D3[embedding-completed.dlq]
Q4 --> D4[plan-created.dlq]
Q5 --> D5[article-generated.dlq]
New agents (SEO, translator, newsletter, LinkedIn, podcast, video) can be added by:
- Implementing
AgentPlugininshared/plugins/agent_plugin.py - Defining a new event contract in
shared/contracts/events.py - Adding routing key + queue in
shared/messaging/topology.py - Creating a new
*-agentservice with its own Dockerfile - Wiring the service in
docker-compose.yml
No direct service-to-service calls — only events on RabbitMQ.
ai-content-factory/
├── docker-compose.yml
├── topics.json
├── shared/ # contracts, messaging, config, services
├── trend-agent/
├── research-agent/
├── embedding-agent/
├── planner-agent/
├── writer-agent/
└── storage-agent/
- Ollama model missing: ensure
ollama-initcompleted (docker compose logs ollama-init) - Embedding OOM: increase Docker memory or run embedding-agent alone first
- No articles in Postgres: check upstream agents and RabbitMQ queue depths in management UI (
http://localhost:15672)