A modular microservices system for monitoring news, filtering, scoring, generating and publishing differentiated content β while keeping a final human-in-the-loop.
Note: This project is currently in progress. Only the ingestion pipeline is functional at this stage. See the Project Status section for details.
This project is built on a microservices architecture, orchestrated by a central core (core/syntinel) and extended with specialized services (services/).
Each component follows the Feature-Sliced Design (FSD) principle for clarity and scalability.
syntinel/
βββ core/ # Central orchestrator
β βββ syntinel/
β βββ orchestrator.py # Entry point for executing business pipelines
β βββ db/ # Database module
β β βββ session.py # DB connection, engine and session configuration
β β βββ models/ # Database models
β β β βββ article.py
β β β βββ draft.py
β β βββ __init__.py # Re-exports for easy imports
β βββ modules/ # Business modules (FSD)
β β βββ ingestion/ # Extraction, deduplication, normalization, Redis
β β β βββ pipeline.py
β β β βββ collector/
β β β βββ base.py
β β β βββ cryptopanic_collector.py
β β βββ scoring/ # Relevance scoring logic
β β βββ publishing/ # Publishing orchestration
β βββ Dockerfile # Build for syntinel-core service
βββ services/ # Specialized microservices
β βββ writer-agent/ # Content generation via CrewAI
β βββ telegram-bot/ # Telegram interface for user interaction
βββ docker-compose.yml # Container orchestration
βββ .env.example # Example environment variables
| Component | Role |
|---|---|
| Syntinel-Core | Main orchestrator: ingestion, scoring, workflow coordination |
| Crawl4AI | (Optional) Multi-source HTTP extraction service |
| Writer-Agent | Stylized content generator using CrewAI (e.g. sarcastic tone) |
| Telegram-Bot | User-friendly interface to validate, edit and publish content |
| PostgreSQL | Central database for headlines, scores, and logs |
| Redis | Cache + queue system (Redis Streams) for ingestion and scoring |
| pgAdmin | Web interface for PostgreSQL administration |
- Scheduler / Orchestrator triggers the ingestion pipeline periodically
- Collectors fetch headlines from third-party APIs (e.g. Cryptopanic)
- Ingestion Pipeline:
- Deduplicates using the DB
- Normalizes articles (cleaning, formatting)
- Inserts into DB if new
- Pushes event to Redis stream
- Scoring Worker consumes Redis stream and applies relevance scoring
- Telegram Bot displays top headlines to the user
- Writer-Agent generates original content
- User Validation: tone selection, editing, final approval
- Automatic Publishing: pushes to X (Twitter) API
- Docker & Docker Compose
- Python 3.9+ (for local development)
- OpenAI API Key (for Writer-Agent)
- Telegram Bot Token (for user interaction)
- X (Twitter) account + API Key (for automated publishing)
# Copy the environment file
cp .env.example .envFill in the .env file with: β’ OPENAI_API_KEY β’ TELEGRAM_BOT_TOKEN β’ POSTGRES_USER, POSTGRES_PASSWORD β’ X_API_KEY (optional)
# Build and launch all containers
docker-compose up -d| Service | URL / Access Info |
|---|---|
| Syntinel-Core API | http://localhost:8000 |
| Writer-Agent API | http://localhost:8002 |
| Telegram-Bot | Available via your Telegram app |
| pgAdmin | http://localhost:5050 (login: admin@syntinel.com / admin) |
| PostgreSQL | localhost:5432 (default: admin / pswd) |
| Redis | localhost:6379 |
The project includes an automated setup script to initialize your development environment quickly and easily:
# Run the development setup script from the project root
python scripts/setup_dev.pyThis script will:
- Check for and install required tools (uv, direnv)
- Set up a Python virtual environment (.venv)
- Install project dependencies using uv
- Configure crawl4ai with Playwright
- Set up direnv for automatic environment activation
Note: If you modify the
.envrcfile or pull changes that modify it, you'll need to rundirenv allowto authorize the changes for security reasons.
To monitor the Redis streams during development:
# Run the Redis monitoring script
python scripts/monitor_redis.py- Syntinel-Core: orchestrator, pipelines, ingestion workers
- Services: isolated, pluggable APIs
- Shared: Pydantic models and common utilities
β’ β
Feature-Sliced Design: api.py, service.py, pipeline.py, collector/
β’ β
Shared interface BaseCollector to trigger fetch() across modules
β’ β
Pre-insert deduplication + ON CONFLICT DO UPDATE fallback
β’ β
Redis Streams for async ingestion
β’ β
run_collector_safely() wrapper with logs + automatic retry
β’ β
Input validation via Pydantic
β’ β
Automated tests with docker-compose.tests.yml
β’ β
Centralized orchestration via orchestrator.py
This project is a work in progress. Current state:
β’ β
Ingestion pipeline: functional (collector, normalization, deduplication, storage)
β’ π Scoring module: in progress
β’ π§ Writer-Agent + Telegram interface: not yet implemented
β’ π§ Publishing module: not yet implemented
I welcome contributions and suggestions β feel free to fork, clone, or reach out.
The orchestrator is the main entry point to run the ingestion pipeline. It provides several options for customization:
# Standard execution (ingestion only)
python -m core.orchestrator
# With JSON export (auto-generated filename)
python -m core.orchestrator --export-json
# With JSON export and custom filename
python -m core.orchestrator --export-json --export-path custom_export.json| Option | Description |
|---|---|
--export-json |
Enable JSON export of collected articles |
--export-path PATH |
Specify a custom path for the JSON export file |
The JSON export contains both raw article data from collectors and normalized data used for database storage.
MIT β Open source, feel free to fork and improve π€