# MLX Router — Local Inference Gateway

<meta charset="utf-8" id="bkmrk-"></meta> <meta content="pandoc" id="bkmrk--1" name="generator"></meta> <meta content="width=device-width, initial-scale=1.0, user-scalable=yes" id="bkmrk--2" name="viewport"></meta> <title id="bkmrk-mlx-router-%E2%80%94-local-i">MLX Router — Local Inference Gateway</title> <style id="bkmrk-%2F%2A-default-styles-pr">
    /* Default styles provided by pandoc.
    ** See https://pandoc.org/MANUAL.html#variables-for-html for config info.
    */
    html {
      color: #1a1a1a;
      background-color: #fdfdfd;
    }
    body {
      margin: 0 auto;
      max-width: 36em;
      padding-left: 50px;
      padding-right: 50px;
      padding-top: 50px;
      padding-bottom: 50px;
      hyphens: auto;
      overflow-wrap: break-word;
      text-rendering: optimizeLegibility;
      font-kerning: normal;
    }
    @media (max-width: 600px) {
      body {
        font-size: 0.9em;
        padding: 12px;
      }
      h1 {
        font-size: 1.8em;
      }
    }
    @media print {
      html {
        background-color: white;
      }
      body {
        background-color: transparent;
        color: black;
        font-size: 12pt;
      }
      p, h2, h3 {
        orphans: 3;
        widows: 3;
      }
      h2, h3, h4 {
        page-break-after: avoid;
      }
    }
    p {
      margin: 1em 0;
    }
    a {
      color: #1a1a1a;
    }
    a:visited {
      color: #1a1a1a;
    }
    img {
      max-width: 100%;
    }
    svg {
      height: auto;
      max-width: 100%;
    }
    h1, h2, h3, h4, h5, h6 {
      margin-top: 1.4em;
    }
    h5, h6 {
      font-size: 1em;
      font-style: italic;
    }
    h6 {
      font-weight: normal;
    }
    ol, ul {
      padding-left: 1.7em;
      margin-top: 1em;
    }
    li > ol, li > ul {
      margin-top: 0;
    }
    blockquote {
      margin: 1em 0 1em 1.7em;
      padding-left: 1em;
      border-left: 2px solid #e6e6e6;
      color: #606060;
    }
    code {
      font-family: Menlo, Monaco, Consolas, 'Lucida Console', monospace;
      font-size: 85%;
      margin: 0;
      hyphens: manual;
    }
    pre {
      margin: 1em 0;
      overflow: auto;
    }
    pre code {
      padding: 0;
      overflow: visible;
      overflow-wrap: normal;
    }
    .sourceCode {
     background-color: transparent;
     overflow: visible;
    }
    hr {
      border: none;
      border-top: 1px solid #1a1a1a;
      height: 1px;
      margin: 1em 0;
    }
    table {
      margin: 1em 0;
      border-collapse: collapse;
      width: 100%;
      overflow-x: auto;
      display: block;
      font-variant-numeric: lining-nums tabular-nums;
    }
    table caption {
      margin-bottom: 0.75em;
    }
    tbody {
      margin-top: 0.5em;
      border-top: 1px solid #1a1a1a;
      border-bottom: 1px solid #1a1a1a;
    }
    th {
      border-top: 1px solid #1a1a1a;
      padding: 0.25em 0.5em 0.25em 0.5em;
    }
    td {
      padding: 0.125em 0.5em 0.25em 0.5em;
    }
    header {
      margin-bottom: 4em;
      text-align: center;
    }
    #TOC li {
      list-style: none;
    }
    #TOC ul {
      padding-left: 1.3em;
    }
    #TOC > ul {
      padding-left: 0;
    }
    #TOC a:not(:hover) {
      text-decoration: none;
    }
    code{white-space: pre-wrap;}
    span.smallcaps{font-variant: small-caps;}
    div.columns{display: flex; gap: min(4vw, 1.5em);}
    div.column{flex: auto; overflow-x: auto;}
    div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
    /* The extra [class] is a hack that increases specificity enough to
       override a similar rule in reveal.js */
    ul.task-list[class]{list-style: none;}
    ul.task-list li input[type="checkbox"] {
      font-size: inherit;
      width: 0.8em;
      margin: 0 0.8em 0.2em -1.6em;
      vertical-align: middle;
    }
    .display.math{display: block; text-align: center; margin: 0.5rem auto;}
    /* CSS for syntax highlighting */
    html { -webkit-text-size-adjust: 100%; }
    pre > code.sourceCode { white-space: pre; position: relative; }
    pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
    pre > code.sourceCode > span:empty { height: 1.2em; }
    .sourceCode { overflow: visible; }
    code.sourceCode > span { color: inherit; text-decoration: inherit; }
    div.sourceCode { margin: 1em 0; }
    pre.sourceCode { margin: 0; }
    @media screen {
    div.sourceCode { overflow: auto; }
    }
    @media print {
    pre > code.sourceCode { white-space: pre-wrap; }
    pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
    }
    pre.numberSource code
      { counter-reset: source-line 0; }
    pre.numberSource code > span
      { position: relative; left: -4em; counter-increment: source-line; }
    pre.numberSource code > span > a:first-child::before
      { content: counter(source-line);
        position: relative; left: -1em; text-align: right; vertical-align: baseline;
        border: none; display: inline-block;
        -webkit-touch-callout: none; -webkit-user-select: none;
        -khtml-user-select: none; -moz-user-select: none;
        -ms-user-select: none; user-select: none;
        padding: 0 4px; width: 4em;
        color: #aaaaaa;
      }
    pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa;  padding-left: 4px; }
    div.sourceCode
      {   }
    @media screen {
    pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
    }
    code span.al { color: #ff0000; font-weight: bold; } /* Alert */
    code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
    code span.at { color: #7d9029; } /* Attribute */
    code span.bn { color: #40a070; } /* BaseN */
    code span.bu { color: #008000; } /* BuiltIn */
    code span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
    code span.ch { color: #4070a0; } /* Char */
    code span.cn { color: #880000; } /* Constant */
    code span.co { color: #60a0b0; font-style: italic; } /* Comment */
    code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
    code span.do { color: #ba2121; font-style: italic; } /* Documentation */
    code span.dt { color: #902000; } /* DataType */
    code span.dv { color: #40a070; } /* DecVal */
    code span.er { color: #ff0000; font-weight: bold; } /* Error */
    code span.ex { } /* Extension */
    code span.fl { color: #40a070; } /* Float */
    code span.fu { color: #06287e; } /* Function */
    code span.im { color: #008000; font-weight: bold; } /* Import */
    code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
    code span.kw { color: #007020; font-weight: bold; } /* Keyword */
    code span.op { color: #666666; } /* Operator */
    code span.ot { color: #007020; } /* Other */
    code span.pp { color: #bc7a00; } /* Preprocessor */
    code span.sc { color: #4070a0; } /* SpecialChar */
    code span.ss { color: #bb6688; } /* SpecialString */
    code span.st { color: #4070a0; } /* String */
    code span.va { color: #19177c; } /* Variable */
    code span.vs { color: #4070a0; } /* VerbatimString */
    code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
  </style><header id="bkmrk-mlx-router-%E2%80%94-local-i-1"># MLX Router — Local Inference Gateway

</header></head><body># MLX Router — Local Inference Gateway

**بِسْمِ ٱللَّهِ ٱلرَّحْمَـٰنِ ٱلرَّحِيمِ**

**Service:** mlx-router (com.alai.mlx-router) **Port:** 11500 (127.0.0.1) **Status:**Production (2026-05-01) **Owner:** ALAI System Infrastructure **MC:** #10429

---

## Overview

MLX Router is ALAI’s local inference gateway that routes AI inference requests to zero-cost MLX models running on ANVIL (Mac Studio M3 Ultra, 96GB). It provides tier-fallback routing: tier1 MLX (local, $0 cost) → tier2 FORGE Ollama ($0 cost) → tier3 Anthropic API (metered cost).

**Purpose:** Reduce inference costs by offloading read-only agent workloads to local MLX models. Anthropic API is reserved for tier3 fallback only.

**Cost Savings:** All MLX and FORGE requests logged at cost\_usd=0. Estimated 95%+ reduction in inference costs for wired agents.

---

## Architecture

```
flowchart LR
    subgraph Caller
        A[Agent/Client]
    end
    
    subgraph MLX-Router["mlx-router.js :11500"]
        R[Route by model_class]
    end
    
    subgraph Tier1["Tier 1: MLX Local (ANVIL)"]
        M1[classify → :11437<br/>Qwen3-8B-4bit]
        M2[code → :11438<br/>Qwen2.5-Coder-32B]
        M3[reason → :11435<br/>Gemma-4-26B]
        M4[audit → :11436<br/>Qwen3-32B]
    end
    
    subgraph Tier2["Tier 2: FORGE Ollama"]
        F[10.0.0.2:11434<br/>qwen3/deepseek/etc]
    end
    
    subgraph Tier3["Tier 3: Anthropic API"]
        C[claude-haiku/sonnet/opus]
    end
    
    A -->|POST /v1/chat| R
    R -->|Health: UP| M1
    R -->|Health: UP| M2
    R -->|Health: UP| M3
    R -->|Health: UP| M4
    R -->|Tier1 DOWN| F
    F -->|Tier2 FAIL| C
    
    M1 -.->|cost_usd=0| CT[cost-tracker.js]
    M2 -.->|cost_usd=0| CT
    M3 -.->|cost_usd=0| CT
    M4 -.->|cost_usd=0| CT
    F -.->|cost_usd=0| CT
    C -.->|metered| CT
```

---

## Service Management

### Start

<div class="sourceCode" id="bkmrk-launchctl-bootstrap-">```
<span id="bkmrk-launchctl-bootstrap--1"><a aria-hidden="true" href="#bkmrk-launchctl-bootstrap--1" tabindex="-1"></a><span class="ex">launchctl</span> bootstrap gui/<span class="va">$(</span><span class="fu">id</span> <span class="at">-u</span><span class="va">)</span> ~/Library/LaunchAgents/com.alai.mlx-router.plist</span>
```

</div>### Stop

<div class="sourceCode" id="bkmrk-launchctl-bootout-gu">```
<span id="bkmrk-launchctl-bootout-gu-1"><a aria-hidden="true" href="#bkmrk-launchctl-bootout-gu-1" tabindex="-1"></a><span class="ex">launchctl</span> bootout gui/<span class="va">$(</span><span class="fu">id</span> <span class="at">-u</span><span class="va">)</span>/com.alai.mlx-router</span>
```

</div>### Restart

<div class="sourceCode" id="bkmrk-launchctl-bootout-gu-2">```
<span id="bkmrk-launchctl-bootout-gu-3"><a aria-hidden="true" href="#bkmrk-launchctl-bootout-gu-3" tabindex="-1"></a><span class="ex">launchctl</span> bootout gui/<span class="va">$(</span><span class="fu">id</span> <span class="at">-u</span><span class="va">)</span>/com.alai.mlx-router</span>
<span id="bkmrk-launchctl-bootstrap--2"><a aria-hidden="true" href="#bkmrk-launchctl-bootstrap--2" tabindex="-1"></a><span class="ex">launchctl</span> bootstrap gui/<span class="va">$(</span><span class="fu">id</span> <span class="at">-u</span><span class="va">)</span> ~/Library/LaunchAgents/com.alai.mlx-router.plist</span>
```

</div>### Check Status

<div class="sourceCode" id="bkmrk-launchctl-print-gui%2F">```
<span id="bkmrk-launchctl-print-gui%2F-1"><a aria-hidden="true" href="#bkmrk-launchctl-print-gui%2F-1" tabindex="-1"></a><span class="ex">launchctl</span> print gui/<span class="va">$(</span><span class="fu">id</span> <span class="at">-u</span><span class="va">)</span>/com.alai.mlx-router</span>
<span id="bkmrk-%23-look-for%3A-state-%3D-"><a aria-hidden="true" href="#bkmrk-%23-look-for%3A-state-%3D-" tabindex="-1"></a><span class="co"># Look for: state = running</span></span>
<span id="bkmrk-%23-get-pid-from-outpu"><a aria-hidden="true" href="#bkmrk-%23-get-pid-from-outpu" tabindex="-1"></a><span class="co"># Get PID from output</span></span>
```

</div>### View Logs

<div class="sourceCode" id="bkmrk-%23-stdout-%28health-pro">```
<span id="bkmrk-%23-stdout-%28health-pro-1"><a aria-hidden="true" href="#bkmrk-%23-stdout-%28health-pro-1" tabindex="-1"></a><span class="co"># Stdout (health probes, routing decisions)</span></span>
<span id="bkmrk-tail--f-%2Ftmp%2Fcom.ala"><a aria-hidden="true" href="#bkmrk-tail--f-%2Ftmp%2Fcom.ala" tabindex="-1"></a><span class="fu">tail</span> <span class="at">-f</span> /tmp/com.alai.mlx-router.stdout.log</span>
<span id="bkmrk--6"><a aria-hidden="true" href="#bkmrk--6" tabindex="-1"></a></span>
<span id="bkmrk-%23-stderr-%28errors%29"><a aria-hidden="true" href="#bkmrk-%23-stderr-%28errors%29" tabindex="-1"></a><span class="co"># Stderr (errors)</span></span>
<span id="bkmrk-tail--f-%2Ftmp%2Fcom.ala-1"><a aria-hidden="true" href="#bkmrk-tail--f-%2Ftmp%2Fcom.ala-1" tabindex="-1"></a><span class="fu">tail</span> <span class="at">-f</span> /tmp/com.alai.mlx-router.stderr.log</span>
```

</div>---

## Health Check

### Endpoint

<div class="sourceCode" id="bkmrk-curl--s-http%3A%2F%2F127.0">```
<span id="bkmrk-curl--s-http%3A%2F%2F127.0-1"><a aria-hidden="true" href="#bkmrk-curl--s-http%3A%2F%2F127.0-1" tabindex="-1"></a><span class="ex">curl</span> <span class="at">-s</span> http://127.0.0.1:11500/health <span class="kw">|</span> <span class="ex">jq</span></span>
```

</div>### Expected Output

<div class="sourceCode" id="bkmrk-%7B-%22status%22%3A-%22ok%22%2C-%22e">```
<span id="bkmrk-%7B"><a aria-hidden="true" href="#bkmrk-%7B" tabindex="-1"></a><span class="fu">{</span></span>
<span id="bkmrk-%22status%22%3A-%22ok%22%2C"><a aria-hidden="true" href="#bkmrk-%22status%22%3A-%22ok%22%2C" tabindex="-1"></a>  <span class="dt">"status"</span><span class="fu">:</span> <span class="st">"ok"</span><span class="fu">,</span></span>
<span id="bkmrk-%22endpoints%22%3A-%7B"><a aria-hidden="true" href="#bkmrk-%22endpoints%22%3A-%7B" tabindex="-1"></a>  <span class="dt">"endpoints"</span><span class="fu">:</span> <span class="fu">{</span></span>
<span id="bkmrk-%22classify%22%3A-%7B-%22avail"><a aria-hidden="true" href="#bkmrk-%22classify%22%3A-%7B-%22avail" tabindex="-1"></a>    <span class="dt">"classify"</span><span class="fu">:</span> <span class="fu">{</span> <span class="dt">"available"</span><span class="fu">:</span> <span class="kw">true</span><span class="fu">,</span> <span class="dt">"lastCheck"</span><span class="fu">:</span> <span class="st">"2026-05-01T09:00:00.000Z"</span><span class="fu">,</span> <span class="dt">"latencyMs"</span><span class="fu">:</span> <span class="dv">8</span> <span class="fu">},</span></span>
<span id="bkmrk-%22code%22%3A-%7B-%22available"><a aria-hidden="true" href="#bkmrk-%22code%22%3A-%7B-%22available" tabindex="-1"></a>    <span class="dt">"code"</span><span class="fu">:</span>     <span class="fu">{</span> <span class="dt">"available"</span><span class="fu">:</span> <span class="kw">true</span><span class="fu">,</span> <span class="dt">"lastCheck"</span><span class="fu">:</span> <span class="st">"2026-05-01T09:00:00.000Z"</span><span class="fu">,</span> <span class="dt">"latencyMs"</span><span class="fu">:</span> <span class="dv">7</span> <span class="fu">},</span></span>
<span id="bkmrk-%22reason%22%3A-%7B-%22availab"><a aria-hidden="true" href="#bkmrk-%22reason%22%3A-%7B-%22availab" tabindex="-1"></a>    <span class="dt">"reason"</span><span class="fu">:</span>   <span class="fu">{</span> <span class="dt">"available"</span><span class="fu">:</span> <span class="kw">true</span><span class="fu">,</span> <span class="dt">"lastCheck"</span><span class="fu">:</span> <span class="st">"2026-05-01T09:00:00.000Z"</span><span class="fu">,</span> <span class="dt">"latencyMs"</span><span class="fu">:</span> <span class="dv">3</span> <span class="fu">},</span></span>
<span id="bkmrk-%22audit%22%3A-%7B-%22availabl"><a aria-hidden="true" href="#bkmrk-%22audit%22%3A-%7B-%22availabl" tabindex="-1"></a>    <span class="dt">"audit"</span><span class="fu">:</span>    <span class="fu">{</span> <span class="dt">"available"</span><span class="fu">:</span> <span class="kw">true</span><span class="fu">,</span> <span class="dt">"lastCheck"</span><span class="fu">:</span> <span class="st">"2026-05-01T09:00:00.000Z"</span><span class="fu">,</span> <span class="dt">"latencyMs"</span><span class="fu">:</span> <span class="dv">5</span> <span class="fu">}</span></span>
<span id="bkmrk-%7D"><a aria-hidden="true" href="#bkmrk-%7D" tabindex="-1"></a>  <span class="fu">}</span></span>
<span id="bkmrk-%7D-1"><a aria-hidden="true" href="#bkmrk-%7D-1" tabindex="-1"></a><span class="fu">}</span></span>
```

</div>**Healthy state:** All four endpoints show `available: true`, latency &lt;50ms.

**Unhealthy state:** If `available: false`, that model\_class will fall to tier2 FORGE on next request.

---

## Model Classes

<table id="bkmrk-model_class-port-mod"><colgroup><col style="width: 11%"></col><col style="width: 6%"></col><col style="width: 27%"></col><col style="width: 9%"></col><col style="width: 32%"></col><col style="width: 12%"></col></colgroup><thead><tr><th>model\_class</th><th>Port</th><th>Model</th><th>RAM (GB)</th><th>Use Case</th><th>Latency</th></tr></thead><tbody><tr><td>classify</td><td>11437</td><td>Qwen3-8B-4bit</td><td>5</td><td>Classification, routing, QA</td><td>~14s</td></tr><tr><td>code</td><td>11438</td><td>Qwen2.5-Coder-32B-Instruct</td><td>19</td><td>Code generation, review</td><td>~117s</td></tr><tr><td>reason</td><td>11435</td><td>Gemma-4-26B (MoE 4B active)</td><td>15</td><td>Reasoning, synthesis, validation</td><td>~94s</td></tr><tr><td>audit</td><td>11436</td><td>Qwen3-32B-4bit</td><td>17</td><td>Architecture audit, analysis</td><td>~120s (est)</td></tr></tbody></table>

**Note on latency:** MLX inference is sequential and slow. 8B models take ~14s, 32B models take ~94-117s. **Not suitable for synchronous user-facing work.** Use for background/async agent tasks only.

---

## Tier Fallback Chain

1. **Tier 1 — MLX Local (ANVIL):** 127.0.0.1 ports 11435-11438, cost=$0 
    - Health-gated: If endpoint `available: false`, skip to tier2
    - Timeout: 120s
2. **Tier 2 — FORGE Ollama:** 10.0.0.2:11434, cost=$0 
    - Models: qwen3:8b (classify), qwen3-coder:latest (code), deepseek-r1:70b (reason), qwen3:32b (audit)
    - Timeout: 60s
3. **Tier 3 — Anthropic API:** Metered cost 
    - Models: claude-haiku-4-5 (classify), claude-sonnet-4-6 (code/reason), claude-opus-4-7 (audit)
    - Timeout: 60s

**Fallback triggers:** HTTP error, timeout, or health probe failure. Router tries tier1 → tier2 → tier3 until success or exhaustion.

---

## Cost Verification

All MLX and FORGE requests log `cost_usd=0` to cost-tracker.js.

<div class="sourceCode" id="bkmrk-%23-check-today%27s-mlx-">```
<span id="bkmrk-%23-check-today%27s-mlx--1"><a aria-hidden="true" href="#bkmrk-%23-check-today%27s-mlx--1" tabindex="-1"></a><span class="co"># Check today's MLX costs (should be 0.0)</span></span>
<span id="bkmrk-node-%7E%2Fsystem%2Ftools%2F"><a aria-hidden="true" href="#bkmrk-node-%7E%2Fsystem%2Ftools%2F" tabindex="-1"></a><span class="ex">node</span> ~/system/tools/cost-tracker.js summary today <span class="kw">|</span> <span class="fu">grep</span> mlx-local</span>
<span id="bkmrk--11"><a aria-hidden="true" href="#bkmrk--11" tabindex="-1"></a></span>
<span id="bkmrk-%23-query-cost_events."><a aria-hidden="true" href="#bkmrk-%23-query-cost_events." tabindex="-1"></a><span class="co"># Query cost_events.db directly</span></span>
<span id="bkmrk-sqlite3-%7E%2Fsystem%2Fdat"><a aria-hidden="true" href="#bkmrk-sqlite3-%7E%2Fsystem%2Fdat" tabindex="-1"></a><span class="ex">sqlite3</span> ~/system/databases/costs.db <span class="dt">\</span></span>
<span id="bkmrk-%22select-backend%2C-sum"><a aria-hidden="true" href="#bkmrk-%22select-backend%2C-sum" tabindex="-1"></a>  <span class="st">"SELECT backend, SUM(cost_usd) as total, COUNT(*) as requests </span></span>
<span id="bkmrk-from-cost_events"><a aria-hidden="true" href="#bkmrk-from-cost_events" tabindex="-1"></a><span class="st">   FROM cost_events </span></span>
<span id="bkmrk-where-backend%3D%27mlx-l"><a aria-hidden="true" href="#bkmrk-where-backend%3D%27mlx-l" tabindex="-1"></a><span class="st">   WHERE backend='mlx-local' </span></span>
<span id="bkmrk-group-by-backend%3B%22"><a aria-hidden="true" href="#bkmrk-group-by-backend%3B%22" tabindex="-1"></a><span class="st">   GROUP BY backend;"</span></span>
<span id="bkmrk--12"><a aria-hidden="true" href="#bkmrk--12" tabindex="-1"></a></span>
<span id="bkmrk-%23-expected%3A-mlx-loca"><a aria-hidden="true" href="#bkmrk-%23-expected%3A-mlx-loca" tabindex="-1"></a><span class="co"># Expected: mlx-local | 0.0 | <count></span></span>
```

</div>---

## Adding a New Model Class

1. **Add MLX endpoint** to `~/system/tools/mlx-router.js` in `MLX_ENDPOINTS`object:
    
    <div class="sourceCode" id="bkmrk-new_class%3A-%7B-url%3A-%27h">```
    <span id="bkmrk-new_class%3A-%7B"><a aria-hidden="true" href="#bkmrk-new_class%3A-%7B" tabindex="-1"></a>new_class<span class="op">:</span> {</span>
    <span id="bkmrk-url%3A-%27http%3A%2F%2F127.0.0"><a aria-hidden="true" href="#bkmrk-url%3A-%27http%3A%2F%2F127.0.0" tabindex="-1"></a>  <span class="dt">url</span><span class="op">:</span> <span class="st">'http://127.0.0.1:11439'</span><span class="op">,</span></span>
    <span id="bkmrk-modelid%3A-%27%2Fusers%2Fmak"><a aria-hidden="true" href="#bkmrk-modelid%3A-%27%2Fusers%2Fmak" tabindex="-1"></a>  <span class="dt">modelId</span><span class="op">:</span> <span class="st">'/Users/makinja/system/research/mlx-models/NewModel-4bit'</span><span class="op">,</span></span>
    <span id="bkmrk-shortname%3A-%27newmodel"><a aria-hidden="true" href="#bkmrk-shortname%3A-%27newmodel" tabindex="-1"></a>  <span class="dt">shortname</span><span class="op">:</span> <span class="st">'newmodel-mlx'</span><span class="op">,</span></span>
    <span id="bkmrk-maxconcurrent%3A-1%2C"><a aria-hidden="true" href="#bkmrk-maxconcurrent%3A-1%2C" tabindex="-1"></a>  <span class="dt">maxConcurrent</span><span class="op">:</span> <span class="dv">1</span><span class="op">,</span></span>
    <span id="bkmrk-%7D-2"><a aria-hidden="true" href="#bkmrk-%7D-2" tabindex="-1"></a>}</span>
    ```
    
    </div>
2. **Add tier2 FORGE fallback** in `FORGE_FALLBACK`:
    
    <div class="sourceCode" id="bkmrk-new_class%3A-%7B-model%3A-">```
    <span id="bkmrk-new_class%3A-%7B-model%3A--1"><a aria-hidden="true" href="#bkmrk-new_class%3A-%7B-model%3A--1" tabindex="-1"></a>new_class<span class="op">:</span> { <span class="dt">model</span><span class="op">:</span> <span class="st">'forge-model:latest'</span><span class="op">,</span> <span class="dt">url</span><span class="op">:</span> <span class="st">'http://10.0.0.2:11434'</span> }</span>
    ```
    
    </div>
3. **Add tier3 Anthropic fallback** in `ANTHROPIC_FALLBACK`:
    
    <div class="sourceCode" id="bkmrk-new_class%3A-%27claude-s">```
    <span id="bkmrk-new_class%3A-%27claude-s-1"><a aria-hidden="true" href="#bkmrk-new_class%3A-%27claude-s-1" tabindex="-1"></a>new_class<span class="op">:</span> <span class="st">'claude-sonnet-4-6'</span></span>
    ```
    
    </div>
4. **Extend capability table** at `~/system/specs/mlx-capability-table.md` with routing rationale.
5. **Restart daemon:**
    
    <div class="sourceCode" id="bkmrk-launchctl-bootout-gu-4">```
    <span id="bkmrk-launchctl-bootout-gu-5"><a aria-hidden="true" href="#bkmrk-launchctl-bootout-gu-5" tabindex="-1"></a><span class="ex">launchctl</span> bootout gui/<span class="va">$(</span><span class="fu">id</span> <span class="at">-u</span><span class="va">)</span>/com.alai.mlx-router</span>
    <span id="bkmrk-launchctl-bootstrap--3"><a aria-hidden="true" href="#bkmrk-launchctl-bootstrap--3" tabindex="-1"></a><span class="ex">launchctl</span> bootstrap gui/<span class="va">$(</span><span class="fu">id</span> <span class="at">-u</span><span class="va">)</span> ~/Library/LaunchAgents/com.alai.mlx-router.plist</span>
    ```
    
    </div>
6. **Verify health:**
    
    <div class="sourceCode" id="bkmrk-curl--s-http%3A%2F%2F127.0-2">```
    <span id="bkmrk-curl--s-http%3A%2F%2F127.0-3"><a aria-hidden="true" href="#bkmrk-curl--s-http%3A%2F%2F127.0-3" tabindex="-1"></a><span class="ex">curl</span> <span class="at">-s</span> http://127.0.0.1:11500/health <span class="kw">|</span> <span class="ex">jq</span> <span class="st">'.endpoints.new_class'</span></span>
    <span id="bkmrk-%23-should-show-availa"><a aria-hidden="true" href="#bkmrk-%23-should-show-availa" tabindex="-1"></a><span class="co"># Should show available: true</span></span>
    ```
    
    </div>

---

## Wiring an Agent

Add `inference:` block to agent’s YAML frontmatter in `~/system/agents/definitions/<agent>.md`:

<div class="sourceCode" id="bkmrk-inference%3A-prefer_in">```
<span id="bkmrk-inference%3A"><a aria-hidden="true" href="#bkmrk-inference%3A" tabindex="-1"></a><span class="fu">inference</span><span class="kw">:</span></span>
<span id="bkmrk-prefer_inference%3A-ml"><a aria-hidden="true" href="#bkmrk-prefer_inference%3A-ml" tabindex="-1"></a><span class="at">  </span><span class="fu">prefer_inference</span><span class="kw">:</span><span class="at"> mlx-router</span></span>
<span id="bkmrk-model_class%3A-classif"><a aria-hidden="true" href="#bkmrk-model_class%3A-classif" tabindex="-1"></a><span class="at">  </span><span class="fu">model_class</span><span class="kw">:</span><span class="at"> classify</span></span>
<span id="bkmrk-router_url%3A-http%3A%2F%2F1"><a aria-hidden="true" href="#bkmrk-router_url%3A-http%3A%2F%2F1" tabindex="-1"></a><span class="at">  </span><span class="fu">router_url</span><span class="kw">:</span><span class="at"> http://127.0.0.1:11500/v1/chat</span></span>
<span id="bkmrk-rationale%3A-%22read-onl"><a aria-hidden="true" href="#bkmrk-rationale%3A-%22read-onl" tabindex="-1"></a><span class="at">  </span><span class="fu">rationale</span><span class="kw">:</span><span class="at"> </span><span class="st">"Read-only classification tasks — no production risk"</span></span>
<span id="bkmrk-wired_by%3A-skillforge"><a aria-hidden="true" href="#bkmrk-wired_by%3A-skillforge" tabindex="-1"></a><span class="at">  </span><span class="fu">wired_by</span><span class="kw">:</span><span class="at"> skillforge/MC</span><span class="co">#<id>/<date></span></span>
```

</div>**Sync to active agents:**

<div class="sourceCode" id="bkmrk-%7E%2Fbin%2Fagent-definiti">```
<span id="bkmrk-%7E%2Fbin%2Fagent-definiti-1"><a aria-hidden="true" href="#bkmrk-%7E%2Fbin%2Fagent-definiti-1" tabindex="-1"></a><span class="ex">~/bin/agent-definitions-sync.sh</span></span>
```

</div>**Currently wired agents (2026-05-01):** - sentinel-tester (classify) - sentinel-validator (reason) - sentinel-architect (audit)

---

## Failure Modes

<table id="bkmrk-failure-symptom-impa"><colgroup><col style="width: 24%"></col><col style="width: 24%"></col><col style="width: 21%"></col><col style="width: 29%"></col></colgroup><thead><tr><th>Failure</th><th>Symptom</th><th>Impact</th><th>Mitigation</th></tr></thead><tbody><tr><td>MLX daemon down</td><td>Health probe shows `available: false`</td><td>Falls to tier2 FORGE</td><td>Automatic failover; check LaunchAgent logs</td></tr><tr><td>FORGE down</td><td>Tier2 request fails</td><td>Falls to tier3 Anthropic</td><td>Cost increase; alert if sustained</td></tr><tr><td>All MLX endpoints down</td><td>All classes fall to tier2/tier3</td><td>Full Anthropic cost</td><td>Restart MLX daemons (4 LaunchAgents on ANVIL)</td></tr><tr><td>mlx-router daemon down</td><td>No service on :11500</td><td>Agent inference fails</td><td>Restart com.alai.mlx-router LaunchAgent</td></tr><tr><td>Timeout (8B model &gt;120s)</td><td>Request slow/stuck</td><td>Falls to tier2</td><td>Normal for large prompts; reduce max\_tokens</td></tr></tbody></table>

---

## Performance Expectations

**Latency (tier1 MLX):** - 8B classify: ~14s (measured) - 32B code: ~117s (measured) - 32B reason: ~94s (measured) - 32B audit: ~120s (estimated)

**Concurrency:** - classify: 2 parallel requests - code/reason/audit: 1 request at a time (MLX is sequential)

**Not for:** - User-facing synchronous requests (too slow) - Real-time classification (&lt;1s SLA)

**Good for:** - Background agent tasks (sentinel audit, QA checks) - Async workflows (overnight batch processing) - Read-only analysis (no Write/Edit risk)

---

## Logs &amp; Debugging

**Daemon logs:**

<div class="sourceCode" id="bkmrk-%23-health-probe-outpu">```
<span id="bkmrk-%23-health-probe-outpu-1"><a aria-hidden="true" href="#bkmrk-%23-health-probe-outpu-1" tabindex="-1"></a><span class="co"># Health probe output every 60s</span></span>
<span id="bkmrk-tail--f-%2Ftmp%2Fcom.ala-2"><a aria-hidden="true" href="#bkmrk-tail--f-%2Ftmp%2Fcom.ala-2" tabindex="-1"></a><span class="fu">tail</span> <span class="at">-f</span> /tmp/com.alai.mlx-router.stdout.log</span>
<span id="bkmrk--18"><a aria-hidden="true" href="#bkmrk--18" tabindex="-1"></a></span>
<span id="bkmrk-%23-example-healthy-ou"><a aria-hidden="true" href="#bkmrk-%23-example-healthy-ou" tabindex="-1"></a><span class="co"># Example healthy output:</span></span>
<span id="bkmrk-%23-%5Bmlx-router%5D-healt"><a aria-hidden="true" href="#bkmrk-%23-%5Bmlx-router%5D-healt" tabindex="-1"></a><span class="co"># [mlx-router] Health probe:</span></span>
<span id="bkmrk-%23-classify%3A-up-%288ms%29"><a aria-hidden="true" href="#bkmrk-%23-classify%3A-up-%288ms%29" tabindex="-1"></a><span class="co">#   classify: UP (8ms)</span></span>
<span id="bkmrk-%23-code%3A-up-%287ms%29"><a aria-hidden="true" href="#bkmrk-%23-code%3A-up-%287ms%29" tabindex="-1"></a><span class="co">#   code: UP (7ms)</span></span>
<span id="bkmrk-%23-reason%3A-up-%283ms%29"><a aria-hidden="true" href="#bkmrk-%23-reason%3A-up-%283ms%29" tabindex="-1"></a><span class="co">#   reason: UP (3ms)</span></span>
<span id="bkmrk-%23-audit%3A-up-%285ms%29"><a aria-hidden="true" href="#bkmrk-%23-audit%3A-up-%285ms%29" tabindex="-1"></a><span class="co">#   audit: UP (5ms)</span></span>
```

</div>**Request routing logs:**

<div class="sourceCode" id="bkmrk-%23-each-request-logs-">```
<span id="bkmrk-%23-each-request-logs--1"><a aria-hidden="true" href="#bkmrk-%23-each-request-logs--1" tabindex="-1"></a><span class="co"># Each request logs tier used</span></span>
<span id="bkmrk-%23-example%3A-%5Bmlx-rout"><a aria-hidden="true" href="#bkmrk-%23-example%3A-%5Bmlx-rout" tabindex="-1"></a><span class="co"># Example: [mlx-router] tier1 classify → qwen3-8b-mlx (470ms)</span></span>
<span id="bkmrk-%23-tier2%2Ftier3-fallba"><a aria-hidden="true" href="#bkmrk-%23-tier2%2Ftier3-fallba" tabindex="-1"></a><span class="co"># Tier2/tier3 fallback logged with reason</span></span>
```

</div>**Cost tracking:**

<div class="sourceCode" id="bkmrk-%23-every-request-crea">```
<span id="bkmrk-%23-every-request-crea-1"><a aria-hidden="true" href="#bkmrk-%23-every-request-crea-1" tabindex="-1"></a><span class="co"># Every request creates a cost_events entry</span></span>
<span id="bkmrk-sqlite3-%7E%2Fsystem%2Fdat-1"><a aria-hidden="true" href="#bkmrk-sqlite3-%7E%2Fsystem%2Fdat-1" tabindex="-1"></a><span class="ex">sqlite3</span> ~/system/databases/costs.db <span class="dt">\</span></span>
<span id="bkmrk-%22select-model%2C-backe"><a aria-hidden="true" href="#bkmrk-%22select-model%2C-backe" tabindex="-1"></a>  <span class="st">"SELECT model, backend, cost_usd, timestamp </span></span>
<span id="bkmrk-from-cost_events-1"><a aria-hidden="true" href="#bkmrk-from-cost_events-1" tabindex="-1"></a><span class="st">   FROM cost_events </span></span>
<span id="bkmrk-where-backend%3D%27mlx-l-1"><a aria-hidden="true" href="#bkmrk-where-backend%3D%27mlx-l-1" tabindex="-1"></a><span class="st">   WHERE backend='mlx-local' </span></span>
<span id="bkmrk-order-by-timestamp-d"><a aria-hidden="true" href="#bkmrk-order-by-timestamp-d" tabindex="-1"></a><span class="st">   ORDER BY timestamp DESC </span></span>
<span id="bkmrk-limit-10%3B%22"><a aria-hidden="true" href="#bkmrk-limit-10%3B%22" tabindex="-1"></a><span class="st">   LIMIT 10;"</span></span>
```

</div>---

## Related Resources

- **Capability Table:**`~/system/specs/mlx-capability-table.md`
- **Ollama Fleet:**`~/system/config/ollama-fleet.json`
- **LaunchAgent:**`~/Library/LaunchAgents/com.alai.mlx-router.plist`
- **Cost Tracker:**`~/system/tools/cost-tracker.js`
- **Agent Definitions:**`~/system/agents/definitions/sentinel-*.md`

---

## MC History

- **MC #10429:** MLX router build + agent wiring (2026-05-01)
- **MC #10391:** SENTINEL v2 audit identified MLX orphans (2026-05-01)
- **MC #10411:** SENTINEL v3 decision item 2 = activate $0 inference

---

**Last Updated:** 2026-05-01 **Status:**Production **Validation:** Proveo 10/10 PASS