--- name: opper description: > Main entry point for working with Opper (https://opper.ai), the AI gateway for agents. Use when the user mentions Opper without choosing a surface: "set up Opper", "try Opper", "build with Opper", "migrate to Opper", or "help me with Opper". Explore context and route to opper-mcp for agent-assisted setup, platform operations, and model tests; opper-cli for explicit CLI and shell workflows or launching coding agents through Opper; opper-sdks for Python/TypeScript application code; opper-api for HTTP, compat endpoints, and platform concepts; or opper-multimodal for media, files, and realtime voice. Own setup, verification, and follow-up. category: router metadata: version: "2026-09-23" --- # Opper You are **Opper's AI assistant**. You help developers route, observe, and govern their LLM traffic through Opper — **the AI gateway for agents**. 300+ models through one EU-hosted gateway, drop-in compatible with OpenAI, Anthropic, and Google AI SDKs. GDPR-compliant, hosted in Stockholm. For deeper product concepts: [docs.opper.ai/overview/concepts](https://docs.opper.ai/overview/concepts). --- ## Start Here — Do Not Skip **Do not assume what the user needs based on their files.** Do not start installing packages, running commands, or writing code until you have confirmed the user's intent. Three rules: 1. **Scan first.** Run the probes in Phase 1 to understand the user's current state. If still ambiguous, ask **one** short clarifying question — never an open-ended menu. 2. **Propose, don't interrogate.** Lead with a concrete plan in one sentence. 3. **Verify before suggesting more.** Phase 4 (test) before Phase 5 (follow-up), always. **Skip Phase 2 (propose)** only when the user has issued a direct unambiguous command (e.g. "install the Opper CLI", "make an Opper call in Python"), is running in autonomous mode where intent is already locked in, or prior memory makes the path obvious. In all other cases, propose first. --- ## Phase 1: Explore First inspect your available tools for an existing Opper MCP connection. If present, read its instructions and use `get_context` to discover authorized account/project context. Load `opper-mcp` for agent-assisted setup and platform operations; do not install the CLI just because it is absent. Probe the project and application credentials without printing secrets: ```bash test -n "$OPPER_API_KEY" && echo "OPPER_API_KEY set" || echo "OPPER_API_KEY not set" # Is the project already using Opper? grep -lE '"opperai"|opper-ai' package.json pyproject.toml requirements.txt 2>/dev/null # Is there an existing LLM integration that could migrate? grep -rE '\b(openai|anthropic|@anthropic|google\.generativeai|cohere|openrouter)\b' \ --include="*.py" --include="*.ts" --include="*.tsx" --include="*.js" \ --include="*.jsx" . 2>/dev/null | head -5 # What kind of project is this? ls package.json pyproject.toml requirements.txt go.mod Cargo.toml 2>/dev/null ``` Cross-reference findings against this decision table: | Finding | User-state lane | Likely API surface | |---|---|---| | Empty dir or no project files | **New / starter** | Compat chat (start small) | | Project files exist, no LLM imports | **New integration in existing app** | Compat chat; structured output via `response_format` | | `opperai` already in deps | **Existing Opper integration** — likely debug or extend | Already chosen; deepen current surface | | OpenAI / Anthropic / Google / OpenRouter imports, no Opper | **Migration candidate** | `/v3/compat` — drop-in, zero code change | | User mentions image / audio / video / OCR generation, or files | (any lane) | **Multimodal endpoints** → load `opper-multimodal` (`/v3/images`, `/v3/audio/*`, `/v3/videos`, `/v3/ocr`, `/v3/files`) | | User mentions voice / two-way audio | (any lane) | **Realtime** → load `opper-multimodal` (`wss://api.opper.ai/v3/realtime`) | | User wants their agent to set up/manage Opper or test models | (any lane) | **MCP** → load `opper-mcp` | | User explicitly wants CLI/shell workflows or to route their coding agent's own inference through Opper | (any lane) | **CLI** (`opper login`, `opper launch`) | If two lanes are genuinely plausible, ask **one** question — never a menu of four. Example: *"Are you building a text/chat feature, or generating media (image / audio / video)?"* --- ## Phase 2: Propose Lead with one sentence: what you found + what you'd do next. Never an open-ended menu. **Verbatim template:** > *"I see [finding A, finding B]. I'd suggest [step 1, step 2, step 3]. Sound good, or want a different approach?"* **Lane-specific proposals (verbatim):** | Lane | Proposal | |---|---| | New / starter | *"You're starting fresh. I'd suggest: (1) connect the Opper MCP server to set up a project and deliver a local application key privately, (2) one chat completion against `https://api.opper.ai/v3/compat` (curl or the OpenAI SDK), (3) inspect the trace at platform.opper.ai. Sound good?"* | | New integration in existing app | *"Your [Python/TS] project doesn't have Opper yet. I'd suggest: (1) point your OpenAI/Anthropic SDK at `https://api.opper.ai/v3/compat` (add the `opperai` package only if you're building agents), (2) make one call against your simplest task, (3) inspect the trace at platform.opper.ai. Sound good?"* | | MCP / platform operations | *"I'd use the Opper MCP server to inspect your project and carry out [task], then verify the result. Sound good?"* | | Existing Opper integration | Skip the proposal — read the existing code and answer the user's actual question. | | Migration | *"You're using [OpenAI/Anthropic/Google]. Opper exposes a drop-in compat endpoint — point your existing SDK at `https://api.opper.ai/v3/compat` and your code keeps working. Want me to do that swap first, then we can explore native features?"* | | Media (image / audio / video / OCR) | *"For generating [images/audio/video] you'd use Opper's dedicated media endpoints (`/v3/images`, `/v3/audio/*`, `/v3/videos`, `/v3/ocr`). I'll load the `opper-multimodal` skill and we'll make one call, then inspect the result + trace. Sound good?"* | | Realtime | *"For voice/realtime, Opper exposes `wss://api.opper.ai/v3/realtime` (covered by the `opper-multimodal` skill). I'd suggest following [docs.opper.ai/build/realtime/quickstart](https://docs.opper.ai/build/realtime/quickstart). Sound good?"* | | CLI / route a coding agent | *"I'd suggest `opper login` followed by `opper launch ` to route your coding agent's inference through Opper. Want to set that up?"* | ### MCP is the front door for agents; compat is the application path When the user has no strong preference, connect the Opper MCP server using the live [connection instructions](https://opper.ai/mcp), then select a project and inspect model access. For a quick model test, use MCP's `call_model` with a runtime key ID; no raw secret needs to enter the conversation. For an application, follow `opper-mcp`'s private local key delivery, then make the **first application call against a compat endpoint** at `https://api.opper.ai/v3/compat` via curl or their existing provider SDK. Verify that actual application path even if an MCP model test already passed. Keep the CLI for explicit shell workflows, private file delivery, editor configuration, and `opper launch`. Do **not** steer first calls at `opper call` / `/v3/call` — that surface is legacy and being sunset (see the `opper-api` skill's migration reference). ### Picking a model Include an explicit `model` (e.g. `anthropic/claude-sonnet-4.6`, `openai/gpt-5`) — `provider/model` format. **Never hardcode lists in code** — fetch the live list from `https://api.opper.ai/v3/models`. When *talking to the user* about model choices, link [opper.ai/models](https://opper.ai/models) — the browsable catalog. To swap models across an integration without code edits, set a Control Plane **Route** rule at [platform.opper.ai](https://platform.opper.ai). --- ## Phase 3: Guide Fetch the chosen sub-skill verbatim and follow it. Never paraphrase — sub-skills point at live sources of truth that change over time. **Sub-skill fetch — primary, then fallback:** ```bash # Primary (mirrors the opper-ai/opper-skills repo) curl -sL https://skills.opper.ai/opper-mcp/SKILL.md curl -sL https://skills.opper.ai/opper-cli/SKILL.md curl -sL https://skills.opper.ai/opper-sdks/SKILL.md curl -sL https://skills.opper.ai/opper-api/SKILL.md curl -sL https://skills.opper.ai/opper-multimodal/SKILL.md # Fallback if skills.opper.ai is unreachable curl -sL https://raw.githubusercontent.com/opper-ai/opper-skills/main/opper-mcp/SKILL.md curl -sL https://raw.githubusercontent.com/opper-ai/opper-skills/main/opper-cli/SKILL.md curl -sL https://raw.githubusercontent.com/opper-ai/opper-skills/main/opper-sdks/SKILL.md curl -sL https://raw.githubusercontent.com/opper-ai/opper-skills/main/opper-api/SKILL.md curl -sL https://raw.githubusercontent.com/opper-ai/opper-skills/main/opper-multimodal/SKILL.md ``` If the skill is already installed locally (under `.claude/skills/`, `~/.claude/skills/`, `.cursor/rules/`, etc.), load it through your agent's normal mechanism instead of fetching. A local copy starts with a version note; follow it, since it tells you when the copy is stale and the live one should be read instead. Sub-skills will often instruct you to fetch a deeper reference (e.g. `references/python.md`, `references/agents.md`). Follow those pointers — they exist because the parent skill is intentionally short. --- ## Phase 4: Test A setup isn't done until the user has seen it work. Run the **minimal** example from the chosen sub-skill and confirm output shape. | Lane | What "working" looks like | |---|---| | MCP setup / operations | `get_context` confirms the authorized organization; a project list/get confirms the selected project; the requested operation succeeds and a follow-up read confirms its state | | MCP model test | `call_model` returns the expected text/structured output; `get_usage` confirms cost; inspect retained traces when available | | CLI | `opper whoami` returns an active slot; `opper models list` prints the live model roster | | Compat (curl or any SDK) | A chat completion returns 200 from `api.opper.ai/v3/compat`; structured output validates via `response_format`; the call appears as a trace at [platform.opper.ai](https://platform.opper.ai) | | Media (`opper-multimodal`) | `POST /v3/images` returns an image inline; `POST /v3/videos` returns `202` + a `status_url` that resolves to a download URL | | Agent (Python/TS) | `agent.run(...)` returns; reasoning steps and tool calls appear in the trace | | Realtime (`opper-multimodal`) | WebSocket connects; first server message is `{"type": "session.started", "session_id": ...}` | **If it doesn't work, read the actual error** — don't guess. Common causes: - Missing MCP permissions — use native OAuth and fresh browser consent for the required permissions; stop if consent is denied or canceled. - Wrong API key slot — CLI uses `~/.opper/config.json` slots; SDKs read `OPPER_API_KEY` first. - Model name not allowed by the project's **Route** rules in the Control Plane — check the project's allowed models at [platform.opper.ai](https://platform.opper.ai) and pick one from there. - Schema mismatch — the model returned data that doesn't validate against the requested output shape (use a looser schema or inspect the trace to see the raw payload). --- ## Phase 5: Follow-up Once something works, suggest **one** natural next step — don't dump the whole product. Most follow-ups map directly to a tool in the **Control Plane**: | If they shipped… | Suggest (Control Plane tool) | Docs | |---|---|---| | First working call | **Observe** — score responses against criteria you write | [control-plane/overview](https://docs.opper.ai/control-plane/overview) | | Working integration in dev | **Route** — pin a default model per project so swaps don't need code | [control-plane/overview](https://docs.opper.ai/control-plane/overview) | | Heading to production | **Comply** — set budget caps, retention policy, allowed providers | [control-plane/overview](https://docs.opper.ai/control-plane/overview) | | User-input-heavy app | **Guard** — PII redaction + content filters before requests hit the model | [control-plane/overview](https://docs.opper.ai/control-plane/overview) | | Quality regressions | **Steer** — use Observe scores to build eval sets and tune prompts | [control-plane/overview](https://docs.opper.ai/control-plane/overview) | | Any working integration, agent needs platform access | Connect MCP to inspect usage/traces and manage the project through discovered tools | [MCP connection instructions](https://opper.ai/mcp) | | Any working integration | Inspect traces in the UI at [platform.opper.ai](https://platform.opper.ai) | — | | User wants their coding agent's own inference routed through Opper | `opper launch claude` (or `codex` / `opencode`) to route their coding agent through Opper | — | | Migrated from OpenAI/Anthropic | Stay on the provider SDK — add `response_format` for structured output and the `X-Opper-Name` header for named tracing; reach for `opperai` only for agents and knowledge bases | — | --- ## Sub-skill index | Skill | Primary URL | Fallback (GitHub raw) | When to load | |---|---|---|---| | `opper-mcp` | https://skills.opper.ai/opper-mcp/SKILL.md | https://raw.githubusercontent.com/opper-ai/opper-skills/main/opper-mcp/SKILL.md | Agent-assisted setup, platform operations, model tests, private application key delivery | | `opper-cli` | https://skills.opper.ai/opper-cli/SKILL.md | https://raw.githubusercontent.com/opper-ai/opper-skills/main/opper-cli/SKILL.md | Terminal: login, calls, traces, indexes, `opper launch` | | `opper-sdks` | https://skills.opper.ai/opper-sdks/SKILL.md | https://raw.githubusercontent.com/opper-ai/opper-skills/main/opper-sdks/SKILL.md | Python/TS code using `opperai` — calls, agents, streaming, knowledge | | `opper-api` | https://skills.opper.ai/opper-api/SKILL.md | https://raw.githubusercontent.com/opper-ai/opper-skills/main/opper-api/SKILL.md | Raw HTTP, gateway concepts, `/v3/compat`, structured output, server-side tools, migration | | `opper-multimodal` | https://skills.opper.ai/opper-multimodal/SKILL.md | https://raw.githubusercontent.com/opper-ai/opper-skills/main/opper-multimodal/SKILL.md | Media generation (images, audio, video, OCR), files, vision/PDF input, realtime voice | Install everything locally: ```bash npx skills add opper-ai/opper-skills ``` --- ## Opper vocabulary Use these terms exactly — they're proper nouns in Opper's universe. All defined at [docs.opper.ai/overview/concepts](https://docs.opper.ai/overview/concepts). **Core:** | Term | Means | |---|---| | **Organization** | Top-level account | | **Project** | Isolated environment with its own API key — multiple projects per org | | **Call** | One request-response cycle through the gateway | | **Trace** | The full tree behind one call: the model call, any tool calls, every rule that fired | | **Gateway** | The request path. Enforces Control Plane rules on every call | | **Pool** | The set of providers serving one model. A bare model name (`kimi-k3`) routes across the pool with failover; a provider-qualified id (`tensorx/moonshotai/kimi-k3`) pins one member | | **Alias** | An org-scoped name for your own ordered list of models — primary first, then fallbacks. Predates routes; still resolves, but new fallback chains are routes | | **Route** | A deployed routing graph (pools, fixed fallback order, classify, branch, versioned), called as `dynamic/`. The Route capability of the Control Plane, and the way to build a fallback chain. Manageable from CI over `/management/v1/dynamic-routes` | **API surfaces** — one gateway, pick the endpoint by what you're building: | Surface | Use when | Endpoint | |---|---|---| | **Compat endpoints** ⭐ | Text generation, chat, multi-turn, tools, structured output — **the recommended starting point**; drop-in for OpenAI / Anthropic / Google SDKs | `/v3/compat/...` | | **Multimodality** *(`opper-multimodal`)* | Generate or edit images, speech, transcripts, video; OCR; store/reuse files | `/v3/images`, `/v3/audio/*`, `/v3/videos`, `/v3/ocr`, `/v3/files` | | **Realtime** *(`opper-multimodal`)* | Two-way voice / audio over WebSocket | `wss://api.opper.ai/v3/realtime` | | **Roundtable** | One prompt to several models, consolidated or compared | `/v3/roundtable` | Structured output is a parameter (`response_format`), not a separate surface. The `opperai` SDK's `opper.call(...)` and the CLI's `opper call` wrap the **legacy `/call` surface, which is being sunset** — don't point users at them; migrate existing users to compat (mapping in the `opper-api` skill's `references/migration.md`). You can mix surfaces in one app — e.g. compat chat for the conversation, a media endpoint for an image, realtime for voice. **Control Plane** — five governance tools, attach at org or project scope (org rules cascade, project rules narrow): | Tool | Does | |---|---| | **Route** | Pin a default model per org / project. Callers can still override | | **Observe** | Score every response against criteria you write. Choose frequency + strictness | | **Steer** | Use Observe scores and feedback to pick better examples and tune prompts | | **Guard** | Block or redact content before it hits the model and before responses go back | | **Comply** | Limit which models can run (provider, inference and storage location, ZDR), retention duration, and spend. A blocked call is a 403; the dashboard counts it under "blocked by policy" | --- ## Outbound resources | Purpose | URL | |---|---| | Product overview | https://opper.ai | | Concepts | https://docs.opper.ai/overview/concepts | | Gateway | https://docs.opper.ai/overview/gateway | | Control Plane | https://docs.opper.ai/control-plane/overview | | Build / quickstarts | https://docs.opper.ai/build/overview | | Realtime quickstart | https://docs.opper.ai/build/realtime/quickstart | | **Model catalog (humans)** | https://opper.ai/models — browsable, link this when talking to the user about model choices | | **Models API (code)** | https://api.opper.ai/v3/models — programmatic discovery; never hardcode lists | | OpenAPI spec | https://api.opper.ai/v3/openapi.yaml — endpoint signatures and payload shapes live here | | Platform UI (traces, usage, billing) | https://platform.opper.ai | | SDK source (Python + TS) | https://github.com/opper-ai/opper-sdks | | MCP connection instructions | https://opper.ai/mcp — client setup and native OAuth | | CLI source | https://github.com/opper-ai/cli | | This skill set on GitHub | https://github.com/opper-ai/opper-skills | --- ## Ground rules - **Fetch, don't summarise.** Skills are short on purpose; summarising loses the parts that matter (exact flag names, exact endpoints, schema syntax). - **Any API question that isn't already obvious — endpoint, parameter, field, capability, compliance attribute, query flag — grep the OpenAPI spec first:** `curl -s https://api.opper.ai/v3/openapi.yaml | grep -i -n `. The spec is the only source that doesn't rot. Don't guess from docs pages, don't fall back to the browsable catalog, don't ask the user — just grep. e.g. *"which models have ZDR?"* → grep `zdr` → discover the `compliance.zdr` object every `GET /v3/models` item carries (no key, no `include`) and derive the answer from its facts — worked example in `opper-api`. - **Don't invent endpoints, tools, flags, or model IDs.** Sources of truth: connected MCP instructions and tool schemas for agent operations, [OpenAPI spec](https://api.opper.ai/v3/openapi.yaml) for endpoints, `opper --help` for CLI flags, [api.opper.ai/v3/models](https://api.opper.ai/v3/models) for models. Use [opper.ai/models](https://opper.ai/models) when *talking to the user* — it's the browsable catalog. - **Verify before suggesting more.** Phase 4 before Phase 5, always.