Documentation — Architecture

# AI Layer — TuneBot & DBA Agent

These are two different systems that happen to share an API key. TuneBot answers questions about Oracle in general, grounded in documentation. DBA Agent investigates your database specifically, by actually querying it. Neither is "AI chat bolted onto a dashboard" — the mechanisms are genuinely different, and worth telling apart.

## TuneBot: retrieval, not memorization

A general-purpose model asked a specific Oracle question will often answer fluently and confidently — and sometimes wrong. TuneBot avoids this by never answering from the model's general training alone. Every question is embedded into a vector and matched by cosine similarity against a corpus of chunked, embedded Oracle documentation.

db/oracle-docs.js — the actual retrieval query
SELECT doc_name, content, 1 - (embedding <=> $1::vector) AS similarity FROM oracle_doc_chunks ORDER BY embedding <=> $1::vector LIMIT $2

The `<=>` operator is pgvector's cosine distance, run against an `ivfflat` index for speed at scale. Matches below a 0.3 similarity threshold are dropped entirely — if nothing in the documentation corpus is genuinely relevant to the question, TuneBot doesn't force a weak match into the answer. The retrieved chunks are injected into the prompt, and the model answers once, grounded in that context, no back-and-forth tool use.

## DBA Agent: a bounded loop with real tools

DBA Agent is a different kind of system entirely — an autonomous loop that can query your actual live database, up to 5 times, deciding after each result whether it has enough information to answer or needs to look further.

Tool | What it does
--- | ---
`run_sql` | Executes an arbitrary read-only query — SELECT/WITH only, enforced by the same guard the SQL Console uses.
`get_active_sessions` | Pulls current session activity.
`get_top_sql` | Pulls top SQL by elapsed time.
`get_health_check` | Reads the connection's most recent health check findings.
`get_addm_findings` | Reads ADDM diagnostic output.

→ Read-only, always. `run_sql` passes through the identical `blockNonSelect` guard used by the SQL Console — a write statement is rejected before it ever reaches your database.
→ Bounded at 5 iterations. On the final iteration, tools are deliberately withdrawn from the model — it cannot request another lookup, only answer with what it already has. This guarantees the loop terminates in a real answer rather than looping indefinitely.

The interface streams two kinds of events while this runs: a `thinking` event each time a tool is called (so you see "🔍 Running SQL query…" in real time), and `token` events for the final answer as it's generated. You watch the investigation happen, not just wait for a result.

## Why two systems, not one

Collapsing these into a single "AI chat" would blur an important distinction: a question about how Oracle behaves in general has a correct answer that doesn't depend on your database — that's retrieval. A question about why your session is blocked right now has no answer until something actually queries your database — that requires tools and iteration. Using the wrong mechanism for either produces worse results: retrieval can't investigate a live problem, and a tool-calling loop is unnecessary overhead for a documentation question.

## Both fail closed without a key

Neither system silently degrades into a worse answer if `OPENAI_API_KEY` or `ANTHROPIC_API_KEY` isn't set. TuneBot returns a clear "not configured" response. DBA Agent is tier-gated and returns the same. This matters for self-hosted installs specifically — running without an AI key is a fully supported mode, not an error state; every check, score, and finding in the health check engine works identically with or without it.

See Health Check Engine for what DBA Agent's `get_health_check` tool is actually reading, or Architecture Overview for how this fits into the rest of the system.