Klu Context
A Context is a document library that Klu indexes for retrieval. Attach a Context to an Action to ground generations in your data, or search it directly through the API.
Before you start
You need a workspace API key. To use retrieval in an Action, you also need an Action with the Context attached.
In the app
Use the app when you want to create a Context from a managed integration or upload files interactively. Open your workspace, create a Context, add its sources, wait for processing to finish, and attach it to the relevant Action.
Through the API
Use the API for application-managed text documents, metadata, search, and programmatic file ingestion. All routes below use the same Bearer authentication as the rest of the Klu API.
Create a Context
Call POST /v1/contexts. name and description are required. responseLength and splitterConfig have defaults.
Create a Context
curl 'https://api.klu.ai/v1/contexts' \
--header 'Authorization: Bearer YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data '{
"name": "Product documentation",
"description": "Public product and support content",
"responseLength": 1024,
"splitterConfig": {
"chunkSize": 256,
"chunkOverlap": 10,
"splitter": "token"
}
}'
Response shape
{
"guid": "33333333-3333-4333-8333-333333333333",
"name": "Product documentation",
"description": "Public product and support content",
"createdAt": "2026-01-01T00:00:00.000Z",
"updatedAt": "2026-01-01T00:00:00.000Z",
"createdById": "USER_ID",
"processed": false,
"metadata": null
}
The create route accepts only the fields shown in its current schema. It does not accept legacy type, loaderId, files, or meta_data fields.
Add a text document
Call POST /v1/contexts/{contextGuid}/documents. Supply content or its accepted alias text. Add arbitrary JSON in metadata for filtering later.
Create a document
curl 'https://api.klu.ai/v1/contexts/YOUR_CONTEXT_GUID/documents' \
--header 'Authorization: Bearer YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data '{
"content": "The Acme plan includes priority support and monthly usage reports.",
"filter": "customer-facing",
"metadata": {
"tenant_id": "tenant_123",
"product": "acme",
"published": true
}
}'
Klu may split one input into multiple documents. The response therefore contains an array of document GUIDs:
Response
{
"docs": ["44444444-4444-4444-8444-444444444444"],
"status": "success"
}
An empty content and text value is accepted by the schema but does not produce useful retrieval data. Validate non-empty content in your application.
List and inspect documents
List documents
curl 'https://api.klu.ai/v1/contexts/YOUR_CONTEXT_GUID/documents?skip=0&limit=100' \
--header 'Authorization: Bearer YOUR_API_KEY'
The list response contains data, total_count, and has_next_page. Each document contains guid, created_at, updated_at, content, filter, metadata, and embedding. The public list currently returns an empty array for embedding.
Fetch one document with GET /v1/contexts/{contextGuid}/documents/{guid}. Both identifiers are scoped together; a document from another Context returns Document not found.
Update or delete a document
Update content and metadata with PUT /v1/contexts/{contextGuid}/documents/{guid}:
Update a document
curl --request PUT 'https://api.klu.ai/v1/contexts/YOUR_CONTEXT_GUID/documents/YOUR_DOCUMENT_GUID' \
--header 'Authorization: Bearer YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data '{
"content": "The Acme plan includes 24-hour priority support and monthly usage reports.",
"metadata": {
"tenant_id": "tenant_123",
"product": "acme",
"published": true
}
}'
The update reprocesses the document. You can explicitly re-embed unchanged content with POST /v1/contexts/{contextGuid}/documents/{guid}/embed.
Delete one document with DELETE /v1/contexts/{contextGuid}/documents/{guid}. Delete all documents in a Context with DELETE /v1/contexts/{contextGuid}/documents/; the bulk route optionally accepts the legacy filter field and returns {"status":"success"} after scheduling the deletion work.
Upload a file
The current file route is a Base64 upload endpoint. It is different from the removed pre-signed form workflow described by older SDK examples.
This Node.js example uploads a local file, then immediately adds the returned URL to a Context:
Upload and attach a file
import { readFile } from 'node:fs/promises'
const apiKey = process.env.KLU_API_KEY
const contextGuid = process.env.KLU_CONTEXT_GUID
const fileData = await readFile('./document.pdf')
const uploadResponse = await fetch('https://api.klu.ai/v1/files/upload', {
method: 'POST',
headers: {
Authorization: `Bearer ${apiKey}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ data: fileData.toString('base64') }),
})
if (!uploadResponse.ok) {
throw new Error(
`Upload failed: ${uploadResponse.status} ${await uploadResponse.text()}`
)
}
const { url } = await uploadResponse.json()
const attachResponse = await fetch(
`https://api.klu.ai/v1/contexts/${contextGuid}/add_files`,
{
method: 'POST',
headers: {
Authorization: `Bearer ${apiKey}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ files: [url] }),
}
)
if (!attachResponse.ok) {
throw new Error(
`Attach failed: ${attachResponse.status} ${await attachResponse.text()}`
)
}
console.log(await attachResponse.json())
POST /v1/files/upload accepts { "data": "BASE64_DATA" } and returns { "url": "SIGNED_URL" }. You can also send a complete data URL. The route recognizes PDF, GIF, PNG, WebP, and JPEG signatures; unrecognized Base64 currently defaults to PNG handling, so do not assume arbitrary formats are preserved correctly.
The returned signed URL expires after ten minutes. Call POST /v1/contexts/{guid}/add_files immediately. Its response is:
{
"created": ["55555555-5555-4555-8555-555555555555"]
}
Those GUIDs identify created Context sources, not documents. Source processing is asynchronous, so a successful attach response does not mean every document is already searchable. Request-body limits are deployment configuration; the public route does not define a fixed file-size promise in its schema.
Search a Context
Call POST /v1/contexts/{guid}/search for similarity search without generating an answer.
Search with metadata
curl 'https://api.klu.ai/v1/contexts/YOUR_CONTEXT_GUID/search' \
--header 'Authorization: Bearer YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data '{
"prompt": "What support is included?",
"number_of_results": 5,
"score": 0.7,
"metadata_filter": {
"tenant_id": "tenant_123",
"published": true
}
}'
The response is an array of matching documents. Each item contains guid, content, score, timestamps, and optional filter, metadata, and embedding fields. A higher score threshold can return fewer than number_of_results items.
Use the plural /contexts/{guid}/search route. The singular /context/{guid}/search path remains as a compatibility route, but new integrations should not use it.
Metadata filter rules
Context search uses metadata_filter. Context prompting uses metadataFilter, while Action execution uses metadata. Follow the field name for the endpoint you call.
Filter keys must be 1–64 characters and contain only letters, numbers, _, ., or -. Values can be:
- a string, number, or boolean
- a non-empty array of those scalar values, with at most 100 entries
Nested objects and null values do not pass the current filter schema.
Prompt a Context
POST /v1/contexts/{guid}/prompt is a testing endpoint that retrieves documents and produces a response.
Prompt a Context
curl 'https://api.klu.ai/v1/contexts/YOUR_CONTEXT_GUID/prompt' \
--header 'Authorization: Bearer YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data '{
"prompt": "Summarize the support policy.",
"responseMode": "search",
"responseLength": 256,
"similarityTopK": 5,
"metadataFilter": {
"published": true
}
}'
The response has text and may include nodes. For production generation, attach the Context to an Action and use the Action execution endpoint so the request follows the Action's deployed prompt and model configuration.
SDK compatibility
The Python package is klu, where the checked-in client is exposed as klu.context. The TypeScript package is @kluai/core, where the checked-in client is exposed as klu.contexts. Older examples that use /v1/context, presign, type, files during Context creation, or meta_data do not match the current app routes. Use the REST examples on this page until your installed SDK version is aligned.