Agent System

Building and extending MetaForge specialist agents

Table of contents

  1. Overview
  2. Agent Naming Reference
  3. Agent-Tool Matrix
    1. Phase 1 Agents
    2. Phase 2 New Agents
    3. Phase 2 Tool Expansions (Existing Agents)
  4. Agent Types
    1. 1. Requirements Agent
    2. 2. Architecture Agent
    3. Module & Development Board Recommendations (v0.2)
      1. Decision Framework by Phase
      2. Phase-Specific Decision Criteria
      3. Component Type Extensions
      4. Example Agent Outputs
      5. Tradeoff Analysis Methodology
      6. Decision Tree for Common Scenarios
    4. 3. Power Budget Agent
    5. 4. BOM Agent
    6. 5. Systems Engineering Agent
    7. 6. Firmware Agent
    8. 7. Simulation Agent
    9. 8. Manufacturing Agent
    10. 9. Test Engineering Agent
    11. 10. Supply Chain Agent
  5. Agent Architecture
    1. Base Agent Pattern (Pydantic AI)
    2. Agent Lifecycle
  6. Creating a Custom Agent
    1. Step 1: Define Agent Class
    2. Step 2: Register Tools
    3. Step 3: Add Validation
  7. Agent Testing
    1. Unit Tests
    2. Integration Tests
  8. Best Practices
    1. 1. Clear Prompts
    2. 2. Structured Output
    3. 3. Error Handling
    4. 4. Tracing
  9. Agent PRDs & Detailed Specs
  10. Next Steps

Overview

MetaForge uses specialist agents rather than a single general-purpose AI. Each agent has:

  • Clear responsibility: Focused on one aspect of hardware design
  • Defined inputs/outputs: Structured data contracts
  • Tool access: Specific tools and APIs needed for its task
  • Validation logic: Output verification and safety checks
flowchart TB
    subgraph "Agent Ecosystem"
        A1[Requirements<br/>Agent]
        A2[Architecture<br/>Agent]
        A3[Power Budget<br/>Agent]
        A4[Schematic<br/>Agent]
        A5[BOM<br/>Agent]
        A6[DFM<br/>Agent]
    end

    I[PRD.md] --> A1
    A1 --> C1[constraints.json]
    C1 --> A2
    A2 --> C2[architecture.md]
    C2 --> A4
    A4 --> C3[schematic-plan.md]

    C2 --> A3
    A3 --> C4[power-budget.json]

    C3 --> A5
    A5 --> C5[bom.csv]

    C3 --> A6
    A6 --> C6[dfm-report.md]

    style A1 fill:#9b59b6,color:#fff
    style A2 fill:#9b59b6,color:#fff
    style A3 fill:#9b59b6,color:#fff
    style A4 fill:#9b59b6,color:#fff
    style A5 fill:#9b59b6,color:#fff
    style A6 fill:#9b59b6,color:#fff

Agent Naming Reference

Canonical Agent Names: MetaForge uses consistent naming across documentation. Abbreviations are used in technical architecture docs, full names in user-facing documentation.

Code Full Name Alternative Names Phase Introduced Disciplines Covered
PMO Programme Orchestration Agent Project Manager Agent Phase 2 Product management, roadmapping
PRD Product Definition Agent Product Manager Agent Phase 1 Market analysis, feature prioritization
REQ Requirements Agent Product Spec Agent, Constraints Agent Phase 1 Requirements extraction, traceability
SYS Systems Agent Architecture Agent, Integration Agent Phase 1 Systems engineering, MBSE, interfaces
ID Industrial Design Agent HF Agent, UX Design Agent Phase 2 Form factor, ergonomics, aesthetics
ME Mechanical Agent Mechanical Engineering Agent Phase 2 CAD, FEA, thermal, tolerance analysis
EE Electronics Agent Electronics Engineering Agent Phase 1 Schematics, PCB, power/signal integrity
FW Firmware Agent Embedded Software Agent Phase 1 Drivers, RTOS, HAL, application code
ROB Robotics Agent Autonomy Agent, AI Agent Phase 2 Motion planning, perception, controls
SIM Simulation Agent Digital Twin Agent Phase 1 SPICE, FEA, CFD, virtual prototyping
TST Test Engineering Agent Validation Agent, QA Agent Phase 1 Test plans, automation, coverage
REL Reliability Agent FMEA Agent, Safety Agent Phase 2 FMEA, FTA, HALT/HASS, MTBF
MFG Manufacturing Agent NPI Agent, Production Agent Phase 1 DFM, DFA, work instructions, yield
SC Supply Chain Agent Supplier Agent, Procurement Agent Phase 1 Sourcing, alternates, EOL tracking
QA Quality Agent QMS Agent, CAPA Agent Phase 2 Quality systems, CAPA, audits
REG Regulatory Agent Compliance Agent, Certification Agent Phase 1 UKCA, FCC, CE, standards mapping
SEC Cybersecurity Agent Security Agent, InfoSec Agent Phase 2 Threat modeling, SBOM, vulnerabilities
FIELD Field Engineering Agent Deployment Agent, Service Agent Phase 2 Installation, calibration, RMA

Usage Guidelines:

  • User Documentation (README.md, docs/index.md): Use full names (e.g., “Requirements Agent”)
  • Technical Architecture (docs/architecture/): Use abbreviations with legend (e.g., “REQ Agent”)
  • Code/APIs: Use lowercase codes (e.g., req_agent, ee_agent)

Phase-Based Agent Count:

  • Phase 1 (v0.1-0.3): 6-8 core agents (REQ, SYS, EE, FW, SIM, TST, MFG, SC, REG)
  • Phase 2 (v0.4-0.6): +6-7 agents (ID, ME, ROB, REL, QA, SEC, FIELD)
  • Phase 3 (v0.7-1.0): +3-5 agents (PMO, PRD, advanced specializations)

Total: 15-20 specialized agents by Phase 3, covering all 25 hardware product development disciplines.


Agent-Tool Matrix

Which tools each agent can access. All agents have access to the Data Layer (Neo4jAdapter, MinIOAdapter) for digital thread and artifact storage.

Phase 1 Agents

Agent EDA Simulation Supply Chain Firmware CI/CD
REQ
SYS
EE KiCad (read-only) NGSpice DigiKey, Mouser, Nexar
FW KiCad (pin mapping) GCC, CMake
SIM KiCad (netlist export) NGSpice
TST KiCad (ERC) GitHub Actions
MFG KiCad (DRC, Gerber, pick-place)
SC DigiKey, Mouser, Nexar
REG

Phase 2 New Agents

Agent CAD Simulation Lab Automation Other
ID SOLIDWORKS, Fusion 360
ME FreeCAD CalculiX, OpenFOAM
ROB NGSpice, Ansys FEA
REL Ansys FEA
QA GitHub Actions, GitLab CI
SEC
FIELD SCPI, VISA, OpenTAP Flash Tools

Phase 2 Tool Expansions (Existing Agents)

Agents introduced in Phase 1 gain additional tool access in Phase 2:

Agent New Tools Added in Phase 2
EE KiCad (write: schematic generation, PCB auto-routing), Altium, LTspice, LCSC
FW Flash Tools (OpenOCD/pyOCD)
SIM LTspice, Ansys FEA
TST SCPI, VISA, OpenTAP, GitLab CI
MFG MacroFab, JLCPCB
SC LCSC

Agent Types

1. Requirements Agent

Purpose: Transforms unstructured PRD into structured constraints

interface RequirementsAgent {
  input: {
    prd: string;           // PRD.md content
  };

  output: {
    constraints: {
      electrical: ElectricalConstraints;
      mechanical: MechanicalConstraints;
      environmental: EnvironmentalConstraints;
      cost: CostConstraints;
    };
    assumptions: Assumption[];
  };

  tools: [
    "Neo4jAdapter",
    "MinIOAdapter"
  ];
}

Workflow:

sequenceDiagram
    participant G as Gateway
    participant A as Requirements Agent
    participant LLM as LLM Provider
    participant V as Validator

    G->>A: Execute(PRD.md)
    A->>LLM: Prompt with PRD
    LLM-->>A: Structured response
    A->>V: Validate constraints
    V-->>A: ✅ Valid
    A-->>G: constraints.json, assumptions.md

Example Output:

{
  "electrical": {
    "supply_voltage": { "min": 2.7, "max": 3.6, "unit": "V" },
    "current_budget": { "active": 50, "sleep": 5, "unit": "mA" },
    "interfaces": ["I2C", "SPI", "GPIO"]
  },
  "mechanical": {
    "max_dimensions": { "x": 50, "y": 50, "z": 10, "unit": "mm" },
    "pcb_layers": 2,
    "mounting": "4x M3 holes"
  }
}

2. Architecture Agent

Purpose: Selects components and creates system architecture

interface ArchitectureAgent {
  input: {
    constraints: Constraints;
  };

  output: {
    architecture: {
      microcontroller: Component;
      sensors: Component[];
      communication: Component[];
      power: PowerArchitecture;
      blockDiagram: MermaidDiagram;
    };
  };

  tools: [
    "DigiKeyAdapter",
    "MouserAdapter",
    "NexarAdapter",
    "Neo4jAdapter",
    "MinIOAdapter"
  ];
}

Workflow:

flowchart TD
    A[Read constraints.json] --> B{Select MCU}
    B --> C[ESP32-C3]

    C --> D{Select Sensors}
    D --> E[BME280<br/>Temp/Humidity]

    E --> F{Power Design}
    F --> G[LiPo Battery<br/>+ Charger]

    G --> H[Generate Block Diagram]
    H --> I[Write architecture.md]

    style C fill:#3498db,color:#fff
    style E fill:#3498db,color:#fff
    style G fill:#3498db,color:#fff

Module & Development Board Recommendations (v0.2)

The Architecture Agent provides intelligent recommendations for modules, development boards, and System-on-Modules (SoMs) based on the project phase, enabling rapid prototyping and cost-effective transitions to production.

Decision Framework by Phase

flowchart TD
    A[Architecture Request] --> B{Project Phase?}

    B -->|POC| C[Modules First Strategy]
    B -->|EVT| D[Evaluate Tradeoffs]
    B -->|DVT/PVT| E[Custom Preferred]

    C --> C1[Dev Boards<br/>Arduino, ESP32, Nucleo]
    C --> C2[Breakout Modules<br/>Adafruit, SparkFun]
    C --> C3[Timeline: 1-2 weeks]

    D --> D1{Form Factor<br/>Strict?}
    D1 -->|Yes| D2[Custom PCB]
    D1 -->|No| D3{Timeline<br/>Critical?}
    D3 -->|Yes| D4[SoM + Carrier]
    D3 -->|No| D5[Custom PCB]

    E --> E1[Custom PCB Default]
    E --> E2{Volume < 500?}
    E2 -->|Yes + Time Critical| E3[Consider SoM]
    E2 -->|No| E1

    style C fill:#2ecc71,color:#fff
    style D2 fill:#3498db,color:#fff
    style D4 fill:#f39c12,color:#fff
    style E1 fill:#3498db,color:#fff

Phase-Specific Decision Criteria

Phase Default Strategy Recommend Modules When Recommend Custom When Timeline Impact
POC Modules First • Timeline < 4 weeks
• Prototype qty < 10
• Form factor flexible
• Team lacks PCB expertise
• Cost target extremely low
• Specific form factor validated
• Team has expertise
Modules save 5-6 weeks
EVT Evaluate Tradeoffs • Time critical (< 8 weeks)
• Flexible form factor
• Volume 100-10K units
• SoM available for domain
• Cost target < $50 BOM
• Strict form factor
• Volume > 100 units
• Supply chain control needed
Custom adds 6-8 weeks
DVT/PVT Custom Preferred • Volume < 500
• Extreme time pressure
• SoM meets all requirements
• Production optimization
• Cost reduction required
• Supply chain independence
Custom enables 2-4x cost reduction

Component Type Extensions

The Architecture Agent supports multiple component abstraction levels:

interface ComponentOrModule {
  type: 'discrete_component' | 'dev_board' | 'system_on_module' | 'breakout_module';
}

interface DevelopmentBoard extends ComponentOrModule {
  type: 'dev_board';
  board_name: string;           // "STM32 Nucleo-F446RE"
  mcu_specs: MCUSpecification;
  pricing: {
    unit_cost: number;          // $24.99
    availability: 'high' | 'medium' | 'low';
    suppliers: string[];        // ["DigiKey", "Mouser", "Arduino.cc"]
  };
  use_case: 'POC' | 'EVT' | 'Low-volume-production';
  transition_path?: string;     // "Migrate to custom STM32F405 for EVT"
  io_capabilities: {
    gpio_count: number;
    adc_channels: number;
    uart_ports: number;
    i2c_buses: number;
    spi_buses: number;
  };
}

interface SystemOnModule extends ComponentOrModule {
  type: 'system_on_module';
  module_name: string;          // "Raspberry Pi Compute Module 4"
  processor_specs: ProcessorSpecification;
  pricing: {
    unit_cost: number;          // $35-$90 (depending on RAM/storage)
    moq: number;                // Minimum order quantity
    lead_time_weeks: number;
  };
  carrier_board_required: boolean;
  use_case: 'EVT' | 'DVT' | 'Production';
  volume_recommendation: {
    min_viable_volume: number;  // 100 units
    max_recommended_volume: number; // 10,000 units
  };
}

interface BreakoutModule extends ComponentOrModule {
  type: 'breakout_module';
  module_name: string;          // "Adafruit BME280"
  sensor_specs: SensorSpecification;
  pricing: {
    unit_cost: number;          // $14.95
    bulk_discount?: number;     // 10+ units: $12.95
  };
  interface: 'I2C' | 'SPI' | 'UART' | 'Analog';
  use_case: 'POC' | 'EVT';
  transition_path?: string;     // "Use discrete BME280 for DVT ($4.20 @ 100)"
}

interface ModuleRecommendations {
  strategy: 'modules_only' | 'hybrid' | 'custom_only';
  phase_specific: {
    POC?: PhaseRecommendation;
    EVT?: PhaseRecommendation;
    DVT?: PhaseRecommendation;
  };
  tradeoff_summary: TradeoffSummary;
  transition_plan?: TransitionPlan;
}

interface TradeoffSummary {
  time_advantage: {
    modules_timeline: string;   // "1-2 weeks"
    custom_timeline: string;    // "6-8 weeks"
    delta_weeks: number;        // 5-6 weeks saved
  };
  cost_breakeven: {
    module_unit_cost: number;
    custom_unit_cost: number;
    breakeven_quantity: number;
  };
  form_factor_impact: {
    module_size: string;        // "70mm x 30mm"
    custom_size: string;        // "40mm x 25mm"
    size_ratio: number;         // 2.1x larger
  };
}

interface TransitionPlan {
  current_phase: 'POC' | 'EVT' | 'DVT';
  next_phase: 'EVT' | 'DVT' | 'Production';
  recommended_changes: string[];
  cost_impact: string;
  timeline_impact: string;
}

Example Agent Outputs

Example 1: WiFi Temperature Sensor (POC Phase)

recommendation:
  strategy: "modules_only"
  rationale: "POC phase prioritizes speed to validation (1-2 weeks vs. 6-8 weeks for custom PCB)"

  components:
    microcontroller:
      type: "dev_board"
      board_name: "ESP32-DevKitC V4"
      mcu_specs:
        core: "ESP32-WROOM-32"
        clock_speed: "240 MHz"
        ram: "520 KB SRAM"
        flash: "4 MB"
        wifi: "802.11 b/g/n"
      pricing:
        unit_cost: 9.99
        supplier: "DigiKey"
      use_case: "POC"
      transition_path: "Migrate to custom ESP32-C3 design for EVT (BOM cost reduction: $9.99  $4.50)"

    sensors:
      - type: "breakout_module"
        module_name: "Adafruit BME280"
        sensor_specs:
          temperature_range: "-40°C to +85°C"
          humidity_range: "0-100% RH"
          pressure_range: "300-1100 hPa"
          interface: "I2C/SPI"
        pricing:
          unit_cost: 14.95
          bulk_discount: 12.95  # 10+ units
        use_case: "POC"
        transition_path: "Use discrete BME280 for DVT ($4.20 @ 100 units)"

  total_cost: 24.94
  time_to_working_prototype: "1-2 days"

  transition_plan:
    next_phase: "EVT"
    recommended_changes:
      - "Design custom PCB with ESP32-C3 module"
      - "Use discrete BME280 sensor with optimized power circuit"
      - "Integrate LiPo charger and power management"
    cost_impact: "$24.94 POC  $4.50 EVT BOM @ 100 units (82% reduction)"
    timeline_impact: "EVT custom PCB: 6-8 weeks design + fab"

Example 2: Drone Flight Controller (POC → EVT Transition)

POC Phase:

recommendation:
  strategy: "modules_only"

  components:
    microcontroller:
      type: "dev_board"
      board_name: "STM32 Nucleo-F446RE"
      mcu_specs:
        core: "STM32F446RET6 (ARM Cortex-M4)"
        clock_speed: "180 MHz"
        ram: "128 KB SRAM"
        flash: "512 KB"
      pricing:
        unit_cost: 24.99
        supplier: "Mouser"
      use_case: "POC"

    imu:
      type: "breakout_module"
      module_name: "SparkFun ICM-42688-P"
      sensor_specs:
        gyro_range: "±2000 dps"
        accel_range: "±16g"
        interface: "SPI"
      pricing:
        unit_cost: 39.95
      use_case: "POC"

  total_cost: 64.94
  time_to_working_prototype: "1-2 weeks"

  tradeoff_analysis:
    advantages:
      - "Validates PID control algorithms without PCB investment"
      - "Saves 6 weeks vs. custom PCB approach"
      - "Low-risk validation before $2,500 NRE commitment"
    limitations:
      - "Form factor 3x larger than production target (36x36mm)"
      - "Cost 2.3x higher than custom design"
      - "Cannot validate final mechanical integration"

EVT Phase Transition:

recommendation:
  strategy: "custom_only"
  rationale: "Strict form factor requirement (36x36mm) + cost target ($30 BOM) necessitate custom PCB"

  components:
    microcontroller:
      type: "discrete_component"
      part_number: "STM32F405RGT6"
      mcu_specs:
        core: "ARM Cortex-M4"
        clock_speed: "168 MHz"
        ram: "192 KB SRAM"
        flash: "1 MB"
      pricing:
        unit_cost: 8.50
        price_at_100: 7.20

    imu:
      type: "discrete_component"
      part_number: "ICM-42688-P"
      pricing:
        unit_cost: 12.00
        price_at_100: 9.80

  total_bom_cost: 28.50  # @ 100 units
  form_factor: "36mm x 36mm (production target achieved)"
  time_to_working_prototype: "6-8 weeks (design + fab + assembly)"

  transition_justification:
    cost_reduction: "$64.94 POC  $28.50 EVT (56% reduction)"
    form_factor_compliance: "Nucleo 70x30mm  Custom 36x36mm"
    production_readiness: "EVT design is production-viable at scale"

Tradeoff Analysis Methodology

The Architecture Agent evaluates module vs. custom design decisions using:

Time Advantage Calculation:

  • Modules: 1-2 weeks (procurement + breadboarding + testing)
  • Custom PCB: 6-8 weeks (schematic 2 weeks + layout 2 weeks + fab 1 week + assembly 1 week + debug 1-2 weeks)
  • Delta: Modules save 5-6 weeks on POC phase

Cost Breakeven Analysis:

Breakeven Quantity = (Module_Cost - Custom_Cost) / Custom_NRE

Example (WiFi Sensor):

  • Module cost: $24.94/unit
  • Custom EVT cost: $18.00/unit (@ 100)
  • Custom NRE: $2,500 (design + fab + assembly setup)
  • Breakeven: ~360 units

Form Factor Impact:

  • Development boards: 2-4x larger than custom designs
  • SoMs + carrier board: 1.2-2x larger than full custom
  • Breakout modules: 1.5-3x larger than discrete components
  • Decision: Acceptable for POC, problematic for production (EVT+)

Decision Tree for Common Scenarios

Scenario 1: “Build POC for WiFi sensor, 2-week timeline” → ✅ Recommend ESP32 DevKit + BME280 breakout → Rationale: Timeline constraint + POC phase = modules optimal

Scenario 2: “EVT for drone FC, 36x36mm form factor, $30 BOM, 100 units” → ✅ Recommend custom STM32F405 PCB → Rationale: Strict form factor + cost target = custom required

Scenario 3: “EVT for Linux vision system, 8-week timeline, flexible form factor” → ✅ Consider Jetson Nano SoM + custom carrier board → Rationale: Linux requirement + time constraint + flexible form factor = SoM viable

Scenario 4: “DVT for IoT sensor, 500 units, $10 BOM target” → ✅ Recommend custom PCB with ESP32-C3 module → Rationale: Production volume + cost target = custom optimization necessary


3. Power Budget Agent

Purpose: Calculates power consumption and battery life

interface PowerBudgetAgent {
  input: {
    architecture: Architecture;
    usage_profile: UsageProfile;
  };

  output: {
    budget: {
      components: PowerBreakdown[];
      total_active: number;
      total_sleep: number;
      battery_life: BatteryLifeEstimate;
    };
  };

  tools: [
    "Neo4jAdapter",
    "MinIOAdapter"
  ];
}

4. BOM Agent

Purpose: Generates bill of materials with pricing and availability

interface BOMAgent {
  input: {
    architecture: Architecture;
    schematic: SchematicPlan;
  };

  output: {
    bom: BOMEntry[];
    alternates: AlternateComponent[];
    costing: CostAnalysis;
  };

  tools: [
    "DigiKeyAdapter",
    "MouserAdapter",
    "NexarAdapter",
    "Neo4jAdapter",
    "MinIOAdapter"
  ];
}

5. Systems Engineering Agent

Purpose: Manages requirements traceability, interface definitions, and cross-subsystem integration

interface SystemsAgent {
  input: {
    requirements: Constraints;
    architecture: Architecture;
  };

  output: {
    traceability: {
      matrix: TraceabilityEntry[];
      coverage: number; // percentage of requirements traced
    };
    interfaces: InterfaceDefinition[];
    integration: IntegrationPlan;
    verification: VerificationPlan;
  };

  tools: [
    "Neo4jAdapter",
    "MinIOAdapter"
  ];
}

interface TraceabilityEntry {
  requirement_id: string;
  requirement_text: string;
  implementation: {
    file: string;
    component: string;
    function?: string;
  };
  verification: {
    test_id: string;
    test_procedure: string;
  };
  status: 'traced' | 'partial' | 'not_traced';
}

Workflow:

flowchart TB
    A[Read Requirements] --> B[Decompose Functions]
    B --> C[Define Interfaces]

    C --> D[Create Traceability<br/>Matrix]

    D --> E{All Requirements<br/>Traced?}
    E -->|No| F[Identify Gaps]
    F --> G[Flag Missing<br/>Implementation]

    E -->|Yes| H[Generate ICD<br/>Interface Control Docs]
    H --> I[Create Integration Plan]
    I --> J[Output Artifacts]

    style E fill:#fff3e0,stroke:#f57c00
    style J fill:#27ae60,color:#fff

Example Output:

{
  "traceability": {
    "matrix": [
      {
        "requirement_id": "REQ-001",
        "requirement_text": "System shall stabilize attitude within 2 seconds",
        "implementation": {
          "file": "firmware/src/attitude_control.c",
          "component": "PID Controller",
          "function": "pid_loop()"
        },
        "verification": {
          "test_id": "TC-012",
          "test_procedure": "Impulse response test on test stand"
        },
        "status": "traced"
      }
    ],
    "coverage": 95
  },
  "interfaces": [
    {
      "name": "IMU_SPI",
      "type": "SPI",
      "subsystem_a": "Flight Control",
      "subsystem_b": "IMU Sensor",
      "signals": ["MOSI", "MISO", "SCK", "CS"],
      "protocol": "SPI Mode 3, 10MHz",
      "data_format": "16-bit big-endian"
    }
  ]
}

6. Firmware Agent

Purpose: Generates embedded software scaffolding, drivers, and application logic

interface FirmwareAgent {
  input: {
    architecture: Architecture;
    pinout: PinoutDefinition;
    requirements: FirmwareRequirements;
  };

  output: {
    firmware: {
      hal: HardwareAbstractionLayer;
      drivers: Driver[];
      rtos_config: RTOSConfig;
      application: ApplicationScaffold;
      build_system: BuildConfig;
    };
    completeness: number; // percentage ready to compile
  };

  tools: [
    "GCCToolchainAdapter",
    "CMakeAdapter",
    "KiCadAdapter",
    "Neo4jAdapter",
    "MinIOAdapter"
  ];
}

interface Driver {
  peripheral: string; // "I2C", "SPI", "UART", "PWM"
  files: string[]; // ["i2c_driver.c", "i2c_driver.h"]
  api: Function[];
  dependencies: string[];
}

Workflow:

flowchart TB
    A[Read Hardware<br/>Architecture] --> B[Select MCU<br/>Toolchain]
    B --> C{RTOS<br/>Needed?}

    C -->|Yes| D[Configure FreeRTOS]
    C -->|No| E[Bare-metal Setup]

    D --> F[Generate HAL Layer]
    E --> F

    F --> G[Generate Drivers<br/>I2C, SPI, UART]
    G --> H[Generate Peripheral<br/>Initialization]

    H --> I[Create Task Structure]
    I --> J[Generate Main Loop]

    J --> K[Add Build System<br/>CMake/Makefile]
    K --> L[Output Source Code<br/>90%+ Complete]

    style C fill:#fff3e0,stroke:#f57c00
    style L fill:#27ae60,color:#fff

Example Output (STM32F4 Drone FC):

// Auto-generated firmware/src/drivers/icm42688_driver.c

#include "icm42688_driver.h"
#include "spi_hal.h"

// Driver generated from component selection + pinout
static SPI_Handle_t imu_spi = {
    .instance = SPI1,
    .cs_pin = GPIOA_PIN4,
    .mode = SPI_MODE3,
    .speed = 10000000 // 10 MHz
};

int32_t icm42688_init(void) {
    // Initialize SPI peripheral
    spi_init(&imu_spi);

    // Verify WHO_AM_I register
    uint8_t who_am_i;
    icm42688_read_reg(ICM42688_WHO_AM_I, &who_am_i);

    if (who_am_i != ICM42688_ID) {
        return -1; // IMU not found
    }

    // Configure accelerometer: ±16g, 1kHz ODR
    icm42688_write_reg(ICM42688_ACCEL_CONFIG0, 0x06);

    // Configure gyroscope: ±2000dps, 1kHz ODR
    icm42688_write_reg(ICM42688_GYRO_CONFIG0, 0x06);

    return 0;
}

int32_t icm42688_read_accel(float accel[3]) {
    uint8_t data[6];
    icm42688_read_regs(ICM42688_ACCEL_DATA_X1, data, 6);

    // Convert to m/s^2
    int16_t raw_x = (data[0] << 8) | data[1];
    int16_t raw_y = (data[2] << 8) | data[3];
    int16_t raw_z = (data[4] << 8) | data[5];

    accel[0] = raw_x * ACCEL_SCALE_16G;
    accel[1] = raw_y * ACCEL_SCALE_16G;
    accel[2] = raw_z * ACCEL_SCALE_16G;

    return 0;
}

Firmware Completeness: 90-95% ready to compile and test


7. Simulation Agent

Purpose: Validates designs through virtual prototyping before physical fabrication

interface SimulationAgent {
  input: {
    schematic: SchematicNetlist;
    mechanical: CADModel;
    requirements: SimulationRequirements;
  };

  output: {
    spice: SPICEResults;
    fea: FEAResults;
    cfd: CFDResults;
    reports: SimulationReport[];
    passed: boolean;
  };

  tools: [
    "NGSpiceAdapter",
    "KiCadAdapter",
    "Neo4jAdapter",
    "MinIOAdapter"
  ];
}

interface SPICEResults {
  dc_analysis: DCOperatingPoint;
  ac_analysis: FrequencyResponse;
  transient: TransientResponse;
  issues: Issue[];
}

Workflow:

flowchart TB
    A[Read Design<br/>Artifacts] --> B{Simulation<br/>Type?}

    B -->|Electrical| C[SPICE Analysis]
    B -->|Mechanical| D[FEA Analysis]
    B -->|Thermal| E[CFD Analysis]

    C --> C1[DC Operating Point]
    C1 --> C2[AC Frequency Response]
    C2 --> C3[Transient Analysis]

    D --> D1[Static Stress]
    D1 --> D2[Modal Analysis]
    D2 --> D3[Vibration Response]

    E --> E1[Thermal Steady-State]
    E1 --> E2[Hotspot Detection]

    C3 --> F[Validate Against<br/>Requirements]
    D3 --> F
    E2 --> F

    F --> G{Pass?}
    G -->|No| H[Generate Issue Report]
    G -->|Yes| I[Generate Pass Report]

    H --> J[Suggest Fixes]
    I --> K[Approve for Fab]

    style G fill:#fff3e0,stroke:#f57c00
    style K fill:#27ae60,color:#fff

Example SPICE Simulation (Power Supply):

simulation_results:
  circuit: "5V Buck Converter"

  dc_analysis:
    output_voltage: 5.02V
    output_current: 1.5A
    efficiency: 89.3%
    ripple_voltage: 12mV (spec: <50mV)

  transient_analysis:
    startup_time: 2.3ms
    overshoot: 3.2% (spec: <5%)
    load_step_response:
      settling_time: 450us
      voltage_dip: 180mV

  issues:
    - severity: warning
      message: "Output capacitor ESR high (120mΩ) - consider lower ESR cap"
      impact: "Ripple could increase with aging"

  recommendation: "PASS - meets all critical requirements"

8. Manufacturing Agent

Purpose: Validates manufacturability and coordinates production preparation

interface ManufacturingAgent {
  input: {
    pcb_design: PCBFiles;
    bom: BillOfMaterials;
    quantity: number;
  };

  output: {
    dfm_report: DFMValidation;
    assembly_instructions: AssemblyDoc;
    work_instructions: WorkInstruction[];
    vendor_quotes: VendorQuote[];
    issues: ManufacturingIssue[];
  };

  tools: [
    "KiCadAdapter",
    "Neo4jAdapter",
    "MinIOAdapter"
  ];
}

interface DFMValidation {
  checks: DFMCheck[];
  score: number; // 0-100
  manufacturability: 'excellent' | 'good' | 'fair' | 'poor';
  estimated_yield: number; // percentage
}

Workflow:

flowchart TB
    A[Read PCB Design] --> B[DFM Validation]

    B --> C[Check Trace Width]
    C --> D[Check Clearances]
    D --> E[Check Via Sizes]
    E --> F[Check Pad Sizes]
    F --> G[Check Component Spacing]

    G --> H{DFM Issues<br/>Found?}

    H -->|Yes| I[Classify Severity]
    I --> J{Can Auto-Fix?}
    J -->|Yes| K[Apply Fixes]
    J -->|No| L[Flag for Review]

    H -->|No| M[Generate Assembly<br/>Instructions]
    K --> M

    M --> N[Create Pick & Place<br/>Files]
    N --> O[Generate Work<br/>Instructions]

    O --> P[Request Vendor<br/>Quotes]
    P --> Q[Output Manufacturing<br/>Package]

    style H fill:#fff3e0,stroke:#f57c00
    style Q fill:#27ae60,color:#fff

Example DFM Report:

dfm_validation:
  score: 87
  manufacturability: "good"
  estimated_yield: 94%

  checks:
    - name: "Minimum trace width"
      status: pass
      value: 0.15mm
      spec: ">0.10mm"

    - name: "Minimum clearance"
      status: pass
      value: 0.18mm
      spec: ">0.15mm"

    - name: "Via aspect ratio"
      status: warning
      value: 8.2
      spec: "<10:1"
      message: "High aspect ratio may reduce yield"

    - name: "Component spacing"
      status: fail
      location: "U3, U4"
      value: 0.8mm
      spec: ">1.0mm"
      message: "Insufficient spacing for pick-and-place"
      fix: "Move U4 1.5mm to right"

  issues:
    - severity: critical
      type: "component_spacing"
      components: ["U3", "U4"]
      description: "Components too close for automated assembly"
      recommendation: "Increase spacing to 1.2mm minimum"
      impact: "Manual assembly required, +$5/board"

  assembly_complexity: "medium"
  recommended_process: "SMT with selective hand-assembly"
  estimated_assembly_time: "12 minutes/board"

9. Test Engineering Agent

Purpose: Generates comprehensive test plans and validation procedures

interface TestEngineeringAgent {
  input: {
    requirements: Requirements;
    architecture: Architecture;
    risk_analysis: FMEA;
  };

  output: {
    test_plan: TestPlan;
    test_cases: TestCase[];
    fmea: FMEAAnalysis;
    coverage: TestCoverage;
  };

  tools: [
    "KiCadAdapter",
    "GitHubActionsAdapter",
    "Neo4jAdapter",
    "MinIOAdapter"
  ];
}

interface TestCase {
  id: string;
  name: string;
  objective: string;
  requirements_traced: string[];
  procedure: TestStep[];
  acceptance_criteria: AcceptanceCriteria;
  equipment_needed: Equipment[];
}

Example Test Plan (Drone Flight Controller):

test_plan:
  product: "Drone Flight Controller v1.0"

  test_phases:
    unit_testing:
      - test_id: "UT-001"
        name: "IMU Communication Test"
        requirements: ["REQ-005"]
        procedure:
          - "Power on DUT"
          - "Read WHO_AM_I register"
          - "Verify response = 0x47"
        acceptance: "WHO_AM_I returns correct value"
        equipment: ["Oscilloscope", "Logic Analyzer"]

      - test_id: "UT-002"
        name: "PWM Output Test"
        requirements: ["REQ-008"]
        procedure:
          - "Configure PWM for 50Hz"
          - "Set duty cycle 5-10%"
          - "Measure output frequency"
        acceptance: "Frequency = 50Hz ±1Hz, Duty cycle accurate ±0.5%"

    integration_testing:
      - test_id: "IT-001"
        name: "Sensor Fusion Test"
        requirements: ["REQ-012", "REQ-013"]
        procedure:
          - "Apply known rotation"
          - "Record attitude estimate"
          - "Compare to ground truth"
        acceptance: "Attitude error <2 degrees RMS"

    system_testing:
      - test_id: "ST-001"
        name: "Stabilization Performance"
        requirements: ["REQ-001"]
        procedure:
          - "Mount on test stand"
          - "Apply impulse disturbance"
          - "Measure settling time"
        acceptance: "Stabilizes within 2 seconds"

  fmea_summary:
    - failure_mode: "IMU sensor failure"
      effect: "Loss of attitude estimate"
      severity: 9
      occurrence: 2
      detection: 3
      rpn: 54
      mitigation: "Dual IMU with voting"

    - failure_mode: "Power supply brownout"
      effect: "MCU reset"
      severity: 7
      occurrence: 3
      detection: 2
      rpn: 42
      mitigation: "Voltage supervisor + brownout detection"

  test_coverage:
    requirements_coverage: 95%
    code_coverage: 78%
    branch_coverage: 65%

10. Supply Chain Agent

Purpose: Extended BOM management with risk analysis, lifecycle tracking, and alternate sourcing

interface SupplyChainAgent {
  input: {
    bom: BillOfMaterials;
    quantity: number;
    target_date: Date;
  };

  output: {
    bom_with_risk: BOMWithRisk;
    alternates: AlternateComponents;
    eol_warnings: EOLWarning[];
    sourcing_strategy: SourcingStrategy;
    lead_time_analysis: LeadTimeAnalysis;
  };

  tools: [
    "DigiKeyAdapter",
    "MouserAdapter",
    "NexarAdapter",
    "Neo4jAdapter",
    "MinIOAdapter"
  ];
}

interface BOMWithRisk {
  entries: BOMEntry[];
  overall_risk: 'low' | 'medium' | 'high' | 'critical';
  risk_score: number; // 0-100
  availability_score: number; // 0-100
}

interface EOLWarning {
  component: string;
  mpn: string;
  status: 'active' | 'nrnd' | 'obsolete';
  last_time_buy?: Date;
  recommended_action: string;
  alternates: Component[];
}

Workflow:

flowchart TB
    A[Read BOM] --> B[Check Each Component]

    B --> C[Query Supplier APIs<br/>Digi-Key, Mouser, Octopart]

    C --> D{Component<br/>Available?}

    D -->|Yes| E[Check Stock Level]
    E --> F{Sufficient<br/>Stock?}
    F -->|Yes| G[Check Price]
    F -->|No| H[Calculate Lead Time]

    D -->|No| I[Find Alternates]

    G --> J[Check Lifecycle]
    J --> K{EOL Risk?}

    K -->|NRND/Obsolete| L[High Risk<br/>Find Alternates]
    K -->|Active| M[Low Risk]

    H --> N[High Risk<br/>Long Lead Time]
    I --> O[Critical Risk<br/>Not Available]

    L --> P[Calculate Risk Score]
    M --> P
    N --> P
    O --> P

    P --> Q[Generate Report]

    style D fill:#fff3e0,stroke:#f57c00
    style K fill:#fff3e0,stroke:#f57c00
    style Q fill:#27ae60,color:#fff

Example Supply Chain Analysis:

bom_risk_analysis:
  overall_risk: "medium"
  risk_score: 65
  availability_score: 78

  components:
    - mpn: "STM32F405RGT6"
      manufacturer: "STMicroelectronics"
      quantity_needed: 100

      availability:
        digi_key:
          stock: 2450
          lead_time: "in stock"
          price_100: "$8.32"
        mouser:
          stock: 1890
          lead_time: "in stock"
          price_100: "$8.45"

      lifecycle:
        status: "active"
        nrnd_risk: "low"

      risk_assessment:
        availability_risk: "low"
        price_risk: "medium" # increased 12% vs 6mo ago
        eol_risk: "low"
        overall: "low"

    - mpn: "ICM-42688-P"
      manufacturer: "TDK InvenSense"
      quantity_needed: 100

      availability:
        digi_key:
          stock: 45
          lead_time: "18 weeks"
          price_100: "$2.85"
        mouser:
          stock: 0
          lead_time: "22 weeks"

      lifecycle:
        status: "active"

      risk_assessment:
        availability_risk: "high" # insufficient stock
        lead_time_risk: "critical" # 18-22 weeks
        overall: "critical"

      recommended_action: "Consider alternate: ICM-20948 (in stock)"

      alternates:
        - mpn: "ICM-20948"
          stock_digi_key: 1250
          lead_time: "in stock"
          price_100: "$3.12"
          compatibility: "drop-in replacement"

  eol_warnings:
    - mpn: "LP2985-33DBVR"
      status: "NRND" # Not Recommended for New Designs
      last_time_buy: "2026-12-31"
      message: "LDO regulator approaching EOL"
      recommended_alternate: "TPS7A2033PDBVR"

  sourcing_strategy:
    recommended: "dual_source"
    primary_supplier: "Digi-Key"
    secondary_supplier: "Mouser"
    critical_components:
      - "ICM-42688-P: Pre-order 150 units (50% buffer)"
      - "STM32F405RGT6: Standard ordering OK"

Agent Architecture

Base Agent Pattern (Pydantic AI)

MetaForge agents are defined using Pydantic AI with Temporal for durable execution. See ADR-001 for the full architecture decision.

from __future__ import annotations

from dataclasses import dataclass
from pydantic import BaseModel, Field
from pydantic_ai import Agent, RunContext
from pydantic_ai.mcp import MCPServerStdio
from temporalio import activity


# --- Base Dependencies (all agents extend this) ---

@dataclass
class BaseAgentDeps:
    """Shared dependencies injected into every agent at runtime."""
    project_path: str
    session_id: str
    design_rules: dict
    knowledge_store: object   # pgvector knowledge layer


# --- Base Output (all agents produce structured output) ---

class AgentOutput(BaseModel):
    """Base output model. Each agent defines a specific subclass."""
    confidence: float = Field(ge=0.0, le=1.0, description="Confidence score")
    assumptions: list[str] = Field(default_factory=list, description="Assumptions made")
    warnings: list[str] = Field(default_factory=list, description="Warnings for review")


# --- MCP Server Connections (shared across agents) ---

neo4j_mcp = MCPServerStdio('python', args=['-m', 'metaforge.mcp.neo4j_server'])
kicad_mcp = MCPServerStdio('python', args=['-m', 'metaforge.mcp.kicad_server'])
spice_mcp = MCPServerStdio('python', args=['-m', 'metaforge.mcp.spice_server'])
freecad_mcp = MCPServerStdio('python', args=['-m', 'metaforge.mcp.freecad_server'])


# --- Example: Requirements Agent Definition ---

class RequirementsOutput(AgentOutput):
    electrical: list[dict] = Field(description="Electrical constraints")
    mechanical: list[dict] = Field(description="Mechanical constraints")
    environmental: list[dict] = Field(description="Environmental constraints")
    cost: list[dict] = Field(description="Cost constraints")


requirements_agent = Agent(
    model='anthropic:claude-sonnet-4-20250514',
    deps_type=BaseAgentDeps,
    output_type=RequirementsOutput,
    mcp_servers=[neo4j_mcp],
    system_prompt=(
        'You are the MetaForge Requirements Agent. '
        'Extract structured engineering constraints from a PRD.'
    ),
)


# --- Custom Tool with Dependency Injection ---

@requirements_agent.tool
async def check_design_rules(
    ctx: RunContext[BaseAgentDeps],
    constraint_name: str,
    proposed_value: float,
) -> str:
    """Check a proposed constraint against known design rules."""
    rules = ctx.deps.design_rules
    if constraint_name in rules:
        rule = rules[constraint_name]
        if rule['min'] <= proposed_value <= rule['max']:
            return f"PASS: {constraint_name}={proposed_value} within range"
        return f"FAIL: {constraint_name}={proposed_value} outside range"
    return f"NO_RULE: No design rule found for {constraint_name}"


# --- Knowledge Retrieval Tool (AI Memory Layer — pgvector + RAG) ---

@requirements_agent.tool
async def retrieve_knowledge(
    ctx: RunContext[BaseAgentDeps],
    query: str,
    top_k: int = 5,
    min_score: float = 0.7,
) -> list[dict]:
    """Semantic search over project knowledge (past sessions, decisions, datasheets)."""
    store = ctx.deps.knowledge_store
    results = await store.search(query, top_k=top_k, min_score=min_score)
    return [{'content': r.content, 'score': r.score, 'source': r.source} for r in results]


# --- Temporal Activity Wrapper ---

@activity.defn
async def run_requirements_agent(
    prd_content: str, project_path: str, session_id: str
) -> dict:
    """Temporal activity — crash-recoverable agent execution."""
    deps = BaseAgentDeps(
        project_path=project_path,
        session_id=session_id,
        design_rules=load_design_rules(project_path),
        knowledge_store=get_knowledge_store(),
    )
    result = await requirements_agent.run(
        f"Extract requirements from this PRD:\n\n{prd_content}",
        deps=deps,
    )
    return result.output.model_dump()

Agent Lifecycle

stateDiagram-v2
    [*] --> Created: Gateway spawns
    Created --> Initializing: Load config
    Initializing --> Ready: Setup complete
    Ready --> Executing: Run requested

    Executing --> Processing: Call LLM
    Processing --> ToolCall: Tool needed
    ToolCall --> Processing: Result
    Processing --> Validating: Response complete

    Validating --> Completed: ✅ Valid
    Validating --> Retry: ❌ Invalid
    Retry --> Processing: Feedback

    Completed --> [*]: Return result

    Executing --> Failed: Error
    Failed --> [*]: Cleanup

Creating a Custom Agent

Step 1: Define Agent Class

import { Agent, AgentConfig, ExecutionContext } from '@metaforge/core';

export class CustomAgent implements Agent {
  name = 'custom-agent';
  version = '1.0.0';
  description = 'Your agent description';

  private llm: LLMProvider;
  private tools: ToolRegistry;

  async initialize(config: AgentConfig): Promise<void> {
    this.llm = config.llmProvider;
    this.tools = config.toolRegistry;
  }

  async execute(context: ExecutionContext): Promise<AgentResult> {
    // 1. Load input
    const input = await this.loadInput(context);

    // 2. Validate input
    const validation = this.validateInput(input);
    if (!validation.valid) {
      throw new Error(`Invalid input: ${validation.errors}`);
    }

    // 3. Build prompt
    const prompt = this.buildPrompt(input);

    // 4. Call LLM
    const response = await this.llm.complete(prompt, {
      tools: this.getTools(),
      temperature: 0.3,
      maxTokens: 4000
    });

    // 5. Parse response
    const output = this.parseResponse(response);

    // 6. Validate output
    const outputValidation = this.validateOutput(output);
    if (!outputValidation.valid) {
      throw new Error(`Invalid output: ${outputValidation.errors}`);
    }

    // 7. Return artifacts
    return {
      artifacts: output.artifacts,
      metadata: output.metadata,
      traces: this.getTraces()
    };
  }

  validateInput(input: any): ValidationResult {
    // Implement input validation
  }

  validateOutput(output: any): ValidationResult {
    // Implement output validation
  }

  private buildPrompt(input: any): string {
    return `
You are a specialist agent for ${this.description}.

Input:
${JSON.stringify(input, null, 2)}

Task:
[Your specific task description]

Output Format:
[Expected JSON schema]
    `.trim();
  }
}

Step 2: Register Tools

export class CustomAgent implements Agent {
  registerTools(registry: ToolRegistry): void {
    registry.register({
      name: 'read_datasheet',
      description: 'Read component datasheet',
      parameters: {
        component: { type: 'string', required: true }
      },
      execute: async (params) => {
        // Tool implementation
      }
    });
  }

  private getTools(): Tool[] {
    return this.tools.getByNames([
      'read_datasheet',
      'search_components'
    ]);
  }
}

Step 3: Add Validation

import { z } from 'zod';

const InputSchema = z.object({
  constraints: z.object({
    voltage: z.number().positive(),
    current: z.number().positive()
  })
});

const OutputSchema = z.object({
  components: z.array(z.object({
    part_number: z.string(),
    manufacturer: z.string(),
    price: z.number()
  }))
});

export class CustomAgent implements Agent {
  validateInput(input: any): ValidationResult {
    try {
      InputSchema.parse(input);
      return { valid: true };
    } catch (error) {
      return {
        valid: false,
        errors: error.errors
      };
    }
  }

  validateOutput(output: any): ValidationResult {
    try {
      OutputSchema.parse(output);
      return { valid: true };
    } catch (error) {
      return {
        valid: false,
        errors: error.errors
      };
    }
  }
}

Agent Testing

Unit Tests

import { describe, it, expect } from 'vitest';
import { CustomAgent } from './custom-agent';

describe('CustomAgent', () => {
  it('validates input correctly', () => {
    const agent = new CustomAgent();
    const result = agent.validateInput({
      constraints: { voltage: 3.3, current: 0.5 }
    });

    expect(result.valid).toBe(true);
  });

  it('generates valid output', async () => {
    const agent = new CustomAgent();
    await agent.initialize(mockConfig);

    const result = await agent.execute(mockContext);

    expect(result.artifacts).toBeDefined();
    expect(agent.validateOutput(result).valid).toBe(true);
  });
});

Integration Tests

describe('CustomAgent Integration', () => {
  it('integrates with gateway', async () => {
    const gateway = await startGateway();
    const result = await gateway.runSkill('custom-skill');

    expect(result.status).toBe('completed');
    expect(result.artifacts).toHaveLength(2);
  });
});

Best Practices

1. Clear Prompts

// ❌ Bad: Vague prompt
const prompt = "Analyze this design";

// ✅ Good: Specific prompt
const prompt = `
Analyze the power consumption of this hardware design.

Given:
- Components: ${components}
- Usage profile: ${usage}

Calculate:
1. Active current (mA)
2. Sleep current (µA)
3. Battery life (days) for ${batteryCapacity}mAh battery

Output as JSON with schema:
{
  "active_ma": number,
  "sleep_ua": number,
  "battery_life_days": number
}
`;

2. Structured Output

// ✅ Use JSON schema validation
const response = await llm.complete(prompt, {
  response_format: { type: "json_object" },
  schema: OutputSchema
});

3. Error Handling

async execute(context: ExecutionContext): Promise<AgentResult> {
  try {
    return await this.executeInternal(context);
  } catch (error) {
    if (error instanceof ValidationError) {
      // Retry with feedback
      return await this.retryWithFeedback(context, error);
    }

    if (error instanceof ToolError) {
      // Log and fail gracefully
      this.logger.error('Tool execution failed', error);
      throw new AgentError('Tool failure', { cause: error });
    }

    throw error;
  }
}

4. Tracing

class CustomAgent implements Agent {
  private traces: Trace[] = [];

  private trace(action: string, data: any): void {
    this.traces.push({
      timestamp: new Date(),
      agent: this.name,
      action,
      data,
      level: 'info'
    });
  }

  async execute(context: ExecutionContext): Promise<AgentResult> {
    this.trace('execution_started', { input: context.input });

    const result = await this.executeInternal(context);

    this.trace('execution_completed', {
      artifacts: result.artifacts.map(a => a.path)
    });

    return { ...result, traces: this.traces };
  }
}

Agent PRDs & Detailed Specs

Agent Document Status
ME (Mechanical) Mechanical Engineering Agent PRD Draft

Next Steps


← HomeTools →