No description
  • TypeScript 100%
Find a file
2026-05-29 12:08:53 -05:00
node_modules init commit 2026-05-29 12:08:53 -05:00
src init commit 2026-05-29 12:08:53 -05:00
.env.example init commit 2026-05-29 12:08:53 -05:00
LICENSE init commit 2026-05-29 12:08:53 -05:00
package-lock.json init commit 2026-05-29 12:08:53 -05:00
package.json init commit 2026-05-29 12:08:53 -05:00
README.md init commit 2026-05-29 12:08:53 -05:00
tsconfig.json init commit 2026-05-29 12:08:53 -05:00

pi-openwebui-autodiscovery

Pi coding agent extension that auto-discovers models from OpenWebUI and registers them as an OpenAI-compatible provider.

Default OpenWebUI base URL in this package:

https://chat.home-net.work

What it does

At Pi startup, this extension:

  1. Calls OpenWebUI's OpenAI-compatible model endpoint:

    https://chat.home-net.work/api/v1/models
    
  2. Reads the returned model IDs.

  3. Registers a Pi provider named openwebui with base URL:

    https://chat.home-net.work/api/v1
    
  4. Makes those models available to Pi without manually maintaining models.json.

Install into a repo

Copy this folder into your repo, for example:

mkdir -p .pi/extensions
cp -r pi-openwebui-autodiscovery .pi/extensions/openwebui-autodiscovery

Pi docs say project-local extensions can live under:

.pi/extensions/

Global extensions can live under:

~/.pi/agent/extensions/

Configure

Create an OpenWebUI API key in:

OpenWebUI -> Settings -> Account -> API Keys

Then export:

export OPENWEBUI_BASE_URL="https://chat.home-net.work"
export OPENWEBUI_API_KEY="your-openwebui-api-key"

Optional overrides:

export OPENWEBUI_PROVIDER_NAME="openwebui"
export OPENWEBUI_PROVIDER_DISPLAY_NAME="OpenWebUI"
export OPENWEBUI_DEFAULT_CONTEXT_WINDOW="131072"
export OPENWEBUI_DEFAULT_MAX_TOKENS="8192"
export OPENWEBUI_DEFAULT_REASONING="true"

Test OpenWebUI directly

curl "https://chat.home-net.work/api/v1/models" \
  -H "Authorization: Bearer $OPENWEBUI_API_KEY"

Then test chat completions with one of the returned model IDs:

curl "https://chat.home-net.work/api/v1/chat/completions" \
  -H "Authorization: Bearer $OPENWEBUI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "replace-with-model-id",
    "messages": [
      {"role": "user", "content": "Say hello from OpenWebUI"}
    ],
    "stream": false
  }'

Use with Pi

From your repo root:

pi --list-models

You should see models under the openwebui provider.

Then run Pi normally and select one of the OpenWebUI models.

Per-model metadata overrides

OpenWebUI model discovery returns model IDs, but not reliable context window, max token, reasoning, or multimodal metadata.

Edit src/index.ts and add overrides:

const MODEL_OVERRIDES: Record<string, ModelOverride> = {
  "qwen3.6-35b-a3b": {
    contextWindow: 131072,
    maxTokens: 8192,
    reasoning: true,
  },
  "llava:latest": {
    contextWindow: 32768,
    maxTokens: 4096,
    reasoning: false,
    input: ["text", "image"],
  },
};

Notes

  • This assumes your OpenWebUI exposes the OpenAI-compatible API at /api/v1.

  • The extension uses OPENWEBUI_API_KEY by name in the registered provider so Pi can read the value from your environment.

  • If your installed Pi package still uses the older @mariozechner/pi-coding-agent type package instead of @earendil-works/pi-coding-agent, change the import in src/index.ts accordingly:

    import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
    

Troubleshooting

OPENWEBUI_API_KEY is not set

Export the variable before launching Pi:

export OPENWEBUI_API_KEY="your-key"

401/403 from /api/v1/models

Regenerate your OpenWebUI API key and make sure API-key auth is enabled in OpenWebUI.

No models appear

Run:

curl "https://chat.home-net.work/api/v1/models" \
  -H "Authorization: Bearer $OPENWEBUI_API_KEY"

If that does not return an object with a data array, the extension has nothing to register.

Error processing chat payload: 'NoneType' object has no attribute 'startswith'

Some OpenWebUI versions can fail when request fields like chat_id/parent_id are null.

This extension now patches outgoing payloads to always send string values for those fields, which avoids that server-side crash.