Hermes Agent Tutorial Part 6: Building a Complete AI Workflow — Automated Daily Tech News Digest

In Parts 1 through 3 of this series, we covered installation and configuration, multi-role systems and skill management, and cron jobs with automated workflows. In this sixth installment, we bring everything together into a single, production-ready project: an automated daily tech news digest system that scrapes headlines, analyzes them through multiple expert lenses, generates a structured report, and delivers it to your team chat every morning.

This is not a toy example. By the end of this guide, you will have a fully functional automation pipeline that demonstrates how Hermes Agent’s roles, skills, scheduler, and delivery channels work in concert to solve real-world problems.


Table of Contents

  1. Project Overview
  2. Architecture and Data Flow
  3. Prerequisites
  4. Step 1: Configure the Environment
  5. Step 2: Build the News Fetcher Skill
  6. Step 3: Define the Expert Roles
  7. Step 4: Create the Analysis Pipeline
  8. Step 5: Schedule the Cron Job
  9. Step 6: Configure Delivery Channels
  10. Step 7: Testing and Validation
  11. Full Project Files
  12. Extending the Project
  13. Conclusion

Project Overview

The goal is simple: every weekday at 8:00 AM, the agent fetches the latest technology news from multiple RSS feeds and APIs, runs the headlines through two specialized experts — an AI Expert and an Investment Expert — synthesizes their analyses into a unified markdown report, and pushes the result to a Feishu group chat (with Slack as a fallback).

What You Will Learn


Architecture and Data Flow

The system follows a four-stage pipeline:

┌─────────────────┐     ┌──────────────────┐     ┌─────────────────┐     ┌─────────────────┐
│  1. FETCH       │────▶│  2. ANALYZE      │────▶│  3. SYNTHESIZE  │────▶│  4. DELIVER     │
│  News Headlines │     │  Multi-Expert    │     │  Merge Reports  │     │  Feishu/Slack   │
└─────────────────┘     └──────────────────┘     └─────────────────┘     └─────────────────┘
        │                        │                        │                        │
        ▼                        ▼                        ▼                        ▼
   RSS/API fetcher          AI Expert              Report generator          Feishu bot
   Skill: news-fetch        Investment Expert      Skill: report-merge       Slack webhook

Stage 1 — Fetch: A custom news-fetch skill retrieves headlines from configured sources and stores them as a normalized JSON file.

Stage 2 — Analyze: Two expert roles independently analyze the headlines. The AI Expert focuses on technical significance, research impact, and engineering implications. The Investment Expert focuses on market signals, funding events, and competitive dynamics.

Stage 3 — Synthesize: A synthesis role merges both analyses into a single coherent report with executive summary, detailed findings, and actionable takeaways.

Stage 4 — Deliver: The final report is formatted as markdown and sent to the configured Feishu group (or Slack channel) with proper threading and tagging.


Prerequisites

Before starting, ensure you have:

Install the Python dependencies:

pip install requests feedparser beautifulsoup4

Step 1: Configure the Environment

Create a dedicated workspace for this project. This keeps all files isolated and version-controllable.

mkdir -p ~/.hermes/projects/news-digest/{skills,roles,data,logs}
export NEWS_DIGEST_DIR="$HOME/.hermes/projects/news-digest"

Update your main ~/.hermes/config.yaml to include the project workspace and enable the required toolsets:

# ~/.hermes/config.yaml
agent:
  name: "news-digest-agent"
  role: "orchestrator"
  log_level: "info"
  workspace: "~/.hermes/projects/news-digest"

llm:
  provider: "openai"
  model: "gpt-4o"
  api_key: "${OPENAI_API_KEY}"
  temperature: 0.5
  max_tokens: 4096
  timeout_seconds: 120

skills:
  directory: "~/.hermes/skills"
  auto_load: true
  allowed:
    - "news-fetch"
    - "report-merge"
    - "web-scraping"

toolsets:
  - "web"
  - "filesystem"
  - "feishu"
  - "slack"

scheduler:
  enabled: true
  timezone: "UTC"
  jobs_file: "~/.hermes/jobs.yaml"

mcp:
  enabled: true
  servers:
    - name: "filesystem"
      command: "npx"
      args: ["-y", "@modelcontextprotocol/server-filesystem", "~/.hermes/projects/news-digest/data"]

logging:
  directory: "~/.hermes/projects/news-digest/logs"
  max_files: 30
  format: "json"

Validate the configuration:

hermes config validate

Step 2: Build the News Fetcher Skill

The news-fetch skill is responsible for collecting headlines from multiple sources, deduplicating them, and writing a normalized JSON file for downstream analysis.

Skill Directory Structure

mkdir -p ~/.hermes/skills/news-fetch

Skill Manifest

Create ~/.hermes/skills/news-fetch/skill.yaml:

name: "news-fetch"
version: "1.0.0"
description: "Fetches and normalizes tech news headlines from RSS feeds and APIs"
author: "your-name"
roles:
  - "orchestrator"
  - "ai"
  - "investment"
dependencies: []
tools:
  - "terminal"
  - "file_manager"
entrypoint: "fetch.py"
auto_activate: false
context_budget: 400

Skill Implementation

Create ~/.hermes/skills/news-fetch/fetch.py:

#!/usr/bin/env python3
"""
news-fetch skill: Collects tech news from RSS feeds and writes normalized JSON.
"""

import json
import sys
import hashlib
from datetime import datetime, timezone
from pathlib import Path

import feedparser
import requests
from bs4 import BeautifulSoup

# Configurable source list
SOURCES = {
    "techcrunch": "https://techcrunch.com/feed/",
    "ars-technica": "https://feeds.arstechnica.com/arstechnica/index",
    "the-verge": "https://www.theverge.com/rss/index.xml",
    "wired": "https://www.wired.com/feed/rss",
}

OUTPUT_DIR = Path.home() / ".hermes" / "projects" / "news-digest" / "data"
MAX_HEADLINES_PER_SOURCE = 10


def fetch_rss(url: str, source_name: str) -> list[dict]:
    """Fetch and parse an RSS feed, returning normalized headline dicts."""
    headlines = []
    try:
        feed = feedparser.parse(url)
        for entry in feed.entries[:MAX_HEADLINES_PER_SOURCE]:
            title = entry.get("title", "").strip()
            link = entry.get("link", "").strip()
            published = entry.get("published", "")
            summary = entry.get("summary", "")
            # Clean HTML from summary
            summary_text = BeautifulSoup(summary, "html.parser").get_text(separator=" ", strip=True)
            # Generate a stable ID from title + source
            item_id = hashlib.sha256(f"{source_name}:{title}".encode()).hexdigest()[:16]
            headlines.append({
                "id": item_id,
                "source": source_name,
                "title": title,
                "url": link,
                "published": published,
                "summary": summary_text[:500],
                "fetched_at": datetime.now(timezone.utc).isoformat(),
            })
    except Exception as exc:
        print(f"[ERROR] Failed to fetch {source_name}: {exc}", file=sys.stderr)
    return headlines


def fetch_all() -> list[dict]:
    """Fetch headlines from all configured sources and deduplicate."""
    all_headlines = []
    seen_ids = set()
    for source_name, url in SOURCES.items():
        print(f"[INFO] Fetching {source_name}...")
        for item in fetch_rss(url, source_name):
            if item["id"] not in seen_ids:
                seen_ids.add(item["id"])
                all_headlines.append(item)
    # Sort by fetch time (newest first)
    all_headlines.sort(key=lambda x: x["fetched_at"], reverse=True)
    return all_headlines


def save_headlines(headlines: list[dict]) -> Path:
    """Persist headlines to a timestamped JSON file."""
    OUTPUT_DIR.mkdir(parents=True, exist_ok=True)
    timestamp = datetime.now(timezone.utc).strftime("%Y%m%d_%H%M%S")
    filepath = OUTPUT_DIR / f"headlines_{timestamp}.json"
    with open(filepath, "w", encoding="utf-8") as f:
        json.dump({
            "meta": {
                "generated_at": datetime.now(timezone.utc).isoformat(),
                "source_count": len(SOURCES),
                "headline_count": len(headlines),
            },
            "headlines": headlines,
        }, f, indent=2, ensure_ascii=False)
    print(f"[INFO] Saved {len(headlines)} headlines to {filepath}")
    return filepath


if __name__ == "__main__":
    headlines = fetch_all()
    if not headlines:
        print("[WARN] No headlines fetched. Check network connectivity and source URLs.", file=sys.stderr)
        sys.exit(1)
    out_path = save_headlines(headlines)
    print(out_path)

Make the script executable:

chmod +x ~/.hermes/skills/news-fetch/fetch.py

Test the skill manually:

python3 ~/.hermes/skills/news-fetch/fetch.py

You should see output similar to:

[INFO] Fetching techcrunch...
[INFO] Fetching ars-technica...
[INFO] Fetching the-verge...
[INFO] Fetching wired...
[INFO] Saved 32 headlines to /root/.hermes/projects/news-digest/data/headlines_20260620_080000.json

Step 3: Define the Expert Roles

We need three roles for this pipeline: the AI Expert, the Investment Expert, and an Orchestrator that manages the synthesis.

AI Expert Role

Create ~/.hermes/roles/ai-expert.yaml:

name: "ai-expert"
description: "Expert in artificial intelligence, machine learning, and software engineering trends"
system_prompt: |
  You are a senior AI researcher and engineer with deep expertise in machine learning,
  large language models, computer vision, robotics, and MLOps.

  When analyzing tech news headlines:
  1. Identify which stories have genuine technical significance versus hype
  2. Assess the maturity of any mentioned technologies (research, prototype, production)
  3. Note implications for practitioners: new tools, deprecated approaches, emerging standards
  4. Highlight any open-source releases, benchmark results, or reproducible claims
  5. Flag potential misinformation or exaggerated claims

  Format your analysis as structured markdown with these sections:
  - **Key Technical Stories** (ranked by significance)
  - **Emerging Trends** (patterns across multiple headlines)
  - **Practitioner Impact** (what engineers should know)
  - **Skeptic's Corner** (claims that need verification)

default_skills:
  - "news-fetch"
  - "web-scraping"
tool_preferences:
  terminal: true
  file_manager: true
  web: true
context_window:
  preferred: 16000
  min: 8000

Investment Expert Role

Create ~/.hermes/roles/investment-expert.yaml:

name: "investment-expert"
description: "Expert in technology investing, market analysis, and startup evaluation"
system_prompt: |
  You are a technology-focused venture capitalist with 15 years of experience
  evaluating startups, market trends, and competitive dynamics.

  When analyzing tech news headlines:
  1. Identify funding rounds, acquisitions, and IPO signals
  2. Assess market positioning and competitive threats
  3. Evaluate business model viability and unit economics mentions
  4. Note regulatory risks or tailwinds
  5. Highlight contrarian opportunities or overvalued sectors

  Format your analysis as structured markdown with these sections:
  - **Funding & M&A Activity** (deals, valuations, investors)
  - **Market Signals** (trends that affect valuations)
  - **Competitive Dynamics** (winners, losers, shifts)
  - **Investment Thesis Updates** (how today's news changes your view)
  - **Risk Alerts** (regulatory, macro, or sector-specific risks)

default_skills:
  - "news-fetch"
  - "web-scraping"
tool_preferences:
  terminal: true
  file_manager: true
  web: true
context_window:
  preferred: 16000
  min: 8000

Orchestrator Role

Create ~/.hermes/roles/orchestrator.yaml:

name: "orchestrator"
description: "Coordinates multi-expert analysis and synthesizes unified reports"
system_prompt: |
  You are a project orchestrator responsible for coordinating multiple domain experts
  and producing unified, actionable reports.

  Your workflow:
  1. Read the raw headline data
  2. Delegate technical analysis to the AI Expert
  3. Delegate market analysis to the Investment Expert
  4. Synthesize both analyses into a single coherent report
  5. Ensure the final output is concise, well-structured, and suitable for busy executives

  The final report must include:
  - **Executive Summary** (3-4 bullet points, under 100 words total)
  - **AI Expert Findings** (summarized, not verbatim)
  - **Investment Expert Findings** (summarized, not verbatim)
  - **Cross-Domain Insights** (where technical and market analysis intersect)
  - **Recommended Actions** (specific, time-bounded recommendations)

  Tone: professional, concise, no fluff. Use markdown formatting for readability.

default_skills:
  - "news-fetch"
  - "report-merge"
tool_preferences:
  terminal: true
  file_manager: true
context_window:
  preferred: 32000
  min: 16000

Step 4: Create the Analysis Pipeline

The analysis pipeline is a single cron job that uses the orchestrator role to drive the entire process. The orchestrator’s prompt instructs it to invoke the news-fetch skill, delegate analysis to the two experts, and synthesize the final report.

The Report Merge Skill

Create a lightweight skill to help with report formatting:

mkdir -p ~/.hermes/skills/report-merge
cat > ~/.hermes/skills/report-merge/skill.yaml << 'EOF'
name: "report-merge"
version: "1.0.0"
description: "Merges multiple analysis sections into a unified markdown report"
author: "your-name"
roles:
  - "orchestrator"
entrypoint: "merge.py"
auto_activate: false
EOF
cat > ~/.hermes/skills/report-merge/merge.py << 'EOF'
#!/usr/bin/env python3
import sys
from datetime import datetime, timezone

def merge_report(sections: list[str], title: str = "Daily Tech Digest") -> str:
    header = f"# {title}\n\n**Generated:** {datetime.now(timezone.utc).strftime('%Y-%m-%d %H:%M UTC')}\n\n---\n\n"
    body = "\n\n---\n\n".join(sections)
    footer = "\n\n---\n\n*This report was generated automatically by Hermes Agent.*"
    return header + body + footer

if __name__ == "__main__":
    # Read sections from stdin, separated by double newlines
    raw = sys.stdin.read()
    sections = [s.strip() for s in raw.split("\n\n---\n\n") if s.strip()]
    print(merge_report(sections))
EOF
chmod +x ~/.hermes/skills/report-merge/merge.py

Step 5: Schedule the Cron Job

Now we define the master cron job that runs the entire pipeline. Create or edit ~/.hermes/jobs.yaml:

jobs:
  - name: "daily-tech-news-digest"
    schedule: "0 8 * * 1-5"
    role: "orchestrator"
    enabled: true
    task: |
      Run the daily tech news digest pipeline:

      1. Execute the news-fetch skill to collect today's headlines.
         Save the output JSON path.
      2. Read the headlines file and present the top 20 stories to the AI Expert.
         Ask for a structured technical analysis.
      3. Present the same headlines to the Investment Expert.
         Ask for a structured market and investment analysis.
      4. Use the report-merge skill to combine both analyses into a single
         markdown document with an executive summary.
      5. Save the final report to ~/.hermes/projects/news-digest/data/daily_report.md
      6. Deliver the report via Feishu to the configured group chat.
         If Feishu fails, fallback to Slack.
    skills:
      - "news-fetch"
      - "report-merge"
    toolsets:
      - "web"
      - "filesystem"
      - "feishu"
      - "slack"
    delivery:
      channel: "feishu"
      target: "${FEISHU_GROUP_CHAT_ID}"
      format: "markdown"
    fallback_delivery:
      channel: "slack"
      target: "${SLACK_WEBHOOK_URL}"
      format: "markdown"
    timeout_seconds: 300
    retries: 2

The schedule: "0 8 * * 1-5" ensures the job runs at 8:00 AM UTC, Monday through Friday only. Adjust the timezone or hour based on your team’s location.

Reload the scheduler to pick up the new job:

hermes scheduler reload

Verify the job is registered:

hermes scheduler list

Step 6: Configure Delivery Channels

Feishu (Lark) Setup

  1. Open your Feishu group chat and add a custom bot.
  2. Copy the webhook URL and extract the chat ID, or use a bot app with API credentials.
  3. Export the credentials in your shell profile:
export FEISHU_APP_ID="cli_xxxxxxxxxxxxxxxx"
export FEISHU_APP_SECRET="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
export FEISHU_GROUP_CHAT_ID="oc_xxxxxxxxxxxxxxxx"

Slack Setup (Fallback)

  1. Create an incoming webhook in your Slack workspace.
  2. Export the URL:
export SLACK_WEBHOOK_URL="https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX"

Testing Delivery

Before relying on the cron schedule, test delivery manually:

hermes run --task "Send a test message to Feishu saying 'Hermes Agent delivery test successful'" --role orchestrator

If the test message appears in your chat, the delivery channel is correctly configured.


Step 7: Testing and Validation

Manual Pipeline Test

Run the entire pipeline on demand to verify each stage:

hermes run --task "Run the daily tech news digest pipeline end-to-end" --role orchestrator

Watch the logs for errors:

tail -f ~/.hermes/projects/news-digest/logs/agent.log

Validate Each Stage

Stage 1 — Fetch: Confirm headlines_*.json is created in ~/.hermes/projects/news-digest/data/.

Stage 2 — Analysis: Check that the agent invokes both the AI Expert and Investment Expert roles. You should see context switches in the logs.

Stage 3 — Synthesis: Verify daily_report.md is generated and contains all required sections.

Stage 4 — Delivery: Confirm the report appears in your Feishu group with proper markdown rendering.

Common Issues and Fixes

IssueCauseFix
No headlines fetchedNetwork blocked or RSS changedVerify URLs with curl, update SOURCES in fetch.py
Role switch failsRole YAML syntax errorRun hermes config validate and check indentation
Feishu message not sentMissing credentialsVerify FEISHU_APP_ID and FEISHU_APP_SECRET are exported
Report too longLLM output exceeds token limitReduce MAX_HEADLINES_PER_SOURCE or summarize before synthesis
Scheduler not firingScheduler daemon not runningStart with hermes scheduler start --daemon

Full Project Files

For convenience, here is a consolidated view of every file created in this project.

~/.hermes/config.yaml

agent:
  name: "news-digest-agent"
  role: "orchestrator"
  log_level: "info"
  workspace: "~/.hermes/projects/news-digest"

llm:
  provider: "openai"
  model: "gpt-4o"
  api_key: "${OPENAI_API_KEY}"
  temperature: 0.5
  max_tokens: 4096
  timeout_seconds: 120

skills:
  directory: "~/.hermes/skills"
  auto_load: true
  allowed:
    - "news-fetch"
    - "report-merge"
    - "web-scraping"

toolsets:
  - "web"
  - "filesystem"
  - "feishu"
  - "slack"

scheduler:
  enabled: true
  timezone: "UTC"
  jobs_file: "~/.hermes/jobs.yaml"

mcp:
  enabled: true
  servers:
    - name: "filesystem"
      command: "npx"
      args: ["-y", "@modelcontextprotocol/server-filesystem", "~/.hermes/projects/news-digest/data"]

logging:
  directory: "~/.hermes/projects/news-digest/logs"
  max_files: 30
  format: "json"

~/.hermes/skills/news-fetch/skill.yaml

name: "news-fetch"
version: "1.0.0"
description: "Fetches and normalizes tech news headlines from RSS feeds and APIs"
author: "your-name"
roles:
  - "orchestrator"
  - "ai"
  - "investment"
dependencies: []
tools:
  - "terminal"
  - "file_manager"
entrypoint: "fetch.py"
auto_activate: false
context_budget: 400

~/.hermes/skills/news-fetch/fetch.py

See the full implementation in Step 2.

~/.hermes/skills/report-merge/skill.yaml

name: "report-merge"
version: "1.0.0"
description: "Merges multiple analysis sections into a unified markdown report"
author: "your-name"
roles:
  - "orchestrator"
entrypoint: "merge.py"
auto_activate: false

~/.hermes/roles/ai-expert.yaml

See the full implementation in Step 3.

~/.hermes/roles/investment-expert.yaml

See the full implementation in Step 3.

~/.hermes/roles/orchestrator.yaml

See the full implementation in Step 3.

~/.hermes/jobs.yaml

See the full implementation in Step 5.


Extending the Project

Once the basic pipeline is stable, consider these enhancements:

Add More News Sources

Extend SOURCES in fetch.py to include industry-specific feeds (AI research, biotech, climate tech). You can also add API-based sources like NewsAPI or Hacker News.

Add a Third Expert

Create a Policy Expert role that analyzes regulatory implications. This is valuable for teams in regulated industries.

Add Sentiment Analysis

Use a lightweight NLP model to score headline sentiment and include a sentiment trend chart in the report.

Store historical reports in a vector database and add a /search command to the Feishu bot that answers questions like “What did we say about OpenAI last month?”

Multi-Language Support

Add a translation skill that generates localized versions of the report for global teams.

Interactive Follow-Up

Configure the Feishu bot to accept replies. When a user asks “Tell me more about story #3,” the agent fetches the full article and provides a deep-dive analysis.


Conclusion

This project demonstrates how Hermes Agent transforms from a conversational assistant into a fully autonomous operations partner. By combining:

…you have built a system that would traditionally require multiple separate tools, scripts, and services. Yet everything lives within a single, version-controllable Hermes Agent configuration.

The true power of this approach is composability. Each component — the fetcher, the experts, the merger, the scheduler — is independently testable and reusable. Tomorrow, you could repurpose the news-fetch skill for a competitive intelligence pipeline. You could redeploy the investment-expert role for startup due diligence. You could schedule the orchestrator to run weekly instead of daily. The architecture scales with your needs.

In the next part of this series, we will explore error handling and observability — how to make your production workflows resilient, debuggable, and auditable at scale.

Stay automated!