From a0aa3a53c207e82349f20ec5a66dfa43756cef3c Mon Sep 17 00:00:00 2001 From: Johnny Chadda Date: Wed, 1 Jul 2026 15:22:06 +0200 Subject: [PATCH 1/3] docs: document the session-scoped routing endpoint for manual use MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a "Routing through a session without the CLI" section to the README explaining the /v3/session//… endpoint that `opper launch` targets: URL shape, sess_ id validation, tag path segments, bearer auth, a raw curl example, and env-var wiring for OpenAI/Anthropic-shaped agents. Also correct the stale `→ /v3/compat` launch annotations: every launchable agent now routes through /v3/session//… except Claude Desktop, which still bakes /v3/compat into its persistent GUI profile. Claude-Session: https://claude.ai/code/session_01Dd669tGULj45v4CaKBAvGU --- README.md | 82 +++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 74 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 2eafd1a..722220b 100644 --- a/README.md +++ b/README.md @@ -52,17 +52,17 @@ Key resolution at request time: `OPPER_API_KEY` env var > the slot named by `--k ## Agents -`opper launch ` starts a supported AI agent with its model traffic transparently routed through Opper. Pass-through args after the agent name go straight to the agent's CLI. After the session, the CLI prints a summary with duration, model, and a traces link. +`opper launch ` starts a supported AI agent with its model traffic transparently routed through Opper. Pass-through args after the agent name go straight to the agent's CLI. Each launch runs inside a fresh Opper **session** so every call the agent makes is grouped together for tracing and cost — see [Routing through a session without the CLI](#routing-through-a-session-without-the-cli) to wire that up by hand. After the session, the CLI prints a summary with duration, model, and a traces link. ```bash opper agents list # NAME / DISPLAY / KIND / STATE / CONFIG / COMMAND -opper launch claude # Anthropic Messages compat → /v3/compat -opper launch claude-desktop # rewire Claude Desktop (GUI) → /v3/compat -opper launch opencode # OpenAI Chat Completions compat → /v3/compat -opper launch codex # OpenAI Responses compat → /v3/compat -opper launch hermes # OpenAI Chat Completions compat → /v3/compat -opper launch openclaw # OpenAI Chat Completions compat → /v3/compat (background gateway) -opper launch pi # OpenAI Chat Completions compat → /v3/compat +opper launch claude # Anthropic Messages shape → /v3/session//v1/messages +opper launch claude-desktop # rewire Claude Desktop (GUI) → /v3/compat (persistent GUI profile) +opper launch opencode # OpenAI Chat Completions shape → /v3/session//chat/completions +opper launch codex # OpenAI Responses shape → /v3/session//responses +opper launch hermes # OpenAI Chat Completions shape → /v3/session//chat/completions +opper launch openclaw # OpenAI Chat Completions shape → /v3/session//chat/completions (background gateway) +opper launch pi # OpenAI Chat Completions shape → /v3/session//chat/completions # Anything after the agent name is forwarded to its CLI — handy for # scripting / cron with non-interactive flags. @@ -92,6 +92,72 @@ opper agents remove claude-desktop # works for any registered adapter This is the non-interactive equivalent of the menu's "Remove Opper integration" action. It clears Opper-owned config (e.g., flips Claude Desktop's `deploymentMode` back to `"1p"`, removes the `opper` provider block from OpenCode / Pi / OpenClaw, etc.) without touching anything you put there yourself. +## Routing through a session without the CLI + +`opper launch` is a thin convenience wrapper. Under the hood it does one thing: it mints a session id and points the agent's inference base URL at a **session-scoped** Opper endpoint, then lets the agent's own SDK speak its native protocol on top. You can wire this up by hand with any OpenAI-, Responses-, or Anthropic-shaped client — no CLI required. + +### The endpoint + +``` +https://api.opper.ai/v3/session/[/:…]/ +``` + +- **``** — a stable id of the form `sess_` (e.g. `sess_3c0a79fd-e8e1-49c5-bc19-62ddd85f00c7`). Reuse the same id for every call in one logical run to group them into a single session. The server validates the format — an id that doesn't start with `sess_` is rejected with `400 {"error":"invalid session id"}`. +- **`:`** — optional attribution tags, added as extra path segments (e.g. `/team:growth/env:prod`). URL-encode values; keep keys to `[A-Za-z][A-Za-z0-9_.-]*` and avoid the reserved `opper.` prefix. +- **``** — whatever path your client's SDK already appends. It also selects the compatibility shape: + +| Client speaks | SDK appends | Full session URL | +|---|---|---| +| OpenAI Chat Completions | `/chat/completions` | `…/v3/session//chat/completions` | +| OpenAI Responses | `/responses` | `…/v3/session//responses` | +| Anthropic Messages | `/v1/messages` | `…/v3/session//v1/messages` | + +It's the same behaviour as the `/v3/compat/...` endpoints, just scoped to a session: the `/v3/session/` prefix takes the place of `/v3/compat`, and the native tail still picks the wire shape. + +### Auth + +Standard Opper bearer token, identical on every shape: + +``` +Authorization: Bearer $OPPER_API_KEY +``` + +(Anthropic SDKs default to `x-api-key` — set `Authorization` explicitly, or use `ANTHROPIC_AUTH_TOKEN`.) + +### Example — a raw call, no CLI + +```bash +SID="sess_$(uuidgen | tr '[:upper:]' '[:lower:]')" + +curl -s "https://api.opper.ai/v3/session/$SID/chat/completions" \ + -H "Authorization: Bearer $OPPER_API_KEY" \ + -H "Content-Type: application/json" \ + -d '{ + "model": "openai/gpt-4o-mini", + "messages": [{"role": "user", "content": "Hello"}] + }' +``` + +The response is an ordinary chat completion, with `cost`, `usage`, and a `meta.trace_uuid` for the call. Every request you send to the same `$SID` — any model, any wire shape — lands in that one session. + +### Point any agent at it + +Set the agent's base URL to the session endpoint (without the native path — the SDK adds that) and use your Opper key: + +```bash +SID="sess_$(uuidgen | tr '[:upper:]' '[:lower:]')" + +# OpenAI-shaped agents (OpenCode, Hermes, Pi, …) +export OPENAI_BASE_URL="https://api.opper.ai/v3/session/$SID" +export OPENAI_API_KEY="$OPPER_API_KEY" + +# Anthropic-shaped agents (Claude Code) +export ANTHROPIC_BASE_URL="https://api.opper.ai/v3/session/$SID" +export ANTHROPIC_AUTH_TOKEN="$OPPER_API_KEY" +``` + +That is exactly what `opper launch` does for you — plus a fresh id per run and an end-of-session cost summary. + ## Ask — built-in support agent `opper ask ""` runs an Opper agent grounded on the locally-installed Opper skills (see below). Useful for "how do I…" questions about the platform, SDKs, or the CLI itself. From 20de977d8302ea2396898dbe36fc9f6dfe7210c0 Mon Sep 17 00:00:00 2001 From: Johnny Chadda Date: Wed, 1 Jul 2026 15:26:52 +0200 Subject: [PATCH 2/3] docs: don't imply OpenCode/Hermes/Pi read OPENAI_* env vars The manual "point a client at it" example listed OpenCode, Hermes, and Pi next to OPENAI_BASE_URL/OPENAI_API_KEY, but those adapters take the base URL from their own provider config files, not those env vars. Split the section into env-var clients (generic OpenAI SDKs, Claude Code) and config-file agents (OpenCode, Hermes, Pi, OpenClaw) so the manual setup actually routes. Addresses Codex review feedback. Claude-Session: https://claude.ai/code/session_01Dd669tGULj45v4CaKBAvGU --- README.md | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 722220b..008c700 100644 --- a/README.md +++ b/README.md @@ -140,23 +140,27 @@ curl -s "https://api.opper.ai/v3/session/$SID/chat/completions" \ The response is an ordinary chat completion, with `cost`, `usage`, and a `meta.trace_uuid` for the call. Every request you send to the same `$SID` — any model, any wire shape — lands in that one session. -### Point any agent at it +### Point a client at it -Set the agent's base URL to the session endpoint (without the native path — the SDK adds that) and use your Opper key: +Set the client's base URL to the session endpoint (without the native path — the SDK adds that) and use your Opper key. How you set it depends on the client: + +**Env-var clients** — any OpenAI-compatible SDK, and env-var-driven agents like Claude Code, read the base URL from the environment: ```bash SID="sess_$(uuidgen | tr '[:upper:]' '[:lower:]')" -# OpenAI-shaped agents (OpenCode, Hermes, Pi, …) +# OpenAI-compatible SDKs / clients export OPENAI_BASE_URL="https://api.opper.ai/v3/session/$SID" export OPENAI_API_KEY="$OPPER_API_KEY" -# Anthropic-shaped agents (Claude Code) +# Claude Code (Anthropic-shaped) export ANTHROPIC_BASE_URL="https://api.opper.ai/v3/session/$SID" export ANTHROPIC_AUTH_TOKEN="$OPPER_API_KEY" ``` -That is exactly what `opper launch` does for you — plus a fresh id per run and an end-of-session cost summary. +**Config-file agents** — OpenCode, Hermes, Pi, and OpenClaw don't read those env vars; they take the base URL from their own provider config (`opencode.json`, Hermes' `base_url`, `~/.pi/agent/models.json`, …). Point that provider's base URL at `https://api.opper.ai/v3/session/` and use your Opper key. + +Either way, that is exactly what `opper launch` does for you — plus a fresh id per run and an end-of-session cost summary. ## Ask — built-in support agent From 46b01a403789ce61cd1ece3fc1aae1c29d1c64f4 Mon Sep 17 00:00:00 2001 From: Johnny Chadda Date: Wed, 1 Jul 2026 15:31:53 +0200 Subject: [PATCH 3/3] docs: carve Claude Desktop out of the per-launch session claim The prose claimed every `opper launch` runs inside a fresh session, but Claude Desktop is the documented exception (persistent /v3/compat GUI profile, ignores routing.baseUrl). Qualify both the Agents intro and the session-routing section opener so users don't expect per-launch session grouping for Desktop. Addresses Codex review feedback. Claude-Session: https://claude.ai/code/session_01Dd669tGULj45v4CaKBAvGU --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 008c700..5e49471 100644 --- a/README.md +++ b/README.md @@ -52,7 +52,7 @@ Key resolution at request time: `OPPER_API_KEY` env var > the slot named by `--k ## Agents -`opper launch ` starts a supported AI agent with its model traffic transparently routed through Opper. Pass-through args after the agent name go straight to the agent's CLI. Each launch runs inside a fresh Opper **session** so every call the agent makes is grouped together for tracing and cost — see [Routing through a session without the CLI](#routing-through-a-session-without-the-cli) to wire that up by hand. After the session, the CLI prints a summary with duration, model, and a traces link. +`opper launch ` starts a supported AI agent with its model traffic transparently routed through Opper. Pass-through args after the agent name go straight to the agent's CLI. Each launch — except Claude Desktop (see the table below) — runs inside a fresh Opper **session** so every call the agent makes is grouped together for tracing and cost — see [Routing through a session without the CLI](#routing-through-a-session-without-the-cli) to wire that up by hand. After the session, the CLI prints a summary with duration, model, and a traces link. ```bash opper agents list # NAME / DISPLAY / KIND / STATE / CONFIG / COMMAND @@ -94,7 +94,7 @@ This is the non-interactive equivalent of the menu's "Remove Opper integration" ## Routing through a session without the CLI -`opper launch` is a thin convenience wrapper. Under the hood it does one thing: it mints a session id and points the agent's inference base URL at a **session-scoped** Opper endpoint, then lets the agent's own SDK speak its native protocol on top. You can wire this up by hand with any OpenAI-, Responses-, or Anthropic-shaped client — no CLI required. +For every launchable agent except Claude Desktop, `opper launch` is a thin convenience wrapper. Under the hood it does one thing: it mints a session id and points the agent's inference base URL at a **session-scoped** Opper endpoint, then lets the agent's own SDK speak its native protocol on top. You can wire this up by hand with any OpenAI-, Responses-, or Anthropic-shaped client — no CLI required. (Claude Desktop is the exception — it rewires a persistent `/v3/compat` GUI profile instead, so it doesn't get a per-launch session.) ### The endpoint