Skip to main content
skill CX Codex

venice-embeddings — Claude Code skill: what it does, how to install

Guides AI agents through querying the Venice POST /api/v1/embeddings endpoint, handling strict schemas, and batching texts properly.

Install into Claude Code · Skills CLI (Vercel) All methods and platforms ↓
npx skills add veniceai/skills --skill venice-embeddings -a claude-code
Open on GitHub

What venice-embeddings does

This skill instructs coding agents on requesting vector embeddings from Venice. The endpoint matches OpenAI's format at https://api.venice.ai/api/v1, allowing standard SDK clients to run without custom wrappers. Venice enforces strict payload validation; unknown keys such as input_type or truncate trigger an immediate 400 status.

Token-ID arrays are rejected by the API. If you use LangChain's OpenAIEmbeddings, you must set check_embedding_ctx_length=False because it tokenizes text into numbers beforehand. Requests accept up to 2048 strings per batch, with each item capped at 8192 estimated tokens.

What it helps with

  • generate vector embeddings for RAG and search pipelines
  • configure OpenAI SDK and LangChain to hit Venice endpoints
  • batch text embedding requests up to 2048 items safely

Example prompts for the agent

  • Write a TypeScript batch embedding helper for Venice using text-embedding-bge-m3.
  • Configure LangChain OpenAIEmbeddings for Venice without triggering 400 token array errors.
  • Draft a curl command to call Venice embeddings with base64 encoding and compression.

How to install venice-embeddings

1Skills CLI (Vercel)

npx skills add veniceai/skills --skill venice-embeddings -a claude-code

2Manually: put the files in place

~/.claude/skills/venice-embeddings/SKILL.md

Copy the whole skill folder; for one project use .claude/skills/venice-embeddings/

Step by step, with commands for each platform: How to install skills in Claude Code: five ways

Questions about venice-embeddings

How to install venice-embeddings in Claude Code?

Run npx skills add veniceai/skills --skill venice-embeddings -a claude-code. Alternatively, place the file manually at ~/.claude/skills/venice-embeddings/SKILL.md.

What does venice-embeddings do?

It gives the agent exact schema details, limits, and code patterns for calling POST /api/v1/embeddings on Venice.

Why does LangChain fail with a 400 error on Venice?

LangChain converts text into numeric token arrays by default, which Venice rejects. Pass check_embedding_ctx_length=False to keep inputs as raw strings.

Source text

SKILL.md · MIT
---
name: venice-embeddings
description: Call POST /embeddings on Venice. Covers request shape (input, model, encoding_format, dimensions, user), text-only input (token arrays rejected), per-input and batch limits, per-model dimensions/privacy, the text-embedding-ada-002 alias, API-key privacy gating, OpenAI/LangChain compatibility, response compression (gzip/br), and practical usage for retrieval, clustering, and RAG.
---

# Venice Embeddings

`POST /api/v1/embeddings` returns vector embeddings for strings. It's OpenAI-compatible: request and response match `https://api.openai.com/v1/embeddings` closely enough that the OpenAI SDK works with `baseURL: "https://api.venice.ai/api/v1"`, with one exception: **token-ID arrays are not accepted** (see below).

Auth: Bearer API key or x402 wallet (`SIGN-IN-WITH-X`) — see [`venice-auth`](../venice-auth/SKILL.md).

## Use when

- You're building retrieval / RAG / similarity search.
- You need text clustering, classification, deduplication, or reranking features.
- You want embeddings from a model Venice runs as **Private** (most of the catalog) rather than an anonymized third-party one — check `model_spec.privacy` on each model.

Text-only: `input` must be a string or an array of strings. For images, run them through a vision chat model and embed the description.

## Minimal request

```bash
curl https://api.venice.ai/api/v1/embeddings \
  -H "Authorization: Bearer $VENICE_API_KEY" \
  -H "Content-Type: application/json" \
  --compressed \
  -d '{
    "model": "text-embedding-bge-m3",
    "input": "Why is the sky blue?"
  }'
```

```json
{
  "object": "list",
  "model": "text-embedding-bge-m3",
  "data": [
    { "object": "embedding", "index": 0, "embedding": [0.0023, -0.0093, 0.0158, ...] }
  ],
  "usage": { "prompt_tokens": 8, "total_tokens": 8 }
}
```

## Request schema

The body is **strict** — unknown top-level fields (e.g. `input_type`, `task`, `truncate`) are rejected with `400`.

| Field | Type | Notes |
|---|---|---|
| `model` | string | **Required.** Model ID from `GET /models?type=embedding`. `text-embedding-ada-002` is accepted as an alias for `text-embedding-bge-m3` (the response `model` then reads `text-embedding-bge-m3`). |
| `input` | string \| string[] | **Required.** A non-empty string, or an array of 1–2048 strings. Token-ID arrays (`number[]` / `number[][]`) are rejected with `400` — see Gotchas. |
| `encoding_format` | `"float"` \| `"base64"` | Default `"float"`. `"base64"` returns each vector as a base64-encoded string — a much smaller payload; decode client-side. |
| `dimensions` | integer ≥ 1 | Optional. Requested output size. Only honoured by models whose `model_spec.supportsCustomDimensions` is `true`; it is forwarded as-is otherwise, and the provider may ignore or reject it. |
| `user` | string | Accepted for OpenAI compatibility; not used for inference, but it does split the error budget per value (see [`venice-errors`](../venice-errors/SKILL.md#error-budget)). |

### Input limits

- **Per item:** Venice estimates tokens as `ceil(chars / 3.2 × 0.95)` and rejects any string over **8192** estimated tokens (≈ 27,500 characters) with `400 "Input text exceeds the maximum token limit of 8192 tokens"`. This cap is the same for every model, including those whose `maxInputTokens` is 32768.
- **Model limit:** models with a smaller `model_spec.maxInputTokens` (e.g. 512 for `text-embedding-multilingual-e5-large-instruct`, 2048 for `gemini-embedding-2-preview`) enforce that limit themselves; Venice's pre-check does not. Chunk to the model's `maxInputTokens`.
- **Batch:** at most **2048** strings per request. Venice returns one embedding per element, in order, with matching `index`.

## Response headers & compression

Send `Accept-Encoding: gzip, br` (curl: `--compressed`; most HTTP clients decode automatically); the response comes back with `Content-Encoding` set. For large batches this matters — float vectors in JSON are big.

Also returned:

- `x-ratelimit-limit-*` / `x-ratelimit-remaining-*` / `x-ratelimit-reset-*` (`requests`, `tokens`) — see [`venice-errors`](../venice-errors/SKILL.md).
- `x-venice-balance-usd` / `x-venice-balance-diem` — current balance, when non-zero.
- `X-Balance-Remaining` — listed in the spec for x402 callers but not currently set by the server; poll `GET /x402/balance/{walletAddress}` instead.

## Using the OpenAI SDK

```ts
import OpenAI from 'openai'

const client = new OpenAI({
  apiKey: process.env.VENICE_API_KEY,
  baseURL: 'https://api.venice.ai/api/v1',
})

const res = await client.embeddings.create({
  model: 'text-embedding-bge-m3',
  input: ['first doc', 'second doc'],
})

const vec0 = res.data[0].embedding
```

The OpenAI Node SDK asks for `base64` when you omit `encoding_format` and decodes it client-side. Venice forwards `encoding_format` to the model; if the decoded vectors look wrong, pass `encoding_format: 'float'` explicitly.

### LangChain

LangChain's `OpenAIEmbeddings` tokenizes input and sends **token arrays** by default, which Venice rejects. Turn that off:

```python
import os
from langchain_openai import OpenAIEmbeddings

emb = OpenAIEmbeddings(
    model="text-embedding-bge-m3",
    base_url="https://api.venice.ai/api/v1",
    api_key=os.environ["VENICE_API_KEY"],
    check_embedding_ctx_length=False,
)
```

Wrappers that build `OpenAIEmbeddings` internally without that flag (e.g. gpt-researcher's `openai` provider) hit the same `400`.

## Batch-embedding pattern

```ts
async function embedBatch(texts: string[], batchSize = 64) {
  const out: number[][] = []
  for (let i = 0; i < texts.length; i += batchSize) {
    const slice = texts.slice(i, i + batchSize)
    const res = await client.embeddings.create({
      model: 'text-embedding-bge-m3',
      input: slice,
      encoding_format: 'float',
    })
    for (const row of res.data) out[i + row.index] = row.embedding
  }
  return out
}
```

- Keep each string under the per-item limits above; batch size is capped at 2048.
- On `429`, back off exponentially and halve the batch — see [`venice-errors`](../venice-errors/SKILL.md).

## Choosing a model

Query `GET /models?type=embedding` for the current catalog. Each entry's `model_spec` exposes:

- `embeddingDimensions` — native output dimension (e.g. 1024 for `text-embedding-bge-m3`, 4096 for `text-embedding-qwen3-8b`).
- `maxInputTokens` — the model's per-input token limit.
- `supportsCustomDimensions` — present and `true` only on models that honour `dimensions` (absent otherwise).
- `privacy` — `"private"` (no retention) or `"anonymized"` (a third-party model; the request is sent without your identity).
- `pricing.input` / `pricing.output` — `{ usd, diem }` per **million** tokens.

Representative IDs: `text-embedding-bge-m3` (private, 1024-d), `text-embedding-qwen3-8b` (private, 4096-d, custom dimensions), `text-embedding-multilingual-e5-large-instruct` (private, 512-token inputs), `text-embedding-3-small` / `text-embedding-3-large` (anonymized, OpenAI, custom dimensions), `gemini-embedding-2-preview` (anonymized, custom dimensions). The list changes — always read it from `/models`.

Always pin the model ID — cosine distances are **not** comparable across different embedding models.

## Error handling

| Code | Meaning |
|---|---|
| `400` | Missing `model`, or a validation error (`details` names the field): token-array input, empty string/array, > 2048 items, item over the 8192-token estimate, unknown field. Non-JSON `Content-Type` → `"'Content-Type' must be 'application/json'"`. Also model-side rejections (e.g. input over the model's own limit), returned with the model's message when one can be extracted, otherwise a generic `"Invalid request parameters…"`. |
| `401` | Invalid API key or SIWX signature. |
| `402` | Insufficient balance or the key's USD/DIEM spend limit reached. Bearer → `"Insufficient USD or Diem balance…"`; x402 → payment-required body + `PAYMENT-REQUIRED` header. A request with **no** credentials at all also gets `402` (x402 discovery challenge), not `401`. |
| `403` | The API key's `modelPrivacy` is `PRIVATE_TEXT` or `PRIVATE_ONLY` and the model is `anonymized`. Also region / provider restrictions, or API access disabled for the account. |
| `404` | Unknown model (the message may suggest a close match). |
| `429` | Rate limited. |
| `500` | Inference failed; retry with jitter. |
| `503` | Model temporarily offline; retry later. |

## Gotchas

- **Token arrays are rejected.** `input: [101, 2023, ...]` or `[[101, ...]]` returns `400 "Token array inputs are not supported. Pass a string or an array of strings."` Send text.
- **API-key privacy applies to embeddings.** A key with `modelPrivacy: PRIVATE_TEXT` (or `PRIVATE_ONLY`) can only call `private` embedding models; `text-embedding-3-*` and `gemini-embedding-2-preview` return `403`. See [`venice-api-keys`](../venice-api-keys/SKILL.md).
- A top-level empty string is rejected with `400`, but empty strings *inside* an array are not pre-checked — filter them out yourself.
- The request must be `Content-Type: application/json`; anything else is rejected with `400 "'Content-Type' must be 'application/json'"` before auth or validation runs.
- Whether returned vectors are L2-normalized depends on the model — verify with `Math.hypot(...v) ≈ 1` before assuming.
- For RAG, store `model` (and `dimensions`, if set) alongside each vector so you can re-embed on upgrade.

© veniceai · MIT · veniceai/skills

Similar skills

All skills for AI and ML →

From the same set23

venice-models This skill documents the Venice API endpoints for picking a model: what each one supports, what it costs, and where it is blocked. CX Codex +1 ★ 160repo stars venice-image-generate Equips AI coding agents to generate images using Venice API endpoints, control style references, seeds, and generate up to four variants in one request. CX Codex +1 ★ 160repo stars venice-image-edit This skill guides an agent through editing images with Venice, combining inputs, upscaling, and removing backgrounds. Use it when a task starts with an existing image. CX Codex +1 ★ 160repo stars venice-errors A skill that maps Venice API error bodies and retry rules so your agent stops burning the per-key error budget. Built for anyone writing a Venice client. CX Codex +1 ★ 160repo stars venice-decisions This skill sends a state and typed questions to Venice, returning probabilities, selections, or scores for code-driven decisions instead of prose. CX Codex +1 ★ 160repo stars venice-crypto-rpc Points your agent at Venice for pay-per-call JSON-RPC across 27 EVM, Starknet and Solana networks. CX Codex +1 ★ 160repo stars venice-chat Enables your agent to interact with Venice's POST /api/v1/chat/completions endpoint. It helps configure web search, reasoning effort, and structured outputs. CX Codex +1 ★ 160repo stars venice-characters Use Venice’s public character API to search personas, inspect reviews, and apply a character to a chat request. Useful for building a character picker or preset personas into an app. CX Codex +1 ★ 160repo stars

Project sponsors

Companies that keep this analytics open
Gold sponsor

Impressions, clicks and code copies — open statistics. We keep the numbers public for the same reason NeBlask itself is public. Become a sponsor