> For the complete documentation index, see [llms.txt](https://docs.borndigital.ai/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.borndigital.ai/digital-agent/conversation-flow/nodes-explained/ai-node/response-variable-and-routing.md).

# Response variable and routing

What the AI node stores after each run, how the flow continues, and how to handle errors and timeouts.

## The response variable

After every run, the AI node stores its result in the variable set in **Configuration → Handling the response → Save in variable** (default `gpt_response`). It is a structured variable; refer to its keys like `{gpt_response['response_text']}`.

| Key                                                                      | Content                                                                                                    |
| ------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------- |
| `response_text`                                                          | The answer of the model.                                                                                   |
| `target_node`                                                            | The node chosen by a transfer tool (Redirect to human, Transfer to node, End process), otherwise empty.    |
| `provider`, `model`                                                      | Provider and model used.                                                                                   |
| `previous_messages_count`                                                | The history length used.                                                                                   |
| `saved_to_history`                                                       | Whether the turn was added to the history.                                                                 |
| `reasoning_summary`                                                      | Summary of the model's reasoning (reasoning models, non-streaming only).                                   |
| `web_search`                                                             | `used_web_search`, `web_search_count` and `annotations` (cited sources).                                   |
| `mcp_call`                                                               | The last MCP tool call of the turn: tool `name`, `server_label`, `arguments`, `output`, `status`, `error`. |
| `mcp_calls`                                                              | All MCP tool calls of the turn.                                                                            |
| `mcp_call_sequence`                                                      | All MCP tool calls of the conversation so far.                                                             |
| `mcp_list_tools`                                                         | The MCP tools that were offered to the model.                                                              |
| `bubble_widget_result`                                                   | The widget returned by an MCP tool, if any.                                                                |
| `total_tokens`, `prompt_tokens`, `completion_tokens`, `reasoning_tokens` | Tokens used in the turn, over all model calls.                                                             |
| `time_to_first_sentence`                                                 | Time until the first streamed sentence (streaming only).                                                   |
| `llm_total_response_time`                                                | Time the whole turn took.                                                                                  |

**Example – log what the indexer returned**: `{gpt_response['mcp_call']['output']}`.

## Knowledge base variables

The built-in [Knowledge base tool](/digital-agent/conversation-flow/nodes-explained/ai-node/tools.md) also fills:

* `kb_document_id` – IDs of the documents used,
* `kb_document_name` – their names,
* `kb_document_url` – their URLs.

Each variable holds a list (stored as JSON text) of the documents the model read. Documents from later searches in the conversation are added to it; the list is not cleared. A document without a URL is left out of `kb_document_url`, so the three lists do not always line up item by item.

The old AI node stored a single document in each of these variables instead – see [Migrating from the old AI node](/digital-agent/conversation-flow/nodes-explained/ai-node/migrating-from-the-old-ai-node.md).

{% hint style="info" %}
`indexer_returned` is filled only by the old AI node. In AI node 2.0, use `mcp_call` (Indexer MCP server) or the `kb_document_*` variables (Knowledge base tool).
{% endhint %}

## Where the flow continues

* Normally to the node set in **Next** in the footer of the editor.
* **Dynamic** (switch next to **Next**) takes the name of the next node from a variable — useful when the target depends on the conversation.
* When the model uses a transfer tool, the flow continues to the chosen node. The editor adds the conditions on `target_node` automatically.

## Errors and timeouts

The AI node never stops the conversation. When something goes wrong, the response variable contains only two keys:

```
{"response_text": "", "error": "<what went wrong>"}
```

| `error` starts with                | Cause                                                                                   |
| ---------------------------------- | --------------------------------------------------------------------------------------- |
| `AI node timeout reached`          | The model did not answer within the **Timeout**.                                        |
| `LLM Connector error`              | The provider returned an error (for example an overloaded model or rejected content).   |
| `AI Node configuration is invalid` | A setting of the node is not valid — usually after editing the flow in the code editor. |
| anything else                      | For example a knowledge-base index that does not exist.                                 |

An error in an **MCP tool** is different: it is reported to the model, which can still answer, and it is recorded in `mcp_call`.

**Recommended pattern:** after an AI node that talks to the user, add a DECISION node that checks whether `{gpt_response['response_text']}` is empty. If it is, play a fallback message (*"Sorry, I could not process that, please try again."*) or hand the conversation over to an operator.

{% hint style="warning" %}
With **Stream sentences** on, the sentences sent before an error have already reached the user.
{% endhint %}
