> Source: https://wexa.ai/docs/automation/run-process-flow

# run-process-flow

[Can be held for approval](/docs/sdks-and-apis/how-every-tool-call-works#lifecycle-and-governance)

Run a process flow against the knowledge base. It returns an `execution_id` for `get-execution`. Needs the `fabric:agent.run` grant.

**Run a process flow**

**Wexa MCP server**

```bash
curl -sS -X POST https://fabric.wexa.ai/mcp/$FABRIC_PROJECT_ID \
  -H "authorization: Bearer $FABRIC_API_KEY" \
  -H "Mcp-Session-Id: $MCP_SESSION_ID" \
  -H "content-type: application/json" -H "accept: application/json" \
  -d '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"run-process-flow","arguments":{"process_flow_id":"6ab1945e7566f41b5c28e308","goal":"Reply OK."}}}'
```

```json
{
  "content": [
    {
      "type": "text",
      "text": "{\"lifecycle_id\":\"qlc_000185\",\"result\":{\"execution_id\":\"d8b83fa9-afa7-4619-886f-55fafe5c9bc6\",\"agentflow_id\":\"6ab1945e7566f41b5c28e308\",\"agentflow_name\":\"docs-fixture-flow\",\"goal\":\"Reply OK.\",\"status\":\"running\"}}"
    }
  ],
  "isError": false
}
```

**REST API**

```bash
curl -sS https://fabric.wexa.ai/v1/run-process-flow \
  -H "authorization: Bearer $FABRIC_API_KEY" \
  -H "content-type: application/json" \
  -d '{"process_flow_id":"6ab1945e7566f41b5c28e308","goal":"Reply OK."}'
```

```json
{
  "lifecycle_id": "qlc_000185",
  "result": {
    "execution_id": "d8b83fa9-afa7-4619-886f-55fafe5c9bc6",
    "agentflow_id": "6ab1945e7566f41b5c28e308",
    "agentflow_name": "docs-fixture-flow",
    "goal": "Reply OK.",
    "status": "running"
  }
}
```

**TypeScript SDK**

```ts
import { Fabric } from '@wexa-fabric/sdk'

const fabric = new Fabric()
const result = await fabric.runProcessFlow({
  process_flow_id: '6ab1945e7566f41b5c28e308',
  goal: 'Reply OK.'
})
```

```ts
// result is the payload itself, with no `.result` to read
{
  execution_id: 'd8b83fa9-afa7-4619-886f-55fafe5c9bc6',
  agentflow_id: '6ab1945e7566f41b5c28e308',
  agentflow_name: 'docs-fixture-flow',
  goal: 'Reply OK.',
  status: 'running'
}
```

**Python SDK**

```python
from wexa import Fabric

fabric = Fabric()
out = fabric.run_process_flow(
    process_flow_id="6ab1945e7566f41b5c28e308",
    goal="Reply OK.",
)
```

```python
# out is the result, already unwrapped
{
    "execution_id": "d8b83fa9-afa7-4619-886f-55fafe5c9bc6",
    "agentflow_id": "6ab1945e7566f41b5c28e308",
    "agentflow_name": "docs-fixture-flow",
    "goal": "Reply OK.",
    "status": "running"
}
```

## Parameters

| Parameter | Type | Required | Notes |
| --- | --- | --- | --- |
| `goal` | string | Required | Natural-language goal for this run. |
| `agentflow_id` | string | Optional | Alias for `process_flow_id`. One of the two is required. |
| `files` | array | Optional | File ids for execution context. Do not pass for now: it makes the execution unreadable (see More details). |
| `flow_name` | string | Optional | Only for compiler (factory) process flows: appended to the goal as the name for the output manifest. It does not select which process flow runs. |
| `input_variables` | object | Optional | Input variables. Ignored on a process flow made from code; put the values in `goal`. |
| `kb_tags` | array | Optional | Extends (does not replace) a knowledge-base agent's tag filter for this run only. Must be an array. See More details. |
| `process_flow_id` | string | Optional | Process flow id to run. Required unless `agentflow_id` is given. A process flow in this project; not found is reported as 502 here. |
| `session_id` | string | Optional | Conversation id that groups several calls as one conversation. |
| `start_from_agent_id` | string | Optional | Agent id to start from, instead of the process flow's first agent. An agent inside that flow; not found is reported as 502 here. |

**Errors**

- `UpstreamError` (502): the id names a single agent, not a process flow; the error says to use `run-agent`.

**Show full response**

A real response, captured from a live call to `run-process-flow`:

`agentflow` came back populated and is shown as `…` here, because the real value runs to
thousands of characters. Read it from your own call rather than from this page.

**Result of run-process-flow**

**REST API**

```json
{
  "lifecycle_id": "qlc_000185",
  "result": {
    "agent_type": "Task",
    "agent_version": null,
    "agentflow": "\u2026",
    "agentflow_id": "6ab1945e7566f41b5c28e308",
    "agentflow_name": "docs-fixture-flow",
    "agents_output": [],
    "anomaly_detected": null,
    "application_user_id": "6a79a770b6c128ccc24bfca7",
    "conclusion": null,
    "created_at": 1790023297.303432,
    "duration_ms": null,
    "end_time": null,
    "executed_by": {
      "_id": "6a79a770b6c128ccc24bfca7",
      "application_user_id": "6a79a770b6c128ccc24bfca7",
      "is_external_application": true,
      "metadata": null,
      "name": "6a79a770b6c128ccc24bfca7",
      "type": "api"
    },
    "execution_context": {},
    "execution_id": "d8b83fa9-afa7-4619-886f-55fafe5c9bc6",
    "files": [],
    "goal": "Reply OK.",
    "goal_template": null,
    "input_variables": {},
    "interop_ask": null,
    "interop_resume": null,
    "is_external_application": true,
    "kb_tags": [],
    "parent_execution_id": null,
    "previews": {},
    "projectID": "6aa9beb7ec8121a43b6c791b",
    "runtime_inputs": {},
    "schedule": null,
    "session_id": null,
    "simulation": false,
    "start_from_agent_id": null,
    "status": "running",
    "task_id": "6ab196817566f41b5c28e31d",
    "total_price": null,
    "total_tokens": null,
    "trigger_source": "api"
  }
}
```

**TypeScript SDK**

```ts
// the object you get back IS the result — there is no `.result` to read
{
  agent_type: 'Task',
  agent_version: null,
  agentflow: '…',
  agentflow_id: '6ab1945e7566f41b5c28e308',
  agentflow_name: 'docs-fixture-flow',
  agents_output: [],
  anomaly_detected: null,
  application_user_id: '6a79a770b6c128ccc24bfca7',
  conclusion: null,
  created_at: 1790023297.303432,
  duration_ms: null,
  end_time: null,
  executed_by: {
    _id: '6a79a770b6c128ccc24bfca7',
    application_user_id: '6a79a770b6c128ccc24bfca7',
    is_external_application: true,
    metadata: null,
    name: '6a79a770b6c128ccc24bfca7',
    type: 'api'
  },
  execution_context: {},
  execution_id: 'd8b83fa9-afa7-4619-886f-55fafe5c9bc6',
  files: [],
  goal: 'Reply OK.',
  goal_template: null,
  input_variables: {},
  interop_ask: null,
  interop_resume: null,
  is_external_application: true,
  kb_tags: [],
  parent_execution_id: null,
  previews: {},
  projectID: '6aa9beb7ec8121a43b6c791b',
  runtime_inputs: {},
  schedule: null,
  session_id: null,
  simulation: false,
  start_from_agent_id: null,
  status: 'running',
  task_id: '6ab196817566f41b5c28e31d',
  total_price: null,
  total_tokens: null,
  trigger_source: 'api'
}

// The TS SDK names these camelCase — lifecycleId, traceId — where Python uses
// lifecycle_id and trace_id. Both are non-enumerable: readable, but omitted by
// Object.keys() and JSON.stringify(). `result.lifecycleId` here is undefined.
result.lifecycleId // 'qlc_000185'
```

**Python SDK**

```python
# a dict subclass; `result` is already unwrapped
{
 "agent_type": "Task",
 "agent_version": None,
 "agentflow": "\u2026",
 "agentflow_id": "6ab1945e7566f41b5c28e308",
 "agentflow_name": "docs-fixture-flow",
 "agents_output": [],
 "anomaly_detected": None,
 "application_user_id": "6a79a770b6c128ccc24bfca7",
 "conclusion": None,
 "created_at": 1790023297.303432,
 "duration_ms": None,
 "end_time": None,
 "executed_by": {
  "_id": "6a79a770b6c128ccc24bfca7",
  "application_user_id": "6a79a770b6c128ccc24bfca7",
  "is_external_application": True,
  "metadata": None,
  "name": "6a79a770b6c128ccc24bfca7",
  "type": "api"
 },
 "execution_context": {},
 "execution_id": "d8b83fa9-afa7-4619-886f-55fafe5c9bc6",
 "files": [],
 "goal": "Reply OK.",
 "goal_template": None,
 "input_variables": {},
 "interop_ask": None,
 "interop_resume": None,
 "is_external_application": True,
 "kb_tags": [],
 "parent_execution_id": None,
 "previews": {},
 "projectID": "6aa9beb7ec8121a43b6c791b",
 "runtime_inputs": {},
 "schedule": None,
 "session_id": None,
 "simulation": False,
 "start_from_agent_id": None,
 "status": "running",
 "task_id": "6ab196817566f41b5c28e31d",
 "total_price": None,
 "total_tokens": None,
 "trigger_source": "api"
}

out.lifecycle_id  # 'qlc_000185' — an attribute, not a key
```

**More details**

Running starts a real, side-effecting run, as running an agent does. The call returns an `execution_id` and finishes: the run is asynchronous, so you poll the execution with [`get-execution`](/docs/agents/get-execution). A run can be scoped to a slice of the knowledge base by tag, so every agent that reads it sees the same evidence.

For KB-to-process-flow, first run a compiler-style process flow (one designed to classify ingested knowledge base evidence into a process hierarchy). Its terminal agent's output (see `get-execution`'s `last_agent_output`) is a `process_flow_manifest` JSON for [`create-process-flow`](/docs/automation/create-process-flow)'s `manifest` argument.

`kb_tags` is additive alongside `create-process-flow`'s `kb_tags`, `manifest.knowledge_base.tags` and the agent's stored context. It applies only to an agent that already has `has_knowledge_base` set; it does not switch an agent into knowledge-base mode. A `files` run is accepted, and every `get-execution` on it then fails with a `ValidationError` (422).

Every agent in a process flow makes its own governed calls. A policy decision that refuses one agent's call refuses that call, not the process flow's right to exist. The execution's trace shows what happened, and the audit record shows what was refused.

### Known limitations

These are faults in the platform today, each with what to do instead.

**`files` makes the execution unreadable.** A run started with `files` is accepted, and every
`get-execution` on it then fails with a `ValidationError` (422), so you cannot read its status or
conclusion. Do not pass `files` for now. Add the content to the
[knowledge base](/docs/context/knowledge-base-add) and pass its tags in `kb_tags` instead.

**`input_variables` is ignored on a process flow made from code.** Input variables fill only the
process flow's goal template (`goal_structure`), and a process flow made with
`create-process-flow` has none. A `{{name}}` in the `goal` is sent as literal text. A `{{name}}` in
an agent's prompt is worse: the run stops in `awaiting_input`, only the console can supply the
value, and no tool ends the run. Write the values into the `goal` instead.

Marked consequential: it is audited in full, and a policy rule may hold it for a person to approve. See [Policy and approvals](/docs/governance/policy-and-approvals).

Every tool call works the same way: [How every tool call works](/docs/sdks-and-apis/how-every-tool-call-works).
