Expert-Level Workflow: From Requirements to Deployment – A Complete Project实战

TL;DR: This final installment of our Hermes Agent series walks you through building a production-ready microservice from scratch—spanning requirements analysis, multi-agent collaboration, automated testing, CI/CD pipeline integration, and deployment to a Kubernetes cluster. You’ll learn how to orchestrate Hermes Agent’s full ecosystem, including MCP tools, cron jobs, and skill reuse, to deliver a complete project in under 4 hours.


🎯 Introduction: Why This Matters

After five parts of building Hermes Agent expertise, you now understand:

But theory without practice is just philosophy. Today, we bridge the gap between individual features and production-grade project delivery. You’ll learn how Hermes Agent transforms from a helpful assistant into a full-stack development orchestrator that can:

Learning Objectives:


📋 Project Overview: The “SmartAlert” Microservice

We’ll build SmartAlert—a real-time incident management service that:

  1. Ingests alerts from multiple sources (Prometheus, Datadog, custom APIs)
  2. Deduplicates and enriches alerts using AI classification
  3. Routes alerts to appropriate teams via Slack, PagerDuty, or email
  4. Provides a dashboard for historical analysis

Technical Stack:

Why this project? It demonstrates every major Hermes Agent capability:


🏗️ Phase 1: Requirements Analysis with Multi-Agent Collaboration

1.1 Initial Prompt Engineering

Create a new project in Hermes Agent:

hermes project init smartalert --template expert-workflow

This generates the following directory structure:

smartalert/
├── .hermes/
│   ├── config.yaml
│   ├── skills/
│   └── workflows/
├── requirements/
├── design/
├── src/
└── deployments/

Now, let’s define our multi-agent workflow. Create workflows/requirements-analysis.yaml:

name: "smartalert-requirements-analysis"
version: "1.0.0"
description: "Multi-agent requirements analysis for SmartAlert"

agents:
  - role: "product_manager"
    model: "gpt-4o"
    system_prompt: |
      You are a senior product manager specializing in incident management.
      Focus on user stories, acceptance criteria, and business value.
      Output structured requirements in YAML format.
  
  - role: "system_architect"
    model: "claude-3-opus"
    system_prompt: |
      You are a systems architect with 15 years of experience in distributed systems.
      Focus on scalability, fault tolerance, and technology choices.
      Output architecture decisions and trade-off analyses.
  
  - role: "security_engineer"
    model: "gpt-4o"
    system_prompt: |
      You are a security engineer specializing in cloud-native applications.
      Focus on authentication, authorization, data encryption, and compliance.
      Output threat models and security requirements.

workflow:
  steps:
    - name: "gather_requirements"
      agent: "product_manager"
      prompt: |
        Analyze the following high-level requirements and produce:
        1. 10-15 detailed user stories with acceptance criteria
        2. Priority matrix (P0-P3)
        3. Non-functional requirements (performance, availability, etc.)
        
        High-level requirements:
        {{user_input}}
      output: "requirements/initial_requirements.yaml"
    
    - name: "review_architecture"
      agent: "system_architect"
      depends_on: ["gather_requirements"]
      prompt: |
        Review the requirements from step 1 and produce:
        1. System architecture diagram (C4 model - level 2)
        2. Technology stack recommendations with justification
        3. API specification (OpenAPI 3.0)
        4. Data model (ER diagram)
        
        Consider:
        - 99.99% availability requirement
        - 10,000 alerts/second peak throughput
        - Multi-region deployment
      output: "design/architecture.yaml"
    
    - name: "security_review"
      agent: "security_engineer"
      depends_on: ["review_architecture"]
      prompt: |
        Perform a security review of the architecture from step 2:
        1. Threat model using STRIDE methodology
        2. Required security controls
        3. Compliance requirements (SOC2, GDPR)
        4. Penetration testing scope
      output: "design/security_requirements.yaml"
    
    - name: "consolidate"
      agent: "product_manager"
      depends_on: ["security_review"]
      prompt: |
        Consolidate all outputs into a single, coherent requirements document.
        Resolve any conflicts between architecture and security requirements.
        Output as a structured markdown document with:
        - Executive summary
        - Technical requirements
        - Security requirements
        - Implementation phases (Phase 1: MVP, Phase 2: Scale, Phase 3: Enterprise)
      output: "requirements/consolidated_requirements.md"

1.2 Executing the Workflow

Run the workflow with our initial prompt:

hermes workflow run smartalert-requirements-analysis \
  --param user_input="Build a real-time alert management system that ingests alerts from Prometheus and Datadog, deduplicates them using AI, routes to Slack/PagerDuty, and provides a dashboard. Must handle 10k alerts/sec with 99.99% uptime."

The workflow executes sequentially, with each agent building on the previous output. After ~15 minutes, you’ll have:

1.3 Key Insight: Agent Handoff Protocol

Notice the depends_on field. Hermes Agent implements a structured handoff protocol:

  1. Each agent receives the complete output of its dependencies
  2. Agents can request clarification via the ask function
  3. Conflicts are flagged in the consolidation step

This prevents the common problem of agents contradicting each other or working from stale information.


🔧 Phase 2: Scaffolding the Project with Custom Skills

2.1 Creating the Microservice Scaffold Skill

Based on the architecture from Phase 1, let’s create a reusable skill. Create skills/microservice-scaffold.yaml:

name: "microservice-scaffold"
version: "2.0.0"
description: "Generates production-ready microservice boilerplate with Go, React, and Kubernetes"

parameters:
  service_name:
    type: string
    description: "Name of the microservice"
    required: true
  go_module_path:
    type: string
    description: "Go module path (e.g., github.com/company/smartalert)"
    required: true
  database:
    type: string
    enum: ["postgresql", "mysql", "none"]
    default: "postgresql"
  include_frontend:
    type: boolean
    default: true
  include_k8s:
    type: boolean
    default: true

steps:
  - name: "generate_backend"
    action: "file_template"
    template: |
      // {{service_name}}/cmd/server/main.go
      package main
      
      import (
          "context"
          "log"
          "net/http"
          "os"
          "os/signal"
          "syscall"
          "time"
          
          "{{go_module_path}}/internal/api"
          "{{go_module_path}}/internal/config"
          "{{go_module_path}}/internal/database"
          "{{go_module_path}}/internal/logger"
      )
      
      func main() {
          cfg := config.Load()
          log := logger.New(cfg.LogLevel)
          
          db, err := database.Connect(cfg.DatabaseURL)
          if err != nil {
              log.Fatal("failed to connect to database", "error", err)
          }
          defer db.Close()
          
          router := api.NewRouter(db, log)
          
          srv := &http.Server{
              Addr:         ":" + cfg.Port,
              Handler:      router,
              ReadTimeout:  15 * time.Second,
              WriteTimeout: 15 * time.Second,
              IdleTimeout:  60 * time.Second,
          }
          
          // Graceful shutdown
          go func() {
              if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
                  log.Fatal("server failed", "error", err)
              }
          }()
          
          quit := make(chan os.Signal, 1)
          signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
          <-quit
          
          ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
          defer cancel()
          srv.Shutdown(ctx)
      }
    output: "{{service_name}}/cmd/server/main.go"

  - name: "generate_dockerfile"
    action: "file_template"
    template: |
      # {{service_name}}/Dockerfile
      FROM golang:1.22-alpine AS builder
      WORKDIR /app
      COPY go.mod go.sum ./
      RUN go mod download
      COPY . .
      RUN CGO_ENABLED=0 GOOS=linux go build -o /app/server ./cmd/server
      
      FROM alpine:3.19
      RUN apk --no-cache add ca-certificates tzdata
      COPY --from=builder /app/server /server
      EXPOSE 8080
      ENTRYPOINT ["/server"]
    output: "{{service_name}}/Dockerfile"

  - name: "generate_helm_chart"
    action: "file_template"
    condition: "{{include_k8s}}"
    template: |
      # {{service_name}}/deployments/helm/values.yaml
      replicaCount: 3
      
      image:
        repository: "{{service_name}}"
        tag: latest
        pullPolicy: Always
      
      service:
        type: ClusterIP
        port: 8080
      
      resources:
        requests:
          memory: "256Mi"
          cpu: "250m"
        limits:
          memory: "512Mi"
          cpu: "500m"
      
      autoscaling:
        enabled: true
        minReplicas: 3
        maxReplicas: 10
        targetCPUUtilizationPercentage: 80
      
      probes:
        liveness:
          path: /healthz
          initialDelaySeconds: 10
          periodSeconds: 10
        readiness:
          path: /readyz
          initialDelaySeconds: 5
          periodSeconds: 5
      
      ingress:
        enabled: true
        annotations:
          kubernetes.io/ingress.class: nginx
          cert-manager.io/cluster-issuer: letsencrypt-prod
        hosts:
          - host: {{service_name}}.example.com
            paths:
              - /api
    output: "{{service_name}}/deployments/helm/values.yaml"

2.2 Applying the Skill

Execute the skill with our project parameters:

hermes skill run microservice-scaffold \
  --param service_name="smartalert" \
  --param go_module_path="github.com/smartotics/smartalert" \
  --param database="postgresql" \
  --param include_frontend=true \
  --param include_k8s=true

This generates 47 files in under 30 seconds, including:

2.3 Expert Tip: Skill Composition

Skills can call other skills. For example, our microservice-scaffold skill could call an api-generator skill to create OpenAPI-compliant endpoints. This composability is what makes Hermes Agent’s skill system powerful for enterprise use.


🚀 Phase 3: Implementing Core Business Logic with MCP Integration

3.1 Connecting External Services via MCP

Create mcp/slack-integration.yaml:

name: "slack-integration"
version: "1.0.0"
provider: "slack"
auth:
  type: "oauth2"
  client_id: "${SLACK_CLIENT_ID}"
  client_secret: "${SLACK_CLIENT_SECRET}"
  scopes:
    - "chat:write"
    - "channels:read"
    - "users:read"

tools:
  - name: "send_alert"
    description: "Send an alert message to a Slack channel"
    input_schema:
      type: object
      properties:
        channel:
          type: string
          description: "Slack channel ID or name"
        message:
          type: string
          description: "Alert message content"
        severity:
          type: string
          enum: ["critical", "warning", "info"]
      required: ["channel", "message"]
    handler: |
      async function handler(args) {
        const blocks = [];
        
        if (args.severity === "critical") {
          blocks.push({
            type: "header",
            text: { type: "plain_text", text: "🚨 CRITICAL ALERT" }
          });
        }
        
        blocks.push({
          type: "section",
          text: { type: "mrkdwn", text: args.message }
        });
        
        const response = await fetch("https://slack.com/api/chat.postMessage", {
          method: "POST",
          headers: {
            "Authorization": `Bearer ${this.accessToken}`,
            "Content-Type": "application/json"
          },
          body: JSON.stringify({
            channel: args.channel,
            blocks: blocks,
            text: args.message  // fallback
          })
        });
        
        return response.json();
      }

Similarly, create MCP integrations for:

3.2 The Alert Processing Pipeline

Now, let’s build the core workflow that ties everything together. Create workflows/alert-pipeline.yaml:

name: "smartalert-pipeline"
version: "1.0.0"
description: "End-to-end alert processing pipeline"

triggers:
  - type: "webhook"
    path: "/api/v1/alerts"
    methods: ["POST"]
    authentication:
      type: "api_key"
      header: "X-API-Key"
  
  - type: "cron"
    schedule: "*/5 * * * *"
    description: "Health check every 5 minutes"

workflow:
  steps:
    - name: "ingest_alert"
      action: "process_webhook"
      input:
        source: "{{trigger.source}}"
        payload: "{{trigger.payload}}"
      output: "alert"
    
    - name: "deduplicate"
      action: "ai_deduplicate"
      depends_on: ["ingest_alert"]
      input:
        alert: "{{steps.ingest_alert.output}}"
        cache: "redis://{{REDIS_HOST}}:6379/0"
        window: "5m"
      output: "dedup_result"
      condition: "{{steps.ingest_alert.output.severity != 'info'}}"
    
    - name: "enrich_alert"
      action: "ai_enrich"
      depends_on: ["deduplicate"]
      input:
        alert: "{{steps.deduplicate.output.alert}}"
        context:
          - type: "prometheus"
            query: "up{job='{{alert.service}}'}"
          - type: "datadog"
            query: "avg:system.cpu.user{service:{{alert.service}}}"
      output: "enriched_alert"
    
    - name: "classify_severity"
      action: "ai_classify"
      depends_on: ["enrich_alert"]
      input:
        alert: "{{steps.enrich_alert.output}}"
        model: "gpt-4o-mini"
        prompt: |
          Classify this alert's severity based on:
          - Historical patterns
          - Current system metrics
          - Business impact
          
          Alert: {{alert}}
          
          Output one of: "critical", "warning", "info"
      output: "classification"
    
    - name: "route_alert"
      action: "mcp_route"
      depends_on: ["classify_severity"]
      input:
        alert: "{{steps.enrich_alert.output}}"
        severity: "{{steps.classify_severity.output}}"
        routing_rules:
          - severity: "critical"
            channels:
              - type: "pagerduty"
                urgency: "high"
              - type: "slack"
                channel: "#incidents-critical"
              - type: "sns"
                topic: "arn:aws:sns:us-east-1:123456789012:critical-alerts"
          - severity: "warning"
            channels:
              - type: "slack"
                channel: "#incidents-warning"
              - type: "email"
                to: "[email protected]"
          - severity: "info"
            channels:
              - type: "slack"
                channel: "#incidents-info"
      output: "routing_result"
    
    - name: "store_alert"
      action: "database_insert"
      depends_on: ["route_alert"]
      input:
        connection: "postgresql://{{DB_USER}}:{{DB_PASS}}@{{DB_HOST}}:5432/smartalert"
        table: "alerts"
        data:
          id: "{{steps.ingest_alert.output.id}}"
          source: "{{steps.ingest_alert.output.source}}"
          severity: "{{steps.classify_severity.output}}"
          enriched_data: "{{steps.enrich_alert.output}}"
          routing_result: "{{steps.route_alert.output}}"
          created_at: "{{now()}}"

3.3 Real-Time Monitoring Dashboard

The frontend workflow generates a React dashboard with:

// src/components/AlertDashboard.tsx
import { useEffect, useState } from 'react';
import { LineChart, BarChart } from 'recharts';
import { useHermesStream } from '@hermes/react-sdk';

interface AlertMetrics {
  total: number;
  critical: number;
  warning: number;
  info: number;
  avgResponseTime: number;
}

export function AlertDashboard() {
  const [metrics, setMetrics] = useState<AlertMetrics>({
    total: 0, critical: 0, warning: 0, info: 0, avgResponseTime: 0
  });
  
  // Real-time subscription via Hermes Agent's SSE endpoint
  const { data, error } = useHermesStream('/api/v1/metrics/stream', {
    onMessage: (msg) => {
      setMetrics(prev => ({
        ...prev,
        ...msg.data
      }));
    }
  });
  
  return (
    <div className="grid grid-cols-4 gap-4 p-6">
      <MetricCard title="Total Alerts" value={metrics.total} color="blue" />
      <MetricCard title="Critical" value={metrics.critical} color="red" />
      <MetricCard title="Warning" value={metrics.warning} color="yellow" />
      <MetricCard title="Avg Response" value={`${metrics.avgResponseTime}ms`} color="green" />
      
      <div className="col-span-4">
        <LineChart width={800} height={400} data={alertHistory}>
          <Line type="monotone" dataKey="count" stroke="#8884d8" />
        </LineChart>
      </div>
    </div>
  );
}

🧪 Phase 4: Automated Testing with Hermes Agent

4.1 Test Generation Workflow

Create workflows/test-generation.yaml:

name: "generate-tests"
version: "1.0.0"
description: "Automatically generate unit, integration, and e2e tests"

steps:
  - name: "analyze_code"
    action: "code_analysis"
    input:
      path: "./src"
      coverage_threshold: 80
    output: "analysis"
  
  - name: "generate_unit_tests"
    action: "ai_generate_tests"
    depends_on: ["analyze_code"]
    input:
      files: "{{steps.analyze_code.output.untested_functions}}"
      framework: "testing"  # Go standard testing
      coverage_goal: 90
    output: "unit_tests"
  
  - name: "generate_integration_tests"
    action: "ai_generate_tests"
    depends_on: ["generate_unit_tests"]
    input:
      type: "integration"
      services:
        - "postgresql"
        - "redis"
        - "prometheus"
      scenarios:
        - "alert_ingestion_and_routing"
        - "deduplication_within_window"
        - "multi_source_correlation"
    output: "integration_tests"
  
  - name: "run_tests"
    action: "execute"
    depends_on: ["generate_integration_tests"]
    input:
      command: |
        cd /workspace/smartalert
        go test ./... -v -count=1 -race -coverprofile=coverage.out
        go tool cover -html=coverage.out -o coverage.html
    output: "test_results"
  
  - name: "fix_failures"
    action: "ai_fix_tests"
    depends_on: ["run_tests"]
    input:
      test_results: "{{steps.run_tests.output}}"
      max_attempts: 3
    condition: "{{steps.run_tests.output.exit_code != 0}}"

4.2 Running the Test Suite

hermes workflow run generate-tests --watch

Hermes Agent will:

  1. Analyze your codebase and identify untested functions
  2. Generate test cases with proper mocking and assertions
  3. Run tests and capture failures
  4. Attempt to fix failing tests (up to 3 iterations)
  5. Generate a coverage report

Example output:

✓ Generated 47 unit tests for 23 functions
✓ Generated 12 integration tests covering 5 scenarios
✓ All tests passing (100% pass rate)
✓ Code coverage: 87.3% (target: 80%)

🚢 Phase 5: CI/CD Pipeline and Deployment

5.1 GitHub Actions Workflow

Create .github/workflows/deploy.yaml:

name: "SmartAlert CI/CD Pipeline"

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      
      - name: Setup Go
        uses: actions/setup-go@v5
        with:
          go-version: '1.22'
      
      - name: Run Hermes Agent Tests
        uses: hermes-agent/action@v2
        with:
          workflow: "generate-tests"
          api-key: ${{ secrets.HERMES_API_KEY }}
      
      - name: Build Docker Image
        run: docker build -t smartalert:${{ github.sha }} .
      
      - name: Security Scan
        uses: aquasecurity/trivy-action@master
        with:
          image-ref: 'smartalert:${{ github.sha }}'
          format: 'sarif'
          output: 'trivy-results.sarif'
  
  deploy:
    needs: test
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/main'
    steps:
      - name: Configure AWS Credentials
        uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: arn:aws:iam::123456789012:role/github-actions-deploy
          aws-region: us-east-1
      
      - name: Push to ECR
        run: |
          aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin 123456789012.dkr.ecr.us-east-1.amazonaws.com
          docker tag smartalert:${{ github.sha }} 123456789012.dkr.ecr.us-east-1.amazonaws.com/smartalert:${{ github.sha }}
          docker push 123456789012.dkr.ecr.us-east-1.amazonaws.com/smartalert:${{ github.sha }}
      
      - name: Deploy to EKS
        run: |
          aws eks update-kubeconfig --name smartalert-cluster --region us-east-1
          helm upgrade --install smartalert ./deployments/helm \
            --set image.tag=${{ github.sha }} \
            --set image.repository=123456789012.dkr.ecr.us-east-1.amazonaws.com/smartalert \
            --namespace smartalert --create-namespace
      
      - name: Verify Deployment
        run: |
          kubectl rollout status deployment/smartalert -n smartalert --timeout=5m
          kubectl get pods -n smartalert -l app=smartalert

5.2 Hermes Agent Deployment Workflow

For more complex deployments, use Hermes Agent’s native deployment workflow:

name: "deploy-smartalert"
version: "1.0.0"



---

*Have questions? Join our [Discord community](https://discord.gg/smartotics) or follow us on [X](https://x.com/smartotics).*