AgentStack
Browse Sign in
Browse Why AgentStack Sell Docs
Sign in
SKILL verified Apache-2.0 Self-run

Agentproto Llm Endpoint

skill-agentproto-ts-agentproto-llm-endpoint · by agentproto

A Claude skill from agentproto/ts.

No reviews yet
0 installs
33 views
0.0% view→install

Install

$ agentstack add skill-agentproto-ts-agentproto-llm-endpoint

✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.

Verified badge

Passed review? Show it. Paste this badge into your README, it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/skill-agentproto-ts-agentproto-llm-endpoint)

Reliability & compatibility

Security review passed
0 installs to date
no reviews yet
1mo ago

Declared compatibility

Claude CodeClaude Desktop

Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work →
Are you the author of Agentproto Llm Endpoint? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

When to use

  • "Route Claude through OpenRouter / Moonshot / Groq / ZAI / xAI"
  • "Use the local LLM proxy" or "point Claude at my gated LLM endpoint"
  • "Why is my model codename rejected?"
  • "Claude Code vs Claude SDK with custom endpoints"
  • Spawn failures: "Invalid API key", "model does not exist", empty turns

The proxy

The LLM endpoint proxy lives in projects/agentproto/ts/packages/llm-endpoint. It exposes an Anthropic-compatible /v1/messages endpoint and maps "secret codenames" to real provider models.

Codename → provider mapping

| Code | Provider | Real model | Claude equivalent | | ----------- | ---------- | ------------------------------- | ------------------- | | jupiter-7 | Moonshot | kimi-k2.7-code | claude-opus-4-8 | | mars-6 | Moonshot | kimi-k2.6 | claude-3-opus | | saturn-5 | OpenRouter | deepseek/deepseek-v4-pro | claude-sonnet-5 | | neptune-4 | OpenRouter | anthropic/claude-sonnet-4.6 | claude-sonnet-4-6 | | uranus-8 | OpenRouter | google/gemini-3.1-pro-preview | claude-fable-5 | | mercury-9 | OpenRouter | z-ai/glm-5.2 | claude-3-haiku | | halley-1 | OpenRouter | deepseek/deepseek-v4-flash | claude-fable-4 | | orion-2 | OpenRouter | xiaomi/mimo-v2.5 | claude-opus-4-6 | | pegasus-3 | OpenRouter | minimax/minimax-m3 | claude-opus-4-9 | | lyra-4 | OpenRouter | tencent/hy3-preview | claude-opus-4-7 | | vega-5 | OpenRouter | stepfun/step-3.7-flash | claude-sonnet-4-5 | | venus-3 | ZAI | glm-5.2 | claude-3-5-fable | | pluto-2 | Groq | qwen/qwen3.6-27b | claude-haiku-4-5 | | atlas-6 | Groq | llama-3.3-70b-versatile | claude-3-5-sonnet | | titan-7 | Groq | openai/gpt-oss-120b | claude-sonnet-4-7 | | nova-1 | xAI | grok-4.5 | claude-opus-4-8 | | pulsar-2 | xAI | grok-3.5 | claude-sonnet-5 |

Running the proxy locally

# From repo root
pnpm --filter=@agentproto/llm-endpoint start
# → listens on http://localhost:18090/v1

Env vars the proxy reads:

  • MOONSHOT_API_KEY — Moonshot native /anthropic endpoint
  • OPENROUTER_API_KEY — OpenRouter (OpenAI-compatible adapter)
  • ZHIPUAI_API_KEY or ZAI_API_KEY — ZAI (OpenAI-compatible adapter)
  • GROQ_API_KEY — Groq (OpenAI-compatible adapter, 128-tool max)

The proxy adapts Anthropic Messages format to OpenAI Chat Completions for OpenRouter/ZAI/Groq. Moonshot exposes a native /anthropic endpoint and needs no adaptation.

Client config

Base URL:   http://localhost:18090/v1   (local), or your own gated public origin
API key:    local  → any non-empty value (e.g. AAAA); the proxy injects the real
                     upstream key server-side and, ungated, does not check it
            public → Authorization: Bearer 
                     (set LLM_ENDPOINT_ACCESS_TOKENS on the proxy; a missing or
                      unlisted token returns 401 — the upstream key stays server-side)

The proxy accepts ?m= query param override and ?p= override.

Adapter-specific behaviors

Claude SDK (claude-sdk adapter) — RECOMMENDED for proxy

  • Model validation: NONE. Passes any model string directly to the SDK.
  • How model is sent: --model CLI arg → SDK options.model.
  • Base URL: Set via options.base_urlANTHROPIC_BASE_URL env.
  • Auth: ANTHROPIC_API_KEY env (set via --auth api-key).

Working spawn via MCP:

{
  "adapter": "claude-sdk",
  "auth": { "mode": "api-key" },
  "model": "neptune-4",
  "options": { "base_url": "http://localhost:18090/v1" },
  "prompt": "..."
}

Working spawn via CLI:

# DOES NOT WORK — CLI has no --base-url flag
agentproto sessions start claude-sdk --model neptune-4 --auth api-key

# WORKAROUND: set env vars before the CLI command
ANTHROPIC_BASE_URL=http://localhost:18090/v1 \
ANTHROPIC_API_KEY=AAAA \
agentproto sessions start claude-sdk --model neptune-4 --prompt "..."

Claude Code (claude-code adapter) — LIMITED with proxy

  • Model validation: STRICT. The claude binary validates ANTHROPIC_MODEL

against Anthropic's real model list. Proxy codenames (neptune-4, etc.) are rejected before any network request.

  • How model is sent: ANTHROPIC_MODEL env var (set via options.model

adapter manifest env: { ANTHROPIC_MODEL: "{value}" }). The ACP wrapper applies it via session/set_config_option(configId: "model") with best-effort fallback to default on rejection.

  • Base URL: Set via options.base_urlANTHROPIC_BASE_URL env.
  • Auth: ANTHROPIC_API_KEY env (api-key mode) or CLAUDE_CODE_OAUTH_TOKEN

(subscription mode).

Result: claude-code with proxy codenames fails with:

> "There's an issue with the selected model (neptune-4). It may not exist or you > may not have access to it."

Workaround: Use claude-sdk instead for proxy access. If you must use claude-code, you are limited to the proxy's regex fallback mappings:

| Model you send | Proxy routes to | | ------------------ | ------------------------------------- | | claude-sonnet-5 | openrouter:deepseek/deepseek-v4-pro | | claude-opus-4-8 | moonshot:kimi-k2.7-code | | claude-fable-5 | moonshot:kimi-k2.7-code | | claude-haiku-4-5 | groq:llama-3.3-70b |

These are NOT the same as the codename mappings — you lose fine-grained provider/model selection.

Why Claude Desktop works with codenames

Claude Desktop (the app) uses the Claude SDK directly (not the claude binary), and the SDK does not validate model names before sending. When you configure a custom endpoint in Claude Desktop settings, the SDK sends the raw model string to your proxy, which resolves the codename.

Claude Code (the CLI/claude-code adapter) uses the claude binary which has strict model validation — this is why the same codename fails there.

Auth patterns

Direct Anthropic API (subscription or api-key)

{
  "adapter": "claude-code",
  "auth": { "mode": "subscription" },
  "prompt": "..."
}

Subscription mode uses CLAUDE_CODE_OAUTH_TOKEN (bearer token from claude auth login). API-key mode uses ANTHROPIC_API_KEY.

Gateway / proxy (Moonshot, OpenRouter, etc.)

{
  "adapter": "claude-sdk",
  "auth": { "mode": "api-key" },
  "model": "neptune-4",
  "options": {
    "base_url": "http://localhost:18090/v1",
    "auth_token": "AAAA"
  },
  "prompt": "..."
}

The auth_token option sets ANTHROPIC_AUTH_TOKENAuthorization: Bearer.

  • Local (localhost:18090): ungated — any value works (AAAA); the proxy

ignores it and uses its own upstream keys.

  • Public (a gated deployment): when LLM_ENDPOINT_ACCESS_TOKENS is set the

proxy enforces a bearer gate, so auth_token MUST be one of those gate tokens — a shared secret you set once on the provider/adapter config (an unlisted token → 401). The upstream provider key is still injected server-side; the gate token is separate from it. Send it via auth_token (→ Authorization: Bearer) or X-Proxy-Accessnever x-api-key, which the gate ignores.

Per-provider API keys

Stored in ~/.agentproto/providers.json (mode 0600):

{
  "openrouter": { "apiKey": "sk-or-v1-...", "updatedAt": "..." },
  "moonshot": { "apiKey": "sk-...", "updatedAt": "..." },
  "anthropic": { "apiKey": "sk-ant-api03-...", "updatedAt": "..." }
}

Set via: agentproto auth provider set or edit the file directly.

Securing a public deployment (gate env vars)

Opt-in env vars on the proxy (unset = off). Full detail in the package README's "Securing a public deployment".

  • LLM_ENDPOINT_ACCESS_TOKENS — app-gate allow-list (comma-separated). Present a

listed token as Authorization: Bearer or X-Proxy-Access: . x-api-key is NOT accepted.

  • LLM_ENDPOINT_EDGE_TOKENS — second, independent layer via X-Edge-Auth, meant

to be enforced at the edge (Cloudflare WAF) so unauthenticated traffic never reaches the origin; also re-checked in-process.

  • LLM_ENDPOINT_PUBLIC_MODELS=1 — exempts ONLY /v1/models (/models) from the

gates so clients can auto-discover models (e.g. Claude Desktop's launch probe); pack lists stay gated.

llm-endpoint print-waf-rule [--host ] emits the Cloudflare custom-rule expression from the configured token(s) — paste into a Block rule (add a /v1/models carve-out when PUBLIC_MODELS is on).

Common failure modes

"Invalid API key" / "Invalid bearer token"

  • Check ~/.agentproto/providers.json has the right key for the provider.
  • For gateway modes, ensure auth_token is set (not just ANTHROPIC_API_KEY).
  • The claude-code adapter scrubs ANTHROPIC_API_KEY when base_url is set

(to prevent leaking your real Anthropic key to a third-party gateway).

"Model does not exist" / "empty turn"

  • claude-code adapter: you're using a proxy codename. Use claude-sdk

instead.

  • claude-sdk adapter: check ANTHROPIC_BASE_URL is actually set (CLI doesn't

support --base-url; use env var or MCP options.base_url).

  • Proxy not running: curl http://localhost:18090/v1/models should return the

codename list.

"empty turn — no assistant output, no tool call"

  • The proxy received the request but the upstream provider returned nothing.
  • Check proxy logs: tail -f /tmp/llm-endpoint.log
  • Common cause: model name mismatch (proxy regex fallback routed to wrong

provider).

Double /v1/v1/ in proxy paths

The proxy base URL should end with /v1 (e.g., http://localhost:18090/v1). The claude binary appends /v1/messages, resulting in /v1/v1/messages. The proxy handles this, but it's noisy in logs.

Daemon caches old adapter code

The daemon (Node.js) caches require()/import() results. After editing an adapter manifest, restart the daemon:

pkill -f "agentproto serve"
~/.agentproto/start-daemon-local.sh --cli workspace

Quick reference: spawn patterns

| Goal | Adapter | Model | Base URL | Auth | | ------------------------------- | ------------- | ----------------- | --------------------------- | -------------- | | Direct Anthropic (subscription) | claude-code | (default) | (none) | subscription | | Direct Anthropic (API key) | claude-code | (default) | (none) | api-key | | OpenRouter Claude Sonnet 4.6 | claude-sdk | neptune-4 | http://localhost:18090/v1 | api-key | | Moonshot Kimi K2.7 | claude-sdk | jupiter-7 | http://localhost:18090/v1 | api-key | | Groq Llama 3.3 70B | claude-sdk | atlas-6 | http://localhost:18090/v1 | api-key | | Claude Code + proxy (limited) | claude-code | claude-sonnet-5 | http://localhost:18090/v1 | api-key |

See also

  • agentproto skill — general daemon/CLI/MCP usage
  • adapter-setup-kit skill — tunnel creation, adapter catalog
  • projects/agentproto/ts/packages/llm-endpoint — proxy source
  • projects/agentproto/ts/adapters/claude-sdk/src/index.ts — SDK adapter

manifest

  • projects/agentproto/ts/adapters/claude-code/src/index.ts — Code adapter

manifest

Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet, be the first.

Versions

  • v0.1.0 Imported from the upstream source.