Skip to main content

Server-Side Flows

Flows on Bowrain Server execute the same processing pipelines available in the CLI, but triggered by events, automations, or manual API calls. Server-side flows run in the background, process content from the ContentStore, and write results back — no local CLI needed.

How Server-Side Flows Work

When a flow runs on the server, it follows this lifecycle:

Eventconnector.push.completedtriggerAutomation rule matchesauto_translateEnqueue translation jobs → workerreadRead blocks from ContentStorestore bindingtoolsProcess through tool pipelinewriteWrite results to ContentStorestore bindingemitEmit flow.completed / flow.failedintended, not yet emitted

Unlike CLI flows that read/write local files, server-side flows operate on the ContentStore — the server's persistent block storage. This means flows can run without any CLI connected.

Triggering Flows

Via Automation Rules

The most common way to run server-side flows is through automation rules. See Automation for details on creating rules.

Example: automatically translate content when it arrives from a connector push:

{
"name": "auto-translate",
"trigger": "connector.push.completed",
"action": {
"type": "run_flow",
"config": {
"flow": "translate",
"target_locales": ["fr", "de", "ja"]
}
}
}

Via API

Trigger a flow manually through the REST API:

# Start a flow execution
curl -X POST https://app.bowrain.cloud/api/v1/projects/:id/flows/run \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"flow": "translate",
"config": {
"target_locales": ["fr"],
"provider": "anthropic",
"model": "claude-sonnet-4.5"
}
}'

# Response:
# {
# "execution_id": "exec-abc123",
# "status": "running",
# "flow": "translate",
# "started_at": "2026-03-09T14:30:00Z"
# }

Via Web UI

The Bowrain web app exposes a superset flow + automation editor under Project > Automations, with three tabs:

  1. Runs — automation run history (see Automation).
  2. Rules — trigger, CEL conditions, and ordered actions. A run_flow action selects a flow from the project's flow registry.
  3. Flows — the flow canvas. This is the same @neokapi/flow-editor component the desktop apps render, wired to the flow-definition REST API. It lists the built-in flows alongside the project's stored flows and edits the latter on a reader → tool(s) → writer graph; transformers such as redaction and normalization are ordinary ordered steps whose placement is validated when the flow is built.

Flows are connector-agnostic: a flow runs server-side on content from any connector. The graph never names one — content that arrived from a content platform, a design tool, a repository, or a developer's checkout is handled identically.

Monitoring Executions

Polling Status

# Check execution status
curl https://app.bowrain.cloud/api/v1/projects/:id/flows/executions/:execId \
-H "Authorization: Bearer $TOKEN"

# Response:
# {
# "execution_id": "exec-abc123",
# "status": "completed",
# "flow": "translate",
# "started_at": "2026-03-09T14:30:00Z",
# "completed_at": "2026-03-09T14:30:42Z",
# "blocks_processed": 47,
# "summary": {
# "translated": 45,
# "skipped": 2
# }
# }

Execution States

StatusDescription
pendingQueued, waiting to start
runningCurrently processing blocks
completedFinished successfully
failedStopped due to an error
cancelledCancelled by user or timeout

Listing Executions

# List recent executions for a project
curl https://app.bowrain.cloud/api/v1/projects/:id/flows/executions \
-H "Authorization: Bearer $TOKEN"

# Filter by flow name
curl "https://app.bowrain.cloud/api/v1/projects/:id/flows/executions?flow=translate" \
-H "Authorization: Bearer $TOKEN"

# Filter by status
curl "https://app.bowrain.cloud/api/v1/projects/:id/flows/executions?status=failed" \
-H "Authorization: Bearer $TOKEN"

Event Flow Diagram

One end-to-end example — the developer route, where a checkout pushes and the server runs the flow. Content arriving through any other connector follows the same server-side path:

DeveloperkapiBowrain ServerTranslatorkapi pushEvent: connector.push.completedAutomation: run translateread → translate → writekapi pullOpen editor, review, approve

Managing Flow Definitions

Project flow definitions are stored server-side and exposed through a project-scoped REST API. The flow editor in the web app (and the desktop apps) drives these endpoints; automations reference a flow by its id.

MethodPathDescription
GET/api/v1/:ws/:id/flowsList flows (built-in catalog + project flows)
GET/api/v1/:ws/:id/flows/:flowIdGet one flow (built-in or project)
POST/api/v1/:ws/:id/flowsCreate a project flow
PUT/api/v1/:ws/:id/flows/:flowIdReplace a project flow
DELETE/api/v1/:ws/:id/flows/:flowIdDelete a project flow

Built-in flows are read-only — the server rejects writes to a flow whose id collides with a built-in. Mutations require the manage_automation permission.

A flow definition is a node/edge graph (reader → tool(s) → writer) rather than a flat step list, so it round-trips losslessly through the visual editor:

curl -X POST https://app.bowrain.cloud/api/v1/acme/proj-1/flows \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "translate-with-qa",
"description": "Translate then run quality checks",
"nodes": [
{"id": "reader", "type": "reader", "name": "auto", "position": {"x": 0, "y": 0}},
{"id": "translate", "type": "tool", "name": "translate", "position": {"x": 250, "y": 0}},
{"id": "qa", "type": "tool", "name": "qa", "position": {"x": 500, "y": 0}},
{"id": "writer", "type": "writer", "name": "auto", "position": {"x": 750, "y": 0}}
],
"edges": [
{"id": "e1", "source": "reader", "target": "translate"},
{"id": "e2", "source": "translate", "target": "qa"},
{"id": "e3", "source": "qa", "target": "writer"}
]
}'

On the developer route, flow definitions can also live in a project's .kapi/flows/ directory and be pushed with the rest of the project.

Composing multi-step work

Multi-step work composes inside a single flow definition — the node graph above chains translate and QA in one run. There is no flow-to-flow chaining: automations react to content events such as connector.push.completed with a fixed set of actions (translate, extract, notify, review tasks, overlay writes — see Automation), and the flow.completed event is defined but not yet emitted, so no automation can react to a flow finishing. See Automation > Loop Prevention for how the automation engine bounds event-driven work.