Klu Actions
An Action is a versioned prompt, model configuration, and optional set of Context libraries and tools. Deploy the Action, then run it by GUID or slug through the public API.
Run an Action
Call POST /v1/actions/{guidOrSlug}/prompt. The input field is required and can be a string, an object of template variables, or an array of messages.
Run an Action
curl 'https://api.klu.ai/v1/actions/YOUR_ACTION_GUID/prompt' \
--header 'Authorization: Bearer YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data '{
"input": {
"topic": "Machine learning",
"task": "Write a two-sentence introduction."
},
"cache": false,
"environment": "production"
}'
A synchronous request returns the generated text in msg, the stored generation identifier in data_guid, and a URL for feedback. full_prompt_sent contains the messages sent to the model. Cost fields are present when the engine reports them.
Synchronous response
{
"msg": "Machine learning helps software learn patterns from data. It can use those patterns to make predictions or decisions.",
"full_prompt_sent": [],
"data_guid": "11111111-1111-4111-8111-111111111111",
"feedback_url": "https://api.klu.ai/v1/feedback/11111111-1111-4111-8111-111111111111",
"cost": {
"input": 0.0001,
"output": 0.0002,
"generation": 0.0003
}
}
When a model returns tool calls, msg is a JSON-encoded string containing the content and tool calls. Parse it only when your Action is configured to return tool calls. Set do_not_execute_tool_calls to true when your application must receive the calls without Klu executing configured tools.
Execution fields
- Name
input- Type
- string | object | Message[]
- Description
Text, template-variable values, or messages used to run the Action.
- Name
messages- Type
- Message[]
- Description
Additional conversation messages. Use the current multimodal message schema shown below.
- Name
cache- Type
- boolean
- Description
Allows a cached generation to be returned. Defaults to
false.
- Name
environment- Type
- string
- Description
Selects a deployed environment. Omit it to use the Action's default resolution.
- Name
version- Type
- number
- Description
Selects a numeric Action version.
- Name
metadata- Type
- object
- Description
Filters documents retrieved from attached Context libraries.
- Name
filter- Type
- string
- Description
Applies the legacy string filter during Context retrieval.
- Name
session- Type
- string
- Description
Adds history from an existing session associated with the Action.
- Name
extUserId- Type
- string
- Description
Associates the generation with an external application identifier.
- Name
async_mode- Type
- boolean
- Description
Queues the generation and returns a result URL. Defaults to
false.
- Name
streaming- Type
- boolean
- Description
Creates a one-time stream and returns its URL. Defaults to
false.
- Name
modelOptions- Type
- object
- Description
Optionally supplies
provider,model, orjsonSchemaoverrides when your workspace permits them.
- Name
store- Type
- boolean
- Description
Requests provider-side storage where supported. Defaults to
false.
Use either environment or version when you need deterministic deployment selection. A missing Action, invalid deployment, unavailable provider key, malformed input, or model error fails the request instead of returning a normal generation.
Filter attached Context
For Action execution, the current field name is metadata.
Run with a metadata filter
curl 'https://api.klu.ai/v1/actions/YOUR_ACTION_GUID/prompt' \
--header 'Authorization: Bearer YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data '{
"input": "Summarize the account history.",
"metadata": {
"tenant_id": "tenant_123",
"region": ["apac", "emea"],
"active": true
}
}'
Filter keys can contain letters, numbers, _, ., and -. Each value must be a string, number, boolean, or a non-empty array of up to 100 of those scalar values.
Use multimodal messages
Message content can be text or an array of typed parts. The current schema accepts text, image_url, input_audio, file, and refusal parts. Provider and model capabilities still determine which parts can be processed.
Run with an image
curl 'https://api.klu.ai/v1/actions/YOUR_ACTION_GUID/prompt' \
--header 'Authorization: Bearer YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data '{
"input": "Describe the supplied image.",
"messages": [
{
"role": "user",
"content": [
{ "type": "text", "text": "What is visible here?" },
{
"type": "image_url",
"image_url": { "url": "https://example.com/example-image.jpg" }
}
]
}
]
}'
Audio parts use Base64 data and a format of wav or mp3:
{
"type": "input_audio",
"input_audio": {
"data": "BASE64_AUDIO_DATA",
"format": "mp3"
}
}
File parts accept file_data, file_id, and filename; each is optional in the schema, but your provider may require a particular combination. Use an accessible URL for image_url, or a correctly encoded data URL when the selected provider supports it.
Stream a response
Set streaming to true. The first response contains an authenticated, time-limited streaming_url and no generated text:
Create a stream
curl 'https://api.klu.ai/v1/actions/YOUR_ACTION_GUID/prompt' \
--header 'Authorization: Bearer YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data '{
"input": "Write a short welcome message.",
"streaming": true
}'
Streaming response
{
"msg": "",
"full_prompt_sent": [],
"data_guid": "11111111-1111-4111-8111-111111111111",
"streaming": true,
"streaming_url": "https://api.klu.ai/api/streamByURL?guid=11111111-1111-4111-8111-111111111111&token=SIGNED_STREAM_TOKEN",
"feedback_url": "https://api.klu.ai/v1/feedback/11111111-1111-4111-8111-111111111111"
}
Open streaming_url as an SSE connection. The stream starts with BEGIN_STREAM, emits JSON token events, and ends after the generation completes. The URL token expires after one hour, and the cached stream can be consumed only once. A repeated or late connection can return No data found in cache or stream has been consumed.
Run asynchronously
Set async_mode to true for background execution. Do not combine it with streaming because the route gives streaming precedence.
Queue an Action
curl 'https://api.klu.ai/v1/actions/YOUR_ACTION_GUID/prompt' \
--header 'Authorization: Bearer YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data '{
"input": "Produce a detailed report.",
"async_mode": true
}'
Queued response
{
"msg": "Running",
"full_prompt_sent": null,
"result_url": "https://api.klu.ai/v1/actions/result/RESULT_KEY"
}
Poll the returned URL with the same Bearer token. While work continues, it returns {"msg":"Generation in Progress","status":"PENDING"}. When ready, it returns {"msg":"...","status":"SUCCESS"}. The result endpoint exposes only those two states in the current contract.
Record feedback
Use the generation's data_guid, or POST directly to the returned feedback_url. Each request creates one feedback record, so submit rating, correction, issue, or action feedback as separate records.
Create feedback
curl 'https://api.klu.ai/v1/feedback/YOUR_DATA_GUID' \
--header 'Authorization: Bearer YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data '{
"type": "rating",
"value": "positive",
"source": "product-ui",
"metadata": {
"surface": "answer-card"
}
}'
The API stores type and value as strings; it does not translate numeric rating conventions in this route. A successful response contains guid, data, type, value, source, created_by_id, metadata, timestamps, and deleted. An unknown data GUID returns Data not found.
The SDK convenience signatures differ by language. In current TypeScript source, klu.feedback.log accepts one object containing dataGuid; in current Python source, it accepts data_guid plus named feedback fields. Check the version installed in your project before using the helper.
Create and use a session
Create a session for an Action, then pass the returned session GUID to each turn.
Create a session
curl 'https://api.klu.ai/v1/sessions' \
--header 'Authorization: Bearer YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data '{
"action": "YOUR_ACTION_GUID",
"name": "Support conversation",
"extUserId": "customer_123"
}'
Session response
{
"guid": "22222222-2222-4222-8222-222222222222",
"name": "Support conversation",
"action": "YOUR_ACTION_GUID",
"ext_user_id": "customer_123"
}
Continue the session
curl 'https://api.klu.ai/v1/actions/YOUR_ACTION_GUID/prompt' \
--header 'Authorization: Bearer YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data '{
"input": "What did I ask you previously?",
"session": "22222222-2222-4222-8222-222222222222"
}'
You can list sessions with GET /v1/sessions?extUserId=customer_123, fetch one with GET /v1/sessions/{guid}, and inspect its generations with GET /v1/sessions/{guid}/data. Session list and data endpoints accept skip and limit.
Prepare a gateway payload
POST /v1/actions/{guid}/gateway_payload formats the deployed Action as an OpenAI-compatible request. It does not execute the model.
Prepare an Action payload
curl 'https://api.klu.ai/v1/actions/YOUR_ACTION_GUID/gateway_payload' \
--header 'Authorization: Bearer YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data '{
"input": {
"question": "What is the capital of France?"
}
}'
The response contains model, messages, model parameters, and a headers object. The headers can include a provider credential plus x-klu-api-key and x-klu-action-guid. Treat the entire response as server-side secret material. Do not return it to a browser or log it.
Forward the payload only to a gateway deployment you operate or trust. This two-call flow is separate from direct Action execution; see Integrate an OpenAI client with the Klu gateway.
A/B experiments
An Experiment routes each request to one of two Actions. Send prompts to POST /v1/experiments/{guid}/prompt using the same input shapes as an Action prompt. The response includes the generated message and feedback URL. Force a specific Action only for diagnostics; a forced request bypasses the normal assignment.
See Compare Actions with experiments for the workflow.
SDK compatibility
The published package names are klu and @kluai/core. Their checked-in Action clients still target the legacy POST /v1/actions/ execution shape, while the current app exposes POST /v1/actions/{guidOrSlug}/prompt and uses metadata for Action retrieval filters. Use the REST contract on this page until your installed SDK version matches those routes.