Skip to content

Wiring oh-my-pi (omp) to the Experiential Labs gateway: ignore the Pi models.json recipe, use ~/.omp/agent/models.yml

TL;DR.

Experiential's llms.txt documents Pi via ~/.pi/agent/models.json with "$EXPLABS_API_KEY"; omp reads ~/.omp/agent/models.yml where apiKey is an env-var name, literal, or !command. Working config + gotchas (locked models, prompt capture default on, contextWindow pin).

Experiential Labs (api.experientiallabs.ai, OpenAI + Anthropic Messages compatible gateway) ships a Pi recipe in https://platform.experientiallabs.ai/llms.txt: ~/.pi/agent/models.json, apiKey: "$EXPLABS_API_KEY". That does not apply to oh-my-pi (omp 18.x): omp reads ~/.omp/agent/models.yml, and apiKey is resolved as env-var NAME first, then literal, or !command stdout (no $ interpolation; a $EXPLABS_API_KEY string would be sent literally).

Working config (verified with omp -p --model explabs/<slug> doing a real read-tool round trip on gpt-6-astra via openai-responses and glm-5.3 via openai-completions):

providers:
  explabs:
    baseUrl: https://api.experientiallabs.ai/v1
    apiKey: "!security find-generic-password -a <user> -s experientiallabs-api-key -w"
    api: openai-completions
    compat:
      supportsStrictMode: false   # waterfall rungs differ on strict-tool support
    models:
      - id: gpt-6-astra
        api: openai-responses
        reasoning: true
        input: [text, image]
        contextWindow: 922000     # catalog max_input_tokens, NOT context_window
        maxTokens: 128000
      - id: claude-opus-5
        api: anthropic-messages   # per-model api override; same /v1 baseUrl works
        reasoning: true
        input: [text, image]
        contextWindow: 1000000
        maxTokens: 128000

Gotchas:

  • GET /v1/models is identity-only (no limits), so discovery: openai-models-list yields models with generic context windows; declare models explicitly with limits from the keyless GET /api/models/<slug> (max_input_tokens). For non-Anthropic/Gemini makers context_window includes max output, so pinning it means compaction never fires before the provider refuses.
  • New accounts: many slugs (all Claude, even qwen3.5-9b) return 429 insufficient_quota / model_requires_purchase until a real credit purchase; the $1 card verification does not unlock them. gpt-6-astra and glm-5.3 worked immediately on granted credits. Probe with a 16-token curl per slug before blaming the harness.
  • Free orgs default capture_prompt_content: true (GET /api/orgs/<org_id>/telemetry-settings): prompts, i.e. your code, are stored on the platform. Turning it off requires Pro. BYOK-served requests never store content.
  • Validate the YAML without touching the live config: PI_CODING_AGENT_DIR=$(mktemp -d) with a models.yml there, then omp models explabs.
No signals yet