SAIA (Academic Cloud Hessen) provider for the OMP coding agent
An OMP plugin that auto-registers all SAIA Academic Cloud models as a provider — no manual configuration needed.
This is the OMP port of pi-saia-plugin. It is part of a broader agent memory ecosystem; see the agent-memory-research survey [arXiv 2512.13564] for the research foundation driving our memory architecture design.
- Dynamic discovery — the provider is registered via OMP's runtime provider API (
pi.registerProvider()withfetchDynamicModels); OMP queries the SAIA/v1/modelsendpoint through the same model-cache pipeline as built-in providers (24 h TTL,omp models refreshto force) - Zero config — API key from
$SAIA_API_KEY(OMP loads.envfiles automatically) or a config-sourced key; no reload needed once the key is set —omp modelsre-runs discovery - Skill included —
/skill:saia-modelsdocuments available models and usage - OpenAI-compatible — uses standard
openai-completionsAPI (chat-ai.academiccloud.de/v1)
# From a local checkout (recommended for development)
omp plugin link /path/to/omp-saia-plugin
# From git
omp plugin install github:koalajoe23/omp-saia-pluginThe plugin is enabled automatically on install. Restart omp if it was running.
Models are dynamically discovered from the SAIA API. The table below lists currently known models with context windows sourced from official SAIA docs.
| Model ID | Name | Context | Reasoning |
|---|---|---|---|
saia/glm-4.7 |
GLM 4.7 | 200K | ✅ |
saia/glm-5.3-flash |
GLM 5.3 Flash | 1.25M | ✅ |
saia/qwen3.5-397b-a17b |
Qwen 3.5 397B | 256K | ✅ |
saia/qwen3.5-122b-a10b |
Qwen 3.5 122B | 256K | ✅ |
saia/qwen3.8-27b |
Qwen 3.8 27B | 262K | ✅ |
saia/devstral-2-123b-instruct-2512 |
DevStral 2 123B | 256K | ❌ |
saia/openai-gpt-oss-120b |
GPT-OSS 120B | 128K | ✅ |
saia/qwen3.6-35b-a3b |
Qwen 3.6 35B | 262K | ✅ |
saia/deepseek-v4-flash-0731 |
DeepSeek V4 Flash 0731 | 1M | ✅ |
saia/mistral-medium-3.5-128b |
Mistral Medium 3.5 | 256K | ✅ |
saia/gemma-4-31b-it |
Gemma 4 31B | 256K | ✅ |
saia/qwen3-30b-a3b-instruct-2507 |
Qwen 3 30B | 256K | ❌ |
saia/qwen3-coder-next |
Qwen 3 Coder Next | 256K | ❌ |
saia/qwen3-omni-30b-a3b-instruct |
Qwen 3 Omni 30B | 256K | ❌ |
saia/apertus-70b-instruct-2509 |
Apertus 70B | 64K | ❌ |
saia/meta-llama-3.1-8b-instruct |
Llama 3.1 8B | 128K | ❌ |
Reasoning status is verified against the live API with
reasoning_effortprobes (2026-09-10); the ✅ set can change as SAIA updates model capabilities. Date-stamped variants (e.g.saia/deepseek-v4-flash-0731) inherit capability and context from their base id. The actual model set may vary — runomp models | grep ^saiato see what's currently available. Most reasoning models expose the fullminimal…maxeffort ladder;mistral-medium-3.5-128b(onlynone/high),openai-gpt-oss-120b(low/medium/high), andqwen3.8-27b(low/medium/xhigh) are restricted to their backend's accepted values.
Date-stamped variants: SAIA sometimes serves date-stamped variants of a model (e.g.
saia/deepseek-v4-flash-0731alongside the basedeepseek-v4-flash). Capability lookups strip a trailing-NNNNstamp, so variants inherit the base model's reasoning support and context window instead of falling back to defaults.
# List available models
omp models | grep ^saia
# Switch to a model
/model saia/glm-4.7
# With thinking level
/model saia/qwen3.5-397b-a17b:high
# Force a refresh of the model list (bypass the 24 h cache)
omp models refresh
# Load the skill for documentation
/skill:saia-modelsThe plugin keeps model capabilities (reasoning, vision, context windows) fresh in the background: a deferred cycle at startup (when the store is stale), then every 6 h while omp runs. Each cycle refreshes the model list, probes unknown models for reasoning (tiny ~2-token calls, ≤2 per cycle), re-scrapes SAIA's docs page weekly for context windows, and stores the result in ~/.omp/agent/saia-models.json. omp picks the fresh data up at its next model discovery (omp models / omp models refresh).
Trigger a reconcile manually: /saia-refresh — then omp models refresh to surface the result immediately.
All timings are env-configurable (invalid values fall back to defaults):
| Variable | Default | Meaning |
|---|---|---|
SAIA_RECONCILE_STARTUP_DELAY_MS |
5000 |
defer reconcile after session start |
SAIA_RECONCILE_INTERVAL_MS |
21600000 |
background cycle (6 h) |
SAIA_RECONCILE_STALE_AFTER_MS |
43200000 |
catch-up at startup if store older |
SAIA_RECONCILE_PROBES_PER_CYCLE |
2 |
probe budget per cycle |
SAIA_RECONCILE_PROBE_TIMEOUT_MS |
20000 |
per-probe timeout |
SAIA_RECONCILE_REVERIFY_MS |
604800000 |
per-model re-verify (7 d) |
SAIA_RECONCILE_SCRAPE_INTERVAL_MS |
604800000 |
docs scrape cadence (7 d) |
SAIA_RECONCILE_SCRAPE_TIMEOUT_MS |
15000 |
scrape fetch timeout |
SAIA_RECONCILE_STORE_PATH |
~/.omp/agent/saia-models.json |
store location |
SAIA_RECONCILE_DISABLED |
unset | set to any truthy value to disable |
Failures degrade silently to the last known state or the static tables; nothing blocks startup or discovery.
The API key is resolved from $SAIA_API_KEY (OMP also loads .env files from the project, ~/.omp/agent/, and ~/.omp/):
export SAIA_API_KEY=your-key
omp models | grep ^saiaWithout a key the saia provider is registered but carries no models; set the variable and run omp models to trigger discovery — no reload needed.
omp-saia-plugin/
├── package.json # OMP plugin manifest (omp.extensions)
├── extensions/
│ ├── index.ts # Provider registration (pi.registerProvider + fetchDynamicModels)
│ ├── discovery.ts # API client: fetchModels(), buildModelDefs()
│ ├── config.ts # ModelDef → ProviderModelConfig transformer
│ ├── constants.ts # Provider ID, base URL, context window table
│ └── types.ts # TypeScript interfaces for API responses
├── skills/
│ └── saia-models/
│ └── SKILL.md # Model documentation skill
└── test/
└── extensions.test.ts # bun test for discovery/config logic
git clone https://github.com/koalajoe23/omp-saia-plugin
cd omp-saia-plugin
bun install
bun check # tsc --noEmit
bun testTest locally:
omp plugin link /path/to/omp-saia-plugin
omp models | grep ^saia| pi | OMP |
|---|---|
pi.registerProvider(id, { models }) — one-shot fetch at startup |
pi.registerProvider(id, { fetchDynamicModels }) — OMP's runtime discovery pipeline (SQLite model cache, 24 h TTL, omp models refresh) |
thinkingLevelMap (pi thinking levels → reasoning_effort) |
thinking: { mode: "effort", efforts: [...] } — OMP levels map 1:1 to vLLM values; compat.supportsReasoningEffort: true |
compat.supportsThinkingTokenBudget |
not exposed by OMP's compat schema (dropped) |
apiKey: "$SAIA_API_KEY" (deferred env resolution) |
resolved at registration; env is re-read inside the discovery callback so the key can appear later |
pi install / /reload |
omp plugin link / omp plugin install; no reload needed for model changes |
This plugin is based on pi-saia-plugin by Tobias Weiss: the model discovery logic, context-window tables, reasoning verification data, and skill content are derived from that project, ported from the pi extension API to OMP's. Thanks to the original author and contributors.
MIT