diff --git a/gui/public/provider-icons/README.md b/gui/public/provider-icons/README.md
index a4346b2a4f..43b1e1a92e 100644
--- a/gui/public/provider-icons/README.md
+++ b/gui/public/provider-icons/README.md
@@ -140,3 +140,85 @@ Both directions are enforced in `gui/tests/integration-marks.test.ts`, including
luminance check that fails any single-ink near-neutral mark left as an image. That
direction was missing until it caught `grok`; the same class of defect had already
shipped once for `prime`, `opencode` and `kimi`.
+
+## Provider marks (2026-09-01)
+
+Sourced for the providers that were rendering a coloured initial tile. Every
+entry below was fetched from the vendor's own domain, taken from the registry's
+`baseUrl`/`dashboardUrl` rather than guessed.
+
+Published as SVG and committed with only comments, `
`/`` and
+`data-name` attributes stripped:
+
+- `digitalocean.svg` — `digitalocean.com` favicon, 32x32.
+- `featherless.svg` — `featherless.ai/favicon.svg`, 256x256.
+- `kilo.svg` — `kilo.ai/favicon/favicon.svg`, 32x32. Keeps its `oklch()` plate.
+- `nanogpt.svg` — `nano-gpt.com/logo.svg`, 181x187, gradient.
+- `nebius.svg` — `nebius.com/favicon/favicon.svg`, 96x96.
+- `neuralwatt.svg` — the site's Webflow-hosted brand asset, 32x32.
+- `parallel.svg` — `parallel.ai/icon.svg`, 96x96.
+- `scaleway.svg` — `scaleway.com/favicon/website/favicon.svg`, 16x16.
+- `synthetic.svg` — `synthetic.new/favicon.svg`, 54x54.
+- `zai.svg` — `z-cdn.chatglm.cn/z-ai/static/logo.svg`, 30x30.
+- `zenmux.svg` — the site's CDN-hosted brand mark, 160x160.
+
+Traced from raster, because the vendor publishes no square SVG mark. Same
+technique as `hermes-agent.svg` and `gajae-code.svg`: `potrace -s --flat` for a
+single-ink silhouette, k-means colour layers (seeded at 3, largest area first)
+for multi-colour art, downsampled to a 160px box first so the trace does not
+follow every upscaled pixel edge.
+
+- `cerebras.svg`, `novita.svg`, `siliconflow.svg`, `deepinfra.svg` — single-ink.
+- `baseten.svg`, `hyperbolic.svg`, `sambanova.svg`, `umans.svg`, `venice.svg`,
+ `vultr.svg`, `bizrouter.svg`, `orcarouter.svg` — colour-layered.
+- `nous.svg` — traced from `nousresearch.com/apple-touch-icon.png` (180x180). This
+ is the Nous Research company mark, distinct from `hermes-agent.svg`, which is
+ the Hermes product's own icon. Attributing one to the other would be wrong even
+ though the same organization ships both.
+
+Found on a docs subdomain after the vendor's marketing site offered only a
+wordmark:
+
+- `together.svg` — `docs.together.ai/favicon.svg`, 1.07:1.
+- `litellm.svg` — `docs.litellm.ai/img/logo.svg`, 1:1. The marketing site's SVGs
+ are third-party model logos, not LiteLLM's own mark.
+
+**The plate problem, recorded because the first pass shipped it.** A favicon is
+usually a glyph on a filled rounded square. Tracing luminance alone captured the
+square and produced a solid box: `baseten` came out 97.7% ink, `bizrouter` 89.3%.
+The fix reads the border ring, takes its median colour as the plate when the ring
+is uniform, and masks by distance from that colour instead of by darkness. It
+found real plates behind `baseten` (#19e76e), `cerebras` (#ef5b27), `hyperbolic`
+(#1a1a1a), `umans`/`bizrouter` (#000000) and `orcarouter` (#ffffff).
+
+### Rejected, and why
+
+- **`nousresearch.com/safari-pinned-tab.svg`** — opens with the full 512-unit
+ frame as its first path, so it renders as a black square. This is the identical
+ candidate the Hermes client mark rejected. The apple-touch-icon was used instead.
+- **LiteLLM's marketing-site SVGs** — third-party model logos, and the favicon
+ traces to a muddy blob with no legible silhouette at 19px. The docs logo was
+ used instead.
+- **Wordmarks refused** for `cerebras` (843x320 from Sanity CDN), `siliconflow`
+ (188x28), `zhipu-bigmodel` (123x25), `vultr` (218x52), `baseten` (1001x151) and
+ `chutes` (192x30). A lockup in the rail's 19px box is an illegible smear, so
+ each was replaced by a traced square mark or left to the fallback.
+
+### Still unmarked, and what was searched
+
+Six ids keep the fallback tile. Each was probed at its registry `baseUrl` and
+`dashboardUrl`, plus the vendor's docs subdomain and the conventional icon paths
+(`/favicon.svg`, `/favicon.ico`, `/apple-touch-icon.png`, `/logo.svg`, `/icon.svg`):
+
+- `chutes` — `chutes.ai` and `docs.chutes.ai` serve only the 192x30 wordmark.
+- `nscale` — `nscale.com` and `docs.nscale.com` returned no icon at any path.
+- `volcengine`, `volcengine-coding-plan`, `volcengine-agent-plan` — the Ark
+ console's SVGs are UI glyphs rather than a product mark.
+- `tencent-coding-plan` — `cloud.tencent.com` serves a 32x32 favicon whose trace
+ is unreadable at 19px.
+
+These are recorded results, not skipped work. Inventing a mark, or borrowing a
+neighbouring brand's, is a misattribution that outlives the commit.
+
+`zhipu-bigmodel` and `zhipu-bigmodel-coding` share `zai.svg`: Z.AI and BigModel
+are the same company, and the mainland console publishes only the wordmark.
diff --git a/gui/public/provider-icons/baseten.svg b/gui/public/provider-icons/baseten.svg
new file mode 100644
index 0000000000..2fa74a269b
--- /dev/null
+++ b/gui/public/provider-icons/baseten.svg
@@ -0,0 +1,13 @@
+
\ No newline at end of file
diff --git a/gui/public/provider-icons/bizrouter.svg b/gui/public/provider-icons/bizrouter.svg
new file mode 100644
index 0000000000..f0644866a3
--- /dev/null
+++ b/gui/public/provider-icons/bizrouter.svg
@@ -0,0 +1,41 @@
+
\ No newline at end of file
diff --git a/gui/public/provider-icons/cerebras.svg b/gui/public/provider-icons/cerebras.svg
new file mode 100644
index 0000000000..56d52a3d3c
--- /dev/null
+++ b/gui/public/provider-icons/cerebras.svg
@@ -0,0 +1,26 @@
+
+
+
diff --git a/gui/public/provider-icons/deepinfra.svg b/gui/public/provider-icons/deepinfra.svg
new file mode 100644
index 0000000000..44c1eb0f4f
--- /dev/null
+++ b/gui/public/provider-icons/deepinfra.svg
@@ -0,0 +1,75 @@
+
+
+
diff --git a/gui/public/provider-icons/digitalocean.svg b/gui/public/provider-icons/digitalocean.svg
new file mode 100644
index 0000000000..2d9a943e90
--- /dev/null
+++ b/gui/public/provider-icons/digitalocean.svg
@@ -0,0 +1,10 @@
+
\ No newline at end of file
diff --git a/gui/public/provider-icons/featherless.svg b/gui/public/provider-icons/featherless.svg
new file mode 100644
index 0000000000..dd171d68e4
--- /dev/null
+++ b/gui/public/provider-icons/featherless.svg
@@ -0,0 +1,4 @@
+
\ No newline at end of file
diff --git a/gui/public/provider-icons/hyperbolic.svg b/gui/public/provider-icons/hyperbolic.svg
new file mode 100644
index 0000000000..a71713acf5
--- /dev/null
+++ b/gui/public/provider-icons/hyperbolic.svg
@@ -0,0 +1,18 @@
+
\ No newline at end of file
diff --git a/gui/public/provider-icons/kilo.svg b/gui/public/provider-icons/kilo.svg
new file mode 100644
index 0000000000..c4b6bb8ba4
--- /dev/null
+++ b/gui/public/provider-icons/kilo.svg
@@ -0,0 +1,13 @@
+
+
\ No newline at end of file
diff --git a/gui/public/provider-icons/litellm.svg b/gui/public/provider-icons/litellm.svg
new file mode 100644
index 0000000000..9db6d0d066
--- /dev/null
+++ b/gui/public/provider-icons/litellm.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/gui/public/provider-icons/nanogpt.svg b/gui/public/provider-icons/nanogpt.svg
new file mode 100644
index 0000000000..4344909a8b
--- /dev/null
+++ b/gui/public/provider-icons/nanogpt.svg
@@ -0,0 +1,74 @@
+
+
\ No newline at end of file
diff --git a/gui/public/provider-icons/nebius.svg b/gui/public/provider-icons/nebius.svg
new file mode 100644
index 0000000000..4d55b7bf0b
--- /dev/null
+++ b/gui/public/provider-icons/nebius.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/gui/public/provider-icons/neuralwatt.svg b/gui/public/provider-icons/neuralwatt.svg
new file mode 100644
index 0000000000..3339f995c7
--- /dev/null
+++ b/gui/public/provider-icons/neuralwatt.svg
@@ -0,0 +1,27 @@
+
\ No newline at end of file
diff --git a/gui/public/provider-icons/nous.svg b/gui/public/provider-icons/nous.svg
new file mode 100644
index 0000000000..5307d5feb2
--- /dev/null
+++ b/gui/public/provider-icons/nous.svg
@@ -0,0 +1,149 @@
+
+
+
diff --git a/gui/public/provider-icons/novita.svg b/gui/public/provider-icons/novita.svg
new file mode 100644
index 0000000000..75f64f25a4
--- /dev/null
+++ b/gui/public/provider-icons/novita.svg
@@ -0,0 +1,32 @@
+
+
+
diff --git a/gui/public/provider-icons/orcarouter.svg b/gui/public/provider-icons/orcarouter.svg
new file mode 100644
index 0000000000..4cd5bf9f47
--- /dev/null
+++ b/gui/public/provider-icons/orcarouter.svg
@@ -0,0 +1,175 @@
+
\ No newline at end of file
diff --git a/gui/public/provider-icons/parallel.svg b/gui/public/provider-icons/parallel.svg
new file mode 100644
index 0000000000..5d87359bf9
--- /dev/null
+++ b/gui/public/provider-icons/parallel.svg
@@ -0,0 +1,13 @@
+
\ No newline at end of file
diff --git a/gui/public/provider-icons/sambanova.svg b/gui/public/provider-icons/sambanova.svg
new file mode 100644
index 0000000000..341c74ea0f
--- /dev/null
+++ b/gui/public/provider-icons/sambanova.svg
@@ -0,0 +1,276 @@
+
\ No newline at end of file
diff --git a/gui/public/provider-icons/scaleway.svg b/gui/public/provider-icons/scaleway.svg
new file mode 100644
index 0000000000..4996b509b4
--- /dev/null
+++ b/gui/public/provider-icons/scaleway.svg
@@ -0,0 +1,11 @@
+
\ No newline at end of file
diff --git a/gui/public/provider-icons/siliconflow.svg b/gui/public/provider-icons/siliconflow.svg
new file mode 100644
index 0000000000..8537ff8e30
--- /dev/null
+++ b/gui/public/provider-icons/siliconflow.svg
@@ -0,0 +1,18 @@
+
+
+
diff --git a/gui/public/provider-icons/synthetic.svg b/gui/public/provider-icons/synthetic.svg
new file mode 100644
index 0000000000..87dfcb7383
--- /dev/null
+++ b/gui/public/provider-icons/synthetic.svg
@@ -0,0 +1,12 @@
+
\ No newline at end of file
diff --git a/gui/public/provider-icons/together.svg b/gui/public/provider-icons/together.svg
new file mode 100644
index 0000000000..2fcc258c45
--- /dev/null
+++ b/gui/public/provider-icons/together.svg
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/gui/public/provider-icons/umans.svg b/gui/public/provider-icons/umans.svg
new file mode 100644
index 0000000000..c6176f143a
--- /dev/null
+++ b/gui/public/provider-icons/umans.svg
@@ -0,0 +1,30 @@
+
\ No newline at end of file
diff --git a/gui/public/provider-icons/venice.svg b/gui/public/provider-icons/venice.svg
new file mode 100644
index 0000000000..d914e79c3b
--- /dev/null
+++ b/gui/public/provider-icons/venice.svg
@@ -0,0 +1,165 @@
+
\ No newline at end of file
diff --git a/gui/public/provider-icons/vultr.svg b/gui/public/provider-icons/vultr.svg
new file mode 100644
index 0000000000..69e60c18d9
--- /dev/null
+++ b/gui/public/provider-icons/vultr.svg
@@ -0,0 +1,15 @@
+
\ No newline at end of file
diff --git a/gui/public/provider-icons/zai.svg b/gui/public/provider-icons/zai.svg
new file mode 100644
index 0000000000..536f3521ee
--- /dev/null
+++ b/gui/public/provider-icons/zai.svg
@@ -0,0 +1,218 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/gui/public/provider-icons/zenmux.svg b/gui/public/provider-icons/zenmux.svg
new file mode 100644
index 0000000000..0f0f3b1800
--- /dev/null
+++ b/gui/public/provider-icons/zenmux.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/gui/src/provider-icons.ts b/gui/src/provider-icons.ts
index 043529cf67..2bf4d6c5a3 100644
--- a/gui/src/provider-icons.ts
+++ b/gui/src/provider-icons.ts
@@ -44,6 +44,41 @@ const PROVIDER_ICON_ALIASES: Record = {
alibaba: "alibaba-color.svg",
"alibaba-token-plan": "alibaba-color.svg",
"alibaba-token-plan-intl": "alibaba-color.svg",
+ baseten: "baseten.svg",
+ bizrouter: "bizrouter.svg",
+ cerebras: "cerebras.svg",
+ deepinfra: "deepinfra.svg",
+ digitalocean: "digitalocean.svg",
+ featherless: "featherless.svg",
+ hyperbolic: "hyperbolic.svg",
+ kilo: "kilo.svg",
+ nanogpt: "nanogpt.svg",
+ nebius: "nebius.svg",
+ neuralwatt: "neuralwatt.svg",
+ nous: "nous.svg",
+ novita: "novita.svg",
+ orcarouter: "orcarouter.svg",
+ parallel: "parallel.svg",
+ sambanova: "sambanova.svg",
+ scaleway: "scaleway.svg",
+ siliconflow: "siliconflow.svg",
+ synthetic: "synthetic.svg",
+ together: "together.svg",
+ umans: "umans.svg",
+ venice: "venice.svg",
+ vultr: "vultr.svg",
+ litellm: "litellm.svg",
+ zenmux: "zenmux.svg",
+ /*
+ * Z.AI and Zhipu's BigModel are the same company on two brands. `zai` is the
+ * international GLM Coding Plan and the mark comes from z.ai; the two
+ * `zhipu-bigmodel*` ids are the mainland console, which publishes only a
+ * horizontal wordmark, so they borrow it rather than render a lockup squeezed
+ * into a 19px box.
+ */
+ zai: "zai.svg",
+ "zhipu-bigmodel": "zai.svg",
+ "zhipu-bigmodel-coding": "zai.svg",
"qwen-cloud": "qwen-portal-color.svg",
"vercel-ai-gateway": "vercel-ai-gateway-color.svg",
vllm: "vllm-color.svg",
diff --git a/gui/tests/provider-marks-assets.test.ts b/gui/tests/provider-marks-assets.test.ts
new file mode 100644
index 0000000000..b6350cafff
--- /dev/null
+++ b/gui/tests/provider-marks-assets.test.ts
@@ -0,0 +1,66 @@
+import { expect, test } from "bun:test";
+import { readFileSync, readdirSync } from "node:fs";
+import { join } from "node:path";
+import { PROVIDER_REGISTRY } from "../../src/providers/registry";
+import { providerIconSrc } from "../src/provider-icons";
+
+const PUBLIC_DIR = join(import.meta.dir, "..", "public", "provider-icons");
+
+function bodyOf(src: string): string {
+ return readFileSync(join(PUBLIC_DIR, src.replace(/^\/provider-icons\//, "")), "utf8");
+}
+
+/** Every asset a provider resolves to, deduplicated -- several ids share one file. */
+function wiredAssets(): string[] {
+ const seen = new Set();
+ for (const entry of PROVIDER_REGISTRY) {
+ const src = providerIconSrc(entry.id);
+ if (src) seen.add(src);
+ }
+ return [...seen].sort();
+}
+
+/*
+ * The three ways a mark passes an SVG parse and still fails as artwork.
+ *
+ * A `` glyph renders per-machine and blank where the font lacks the
+ * character -- that is what disqualified the Hermes repo favicon, 113 bytes whose
+ * entire body was one text element. An `` or a base64 payload is a raster
+ * wearing an SVG costume: it will not scale into the 19px tile and cannot be
+ * masked. Neither is visible in review; both are visible here.
+ */
+test("every wired provider mark is drawn geometry, not text or a wrapped raster", () => {
+ const broken: string[] = [];
+ for (const src of wiredAssets()) {
+ const body = bodyOf(src);
+ if (/]/.test(body)) broken.push(`${src}: renders a glyph`);
+ if (/]/.test(body)) broken.push(`${src}: embeds a raster`);
+ if (/;base64,/.test(body)) broken.push(`${src}: carries a base64 payload`);
+ if (!/<(path|circle|rect|polygon|ellipse|line|polyline)[\s>]/.test(body)) {
+ broken.push(`${src}: carries no vector geometry`);
+ }
+ }
+ expect(broken).toEqual([]);
+});
+
+/*
+ * A wordmark in a square slot.
+ *
+ * The rail draws a 19px box. A horizontal lockup scaled into it is an illegible
+ * smear, which is what disqualified the MiniMax docs asset (129x32) in the
+ * previous unit and several vendor logos in this one. The viewBox is the only
+ * thing that says which shape a file is, and it is not something review catches.
+ *
+ * The threshold is deliberately loose: 2.5 admits a slightly wide mark and still
+ * rejects the 4:1-and-up lockups that actually caused the problem.
+ */
+test("no wired provider mark is a horizontal wordmark", () => {
+ const lockups: string[] = [];
+ for (const src of wiredAssets()) {
+ const box = bodyOf(src).match(/viewBox="[-\d.eE]+[ ,]+[-\d.eE]+[ ,]+([\d.eE]+)[ ,]+([\d.eE]+)"/);
+ if (!box) continue;
+ const ratio = Number(box[1]) / Number(box[2]);
+ if (Number.isFinite(ratio) && ratio > 2.5) lockups.push(`${src}: ${ratio.toFixed(2)}:1`);
+ }
+ expect(lockups).toEqual([]);
+});