Skip to main content
bpx-endpoints: Every Model Endpoint, One Command

bpx-endpoints: Every Model Endpoint, One Command

pi has presets for the big providers. This is for everything else: the proxy, the box under the desk, the gateway with its own key dance.

LiveOpen Sourceopen-source

A pi extension that manages custom model endpoints (OpenAI-compatible proxies, self-hosted LM Studio/Ollama/vLLM, regional gateways) through one /endpoints command, with model discovery, models.dev metadata, and safe reasoning-effort mapping.

pi ships presets for the big hosted providers, and those presets are good — correct base URLs, correct metadata, nothing for you to do. That covers you right up until your models live somewhere pi has never heard of. A load balancer sitting in front of a few model accounts. An inference box you run yourself.

A regional gateway with its own key dance.

At that point the stock answer is hand-editing ~/.pi/agent/models.json, and then hand-editing it again every time the endpoint's model list changes. Which is exactly the kind of chore I build tools to kill.

bpx-endpoints puts all of it behind one command. Point /endpoints at a base URL and it discovers the model list, pulls parameter metadata from pi's own registry plus models.dev, generates the config, and registers the models into your live session. No restart. No hand-written JSON.

It's the sibling of bpx-consult in the same monorepo: small, sharp extensions for a harness that's deliberately lean.

What it actually covers

Worth being precise about the scope, because it's easy to assume this duplicates pi's preset catalog. It doesn't. The presets already handle the known providers correctly, and I'm not interested in maintaining a second copy of that list. bpx-endpoints is for the deployments the presets can't know about:

  • OpenAI-compatible proxies and load balancers
  • Self-hosted endpoints (LM Studio, Ollama, vLLM)
  • Regional gateways
  • Anything where you supply the base URL, protocol, and key yourself

Discovery that survives contact with real endpoints

Every endpoint claims to be OpenAI-compatible. Then you fetch its model list and find out what "compatible" meant to whoever built it. So discovery is written defensively.

It reads bare arrays, data[], models[], data.models[] nesting, and object-keyed maps. Duplicate ids drop, id-less entries skip, and both get counted into warnings you'll see in /endpoints doctor rather than vanishing. Ollama gets special handling because its chat API lives at /v1 while its model list lives at /api/tags, so discovery.modelsUrl bypasses the base-URL-plus-path assembly entirely.

There's an opt-in path prober for the endpoints that put their model list somewhere unexpected: when the configured URL 404s, it tries the common variants at the origin and caches whichever one worked. It will never probe around a 401 or 403, though. An auth failure is an answer, and guessing at more URLs with a bad key is how you get yourself rate-limited. Transient failures (network blips, 429s honoring Retry-After, 5xx) retry with backoff.

Auth failures don't.

The reasoning-effort trap

This is the bit I'm most pleased with, and the reason 0.2.0 exists. pi resolves the wire value for thinking with model.thinkingLevelMap[level] ?? level. That ?? is a trapdoor: if a metadata source's map has a gap, pi falls through and sends pi's own level name, "xhigh" or "max", as the wire value. And whether that leaked name is legal depends entirely on the model. off is never sent as the literal "off". max and xhigh are real wire values on plenty of newer models and rejected outright by older ones and by most self-hosted servers. So the request 400s, sometimes, and only ever when you turn thinking up.

bpx-endpoints therefore never copies a metadata source's map verbatim. It always emits a complete one. Every pi level, no nulls, no gaps. When the endpoint is unknown, that's a canonical safe map nothing can leak through.

When you opt into the live probe, it sends four one-token completions to find out which effort values the endpoint actually accepts, then maps every pi level onto the nearest one that works. A manual list in your config beats the probe. An endpoint that accepts nothing at all gets its reasoning models registered as non-reasoning, with a warning, rather than a config that 400s on you later.

And if you've hand-authored a complete map yourself in models.custom.json, it's never clobbered. Which brings me to the rule the whole thing is built on.

It never writes to your models.json

pi's native ~/.pi/agent/models.json stays yours. bpx-endpoints keeps its managed config in one flat, schema-validated file beside it and its derived state (discovered models, metadata cache, generated config, your override layer) in its own directory. Config dir is created 0700, its JSON files 0600.

Secrets don't have to be literals, either. apiKey, custom headers, and (as of 0.2.0) baseUrl all accept $VAR / ${VAR} environment references and whole-value !command shell references. Mid-URL works too: http://${MY_HOST}:8080/v1. Expansion happens at use time, during discovery and tests and registration, so the config file keeps the reference and nothing resolved ever lands on disk. An unset variable fails fast with the profile id in the message instead of quietly sending an empty key.

Fail-soft, all the way down

A config manager that bricks your session when its own file goes bad is worse than no config manager. So every layer degrades instead of dying. A missing generated config is just onboarding. An invalid one skips registration but leaves the manager, refresh, doctor, and recovery all working.

An invalid override layer is ignored with a warning while the generated endpoints still register.

My favourite one: if your managed config is malformed, /endpoints settings refuses to open. Earlier it would fall back to defaults, and the first save would then write those defaults straight over the broken file — destroying the exact recovery data doctor exists to protect.

The panel

The manager is a real pi-native TUI, not more chat text scrolling past. Framed, centered at 104 columns, filled with your theme's card colour, selected rows highlighted — so it reads as a dialog you're inside of. Add, edit, clone, delete, refresh, test, drill into per-model parameter sources and inclusion policy, all in the same panel session. The advanced override layer is one keystroke away when you need it and invisible when you don't.

Subcommands exist for scripting and recovery: doctor, refresh, test --all, probe-reasoning, export (which recursively masks secrets, including the ones hiding in custom headers), status, open. But the panel is the point.

Install

pi install npm:@booplex/bpx-endpoints

Needs pi 0.80+ and Node 22.19+. MIT, 111 tests, source at gabelul/bpx-mono. If you're already running bpx-consult, this installs alongside it and shares the same settings picker.

Built With

pi extensionTypeScriptTypeBoxmodels.devpi-tuinpmMIT

Related Work

Next Step

Need something this practical for your own product or business?

I build practical websites, admin tools, and product experiences that are easier to run once they are live, not just easier to launch.