# How Magnitude's ICN Manages Hardware Profiling and Memory Topology with the icn‑hardware Crate

> Magnitude's ICN uses the icn-hardware crate to manage hardware profiling and memory topology. Discover CPU layout and memory characteristics via type-safe RPC.

- Repository: [Magnitude/magnitude](https://github.com/magnitudedev/magnitude)
- Tags: internals
- Published: 2026-09-06

---

**Magnitude's Inter‑Component Network (ICN) discovers and exposes CPU topology, NUMA node layout, and memory characteristics through the dedicated `icn‑hardware` Rust crate, which aggregates sysfs data and serves it via type‑safe RPC.**

The `icn‑hardware` crate lives in `packages/acn-hardware` and forms the bedrock of hardware awareness across the Magnitude platform. It abstracts Linux kernel interfaces into structured data that the Agent Communication Network (ACN) can query, cache, and forward to clients.

## Core Data Structures in icn‑hardware

### HardwareInfo: The Central Aggregation Point

The **`HardwareInfo`** struct is the primary entry point for hardware discovery. Defined in [`packages/acn-hardware/src/lib.rs`](https://github.com/magnitudedev/magnitude/blob/main/packages/acn-hardware/src/lib.rs), it combines CPU topology and memory topology into a single coherent view.

```rust
// Conceptual signature based on crate implementation
pub struct HardwareInfo {
    pub topology: Topology,
    pub memory: MemoryTopology,
}

impl HardwareInfo {
    /// Gathers hardware information from the local system.
    /// This walks /sys/devices/system/cpu and /sys/devices/system/node.
    pub fn gather() -> Result<Self, HardwareError>;
}

```

The `gather()` method is invoked once at daemon startup and its results are cached for subsequent RPC calls. This avoids repeated filesystem traversal during hot‑path operations.

### Topology: CPU Hierarchy Discovery

The **`Topology`** struct—implemented in [`packages/acn-hardware/src/topology.rs`](https://github.com/magnitudedev/magnitude/blob/main/packages/acn-hardware/src/topology.rs)—represents the hierarchical relationship between sockets, physical cores, and hardware threads.

| Field | Description | Source |
|-------|-------------|--------|
| `sockets` | Vec of `Socket` structs, each containing cores | `/sys/devices/system/cpu/cpu*/topology/physical_package_id` |
| `cores` | Per‑socket core lists with thread siblings | `/sys/devices/system/cpu/cpu*/topology/core_id` |
| `thread_siblings` | Bitmask of threads sharing L1/L2 | `/sys/devices/system/cpu/cpu*/topology/thread_siblings_list` |

The topology walker parses these sysfs files to build a `hwloc`‑compatible representation without external C library dependencies.

### MemoryTopology: NUMA and Bandwidth Awareness

The **`MemoryTopology`** struct—defined in [`packages/acn-hardware/src/memory.rs`](https://github.com/magnitudedev/magnitude/blob/main/packages/acn-hardware/src/memory.rs)—captures NUMA node layout and inter‑node distances.

```rust
pub struct NumaNode {
    pub id: u32,
    pub cpus: Vec<u32>,        // CPUs local to this node
    pub start_addr: u64,       // Start of physical memory range
    pub size: u64,             // Total node memory in bytes
    pub free: u64,             // Available memory (from /proc/meminfo)
}

pub struct MemoryTopology {
    pub nodes: Vec<NumaNode>,
    pub distances: Vec<Vec<u32>>, // NUMA distance matrix
}

```

The distance matrix is populated from `/sys/devices/system/node/node*/distance`, which exposes the kernel's relative memory latency estimates. This enables higher‑level scheduling components to make locality‑aware placement decisions.

## RPC Integration: From Crate to Client

### Protocol Definition in acn‑protocol

The hardware profile is exposed through the **`HardwareProfile`** RPC boundary, declared in [`packages/acn-protocol/src/boundary/hardware.ts`](https://github.com/magnitudedev/magnitude/blob/main/packages/acn-protocol/src/boundary/hardware.ts):

```typescript
// Effect‑Schema definition for type‑safe serialization
export const HardwareProfileSchema = Schema.Struct({
  topology: TopologySchema,
  memoryTopology: MemoryTopologySchema,
  gatheredAt: Schema.Number, // Unix timestamp for cache validation
});

export type HardwareProfile = typeof HardwareProfileSchema.Type;

// RPC declaration with replaySafe policy
export const HardwareProfileRpc = Rpc.make("HardwareProfile", {
  request: Schema.Void,
  response: HardwareProfileSchema,
  policy: RpcPolicy.replaySafe, // No side‑effects, safe to retry
});

```

The **`replaySafe`** policy signals that the operation is read‑only and idempotent, allowing the RPC layer to optimize retry behavior.

### Daemon Handler in acn

The ACN daemon implements this RPC in [`packages/acn/src/hardware-handler.ts`](https://github.com/magnitudedev/magnitude/blob/main/packages/acn/src/hardware-handler.ts):

```typescript
import { HardwareInfo } from "@magnitude/icn-hardware";

export class HardwareHandler implements RpcHandler<typeof HardwareProfileRpc> {
  private cachedInfo: HardwareInfo | null = null;

  async handle(): Promise<HardwareProfile> {
    if (!this.cachedInfo) {
      // Delegate to Rust crate via FFI or WASM bridge
      this.cachedInfo = await HardwareInfo.gather();
    }
    return this.toSchema(this.cachedInfo);
  }

  private toSchema(info: HardwareInfo): HardwareProfile {
    // Normalize to Effect‑Schema, ensuring Option types for optional fields
    return {
      topology: normalizeTopology(info.topology),
      memoryTopology: normalizeMemory(info.memory),
      gatheredAt: Date.now(),
    };
  }
}

```

The handler maintains an in‑memory cache of the `HardwareInfo` struct, refreshing only on explicit invalidation or daemon restart.

### Client Consumption in client‑common

Clients access this data through [`packages/client-common/src/operations/hardware.ts`](https://github.com/magnitudedev/magnitude/blob/main/packages/client-common/src/operations/hardware.ts):

```typescript
import { sdk } from "@magnitude/sdk";
import { createQuery } from "@effect-rx/rx-query";

export const useHardwareProfile = () => {
  return createQuery(
    sdk.getHardwareProfile, // SDK method wrapping the RPC
    {
      staleTime: 5 * 60 * 1000, // 5 minute cache
      refetchOnWindowFocus: false,
    }
  );
};

```

The query integrates with the reactive cache system, ensuring multiple UI components share the same underlying RPC result.

## Practical Usage Examples

### TypeScript Client: Rendering Topology

```typescript
import { useHardwareProfile } from "@magnitude/client-common";

function CpuTopologyView() {
  const { data: profile, isLoading } = useHardwareProfile();

  if (isLoading) return <Spinner />;

  return (
    <div>
      <h3>CPU Topology</h3>
      <p>Total sockets: {profile.topology.sockets.length}</p>
      <ul>
        {profile.topology.sockets.map((socket, idx) => (
          <li key={idx}>
            Socket {idx}: {socket.cores.length} cores, {" "}
            {socket.cores.reduce((sum, c) => sum + c.threads.length, 0)} threads
          </li>
        ))}
      </ul>

      <h3>NUMA Layout</h3>
      <table>
        <thead>
          <tr><th>Node</th><th>CPUs</th><th>Memory</th></tr>
        </thead>
        <tbody>
          {profile.memoryTopology.nodes.map(node => (
            <tr key={node.id}>
              <td>{node.id}</td>
              <td>{node.cpus.join(", ")}</td>
              <td>{(node.size / 1e9).toFixed(1)} GB</td>
            </tr>
          ))}
        </tbody>
      </table>
    </div>
  );
}

```

### Rust: Direct Crate Usage for Custom Tools

```rust
use icn_hardware::{HardwareInfo, Topology, MemoryTopology};

fn analyze_numa_locality(pid: u32) -> Result<(), Box<dyn std::error::Error>> {
    // Load current hardware configuration
    let hw = HardwareInfo::gather()?;

    // Find which NUMA node owns the majority of process memory
    let node_usage = read_process_numa_pages(pid)?;
    let best_node = node_usage
        .iter()
        .enumerate()
        .max_by_key(|(_, &pages)| pages)
        .map(|(idx, _)| idx)
        .unwrap_or(0);

    let target_node = &hw.memory.nodes[best_node];
    println!(
        "Process {} prefers NUMA node {} with {} local CPUs",
        pid, target_node.id, target_node.cpus.len()
    );

    // Use distance matrix to find failover nodes
    let distances = &hw.memory.distances[best_node];
    let alternatives: Vec<_> = distances
        .iter()
        .enumerate()
        .filter(|(idx, d)| *idx != best_node && **d < 20) // Local/remote threshold
        .map(|(idx, d)| (idx, d))
        .collect();

    println!("Failover candidates: {:?}", alternatives);
    Ok(())
}

```

## Dynamic Refresh and Hot‑Plug Support

While the default cache‑at‑startup pattern covers most deployment scenarios, `icn‑hardware` supports explicit re‑discovery:

```rust
// Force a fresh hardware scan, useful after CPU hot‑plug
pub fn HardwareInfo::gather_fresh() -> Result<Self, HardwareError>;

```

The RPC handler exposes this through a separate `RefreshHardwareProfile` RPC (also `replaySafe`), which invalidates the daemon's cache and triggers `gather_fresh()` on the next request.

## Summary

- **`icn‑hardware`** in `packages/acn-hardware` provides the authoritative hardware discovery implementation for Magnitude's ICN.
- **Topology** ([`src/topology.rs`](https://github.com/magnitudedev/magnitude/blob/main/src/topology.rs)) and **MemoryTopology** ([`src/memory.rs`](https://github.com/magnitudedev/magnitude/blob/main/src/memory.rs)) parse Linux sysfs to build structured CPU and NUMA representations.
- The **HardwareInfo::gather()** method is the single entry point, caching results for performance.
- **Effect‑Schema** ([`packages/acn-protocol/src/boundary/hardware.ts`](https://github.com/magnitudedev/magnitude/blob/main/packages/acn-protocol/src/boundary/hardware.ts)) ensures type‑safe serialization across the RPC boundary.
- The **ACN daemon** ([`packages/acn/src/hardware-handler.ts`](https://github.com/magnitudedev/magnitude/blob/main/packages/acn/src/hardware-handler.ts)) serves cached profiles with `replaySafe` semantics.
- **Client SDK** utilities ([`packages/client-common/src/operations/hardware.ts`](https://github.com/magnitudedev/magnitude/blob/main/packages/client-common/src/operations/hardware.ts)) integrate hardware data into reactive UI flows.

## Frequently Asked Questions

### How does icn‑hardware detect CPU topology on non‑Linux platforms?

The crate currently targets Linux exclusively, reading from `/sys/devices/system`. On unsupported platforms, `HardwareInfo::gather()` returns a `HardwareError::UnsupportedPlatform` which the daemon handles by returning a degraded profile with topology fields set to empty defaults.

### Can the hardware profile be used for affinity‑aware agent scheduling?

Yes. The NUMA distance matrix exposed in `MemoryTopology::distances` enables scheduling decisions that minimize cross‑node memory access. Higher‑level Magnitude components consume this data through the SDK's `getHardwareProfile()` method.

### What triggers a cache refresh in the ACN daemon?

By default, the cache is populated once at daemon startup. Explicit refresh requires calling the `RefreshHardwareProfile` RPC or restarting the daemon. There is no automatic inotify‑based refresh to avoid complexity with CPU hot‑plug edge cases.

### Are memory bandwidth estimates available on all systems?

Bandwidth hints depend on kernel configuration. When `/sys/devices/system/node/node*/meminfo` lacks bandwidth data, `icn‑hardware` omits the optional field from the schema, and consumers fall back to distance‑based heuristics.