Sessions, Skills, and Workflows API
Sessions group related Action Data for multi-turn use. Skills are reusable prompt-time capabilities. Workflows execute ordered blocks and expose per-run result URLs.
All routes require Authorization: Bearer YOUR_API_KEY and use https://api.klu.ai/v1. See Actions API for Action input, streaming, asynchronous result, Skill attachment, and Context attachment contracts.
Session endpoints
| Method | Endpoint | Purpose |
|---|---|---|
GET | /sessions | List Sessions |
POST | /sessions | Create a Session for an Action |
GET | /sessions/{guid} | Get a Session |
PUT | /sessions/{guid} | Rename a Session or change its external user ID |
DELETE | /sessions/{guid} | Delete a Session |
GET | /sessions/{guid}/data | List Data recorded in the Session |
curl --request POST 'https://api.klu.ai/v1/sessions' \
--header 'Authorization: Bearer YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data '{
"name":"Customer 8472",
"action":"ACTION_GUID",
"extUserId":"customer-8472"
}'
action is required; name and extUserId are optional. The response contains guid, optional name, the Action GUID, and optional ext_user_id. Use the returned Session GUID in an Action run to maintain the relationship described in Actions API.
List accepts optional extUserId, skip, and limit. Session Data accepts skip and limit. Both default to 0/100 and return { data, total_count, has_next_page }. Session update requires name and optionally accepts extUserId.
Python and TypeScript clients support create/get/delete and list or Data pagination. Their high-level Session clients intentionally do not support update; call PUT /sessions/{guid} directly when needed.
Skill endpoints
| Method | Endpoint | Purpose |
|---|---|---|
GET | /skills | List Skills |
GET | /skills/types | List available Skill types and metadata definitions |
POST | /skills | Create a Skill |
GET | /skills/{guid} | Get a Skill |
PUT | /skills/{guid} | Rename a Skill |
DELETE | /skills/{guid} | Delete a Skill |
POST | /skills/{skill}/prompt | Run a prompt through a Skill |
Discover the available types and metadata definitions before configuring a Skill.
curl 'https://api.klu.ai/v1/skills/types' \
--header 'Authorization: Bearer YOUR_API_KEY'
The create schema requires name and type and optionally accepts metadata entries with name, required, value, and optional type. The current controller does not resolve the submitted type; it looks for an existing Skill whose name equals the submitted name. As a result, the public create route cannot reliably create an arbitrary new Skill and commonly returns 404 Type not found. Configure new Skills in Klu until this route is corrected.
A Skill response contains guid, name, type, nullable metadata, and timestamps. The list schema accepts skip and limit and returns { data, total_count, has_next_page }, but the current query does not apply either parameter and returns all non-deleted workspace Skills. Do not rely on has_next_page for Skill pagination. Update is CRUD-only and requires a new name; it does not replace type or metadata.
Prompt a Skill with a plain string:
curl --request POST 'https://api.klu.ai/v1/skills/SKILL_GUID/prompt' \
--header 'Authorization: Bearer YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data '{"prompt":"Rewrite this response using the approved terminology."}'
The response is { "msg": "..." }. This route accepts only prompt; it has no public streaming, async, Session, or structured-output options.
Python exposes klu.skills for get, list, and delete, while create/update are explicitly unsupported. The TypeScript Klu client has no top-level Skills client. Use REST for complete Skill CRUD and direct prompting.
Workflow endpoints
| Method | Endpoint | Purpose |
|---|---|---|
POST | /workflows | Create an empty Workflow for an App |
GET | /workflows/{guid} | Get a Workflow |
PUT | /workflows/{guid} | Rename a Workflow |
DELETE | /workflows/{guid} | Soft-delete a Workflow |
POST | /workflows/{guid}/trigger | Trigger the saved Workflow |
POST | /workflows/playground | Trigger with optional temporary block definitions |
GET | /workflows/{guid}/result/{run_guid} | Read the final result |
GET | /workflows/{guid}/result/{run_guid}/dataset | Read block-level outputs |
Create requires name and an App GUID:
curl --request POST 'https://api.klu.ai/v1/workflows' \
--header 'Authorization: Bearer YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data '{"name":"Triage support request","app":"APP_GUID"}'
The response contains guid, name, slug, timestamps, and creator. Creation makes the Workflow record only. The public CRUD router has no endpoints for adding, ordering, or configuring blocks; configure blocks in Klu before triggering. A Workflow with no non-deleted blocks returns 404 with Workflow has no blocks when triggered.
Trigger input is an optional array of key/value objects. Values can be strings, nested objects, or null.
curl --request POST 'https://api.klu.ai/v1/workflows/WORKFLOW_GUID/trigger' \
--header 'Authorization: Bearer YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data '{
"input":[
{"ticket":"I cannot reset MFA.","customer":{"plan":"pro"}}
]
}'
{
"msg": "Workflow triggered",
"status": "success",
"blocks": [
{
"feedback_url": "https://api.klu.ai/v1/feedback/DATA_GUID",
"data_guid": "DATA_GUID",
"result_url": "RESULT_URL",
"action": { "guid": "ACTION_GUID", "name": "Classify ticket" }
}
],
"run_guid": "RUN_GUID",
"has_output_block": true
}
Trigger success means block work was dispatched and result URLs were created. It does not guarantee that every block has finished. Poll each result_url or read the run routes after completion. GET .../result/{run_guid} returns { "result": "..." }; the Dataset variant returns { "final": "...", "blocks": [{ "guid", "name", "output" }] }. The current Dataset controller leaves final as an empty string, so use the ordered blocks outputs or the non-Dataset result route for the final value. A missing Workflow or run returns 404.
The playground route accepts workflow, optional input, and optional blocks. It is intended for testing alternate block definitions; use the saved trigger route for normal production runs.
Python klu.workflows defines trigger and result helpers, but its trigger accepts a dictionary while the current route requires an array, and its result helpers construct older paths. Its CRUD methods are explicitly unsupported; list and get_runs also target routes that the current public router does not register. The TypeScript Klu client has no top-level Workflow client. Use REST for current Workflow CRUD, trigger, result, and playground contracts, and use GET /apps/{guid}/workflows for the public Workflow list.
Errors and limits
Malformed UUIDs or bodies return 400; missing Sessions, Skills, Workflows, Actions, Apps, or runs return 404. API keys scope operations to their workspace. Deletes remove resources from public reads, and no restore route is exposed here. Workflow execution can also fail after dispatch because an Action, Provider, or block input fails; inspect result URLs and the generated Data records rather than treating the trigger response as completion proof.