Agentic Software Engineering in Go: Production Operations & Metrics

Observability, continuous improvement, and scaling beyond the individual

The Problem: The “Black Box” Factory

Most agentic factories are black boxes:

The problem: Without observability and continuous improvement, factories degrade over time:

The Observability Stack

The Observability Stack provides full visibility into factory operations.

1. Metrics Pipeline

// pkg/metrics/metrics.go — Factory metrics collection
type FactoryMetrics struct {
    // Task metrics
    TasksSubmitted    int64
    TasksCompleted    int64
    TasksFailed       int64
    AverageDuration   float64
    TasksByType       map[string]int64

    // Verification metrics
    VerificationPassRate float64
    AverageVerificationDuration float64
    VerificationErrorsByType map[string]int64

    // Agent metrics
    ActiveWorkers     int
    AverageAutonomyLevel string
    AutonomyScoreDistribution map[string]int64

    // Security metrics
    PromptInjectionsBlocked int64
    SecurityViolations      int64
    RBACViolations          int64

    // Timestamp
    Timestamp time.Time
}
// Metrics collection example
func RecordTaskSubmitted(taskType string) {
    metrics.TaskSubmitted++
    metrics.TasksByType[taskType]++
}

func RecordVerificationResult(success bool, duration time.Duration) {
    if success {
        metrics.VerificationPassRate = (metrics.VerificationPassRate*float64(metrics.VerificationSubmitted-1) + 1) / float64(metrics.VerificationSubmitted+1)
    } else {
        metrics.VerificationErrorsByType[getErrorType()]++
    }
    metrics.AverageVerificationDuration = (metrics.AverageVerificationDuration*float64(metrics.VerificationSubmitted) + duration.Seconds()) / float64(metrics.VerificationSubmitted+1)
    metrics.VerificationSubmitted++
}

2. Log Correlation

// Structured logging with correlation IDs
type LogEntry struct {
    CorrelationID string      `json:"correlation_id"`
    TraceID       string      `json:"trace_id"`
    Timestamp     time.Time   `json:"timestamp"`
    Level         string      `json:"level"`
    Component     string      `json:"component"`
    Action        string      `json:"action"`
    Success       bool        `json:"success"`
    Metadata      map[string]string `json:"metadata"`
}

func LogAgentAction(correlationID, component, action string, success bool, metadata map[string]string) {
    entry := LogEntry{
        CorrelationID: correlationID,
        Component:    component,
        Action:       action,
        Success:      success,
        Metadata:     metadata,
        Timestamp:    time.Now(),
    }
    structuredLog(entry)
}

3. Tracing

# OpenTelemetry tracing integration
func (fo *FactoryOrchestrator) startTracing(ctx context.Context) {
    tp := trace.NewTracerProvider(
        trace.WithBatcher(func(spans []trace.Span) error {
            exportSpans(spans)
        }),
    )
    traceProvider = tp

    # Create spans for factory operations
    ctx, span := trace.SpanFromContext(ctx, "factory_start")
    # ... record span events
    span.End()
}

4. Dashboards

# Factory metrics dashboard endpoint
func (fo *FactoryOrchestrator) GetMetrics() factory.Metrics {
    fo.mu.RLock()
    defer fo.mu.RUnlock()

    return factory.Metrics{
        WorkersTotal:         fo.workerCount,
        WorkersBusy:          busyCount,
        TasksPending:         len(fo.taskQueue),
        TasksCompleted:      completedCount,
        TasksFailed:          failedCount,
        VerificationPassRate: verificationPassRate,
        AverageDuration:      averageDuration,
    }
}

Observability Dashboard

dashboard
    title "Agentic Software Factory Observability"

    grid "Tasks" {
        stat "Tasks Submitted/hr" metrics.TasksSubmitted/3600 "green"
        stat "Tasks Completed/hr" metrics.TasksCompleted/3600 "yellow"
        stat "Tasks Failed/hr" metrics.TasksFailed/3600 "red"
    }

    grid "Verification" {
        stat "Pass Rate" metrics.VerificationPassRate "green"
        stat "Avg Duration" fmt.Sprintf("%.1fs", metrics.AverageVerificationDuration) "yellow"
    }

    grid "Factory" {
        stat "Active Workers" metrics.ActiveWorkers "yellow"
        stat "Autonomy Level" metrics.AutonomyLevel "yellow"
    }

    grid "Security" {
        stat "Prompt Injections Blocked" metrics.PromptInjectionsBlocked "green"
        stat "Security Violations" metrics.SecurityViolations "red"
    }

Continuous Improvement Pipeline

flowchart TD
    A[Collect Metrics] --> B[Analyze Trends]
    B --> C[Identify Improvements]
    C --> D[Update Configurations]
    D -->[E Deploy]
    E -->|A/B Test| F[Measure Impact]
    F -->|Improve| A
    G[Regress] -->|Rollback| A

Improvement Loop

# Improvement pipeline
func (fo *FactoryOrchestrator) RunImprovementCycle() error {
    # 1. Collect metrics from last cycle
    metrics := fo.CollectMetrics()

    # 2. Analyze trends
    trends := fo.AnalyzeTrends(metrics)

    # 3. Identify improvement opportunities
    improvements := fo.IdentifyImprovements(trends)

    # 4. Apply configurations
    for _, improvement := range improvements {
        if err := fo.ApplyConfiguration(improvement); err != nil {
            return err
        }
    }

    # 5. A/B test if needed
    if len(improvements) > 1 {
        results := fo.RunABTest(improvements)
        if !results[0].BetterThan(results[1]) {
            # Revert the worse improvement
            fo.RevertConfiguration(improvements[1])
        }
    }

    return nil
}

A/B Testing Factory Configurations

# A/B test two factory configurations
func (fo *FactoryOrchestrator) A/BTest(configA, configB string, duration time.Duration) (bool, error) {
    # 1. Apply config A
    err := fo.ApplyConfiguration(configA)
    if err != nil {
        return false, err
    }

    # Record metrics during A
    metricsA := fo.RecordMetrics(duration)

    # Apply config B
    err = fo.ApplyConfiguration(configB)
    if err != nil {
        return false, err
    }

    # Record metrics during B
    metricsB := fo.RecordMetrics(duration)

    # Compare results
    return metricsB.BetterThan(metricsA), nil
}

Improvement Categories

Improvement Categories
Category Description Example Improvements
Model Routing Switch models based on task type Use haiku for simple tasks, sonnet for complex
Prompt Optimization Refine prompts based on failure patterns Add missing constraints, clarify success criteria
Autonomy Calibration Adjust autonomy based on success/failure Raise/lower autonomy thresholds
Context Updates Add missing ADRs/specs based on gaps Add new ADRs for frequently failed areas
Scheduler Tuning Optimize worker pool size and timing Adjust pool size, timeout values
Security Rules Update prompt injection patterns Add new blocked patterns, refine RBAC

Improvement Dashboard

gantt
    title Factory Improvement Cycle
    dateFormat  YYYY-MM-DD
    section Metrics Collection
    Metrics Collection          :active, m1, 2024-01-01, 1d
    Trend Analysis              :after m1, 1d
    Improvement Identification  :after m2, 1d
    Configuration Updates       :after m3, 3d
    A/B Testing                 :after m4, 7d
    Result Analysis             :after m5, 2d

Quick Start

# Initialize with observability
asf init --with-observability

# Start factory with metrics
asf factory start

# Access metrics at http://localhost:8080/metrics

# Run improvement cycle
asf factory improve

# View dashboard at http://localhost:8080/dashboard

# The factory will automatically:
# 1. Collect metrics on every operation
# 2. Analyze trends and identify improvements
# 3. Apply configuration updates
# 4. Run A/B tests to validate improvements
# 5. Provide dashboard for monitoring

Why Observability Matters

Why Observability Matters
Concern Without Observability With Observability
Quality Tracking “It seems to work” Data-driven quality metrics
Cost Optimization Unknown costs Model routing, prompt optimization
Security Posture Unknown vulnerabilities Tracked violations and block rates
Team Decisions Anecdotal, subjective Data-driven improvements
Scaling Decisions Guesswork Metrics-based scaling
Incident Response Blind to issues Immediate visibility
Continuous Improvement Ad hoc, reactive Systematic, iterative

Quick Start

# Initialize with observability
asf init --with-observability

# Start factory with metrics endpoint
asf factory start

# Access metrics at http://localhost:8080/metrics
# Access dashboard at http://localhost:8080/dashboard

# Run improvement cycle
asf factory improve

# View trend analysis and apply recommended configurations

Next: Case Study

In the next post, we’ll present a case study of an end-to-end implementation: taking a feature from specification through to production deployment.


All code examples are in Go 1.23+. Diagrams use white-background Archify for presentation-ready architecture visualizations.

Sources & References