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:
- Part 1: Installation and basic workflows
- Part 2: Multi-role collaboration between AI, developers, and domain experts
- Part 3: Skill system design and reuse
- Part 4: Cron-based automation for content pipelines
- Part 5: MCP protocol integration for tool extension
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:
- Analyze ambiguous requirements and generate structured specifications
- Coordinate multiple specialized agents (architect, backend, frontend, DevOps)
- Execute automated testing with real-time feedback loops
- Deploy to Kubernetes with zero-downtime strategies
- Monitor and alert on production metrics
Learning Objectives:
- Design multi-phase workflows that handle real-world project complexity
- Implement Hermes Agent’s
workflow_chainingfeature for pipeline orchestration - Configure MCP-based integration with AWS, GitHub, and Slack APIs
- Build a reusable “project scaffold” skill that accelerates future development
📋 Project Overview: The “SmartAlert” Microservice
We’ll build SmartAlert—a real-time incident management service that:
- Ingests alerts from multiple sources (Prometheus, Datadog, custom APIs)
- Deduplicates and enriches alerts using AI classification
- Routes alerts to appropriate teams via Slack, PagerDuty, or email
- Provides a dashboard for historical analysis
Technical Stack:
- Backend: Go 1.22 (performance-critical), PostgreSQL 16, Redis 7
- Frontend: React 18 with TypeScript, Vite, Tailwind CSS
- Infrastructure: Docker, Kubernetes (EKS), Terraform, Helm
- CI/CD: GitHub Actions + ArgoCD
Why this project? It demonstrates every major Hermes Agent capability:
- Multi-agent collaboration (architect + developer + SRE)
- MCP integration (Slack, PagerDuty, AWS)
- Cron-based health checks and report generation
- Skill reuse (we’ll create a reusable
microservice-scaffoldskill)
🏗️ 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:
requirements/initial_requirements.yaml: 12 user stories with acceptance criteriadesign/architecture.yaml: C4 model diagrams, OpenAPI spec, data modeldesign/security_requirements.yaml: 23 security requirements with STRIDE analysisrequirements/consolidated_requirements.md: Comprehensive 40-page requirements document
1.3 Key Insight: Agent Handoff Protocol
Notice the depends_on field. Hermes Agent implements a structured handoff protocol:
- Each agent receives the complete output of its dependencies
- Agents can request clarification via the
askfunction - 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:
- Go backend with graceful shutdown, structured logging, and health checks
- React frontend with Vite, TypeScript, and Tailwind CSS
- Docker multi-stage builds
- Helm chart with HPA, probes, and ingress
- GitHub Actions CI/CD pipeline
- Terraform infrastructure code
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:
- PagerDuty: Trigger incidents, acknowledge, resolve
- Prometheus: Query metrics, check alert rules
- Datadog: Fetch monitors, post events
- AWS SNS: Send notifications to multiple channels
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: "oncall-team@example.com"
- 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:
- Analyze your codebase and identify untested functions
- Generate test cases with proper mocking and assertions
- Run tests and capture failures
- Attempt to fix failing tests (up to 3 iterations)
- 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"
description: "Alerts on deploy failures and rollbacks"
author: "sre-team"
trigger:
event: "deployment.failed"
cooldown_minutes: 5
steps:
- name: "collect-context"
action: "git.log"
params:
lines: 20
- name: "notify"
action: "slack.post"
params:
channel: "#ops-alerts"
template: "deploy_failed"
What this buys you: a skill is just a folder with a skill.yaml and a prompt. The trigger block is the part people forget — without cooldown_minutes one failing deploy pages the channel eleven times in ninety seconds.
Have questions? Join our Discord community or follow us on X.
Have questions? Join our Discord community or follow us on X.