AI chat & ai-action nodes

The agentic chat sidebar: fourteen tools, an approval gate on writes, saved conversations, plus a model inside the flow with an ai-action node.

6 min read

Two different tools, one provider (set it up first): chat is you and the model working over your flow together, and it can read, run, and propose edits. ai-action is your flow talking to the model while it runs.

The Chat tab

Open the Chat tab in the inspector. It’s an agentic assistant, not just a Q&A box: your workspace is the context, and the model has tools to act on it. It can list and read your flows, run one and read back the failing node’s real request and response, read a run you started yourself out of the history, and check a flow for drift against an OpenAPI spec, then answer with what it actually found rather than a guess. So questions can be direct:

  • “Why did this assertion fail?” It can run the flow, or read back the run you already did.
  • “Write a check that verifies the response body is a non-empty array of users.”
  • “Which of my flows still send a hardcoded token?”

Enter sends; Shift+Enter makes a newline. If no provider is configured, the chat points you to Settings.

What it can actually do

All fourteen need 1.0.0-rc.5 or newer. rc.4 gives the chat six: list_flows, read_flow, run_flow, detect_drift, create_flow and edit_flow. The MCP server has exposed its fourteen since @bandura/cli 1.0.0-rc.4.

Fourteen tools, and they matter because they are the difference between an assistant that recalls and one that checks:

ToolWhat it does
list_flows / read_flowDiscover the flows in the workspace and read one’s YAML.
run_flowExecute a flow and read per-node results, captured variables and request snapshots.
describe_node_typesThe exact schema this build implements, read from the parser’s own validator.
lint_flowStatic analysis: unreachable nodes, empty loops, TLS verification off, literal-looking credentials.
search_flowsFind nodes by type, URL substring, auth type or free text, across every flow.
search_contextRelevance-ranked search of the workspace, for when it does not yet know where to look.
get_project_statusA snapshot of the workspace and this build: version, flow and node counts, parse errors.
list_runs / read_runThe durable run history, including runs you started.
detect_driftCompare a flow against an OpenAPI spec, deterministically.
read_error_logThe tail of the local error log, when the app itself misbehaves.
create_flow / edit_flowPropose a new flow or an edit, behind the approval gate below.

describe_node_types is worth singling out. It is generated from the validator rather than written by hand, so the assistant is reading the schema this exact build enforces instead of remembering a version of the format from its training data.

Writes are gated

Creating a new flow or editing one comes back as a diff you approve or discard. Nothing is written to disk until you say so, and every file path is checked to stay inside your workspace.

Anything that shows the model a resolved request is redacted first, on the live run path and on the history replay alike. A stored run holds the real Authorization value rather than the ${{ env.TOKEN }} template it came from, so redacting only one of the two would be worth nothing.

Because the chat works by calling tools, the model behind it has to support tool calling. Claude does; so do the mainstream OpenAI-compatible models. A small local model without tool support will talk but won’t act, so pick a tool-capable tag.

Conversations are kept

Needs 1.0.0-rc.5 or newer. On rc.4 and earlier a conversation lives only as long as the panel is open, and there is no context budget and no workspace retrieval.

Conversations survive a restart. They are stored locally in a chat.db file in the app’s user data directory, scoped to the workspace they were had in, titled from their first message, and reachable from the History control in the chat panel.

Turn ai.persistChatHistory off and new conversations stop being written to disk and saved ones stop being listed. It does not delete what is already there.

What it costs to remember

Resending an entire long conversation on every message is how an assistant gets expensive. Two settings bound that, both in settings.json:

  • ai.historyTokenBudget (12000 by default) is roughly how much past conversation gets resent. Older turns beyond it are left out of the request and stay in your saved history regardless.
  • ai.autoCompact (on by default) replaces those oldest turns with a short summary instead of dropping them. It costs one extra request when it happens, and if that request fails the turn proceeds with a plain mechanical summary rather than failing. Saving you money must never be the reason a message goes unanswered.

Automatic workspace retrieval

ai.contextRetrieval is off by default. With it on, every message you send first searches the workspace and attaches the most relevant parts, which costs tokens on every message, billed to your own key. With it off the assistant can still search whenever it decides it needs to, using search_context, which covers the case where retrieval actually helps.

The search is local and lexical, running against an index on your machine. It is not an embedding service, and that is a licence commitment rather than a preference: the EULA names exactly two network requests Bandura makes on its own, and an embedding API call would be a third.

Nothing credential-shaped is indexed. Values under secret-looking field names are withheld when the index is built, and any chunk matching a common credential format is dropped. Those two filters catch credential-shaped names and common credential formats; neither can recognise a bespoke opaque value sitting under an ordinary field name, so treat them as defence in depth rather than a guarantee.

The ai-action node

An ai-action node makes a model call one step of the flow, with the run’s context (response data, variables) available to the prompt:

- id: summarize_failures
  type: ai-action
  config:
    prompt: "Summarize which assertions failed and suggest a fix."
    output: aiSummary # optional: where the reply lands
  next: null

The reply is stored in variables under the output name, readable by every later node, the same as a captured value. On the graph the node shows a thinking state while the model responds.

Good uses: summarizing a batch of results at the end of a run, classifying a free-text response before a condition branches on it, generating varied test data mid-flow.

In the app, ai-action nodes use the same provider as chat. They also run headlessly. The CLI and MCP server read the environment instead: ANTHROPIC_API_KEY (with ANTHROPIC_MODEL to pick the model), GEMINI_API_KEY for Gemini, or BANDURA_AI_BASE_URL plus BANDURA_AI_API_KEY for any OpenAI-compatible endpoint. So an ai-action flow works in CI too, against a hosted API or a model running on the runner itself. Full list: Headless runs.

A caution worth stating: model output isn’t deterministic. For pass/fail decisions in CI, prefer assertion nodes with concrete check expressions, and let ai-action handle the judgment-and-prose work around them.

Next: The MCP server runs the same loop from your coding agent instead, and running a local model keeps every prompt and payload on your machine.

Last updated

Looking for something else? All 37 articles are on one page in the Help Center.