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:
- Conversation & pipeline endpoints (AI Flow-native) — the chat/“ask” surface.
- Workflow & agent control endpoints (shared cluster handlers) — start/resume/signal/status.
1. Conversation & pipeline
Section titled “1. Conversation & pipeline”POST /workflow/request — submit a turn
Section titled “POST /workflow/request — submit a turn”The core “ask” call. Persists the request, assembles conversation memory, and feeds the record into the tenant’s pipeline.
Body
| Field | Type | Notes |
|---|---|---|
conversationid | ulid | Required. Must belong to the caller. |
instanceid | ulid | Target instance/pipeline. |
inputid | string | The pipeline input port to feed. |
record | object | The payload; record.prompt is the user text. |
inmemory | bool | Whether this turn is retained as conversation memory. |
Behavior
- Loads the tenant’s engine; 400 if none.
- Validates the conversation (
createdby == caller); 400 if not found. - Persists
mlflow_instance_request. - Builds
memoryentriesfrom priorinmemory=trueturns (role:user←record.prompt,role:assistant←record.mlresponse[0].choices[0].message.content). - 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": {...}}}.
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." } }'GET /workflow/request — list requests
Section titled “GET /workflow/request — list requests”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.
GET /workflow/response — list responses
Section titled “GET /workflow/response — list responses”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.
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" }2. Workflow & agent control
Section titled “2. Workflow & agent control”These are shared cluster handlers mounted by AI Flow. They start, resume, signal, cancel, and inspect workflow instances.
Starting a workflow
Section titled “Starting a workflow”| Method | Path | Permission | Notes |
|---|---|---|---|
| POST | /workflow/start | workflow.start | Async start. Also /product/:product/workflow/start. |
| POST | /workflow/start/sync | workflow.start | Synchronous; optional ?async=. |
| POST | /workflow/start/sync/response | workflow.start | Start and block for responses. |
| POST | /workflow/open/start | any-DC-cluster JWT | Cross-cluster async start. |
| POST | /workflow/open/start/sync/response | any-DC-cluster JWT | Cross-cluster start + responses. |
Start body (all optional unless noted; provide one of workflow/workflowname/workflowid/workflowpath):
| Field | Meaning |
|---|---|
workflowname | Name of a deployed definition. |
workflowid | Definition ID. |
workflow | Inline definition object (same shape as a YAML flow). |
workflowpath | Path/URI to a definition. |
starttask | Node to start at (defaults to the first). |
tasklist | Restrict to a subset of tasks. |
context | Initial context (your vars overrides). |
model | Global model routing hint. |
selectors | Per-task selector overrides: { "task-name": { "gpu": true } }. |
affinity, affinity-key, pin-agent, restart-on-failure | Affinity controls. |
tag / workertag, workerdomain, workerid, workerids | Worker routing. |
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" } } }'Resuming, signaling, canceling
Section titled “Resuming, signaling, canceling”| Method | Path | Permission | Body |
|---|---|---|---|
| POST | /workflow/resume, /workflow/event | workflow.resume | instanceid, event, node, data |
| POST | /workflow/signal | workflow.signal | instanceid, signal_name, data — resumes a Wait node |
| POST | /workflow/cancel | workflow.cancel | instanceid |
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"}}'Status & inspection
Section titled “Status & inspection”| Method | Path | Permission | Purpose |
|---|---|---|---|
| GET | /workflow/status | workflow.status | Instance status. Query: instanceid. |
| GET | /workflow/responses | workflow.status | Responses for an instance. Query: instanceid. |
| GET | /workflow/logs, /workflow/open/logs | workflow.logs | Instance logs. |
| GET | /workflow/config | workflow.config | What definitions/tasks the tenant has (API-key or JWT). |
| GET | /workflow/list | workflow.list | List instances. |
| GET | /pipeline/active | JWT | Active pipelines: {"pipelines":[…]}. |
Agents & queue
Section titled “Agents & queue”| Method | Path | Permission | Purpose |
|---|---|---|---|
| GET | /agents | agents.list | List registered agents. |
| GET | /workflow/queue | queue.status | Overflow work-queue state (tenant-scoped). |
| DELETE | /workflow/queue/:id | queue.cancel | Cancel a queued item (ownership-checked). |
Superadmin (/admin/*)
Section titled “Superadmin (/admin/*)”Require CheckSuperAdminAccess (cross-tenant visibility):
| Method | Path |
|---|---|
| GET | /admin/agents, /admin/agents/:id |
| GET | /admin/queue, /admin/instances |
| DELETE | /admin/queue/:id |
3. Generic entity API (v2 surfaces)
Section titled “3. Generic entity API (v2 surfaces)”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.
4. Response envelopes & errors
Section titled “4. Response envelopes & errors”- 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-failedai-flow-request-required-field-not-found(with{{field}})ai-flow-query-parsing-failedai-flow-ctx-tenant-not-found
- Unmatched routes return
404(logged).
5. Notes & known issues
Section titled “5. Notes & known issues”- 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/request400s 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): theinstanceid/conversationidfilter branches currently read theidquery param instead of the matching one. Filter byfilter=orid=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.