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
checkthat 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_flowandedit_flow. The MCP server has exposed its fourteen since@bandura/cli1.0.0-rc.4.
Fourteen tools, and they matter because they are the difference between an assistant that recalls and one that checks:
| Tool | What it does |
|---|---|
list_flows / read_flow | Discover the flows in the workspace and read one’s YAML. |
run_flow | Execute a flow and read per-node results, captured variables and request snapshots. |
describe_node_types | The exact schema this build implements, read from the parser’s own validator. |
lint_flow | Static analysis: unreachable nodes, empty loops, TLS verification off, literal-looking credentials. |
search_flows | Find nodes by type, URL substring, auth type or free text, across every flow. |
search_context | Relevance-ranked search of the workspace, for when it does not yet know where to look. |
get_project_status | A snapshot of the workspace and this build: version, flow and node counts, parse errors. |
list_runs / read_run | The durable run history, including runs you started. |
detect_drift | Compare a flow against an OpenAPI spec, deterministically. |
read_error_log | The tail of the local error log, when the app itself misbehaves. |
create_flow / edit_flow | Propose 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.