Remote Runtime API
This reference describes the public-safe runtime API shape after an agent or
runtime product is deployed. The externally visible base URL is the hosted
PublicEndpoint returned by the control plane.
Use placeholders in public examples:
https://<public-endpoint>Entry Model
The runtime pod may implement local routes, but public callers should treat the
gateway-facing PublicEndpoint routes as the contract.
Authentication
| Client | Recommended authentication |
|---|---|
| SDK, CLI, automation | Authorization: Bearer <api_key> |
| Hosted browser session | ae_ui_session cookie created by the hosted link flow |
| Hermes terminal WebSocket | bearer auth plus Sec-WebSocket-Protocol: ks-terminal.v1 |
External callers should not manufacture internal gateway headers such as
X-Auth-Agent-Id, X-Auth-Account-Id, or runtime-specific forwarded headers.
Bearer Token Enforcement
The hosted runtime requires Authorization: Bearer <token>. The local dev
server does not enforce auth by default, but in production the gateway injects
and validates the Bearer token. Clients should always send it to keep local
and hosted behavior consistent.
Common Headers
| Header | Use |
|---|---|
Authorization: Bearer <api_key> | API calls through the public endpoint |
Content-Type: application/json | JSON requests |
Accept: application/json | Non-streaming responses |
Accept: text/event-stream | Streaming responses |
The multipart/form-data boundary for upload routes should be generated by the
HTTP client.
Runtime Types
| Runtime | Primary public surface |
|---|---|
| Code-framework Agent | /v1/responses, /v1/chat/completions, workspace files, hosted UI actions |
| Hermes | dashboard, /v1/* proxy, terminal WebSocket, workspace files |
| OpenClaw | OpenClaw gateway plus KsADK workspace files |
OpenAI-Compatible Routes
POST /v1/responses
The entry point for Responses-compatible clients.
| Field | Meaning |
|---|---|
input | User input string, or message/content array |
model | Optional model override |
instructions | Request-level system/developer instructions |
conversation | Stable conversation id or { "id": "..." } |
previous_response_id | Continuation handle for compatible clients |
safety_identifier | Stable end-user id, hash before sending |
stream | true returns SSE |
metadata | Runtime-reserved request metadata |
curl -sS https://<public-endpoint>/v1/responses \
-H "Authorization: Bearer <api_key>" \
-H "Content-Type: application/json" \
-d '{"input":"hello","stream":false}'POST /v1/chat/completions
The entry point for Chat Completions-compatible clients.
curl -sS https://<public-endpoint>/v1/chat/completions \
-H "Authorization: Bearer <api_key>" \
-H "Content-Type: application/json" \
-d '{"model":"my-model","messages":[{"role":"user","content":"hello"}]}'Responses and Chat Completions keep their own protocol semantics at the public boundary. KsADK normalizes both into runner input before invoking framework code.
Hosted UI Actions
The hosted UI uses action-style routes to manage sessions, events, uploads,
workspace files, cancellation, and model listing. Public API clients should
prefer the OpenAI-compatible /v1/* routes and only target action routes when
integrating the hosted UI surface directly.
All action paths live under POST /agentengine/api/v1/* (download surfaces are
GET) and return a unified action envelope:
{
"Code": 0,
"Message": "Success",
"RequestId": "req_abc123",
"Action": "RunAgent",
"Data": { /* action-specific payload */ }
}| Group | Purpose | Actions |
|---|---|---|
| Sessions | Create, get, list, delete sessions, read projected chat messages | CreateSession, GetSession, ListSessions, ListSessionMessages, DeleteSession |
| Runs | Invoke or cancel a run, subscribe to events | RunAgent, SubscribeRunEvents, CancelRun |
| Events | List historical session events with incremental resume and older-page cursors | ListSessionEvents |
| Files | Upload, download attachments, workspace files, export archive | UploadFile, AttachmentContent, ListWorkspaceFiles, AddWorkspaceFile, DeleteWorkspaceFile, GetWorkspaceFileContent, ExportWorkspaceZip |
| Models | List the available model catalog | ListAgentModels |
| UI Bootstrap | Bootstrap metadata for UI rendering and capability discovery | GetAgentUiBootstrap |
New in 0.6.7
checkpoint/resume and GetAgentUiBootstrap capability visibility are governed
by the RuntimeCapabilities and RunLifecycle returned by bootstrap. Public
API clients usually do not target these action routes directly; prefer the
OpenAI-compatible /v1/*.
Sessions
- Probe capabilities: call
GetAgentUiBootstrapfirst to checkCapabilities.WorkspaceFiles,Capabilities.ResumeRun, etc. - Create a session:
CreateSession, takeSession.SessionId. - Pull history:
ListSessionsfor the sidebar andListSessionMessagesfor chat history; useListSessionEventsdirectly only for debugging or raw timelines. - Start a run:
RunAgent(foreground or background), subscribe to progress viaSubscribeRunEvents. - Reclaim a session:
DeleteSessionto release persisted records.
CreateSession
Creates (or reuses) a session. When SessionId is omitted, the runtime generates one.
POST /agentengine/api/v1/CreateSession, JSON body:
| Field | Type | Required | Notes |
|---|---|---|---|
AgentId | string | yes | Target agent id |
UserId | string | no | Defaults to user |
SessionId | string | no | Reuse an existing session; runtime generates one when omitted |
{
"AgentId": "my-agent",
"UserId": "user",
"SessionId": "local-demo-session"
}{
"Code": 0,
"Message": "Success",
"RequestId": "req_abc123",
"Action": "CreateSession",
"Data": {
"Session": {
"SessionId": "local-demo-session",
"AgentId": "my-agent",
"UserId": "user",
"Title": "New session",
"TitleSource": "fallback_first_prompt",
"Summary": null,
"FirstPrompt": "",
"LastPrompt": "",
"ActiveInvocationId": "",
"ActiveRunStatus": "",
"ActiveRunMode": "unknown",
"ActiveRunTrigger": "unknown",
"ActiveRunUpdatedAt": "",
"Model": null,
"ContextUsage": null,
"TokenUsage": null,
"State": {},
"CreatedAt": 1719900000.0,
"UpdatedAt": 1719900000.0,
"Version": 1
}
}
}Session payload fields:
| Field | Notes |
|---|---|
SessionId / AgentId / UserId | Session primary key triple |
Title / TitleSource | Session title and its source (fallback_first_prompt, heuristic, etc.) |
Summary | Runtime-maintained session summary |
FirstPrompt / LastPrompt | Truncated first/last user message preview |
ActiveInvocationId / ActiveRunStatus | Active run invocation and status for this session; stale orphaned active runs are read as interrupted |
ActiveRunMode / ActiveRunTrigger | 0.6.9+ two independent run dimensions: background / foreground / unknown and new_run / checkpoint_resume / approval_resume / unknown |
ActiveRunUpdatedAt | 0.6.9+ timestamp from active_run itself, mainly for diagnostics; orphan detection uses the session UpdatedAt heartbeat |
Model | Model metadata from the most recent run when available |
ContextUsage | 0.6.9+ latest-turn context-window usage: used_tokens, cached_tokens, context_window_tokens, percent |
TokenUsage | 0.6.9+ cumulative session token usage: input_tokens, output_tokens, total_tokens, turns, last_response_id, and detail fields |
State | Session state dict (sanitized) |
CreatedAt / UpdatedAt / Version | Timestamps and version |
Continuity | Optional: continuity info from the runner adapter |
| Status | Scenario | detail |
|---|---|---|
400 | Missing AgentId | Pydantic validation failure |
503 | Session backend unavailable | {"code":"session_backend_unavailable","message":...} |
ListSessions
Paginated list of sessions for an Agent/User, page-based pagination.
POST /agentengine/api/v1/ListSessions:
| Field | Type | Required | Notes |
|---|---|---|---|
AgentId | string | yes | Target agent id |
UserId | string | no | Defaults to user |
Page | int | no | 1-based, default 1, min 1 |
PageSize | int | no | Default 20, range 1..200 |
{
"AgentId": "my-agent",
"UserId": "user",
"Page": 1,
"PageSize": 20
}{
"Code": 0,
"Message": "Success",
"RequestId": "req_abc123",
"Action": "ListSessions",
"Data": {
"Sessions": [ /* Session payload, same as CreateSession */ ],
"Total": 42,
"Page": 1,
"PageSize": 20
}
}Pagination fields:
| Field | Notes |
|---|---|
Total | Total session count for this Agent/User |
Page / PageSize | Current page and page size (echoed back) |
The runtime computes offset as (Page - 1) * PageSize.
GetSession
Fetch a single session with its latest events.
POST /agentengine/api/v1/GetSession:
| Field | Type | Required | Notes |
|---|---|---|---|
SessionId | string | yes | Target session id |
{ "SessionId": "local-demo-session" }{
"Code": 0,
"Message": "Success",
"RequestId": "req_abc123",
"Action": "GetSession",
"Data": {
"Session": { /* same Session payload as CreateSession */ }
}
}| Status | Scenario | detail |
|---|---|---|
404 | Session not found | Session not found |
DeleteSession
Delete a session and cancel any detached stream still running for it.
POST /agentengine/api/v1/DeleteSession:
| Field | Type | Required | Notes |
|---|---|---|---|
SessionId | string | yes | Target session id |
{ "SessionId": "local-demo-session" }{
"Code": 0,
"Message": "Success",
"RequestId": "req_abc123",
"Action": "DeleteSession",
"Data": { "Deleted": true }
}Side Effect
Before deletion, the runtime cancels detached background streams for that
session to avoid dangling in_progress run_status events.
| Status | Scenario | detail |
|---|---|---|
404 | Session not found | Session not found |
Runs
RunAgent
Invoke an agent for one conversation turn. Supports foreground sync, foreground streaming, and background execution modes.
POST /agentengine/api/v1/RunAgent, JSON body (based on RunAgentActionRequest):
| Field | Type | Required | Notes |
|---|---|---|---|
AgentId | string | yes | Target agent id |
Messages | array | no | Message array (Chat Completions style); mutually exclusive with ResponsesInput |
ResponsesInput | any | no | Responses-style input; mutually exclusive with Messages |
UserId | string | no | Defaults to user |
AccountId | string | no | 0.6.5+ account-scoped id, passed through to the runner |
SessionId | string | no | Associated session; runtime creates one when omitted |
InvocationId | string | no | Caller-provided invocation id; runtime generates one when omitted |
ApiFormat | string | no | responses (default) or chat_completions |
Stream | bool | no | true returns SSE; default false |
Background | bool | no | 0.6.5+ true returns a job handle immediately, runs in background, progress via SubscribeRunEvents; default false |
Model | string | no | Model or agent name override |
ModelMetadata | object | no | Model metadata, including reasoning / multimodal / context_window_tokens |
ModelOptions | object | no | Request-level model options (temperature, max_tokens, etc.) passed through to the runner |
PreviousResponseId | string | no | Responses continuation handle; written into request metadata |
Foreground sync call:
{
"AgentId": "my-agent",
"Messages": [{"role": "user", "content": "hello"}],
"ApiFormat": "responses",
"Stream": false
}Background execution:
{
"AgentId": "my-agent",
"Messages": [{"role": "user", "content": "summarize the workspace"}],
"Background": true,
"InvocationId": "inv_demo_001",
"AccountId": "acct_42",
"Model": "glm-5.1",
"ModelMetadata": {"reasoning": true, "multimodal": false, "context_window_tokens": 128000},
"ModelOptions": {"temperature": 0.2, "max_tokens": 4096}
}Background and Stream are mutually exclusive
Background: true ignores Stream and returns a job handle immediately. A
foreground Stream: true returns SSE. The two cannot be enabled together.
Foreground sync (Background: false, Stream: false) returns a Responses or
Chat Completions payload wrapped in the action envelope:
{
"Code": 0,
"Message": "Success",
"RequestId": "req_abc123",
"Action": "RunAgent",
"Data": {
"id": "resp_a1b2c3",
"object": "response",
"status": "completed",
"model": "glm-5.1",
"output": [{"type": "message", "role": "assistant", "content": [{"type": "output_text", "text": "..."}]}],
"output_text": "...",
"session_id": "local-demo-session"
}
}Background execution (Background: true) returns a job handle immediately:
{
"Code": 0,
"Message": "Success",
"RequestId": "req_abc123",
"Action": "RunAgent",
"Data": {
"InvocationId": "inv_demo_001",
"Status": "running",
"Background": true,
"SubscribeUrl": "/agentengine/api/v1/SubscribeRunEvents?SessionId=local-demo-session&InvocationId=inv_demo_001"
}
}Background response fields:
| Field | Notes |
|---|---|
InvocationId | Run invocation id, used for subscribe and cancel |
Status | running means the background task is ready |
Background | Always true |
SubscribeUrl | Relative path; prepend the host to use as the SSE subscribe entry |
Foreground Stream: true returns text/event-stream; events are normalized by
the runtime before delivery:
curl -N https://<public-endpoint>/agentengine/api/v1/RunAgent \
-H "Authorization: Bearer <api_key>" \
-H "Content-Type: application/json" \
-d '{"AgentId":"my-agent","Messages":[{"role":"user","content":"count to three"}],"Stream":true}'Clients should handle text deltas, tool events, errors, and completion events.
| Status | Scenario | detail |
|---|---|---|
400 | Both Messages and ResponsesInput, or neither | Pydantic / runtime validation failure |
409 | A resume for this session is already running | {"code":"resume_already_running",...} |
500 | Runner not initialized or load failure | Runner 未初始化 |
0.6.5+ pass-through fields
AccountId, InvocationId, ModelMetadata, and ModelOptions are passed
through to the runner unchanged, enabling per-account isolation of
Skill/Workspace/Sandbox/Memory and request-level model overrides. When
AccountId is omitted, the runner falls back to the runtime default account.
SubscribeRunEvents
Subscribe to run events for an invocation via SSE. Supports a 5-minute reconnect window.
GET /agentengine/api/v1/SubscribeRunEvents, parameters via query string:
| Param | Type | Required | Notes |
|---|---|---|---|
SessionId | string | yes | Target session id |
InvocationId | string | yes | Target run invocation id |
AfterSeqId | int | no | Only emit events with SeqId > AfterSeqId; default 0 |
/agentengine/api/v1/SubscribeRunEvents?SessionId=local-demo-session&InvocationId=inv_demo_001&AfterSeqId=12Accept: text/event-stream. Each event is data: <json>\n\n; on terminal status
the stream emits data: [DONE]\n\n and closes:
data: {"EventId":"evt_1","SessionId":"local-demo-session","InvocationId":"inv_demo_001","EventType":"run_status","Content":{"status":"in_progress"},"SeqId":13,"Timestamp":1719900001.0}
data: {"EventId":"evt_2","EventType":"tool_result","Content":{...},"SeqId":14,...}
data: {"EventId":"evt_3","EventType":"run_status","Content":{"status":"completed"},"SeqId":15,...}
data: [DONE]Event payload fields:
| Field | Notes |
|---|---|
EventId / SessionId | Event and its session |
InvocationId | Associated run invocation id |
Author | Event author (agent or user) |
EventType | Event type (run_status, tool_result, run_checkpoint, etc.) |
Content | Event content dict |
Timestamp | Event timestamp |
SeqId | Monotonic per-session sequence number, used for resumption |
Metadata | Event metadata |
5-minute reconnect window
A streaming connection has a maximum lifetime of 5 minutes
(deadline = now + 5min). When the deadline is reached the connection closes
silently and does not emit [DONE]. Clients should record the largest
SeqId consumed and pass it as AfterSeqId on the next reconnect; as long as
the run has not reached a terminal status, reconnecting continues to deliver
subsequent events.
Terminal statuses (any one triggers [DONE]):
| status | Meaning |
|---|---|
completed | Normal completion |
failed / error | Failure |
cancelled / canceled | Cancelled |
aborted | Aborted |
interrupted | Interrupted |
| Status | Scenario | detail |
|---|---|---|
400 | Missing SessionId or InvocationId | SessionId and InvocationId are required |
CancelRun
Request cancellation of an in-flight run (both detached stream and runner channel).
POST /agentengine/api/v1/CancelRun:
| Field | Type | Required | Notes |
|---|---|---|---|
AgentId | string | no | Target agent id (not currently enforced) |
InvocationId | string | yes | Run invocation id to cancel |
{ "AgentId": "my-agent", "InvocationId": "inv_demo_001" }{
"Code": 0,
"Message": "Success",
"RequestId": "req_abc123",
"Action": "CancelRun",
"Data": {
"Cancelled": true,
"Found": true,
"Status": "cancelling",
"RunnerCancelStatus": "accepted"
}
}| Field | Notes |
|---|---|
Cancelled | Whether cancellation was initiated (true if either detached stream or runner accepted) |
Found | Whether a detached stream was located |
Status | Aggregated status: cancelling / not_found / unsupported / error |
RunnerCancelStatus | Runner-side result: accepted / cancelling / cancelled / not_found / unsupported / error |
Events
ListSessionEvents
Paginated list of historical events for a session. Without a seq cursor,
Offset / Limit page backward from the latest event window. AfterSeqId is
for reconnect/incremental reads; BeforeSeqId is for loading older history.
POST /agentengine/api/v1/ListSessionEvents:
| Field | Type | Required | Notes |
|---|---|---|---|
SessionId | string | yes | Target session id |
Offset | int | no | 0-based offset, default 0 |
Limit | int | no | Page size, min 1 |
AfterSeqId | int | no | 0.6.9+ return events with SeqId > AfterSeqId for reconnect catch-up |
BeforeSeqId | int | no | 0.6.9+ return events with SeqId < BeforeSeqId for older pages |
{ "SessionId": "local-demo-session", "Offset": 0, "Limit": 50 }{
"Code": 0,
"Message": "Success",
"RequestId": "req_abc123",
"Action": "ListSessionEvents",
"Data": {
"Events": [ /* event payload, same as SubscribeRunEvents */ ],
"Total": 128,
"Offset": 0,
"Limit": 50,
"AfterSeqId": null,
"BeforeSeqId": null
}
}Pagination fields:
| Field | Notes |
|---|---|
Total | Total event count for this session |
Offset | Current offset (defaults to 0) |
Limit | Current page size (falls back to the returned count when not sent) |
AfterSeqId / BeforeSeqId | Echoed seq cursors; they move in opposite directions and should not be mixed |
ListSessionMessages
Project the raw event log into chat messages that the Web UI can render
directly. The server handles assistant snapshot de-duplication, reasoning
merging, tool / approval pairing, and attachment normalization so clients do not
need to reconstruct messages from ListSessionEvents.
POST /agentengine/api/v1/ListSessionMessages:
| Field | Type | Required | Notes |
|---|---|---|---|
AgentId | string | no | When present, the server fetches runtime ListSessionEvents and projects them in one place; when omitted, hosted reads the local session store |
SessionId | string | yes | Target session id |
Limit | int | no | Maximum messages to return, default 50, range 1..200 |
AfterSeqId | int | no | Return incremental messages with SeqId > AfterSeqId; used for reconnect catch-up and not truncated to Limit |
BeforeSeqId | int | no | Return the latest page before SeqId < BeforeSeqId; used for loading older history |
IncludeReasoning | bool | no | Include Reasoning[] inside assistant messages |
IncludeToolEvents | bool | no | Include ToolEvents[] inside assistant messages |
IncludeAttachments | bool | no | Include Attachments[] on user messages, default true |
{
"SessionId": "local-demo-session",
"Limit": 50,
"IncludeAttachments": true
}{
"Code": 0,
"Message": "Success",
"RequestId": "req_abc123",
"Action": "ListSessionMessages",
"Data": {
"SessionId": "local-demo-session",
"Messages": [
{
"MessageId": "evt_user_1",
"Role": "user",
"Content": {"text": "Summarize this file"},
"SeqId": 21,
"InvocationId": "inv_demo_001",
"Timestamp": 1719900001.0,
"Attachments": [
{
"file_uri": "ae-upload://abc123_report.pdf",
"name": "report.pdf",
"mime": "application/pdf",
"size": 204800,
"url": "/agentengine/api/v1/AttachmentContent?FileUri=ae-upload%3A%2F%2Fabc123_report.pdf",
"is_image": false
}
]
},
{
"MessageId": "evt_assistant_1",
"Role": "assistant",
"Content": {"text": "Here is the summary..."},
"SeqId": 24,
"InvocationId": "inv_demo_001",
"ResponseId": "resp_a1b2c3",
"TraceId": "trace_abc",
"RootSpanId": "span_root"
}
],
"LatestSeqId": 24,
"HasMore": true,
"NextCursor": 20
}
}Pagination fields:
| Field | Notes |
|---|---|
LatestSeqId | SeqId of the last message in the page; pass it to SubscribeRunEvents(AfterSeqId=...) as the reconnect starting point |
HasMore | Whether older messages remain |
NextCursor | Older-page cursor; pass it as BeforeSeqId=NextCursor on the next request |
Reconnect detection
ListSessionMessages only projects historical messages. To decide whether an
SSE stream should reconnect, read GetSession.ActiveRunStatus /
ActiveInvocationId, then call SubscribeRunEvents(AfterSeqId=LatestSeqId).
Files
UploadFile
Upload an attachment and return an ae-upload:// handle for use by RunAgent /
AttachmentContent.
POST /agentengine/api/v1/UploadFile, multipart/form-data:
| Field | Type | Required | Notes |
|---|---|---|---|
file | binary | yes | Upload file content |
curl -sS https://<public-endpoint>/agentengine/api/v1/UploadFile \
-H "Authorization: Bearer <api_key>" \
-F "file=@report.pdf"{
"Code": 0,
"Message": "Success",
"RequestId": "req_abc123",
"Action": "UploadFile",
"Data": {
"FileData": {
"fileUri": "ae-upload://abc123_report.pdf",
"displayName": "report.pdf",
"mimeType": "application/pdf",
"sizeBytes": 204800
}
}
}AttachmentContent
Read the bytes of an uploaded attachment by its ae-upload:// handle, returning
the original content-type.
GET /agentengine/api/v1/AttachmentContent?FileUri=...:
| Param | Type | Required | Notes |
|---|---|---|---|
FileUri | string | yes | fileUri returned by UploadFile |
/agentengine/api/v1/AttachmentContent?FileUri=ae-upload://abc123_report.pdfHTTP/1.1 200 OK
Content-Type: application/pdf
Content-Disposition: inline; filename="report.pdf"
<binary bytes>Prefix Resolution
Paths with the ae-upload:// prefix resolve to hosted upload content and return
its byte stream; paths without that prefix are treated as workspace-relative
paths.
| Status | Scenario | detail |
|---|---|---|
404 | Attachment not found | Attachment not found |
ListWorkspaceFiles
List workspace file entries (proxied to /_ksadk/workspace/v1/entries).
POST /agentengine/api/v1/ListWorkspaceFiles:
| Field | Type | Required | Notes |
|---|---|---|---|
AgentId | string | no | Target agent id (not currently enforced) |
Path | string | no | Workspace-relative path, default . |
Recursive | bool | no | Recurse into subdirectories, default false |
{ "Path": ".", "Recursive": true }{
"Code": 0,
"Message": "Success",
"RequestId": "req_abc123",
"Action": "ListWorkspaceFiles",
"Data": {
"Entries": [
{ "Path": "notes/todo.md", "Type": "file" },
{ "Path": "notes/", "Type": "dir" }
]
}
}AddWorkspaceFile
Add or overwrite a workspace file (proxied to /_ksadk/workspace/v1/files/<path>).
POST /agentengine/api/v1/AddWorkspaceFile, multipart/form-data:
| Field | Type | Required | Notes |
|---|---|---|---|
file | binary | yes | Upload file content |
Path | string | yes | Workspace-relative path |
AgentId | string | no | Target agent id (not currently enforced) |
curl -sS https://<public-endpoint>/agentengine/api/v1/AddWorkspaceFile \
-H "Authorization: Bearer <api_key>" \
-F "Path=notes/todo.md" \
-F "file=@todo.md"{
"Code": 0,
"Message": "Success",
"RequestId": "req_abc123",
"Action": "AddWorkspaceFile",
"Data": { "Path": "notes/todo.md", "Size": 128 }
}DeleteWorkspaceFile
Delete a workspace file (proxied to /_ksadk/workspace/v1/files/<path>).
POST /agentengine/api/v1/DeleteWorkspaceFile:
| Field | Type | Required | Notes |
|---|---|---|---|
AgentId | string | no | Target agent id (not currently enforced) |
Path | string | yes | Workspace-relative path |
{ "Path": "notes/old.md" }{
"Code": 0,
"Message": "Success",
"RequestId": "req_abc123",
"Action": "DeleteWorkspaceFile",
"Data": { "Deleted": true }
}GetWorkspaceFileContent
Read workspace file content, returning the original content-type and disposition.
GET /agentengine/api/v1/GetWorkspaceFileContent?FilePath=...:
| Param | Type | Required | Notes |
|---|---|---|---|
FilePath | string | yes | Workspace-relative path |
AgentId | string | no | Target agent id (not currently enforced) |
/agentengine/api/v1/GetWorkspaceFileContent?FilePath=notes/todo.mdHTTP/1.1 200 OK
Content-Type: text/markdown
Content-Disposition: inline; filename="todo.md"
<file bytes>HTML files are returned with an injected preview CSP so they can be embedded in the hosted UI preview pane.
ExportWorkspaceZip
Package the workspace (or a subdirectory) as a zip download.
GET /agentengine/api/v1/ExportWorkspaceZip:
| Param | Type | Required | Notes |
|---|---|---|---|
Path | string | no | Workspace-relative directory, default . |
AgentId | string | no | Target agent id (not currently enforced) |
/agentengine/api/v1/ExportWorkspaceZip?Path=.HTTP/1.1 200 OK
Content-Type: application/zip
Content-Disposition: attachment; filename="workspace.zip"
<zip bytes>The filename is derived from Path: workspace.zip for the root, or
workspace-<dir-with-dashes>.zip for a subdirectory. Symlinks and out-of-tree
paths are skipped so the archive only contains regular files under the workspace
root.
Models
ListAgentModels
List the available model catalog, including the current model and its source.
POST /agentengine/api/v1/ListAgentModels:
| Field | Type | Required | Notes |
|---|---|---|---|
AgentId | string | no | Target agent id (not currently used) |
Name | string | no | Model name filter (not currently used) |
{}{
"Code": 0,
"Message": "Success",
"RequestId": "req_abc123",
"Action": "ListAgentModels",
"Data": {
"Models": [
{
"id": "glm-5.1",
"display_name": "glm-5.1",
"context_window_tokens": 128000,
"max_output_tokens": 32000,
"capabilities": {
"multimodal_input_image": true,
"multimodal_input_video": false,
"multimodal_input_file": false
},
"limits": {
"context_window_tokens": 128000,
"max_input_tokens": 128000,
"max_output_tokens": 32000,
"max_reasoning_tokens": 8192,
"rpm": 600,
"tpm": 200000
},
"pricing": {},
"auto_compact_threshold_tokens": 102400,
"auto_compact_threshold_percentage": 0.8
}
],
"Current": "glm-5.1",
"Source": "OPENAI_MODEL_NAME"
}
}Models element fields (normalized by normalize_model_metadata):
| Field | Notes |
|---|---|
id / display_name | Model id and display name |
context_window_tokens / max_output_tokens / max_input_tokens / max_reasoning_tokens | Token context limits |
capabilities | Capability set, including multimodal_input_image/video/file |
limits | Normalized limits dict (rpm / tpm, etc.) |
pricing | Pricing dict |
auto_compact_threshold_tokens / _percentage | Auto-compact thresholds |
Current is the runtime's current model, and Source names the source env var
(OPENAI_MODEL_NAME / MODEL_NAME / COZE_MODEL_NAME). The OpenAI-compatible
GET /v1/models returns the same data with a different top-level envelope.
UI Bootstrap
GetAgentUiBootstrap
Returns the bootstrap metadata needed by the hosted UI for rendering and capability discovery. This is the first call the hosted UI makes on startup.
POST /agentengine/api/v1/GetAgentUiBootstrap:
| Field | Type | Required | Notes |
|---|---|---|---|
AgentId | string | no | Target agent id; defaults to the runtime agent name |
SessionId | string | no | Associated session (echoed back in the response) |
{ "AgentId": "my-agent", "SessionId": "local-demo-session" }{
"Code": 0,
"Message": "Success",
"RequestId": "req_abc123",
"Action": "GetAgentUiBootstrap",
"Data": {
"Agent": {
"AgentId": "my-agent",
"Name": "my-agent",
"Description": "demo agent",
"Framework": "langgraph"
},
"Modules": ["Chat", "Build", "Deploy"],
"Capabilities": {
"Attachments": true,
"WorkspaceFiles": true,
"Approval": true,
"Thinking": true,
"StopRun": true,
"ResumeRun": true,
"RuntimeCapabilities": { /* runner.get_runtime_capabilities() echoed verbatim */ },
"CheckpointResumeCapability": {
"Supported": true,
"Checkpoint": {},
"ResumeRun": {}
},
"RunLifecycle": {
"Enabled": true,
"Resume": true,
"Abort": true,
"Checkpoints": true,
"CheckpointResume": true,
"CheckpointResumePreview": true
},
"MCP": false,
"HostedRuntime": false,
"NativeTerminal": { "Enabled": false, "Mode": null, "Protocol": "ks-terminal.v1", "Path": null },
"BuiltinTools": []
},
"WorkspaceFiles": { "Enabled": true },
"AccessMode": "Owner",
"SharePermissions": { "Interactive": true, "DefaultPath": "/chat", "SharePath": "/chat" },
"CustomUI": {
"Enabled": false,
"Profile": null,
"Path": null,
"Url": null,
"BundlePath": null
},
"ApiFormats": ["responses", "chat_completions"],
"Stream": true,
"SessionId": "local-demo-session",
"SessionBackend": "memory",
"HostedRuntime": null,
"Model": { "id": "glm-5.1", "source": "OPENAI_MODEL_NAME", /* ... */ }
}
}Top-level Data fields:
| Field | Notes |
|---|---|
Agent | Agent id / name / description / framework (from detection_result) |
Modules | UI module list |
Capabilities | Runtime capability set, see table below |
WorkspaceFiles | Workspace files bootstrap |
AccessMode | Access mode, always Owner |
SharePermissions | Sharing and default paths |
CustomUI | Custom UI resource info (0.6.7 normalized) |
ApiFormats | Supported API shapes: responses, chat_completions |
Stream | Whether streaming is supported |
SessionBackend | Session backend description (memory / postgres, etc.) |
Model | Current model metadata |
Capabilities sub-fields:
| Field | Notes |
|---|---|
Attachments / WorkspaceFiles | Attachment and workspace files capabilities |
Approval / Thinking / StopRun / ResumeRun | Run-control capabilities |
RuntimeCapabilities | Capability set returned verbatim by the runner (includes Checkpoint, ResumeRun, etc.) |
CheckpointResumeCapability | 0.6.7 normalized: Supported + Checkpoint + ResumeRun detail |
RunLifecycle | 0.6.7 normalized: run lifecycle semantics (Resume, Abort, Checkpoints, CheckpointResume, CheckpointResumePreview) |
MCP / HostedRuntime | Platform capability flags, currently fixed false |
NativeTerminal | Terminal capability (Enabled / Mode / Protocol / Path) |
BuiltinTools | Builtin tool descriptions |
CustomUI sub-fields (0.6.7):
| Field | Notes |
|---|---|
Enabled | Whether custom UI is enabled |
Profile | UI profile name |
Path / Url | Custom UI path or external URL |
BundlePath | Custom UI bundle path |
0.6.7 capability visibility
CheckpointResumeCapability and RunLifecycle are 0.6.7-normalized
capability descriptors. Callers should use these to decide whether
checkpoint/resume is available; if Supported is false or
RunLifecycle.CheckpointResume is false, treat checkpoint/resume as
unsupported.
Checkpoint and Resume Actions
New in 0.6.7
The four action paths below are allow-listed by the gateway Hosted UI filter,
POST /agentengine/api/v1/*. Public API clients usually do not target these
directly; prefer /v1/*.
| Action | Method and path | Purpose |
|---|---|---|
ListSessionCheckpoints | POST /agentengine/api/v1/ListSessionCheckpoints | List checkpoints under a session for resume selection |
GetCheckpointResumePreview | POST /agentengine/api/v1/GetCheckpointResumePreview | Preview the content and impact of resuming from a checkpoint |
ResumeRun | POST /agentengine/api/v1/ResumeRun | Resume a run from a checkpoint |
CancelRun | POST /agentengine/api/v1/CancelRun | Cancel an in-flight run |
Capability visibility is governed by the RunLifecycle and RuntimeCapabilities
(including CheckpointResumeCapability) returned by GetAgentUiBootstrap. If
bootstrap does not declare the capability, callers should treat checkpoint/resume
as unsupported.
ListSessionCheckpoints
POST /agentengine/api/v1/ListSessionCheckpoints:
| Field | Type | Required | Notes |
|---|---|---|---|
AgentId / SessionId | string | yes | Session location |
RunId | string | no | Filter by run |
Framework | string | no | Filter by framework |
OnlyResumable | bool | no | Only return resumable checkpoints, default false |
Offset / Limit | int | no | Pagination, Limit range 1..500 |
Returns a Checkpoints array; each element includes RunId, CheckpointId,
Framework, FrameworkRef, IsResumable, ResumeStatus, IsTerminal,
CheckpointStatus, Backend, Scope, Durable, ResumeCount,
ReplayAllowed, and ExpiresAt.
GetCheckpointResumePreview
POST /agentengine/api/v1/GetCheckpointResumePreview:
| Field | Type | Required | Notes |
|---|---|---|---|
AgentId / SessionId | string | yes | Session location |
RunId / CheckpointId | string | yes | Checkpoint location |
Returns Preview containing Checkpoint, Capabilities, CanResume, Reason,
NextNode, ExpectedAction, ToolReceipts, Risk (with Level and side-effect
counts), and Summary.
ResumeRun
POST /agentengine/api/v1/ResumeRun:
| Field | Type | Required | Notes |
|---|---|---|---|
AgentId / SessionId | string | yes | Session location |
RunId / CheckpointId | string | yes | Checkpoint location |
ResumeAttemptId | string | no | Resume attempt id; runtime generates one when omitted |
InvocationId | string | no | Invocation id passed through to the runner |
Stream | bool | no | true returns SSE |
Model / ModelMetadata / ModelOptions | string / object | no | Model parameter pass-through |
ResumeInstructionEnabled | bool | no | 0.6.7 Whether to allow injecting a resume instruction |
ResumeInstruction | string | no | 0.6.7 resume instruction text |
A terminal checkpoint returns status: "noop" rather than 409 to avoid
blocking the UI. A non-terminal but non-resumable checkpoint returns 409.
GetAgentUiBootstrap
GetAgentUiBootstrap returns the bootstrap metadata for hosted UI rendering and
capability discovery; the field table is in the UI Bootstrap
section above.
Pagination Fields
ListSessions and ListSessionEvents support pagination but use different
field names:
| Endpoint | Field group | Fields |
|---|---|---|
ListSessions | page-based | Page, PageSize, Total |
ListSessionEvents | offset-based | Offset, Limit, Total |
ListSessionCheckpoints | offset-based | Offset, Limit, Total |
When resolving an ae-upload:// attachment, AttachmentContent uses the
ae-upload:// prefix to locate hosted upload content and returns its byte
stream; paths without that prefix are treated as workspace-relative paths.
RunAgent Pass-through Fields
RunAgent (hosted UI action) passes request-level model parameters through to
the runner, just like /v1/responses and /v1/chat/completions:
| Field | Meaning |
|---|---|
ModelMetadata | Model metadata, including reasoning, multimodal, context_window_tokens |
ModelOptions | Request-level model options (temperature, max_tokens, etc.) |
ModelMetadata.reasoning flags reasoning mode, multimodal flags multimodal
capability, and context_window_tokens flags the model context window size.
Workspace Files
Code-framework runtimes, and runtime products that enable the KsADK workspace surface, can all use the workspace routes.
- List files.
- Get file content or metadata.
- Add or update a file.
- Delete a file when allowed.
- Export a workspace archive when supported.
The hosted UI download surfaces typically include:
GET /agentengine/api/v1/AttachmentContentGET /agentengine/api/v1/GetWorkspaceFileContentGET /agentengine/api/v1/ExportWorkspaceZip
All paths must be relative to the workspace root. Public examples must not expose host absolute paths.
Hermes-Specific Boundary
Hermes wraps its own dashboard and API server. The public docs only describe these surfaces:
| Surface | Purpose |
|---|---|
/ | Hermes dashboard |
/v1/* | Hermes API proxy surface |
/_ksadk/workspace/v1/* | KsADK workspace files |
/_ksadk/terminal/ws | terminal WebSocket |
Terminal clients must use:
Sec-WebSocket-Protocol: ks-terminal.v1OpenClaw-Specific Boundary
The upstream OpenClaw gateway owns its native routes. KsADK public docs only commit to the platform-supplemented contract:
| Surface | Purpose |
|---|---|
| OpenClaw gateway root | OpenClaw native UI and API |
/_ksadk/workspace/v1/* | KsADK workspace files |
| health route | Gateway liveness exposed by the runtime product |
Do not write every upstream OpenClaw native endpoint as a KsADK contract unless it is implemented or stabilized by KsADK.
Streaming Output
Streaming calls use SSE:
Accept: text/event-streamClients should handle text deltas, tool events, errors, and completion events. LangGraph and ADK internal events may differ, but public clients should consume the runtime-normalized stream.
Public Doc Rules
Public examples must not include private endpoint hostnames, real API keys, gateway tokens, cookies, kdocs tokens, internal forwarded headers, kubeconfig paths, cluster names, private image registries, customer data, session ids, or workspace paths.