Embedding Batch Planner
knowledge.generate_embeddings_batch_plan
Overview
Plan the requests, do not send them. You give us the items you intend to embed — each with its text or with a token count you already have — plus your provider's limits, and we hand back which item goes in which request, how many tokens each request carries, and which items are too large for any request at all. Nothing is embedded, no provider is called and no vector comes back; the answer is a grouping of your identifiers. Every item lands in exactly one batch or in the oversized list, so a plan never quietly loses work. Two packing modes are available: fill requests in order, or pack largest-first to need fewer requests at the cost of the original order. Reach for context.pack_chunks instead when you want to select a subset for one context window rather than partition a whole corpus across many requests.
Embedding providers cap both the tokens and the items in one request, and discovering that mid-run means a half-embedded corpus and a retry you cannot resume cleanly. Planning the requests first turns that into an answer you can inspect, store and replay.
Reliability
The same items, limits and tokenizer version always produce the same plan, ties included, because every ordering ends at the id. Counts measured from text come from the pinned tokenizer whose version comes back in the summary; a tokenizer upgrade can shift an item between requests, which is why we tell you which version did the counting. Counts you supplied are trusted untouched. Failures, none of which get better on their own: BATCH_ITEMS_INVALID means items was empty, an entry was not an object, an id was missing, blank or over 256 characters, a tokenCount was not an integer in range, or an entry carried a property we do not accept — fix the entry named in the error and retry; BATCH_ITEM_ID_DUPLICATE means two entries share an id, and the error says which position repeated it; BATCH_ITEM_TOKENS_MISSING means an entry has neither text nor tokenCount — add one of them; BATCH_MODEL_LIMITS_INVALID means maxTokensPerRequest was missing, a limit was outside its range, or modelLimits carried a property we do not accept; BATCH_LIMIT_EXCEEDED means you sent more than 20000 items, an item text was over 200000 characters, or the ids alone would fill the response — plan the corpus in parts; BATCH_REQUEST_LIMIT_EXCEEDED means the plan needs more requests than modelLimits.maxRequests allows, and the error carries the number actually needed so you can raise the cap or split the corpus; BATCH_TOKENIZER_UNSUPPORTED means the encoding you named is not one we have, and the supported list comes back with the error.
Context footprint
The response carries ids, counts and reason codes only, never your text. Up to 20000 ids come back across the batches, and a request whose ids alone would exceed 1000000 characters is refused rather than answered. A successful call costs 1 execution credit.
When to use it
Before an embedding run, once you know your items and your provider's limits.
When you want the vectors themselves, or when you want to choose which chunks to keep rather than how to group all of them.
Powered by JTokkit, an open-source tokenizer reproducing OpenAI tiktoken encodings, with Squillify's own partitioning and limit rules on top.
Scope
Non-goals
- Does not compute, request or store an embedding vector
- Does not call an embedding provider or any other endpoint
- Does not select a subset — every item is planned or reported as oversized
- Does not truncate an oversized item to make it fit
- Does not return the text you sent, only your ids
Properties
Capabilities
Cost & billing
Flat rate per invocation
File handling
How we handle your data
What this means
This skill may receive sensitive content, but it does not target sensitive data and returns only a structured non-sensitive result.
Squillify guarantees
- Runs inside Squillify
- This skill runs inside Squillify.
- Payloads are not sent to an external service by this skill.
- Squillify does not permanently store submitted payloads.
- Telemetry records metadata only, not submitted content.
- Submitted payloads are not used for training.
- Submitted payloads are not reviewed by humans.
- This skill does not target sensitive data.
- The response does not contain submitted content.
Your responsibility
Squillify does not determine whether submitted content is sensitive. Your application is responsible for deciding what data it is allowed to submit. Your application is responsible for securing the response.
Input schema
| Field | Type | Required | Description |
|---|---|---|---|
| items | array | Yes | From 1 through 20000 closed items {id} plus text or tokenCount, never neither. |
| modelLimits | object | Yes | Closed provider ceilings: required maxTokensPerRequest plus optional maxItemsPerRequest, maxTokensPerItem and maxRequests. |
| tokenizer | string | No | Encoding used when counting from text; omit it for cl100k_base. |
| ordering | string | No | Sequence items are considered in; omit it for INPUT_ORDER. |
| packing | string | No | How items fill requests; omit it for SEQUENTIAL. |
Output schema
| Field | Type | Required | Description |
|---|---|---|---|
| batches | array | Yes | One closed planned request per batch, empty when every item was oversized. |
| oversized | array | Yes | Items no single request can carry, each a closed {id, tokenCount, reasonCode} object; empty when everything fits. |
| summary | object | Yes | Closed plan receipt with batchCount, itemCount, totalTokens, maxBatchTokens, packing, ordering, tokenizer and tokenizer_version. |
API contract
POST /v1/executecurl -sS -X POST "$BASE/v1/execute" -H "Authorization: Bearer $KEY" -H 'Content-Type: application/json' -d '{"skillKey":"knowledge.generate_embeddings_batch_plan","input":{"items":[{"id":"c1","tokenCount":420},{"id":"c2","text":"Second chunk."}],"modelLimits":{"maxTokensPerRequest":8191,"maxItemsPerRequest":2048},"packing":"SEQUENTIAL"}}'import { Squillify } from "@squillify/sdk";
const sq = new Squillify({ apiKey: process.env.SQUILLIFY_API_KEY });
const { output } = await sq.execute("knowledge.generate_embeddings_batch_plan", {"items":[{"id":"chunk-1","text":"We refund an unused subscription within 30 days."},{"id":"chunk-2","text":"A refund needs the original order id."},{"tokenCount":40,"id":"chunk-3"}],"modelLimits":{"maxTokensPerItem":32,"maxTokensPerRequest":32,"maxItemsPerRequest":2}});Errors
| Code | HTTP | Retryable | Description |
|---|---|---|---|
| VALIDATION_ERROR | 400 | No | The request payload failed schema validation. |
| UNAUTHORIZED | 401 | No | Missing or invalid API key. |
| SKILL_NOT_ACCESSIBLE | 403 | No | The API key is not granted access to this skill. |
| SKILL_NOT_AVAILABLE_FOR_PLAN | 403 | No | This skill is not included in your current plan. |
| PLAN_ELIGIBILITY_UNAVAILABLE | 503 | Yes | Plan eligibility could not be decided. Retry after backoff. |
| SKILL_NOT_FOUND | 404 | No | The requested skill or version does not exist. |
| TENANT_RATE_LIMITED | 429 | Yes | Request rate limit exceeded. Retry after backoff. |
| QUOTA_EXCEEDED | 429 | Yes | Plan quota exhausted. Retryable once the quota period resets. |
| EXECUTION_TIMEOUT | 504 | Yes | Execution exceeded the allowed time budget. |
| BATCH_ITEMS_INVALID | 400 | No | The request payload failed this skill's input validation. |
| BATCH_ITEM_ID_DUPLICATE | 400 | No | The request payload failed this skill's input validation. |
| BATCH_ITEM_TOKENS_MISSING | 400 | No | The request payload failed this skill's input validation. |
| BATCH_MODEL_LIMITS_INVALID | 400 | No | The request payload failed this skill's input validation. |
| BATCH_LIMIT_EXCEEDED | 429 | No | A size, quota, rate, or time limit was exceeded. |
| BATCH_REQUEST_LIMIT_EXCEEDED | 429 | No | A size, quota, rate, or time limit was exceeded. |
| BATCH_TOKENIZER_UNSUPPORTED | 400 | No | The skill does not support the requested variant. |
Other limits
| Limit | Value |
|---|---|
| Recommended inline bytes | 32 KiB |
Limitations
- Does not compute, request or store an embedding vector
- Does not call an embedding provider or any other endpoint
- Does not select a subset — every item is planned or reported as oversized
- Does not truncate an oversized item to make it fit
- Does not return the text you sent, only your ids
- Getting embeddings — nothing here calls a model
- Selecting the best chunks for one context window, which context.pack_chunks does
- Planning a corpus you have not sized: an item needs text or a token count
How to call
POST /v1/execute (requires authentication)
{
"skillKey": "knowledge.generate_embeddings_batch_plan",
"input": {
"items": [
{
"id": "chunk-1",
"text": "We refund an unused subscription within 30 days."
},
{
"id": "chunk-2",
"text": "A refund needs the original order id."
},
{
"tokenCount": 40,
"id": "chunk-3"
}
],
"modelLimits": {
"maxTokensPerItem": 32,
"maxTokensPerRequest": 32,
"maxItemsPerRequest": 2
}
}
}Examples
Two limits binding at once, and one item too large to embed
{
"items": [
{
"id": "chunk-1",
"text": "We refund an unused subscription within 30 days."
},
{
"id": "chunk-2",
"text": "A refund needs the original order id."
},
{
"tokenCount": 40,
"id": "chunk-3"
}
],
"modelLimits": {
"maxTokensPerItem": 32,
"maxTokensPerRequest": 32,
"maxItemsPerRequest": 2
}
}{
"batches": [
{
"index": 0,
"itemIds": [
"chunk-1",
"chunk-2"
],
"itemCount": 2,
"tokenCount": 18
}
],
"summary": {
"batchCount": 1,
"itemCount": 3,
"totalTokens": 58,
"maxBatchTokens": 18,
"packing": "SEQUENTIAL",
"ordering": "INPUT_ORDER",
"tokenizer": "cl100k_base",
"tokenizer_version": "jtokkit-1.1.0"
},
"oversized": [
{
"id": "chunk-3",
"tokenCount": 40,
"reasonCode": "EXCEEDS_MAX_TOKENS_PER_ITEM"
}
]
}Largest-first packing needing fewer requests than filling in order
{
"modelLimits": {
"maxTokensPerRequest": 100
},
"items": [
{
"tokenCount": 60,
"id": "a"
},
{
"tokenCount": 60,
"id": "b"
},
{
"tokenCount": 40,
"id": "c"
},
{
"tokenCount": 40,
"id": "d"
}
],
"packing": "FIRST_FIT_DECREASING"
}{
"batches": [
{
"index": 0,
"itemIds": [
"a",
"c"
],
"itemCount": 2,
"tokenCount": 100
},
{
"index": 1,
"itemIds": [
"b",
"d"
],
"itemCount": 2,
"tokenCount": 100
}
],
"summary": {
"batchCount": 2,
"itemCount": 4,
"totalTokens": 200,
"maxBatchTokens": 100,
"packing": "FIRST_FIT_DECREASING",
"ordering": "INPUT_ORDER",
"tokenizer": "cl100k_base",
"tokenizer_version": "jtokkit-1.1.0"
},
"oversized": []
}Recommended use cases
- Turn the chunks of a document set into the exact embedding requests to send
- Check whether a corpus fits a provider's request quota before starting a run
- Find the items that need splitting before an embedding job, not during it
Avoid for
- Getting embeddings — nothing here calls a model
- Selecting the best chunks for one context window, which context.pack_chunks does
- Planning a corpus you have not sized: an item needs text or a token count
Related skills
Composable with
Safety & privacy
- Runs without calling any external service.
- Your payloads are never stored permanently.
- Telemetry captures metadata only — never your payload contents.
- We never train models on your payloads.
- No human reviews your payloads.