Publish as model
A deployed Core can be registered as a chat model that any OpenAI-compatible client can reach. This is how a ScaiFlow agent becomes addressable from ScaiBot, custom apps, third-party integrations, or just curl.
The flag#
On the flow's Flow properties panel, check Publish as chat model:
"config": {
"publish_as_model": true,
"model_visibility_group_ids": ["group_acme_eng", "group_acme_ops"]
}
The compiler surfaces this on the YAML manifest under manifest.publish_as_model and manifest.model_visibility_group_ids. The deploy step reads them and acts.
What happens at deploy#
- ScaiFlow's
DeployService.deploy_flowfirst callsPOST /v1/modules/scaicore/coresto create the Core (returnscore_id). - If
publish_as_modelistrue, it then callsPOST /v1/modules/scaicore/cores/{core_id}/publishwith optionalgroup_idsasCorePublishRequest.group_ids. - ScaiGrid sets the Core's runtime mode to
modeland registers aFrontendModelreachable via/v1/chat/completionsat slugscaicore/{tenant_slug}/{core.slug}.
The publish call is idempotent — re-deploying with publish_as_model: true updates the registration; toggling it off doesn't currently un-publish (that requires a manual admin call). See Troubleshooting: changing publish state.
Visibility scoping#
The optional model_visibility_group_ids array forwards to ScaiKey-group scoping on the published FrontendModel. Members of any listed group can call the model; others get a 403 from /v1/chat/completions. Leave empty for visibility to the default scope (typically the whole tenant).
Invoking the published model#
1 2 3 4 5 6 7 8 9 10 11 12 | |
The Core's entry node receives the request payload as input (mapping varies by entry kind — for entry_api, the payload's input field is what reaches the trigger's emitted scope).
Why this isn't an entry kind#
There is no entry_chat node. The chat surface is owned by ScaiGrid's /v1/chat/completions endpoint, which routes to a Core via its published slug. The Core itself doesn't have a "chat trigger" — its entry is still api or webhook. The OpenAI-compatible layer is a thin shim ScaiGrid manages.
This split keeps the flow graph honest: there's no special chat-shaped block kind in the IR, no risk of authors trying to mix chat-state-machine semantics into a graph that the runtime would silently ignore.
Conversational state (entity mode)#
Stateless Cores (the default) treat every chat completion request independently. For multi-turn conversations with memory, set the Core's instance mode to entity (per-conversation instance) and use the entity_id field on invocations to thread state. This is a ScaiCore-level concern; ScaiFlow doesn't currently expose instance_mode on the canvas — set it via manifest.scaiflow_meta or compile and deploy manually until the canvas picks it up. See ScaiCore: Instance modes.