Skip to content
Talk to our solutions team

AI Flow API

Reference for the aiflow.svc (AI Flow) HTTP surface. For concepts and authoring see the AI Flow docs.

The HTTP surface of AI Flow (aiflow.svc). Routes are registered in rest/root.go.

  • Base URL: your deployment host (e.g. https://ai-ml.example.com).
  • Content type: application/json.
  • Auth: Authorization: Bearer <JWT> on most routes; some accept an API key; /workflow/open/* accept a cross-DC-cluster JWT; /admin/* require superadmin.
  • Authorization: most workflow routes are additionally checked against per-tenant access rules by permission name (e.g. workflow.start). A denied call returns 403.

Two families of endpoints share this service:

  1. Conversation & pipeline endpoints (AI Flow-native) — the chat/“ask” surface.
  2. Workflow & agent control endpoints (shared cluster handlers) — start/resume/signal/status.

The core “ask” call. Persists the request, assembles conversation memory, and feeds the record into the tenant’s pipeline.

Body

FieldTypeNotes
conversationidulidRequired. Must belong to the caller.
instanceidulidTarget instance/pipeline.
inputidstringThe pipeline input port to feed.
recordobjectThe payload; record.prompt is the user text.
inmemoryboolWhether this turn is retained as conversation memory.

Behavior

  1. Loads the tenant’s engine; 400 if none.
  2. Validates the conversation (createdby == caller); 400 if not found.
  3. Persists mlflow_instance_request.
  4. Builds memoryentries from prior inmemory=true turns (role:userrecord.prompt, role:assistantrecord.mlresponse[0].choices[0].message.content).
  5. Dispatches into the flow engine via SendDataPipeRecord(instanceid, inputid, record, {conversationid, environment}).

Response: the created request row, in the v1 envelope {"data":{"mlflow_instance_request": {...}}}.

Terminal window
curl -X POST https://<host>/workflow/request \
-H "Authorization: Bearer $JWT" -H "Content-Type: application/json" \
-d '{
"conversationid": "01H..",
"instanceid": "01HB..",
"inputid": "user-input",
"inmemory": true,
"record": { "prompt": "Summarize the Q3 report." }
}'

Query params: id, instanceid, conversationid, filter (SQL-fragment), page (default 1), pagesize (default 10000 = “all”). Always scoped to createdby = <caller>, ordered createdon desc.

POST /workflow/response — persist a response

Section titled “POST /workflow/response — persist a response”

Body mirrors a mlflow_instance_response row (instanceid, outputid, record, conversationid, inmemory). Returns the created row.

Same query semantics as GET /workflow/request.

POST /workflow/conversation — create a conversation

Section titled “POST /workflow/conversation — create a conversation”

Body: instanceid (required), title, description, context. The caller’s user identity is injected into context.user. Returns the created conversation.

Terminal window
curl -X POST https://<host>/workflow/conversation \
-H "Authorization: Bearer $JWT" -H "Content-Type: application/json" \
-d '{"instanceid":"01HB..","title":"Q3 review"}'

GET /workflow/conversation — list conversations

Section titled “GET /workflow/conversation — list conversations”

Eager-loads child mlflow_instance_request + mlflow_instance_response rows. Query: id, instanceid, filter, page, pagesize. Scoped to the caller.

GET /workflow/conversation/:id/memory — read memory

Section titled “GET /workflow/conversation/:id/memory — read memory”

Returns the in-memory turns for a conversation, sorted ascending by createdon:

{ "id": "01H..", "memory": [ { "role": "user", "prompt": "" }, ] }

PUT /workflow/conversation/:id/memory/clean — evict memory

Section titled “PUT /workflow/conversation/:id/memory/clean — evict memory”

Soft-evicts: sets inmemory=false on every memory entry (nothing is deleted).

{ "id": "01H..", "message": "memory cleaned successfully for the conversation" }

These are shared cluster handlers mounted by AI Flow. They start, resume, signal, cancel, and inspect workflow instances.

MethodPathPermissionNotes
POST/workflow/startworkflow.startAsync start. Also /product/:product/workflow/start.
POST/workflow/start/syncworkflow.startSynchronous; optional ?async=.
POST/workflow/start/sync/responseworkflow.startStart and block for responses.
POST/workflow/open/startany-DC-cluster JWTCross-cluster async start.
POST/workflow/open/start/sync/responseany-DC-cluster JWTCross-cluster start + responses.

Start body (all optional unless noted; provide one of workflow/workflowname/workflowid/workflowpath):

FieldMeaning
workflownameName of a deployed definition.
workflowidDefinition ID.
workflowInline definition object (same shape as a YAML flow).
workflowpathPath/URI to a definition.
starttaskNode to start at (defaults to the first).
tasklistRestrict to a subset of tasks.
contextInitial context (your vars overrides).
modelGlobal model routing hint.
selectorsPer-task selector overrides: { "task-name": { "gpu": true } }.
affinity, affinity-key, pin-agent, restart-on-failureAffinity controls.
tag / workertag, workerdomain, workerid, workeridsWorker routing.
Terminal window
curl -X POST https://<host>/workflow/start/sync/response \
-H "Authorization: Bearer $JWT" -H "Content-Type: application/json" \
-d '{
"workflowname": "deployment-pipeline",
"context": { "strategy": "canary", "version": "2.1.0" },
"selectors": { "build-one-service": { "tag": "builder" } }
}'
MethodPathPermissionBody
POST/workflow/resume, /workflow/eventworkflow.resumeinstanceid, event, node, data
POST/workflow/signalworkflow.signalinstanceid, signal_name, data — resumes a Wait node
POST/workflow/cancelworkflow.cancelinstanceid
Terminal window
curl -X POST https://<host>/workflow/signal \
-H "Authorization: Bearer $JWT" -H "Content-Type: application/json" \
-d '{"instanceid":"01HB..","signal_name":"approved","data":{"approver_name":"alice"}}'
MethodPathPermissionPurpose
GET/workflow/statusworkflow.statusInstance status. Query: instanceid.
GET/workflow/responsesworkflow.statusResponses for an instance. Query: instanceid.
GET/workflow/logs, /workflow/open/logsworkflow.logsInstance logs.
GET/workflow/configworkflow.configWhat definitions/tasks the tenant has (API-key or JWT).
GET/workflow/listworkflow.listList instances.
GET/pipeline/activeJWTActive pipelines: {"pipelines":[…]}.
MethodPathPermissionPurpose
GET/agentsagents.listList registered agents.
GET/workflow/queuequeue.statusOverflow work-queue state (tenant-scoped).
DELETE/workflow/queue/:idqueue.cancelCancel a queued item (ownership-checked).

Require CheckSuperAdminAccess (cross-tenant visibility):

MethodPath
GET/admin/agents, /admin/agents/:id
GET/admin/queue, /admin/instances
DELETE/admin/queue/:id

AI Flow auto-mounts the platform data layer-api’s v2 REST and Schema surfaces, exposing generic per-entity CRUD and schema introspection for the mlflow_* entities, backed by the per-tenant engine. Consult the the platform data layer-api surface docs for the exact routes; these are primarily for tooling and admin use rather than the flow-authoring path.

  • Success (native handlers): the v1 envelope {"data":{"<entity>": row | [rows]}}, preserved for backward compatibility across the v1→v2 migration.
  • Errors use codes prefixed ai-flow-…, e.g.:
    • ai-flow-json-request-parse-failed
    • ai-flow-request-required-field-not-found (with {{field}})
    • ai-flow-query-parsing-failed
    • ai-flow-ctx-tenant-not-found
  • Unmatched routes return 404 (logged).
  • Tenant required. Every request resolves a CPET tenant from its JWT/headers; a missing tenant yields ai-flow-ctx-tenant-not-found.
  • Engine must be loaded. POST /workflow/request 400s if the tenant’s engine hasn’t been initialized yet (the service gates its HTTP surface on the first workflow load, so this is rare after startup).
  • Known bug (handle_get_pipeline_request.go / handle_get_pipeline_response.go): the instanceid/conversationid filter branches currently read the id query param instead of the matching one. Filter by filter= or id= until fixed.

See the authoring flows doc for how to write the flows these endpoints run, and concepts for the objects (instance, conversation, memory) these endpoints act on.