Agent System
Building and extending MetaForge specialist agents
Table of contents
- Overview
- Agent Naming Reference
- Agent-Tool Matrix
- Agent Types
- Agent Architecture
- Creating a Custom Agent
- Agent Testing
- Best Practices
- Agent PRDs & Detailed Specs
- 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
- Tool Adapters - Integrating external tools
- API Reference - Gateway API documentation
- Architecture - System internals
- AI Memory & Knowledge - Knowledge Layer: pgvector embeddings, RAG retrieval, session memory
- System Observability - Agent metrics, distributed tracing, LLM cost tracking
- Examples - Real agent implementations