Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
19faea5
feat(agent): add `dbt-optimizer` agent with 6-lane detection prompt a…
anandgupta42 Aug 12, 2026
0c3c316
fix(agent): address PR #1092 review findings from Bugbot and CodeRabbit
anandgupta42 Aug 12, 2026
3298014
docs: document the `dbt-optimizer` agent (and surface the reviewer) i…
anandgupta42 Aug 12, 2026
db65b3e
fix(agent): address PR #1092 round-2 review findings (lexer guard, de…
anandgupta42 Aug 12, 2026
1a388ce
fix(agent): address PR #1092 round-3 review findings (path resolution…
anandgupta42 Aug 12, 2026
fb2f08b
fix(agent): block PostgreSQL E-string escape bypass in the analyze gu…
anandgupta42 Aug 12, 2026
4e7bbd2
fix(agent): pass `always` in the analyze-gate permission ask (PR #109…
anandgupta42 Aug 12, 2026
5db195b
test(agent): PR #1092 review nits — negation boundary, all-occurrence…
anandgupta42 Aug 12, 2026
03f314a
fix(agent): PR #1092 follow-ups — undecidable rewrites independent of…
anandgupta42 Aug 12, 2026
6fac6c2
fix(agent): enforce tool permissions for built-ins + close side-effec…
anandgupta42 Aug 12, 2026
9e95a1a
fix(agent): PR #1092 round 6 — correct registry exposure via Permissi…
anandgupta42 Aug 12, 2026
ce69169
fix(agent): PR #1092 round 7 — CR-lexing, identifier dollar-signs, un…
anandgupta42 Aug 12, 2026
93a9418
fix(agent): PR #1092 round 8 — invalid-tool exemption, BFS impact dep…
anandgupta42 Aug 12, 2026
c94ae11
fix(agent): quoted-identifier side-effect calls escalate to write (PR…
anandgupta42 Aug 12, 2026
74f6aae
test(agent): live-eval harness hardening from first real runs
anandgupta42 Aug 13, 2026
225cb4d
chore(docs): drop internal research documents from the PR
anandgupta42 Aug 14, 2026
1302039
fix(agent): PR #1092 round 9 — quoted-call comment wedge, bracket ide…
anandgupta42 Aug 14, 2026
03de86f
fix(agent): PR #1092 round 10 — stored approvals cannot override conf…
anandgupta42 Aug 14, 2026
81ec904
fix(agent): PR #1092 round 11 — subscript-visible brackets, session-p…
anandgupta42 Aug 14, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions docs/docs/configure/agents.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ Agents define different AI personas with specific models, prompts, permissions,
|-------|------------|-------------|
| `builder` | Create and modify dbt models, SQL pipelines, and data transformations | Full read/write. SQL mutations prompt for approval. |
| `analyst` | Explore data, run SELECT queries, inspect schemas, generate insights | Read-only (enforced). SQL writes denied. Safe bash commands auto-allowed. |
| `reviewer` | dbt PR review — runs the deterministic verdict engine and posts a signed verdict | Read-only. Edits denied; every bash command prompts. See [dbt PR Review](../usage/dbt-pr-review.md). |
| `dbt-optimizer` | Scan a dbt project for fixable issues (materialization, SQL, DAG, tests) and propose fixes with cost/impact evidence | Read + approval-gated writes. Edits and bash prompt; the direct SQL write tool is denied non-overridably. See [Agent Modes](../data-engineering/agent-modes.md#dbt-optimizer). |
| `plan` | Plan before acting — restricted to planning files only | Minimal — no edits, no bash, no SQL |

### Builder
Expand All @@ -27,6 +29,14 @@ Truly read-only mode for safe data exploration:
!!! tip
Use `analyst` when exploring data to ensure no accidental writes. Switch to `builder` when you're ready to create or modify models.

### Reviewer

Read-only dbt PR reviewer. Runs the `dbt_pr_review` verdict engine (column lineage, query equivalence, PII, grade) and presents the signed verdict. Edits and SQL writes are denied; every bash command prompts for approval. Full details: [dbt PR Review](../usage/dbt-pr-review.md).

### dbt-Optimizer

Scans a dbt project for fixable issues and proposes fixes with cost and impact reporting, in four phases: read-only scan → user selects candidates → verified fixes → impact report/PR. File edits and bash prompt for approval; the direct SQL write tool is denied non-overridably; dbt builds run only as user-approved commands against a dev target. Full details: [Agent Modes → dbt-Optimizer](../data-engineering/agent-modes.md#dbt-optimizer).

### Plan

Planning mode with minimal permissions. Can only read files and edit plan files in `.opencode/plans/`. No SQL, no bash, no file modifications.
Expand Down
75 changes: 69 additions & 6 deletions docs/docs/data-engineering/agent-modes.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
# Agent Modes

altimate runs in one of three specialized modes. Each mode has different permissions, tool access, and behavioral guardrails.
altimate runs in one of five specialized modes. Each mode has different permissions, tool access, and behavioral guardrails.

| Mode | Access | Purpose |
|---|---|---|
| **Builder** | Read/Write | Create and modify data pipelines |
| **Analyst** | Read-only | Safe exploration and cost analysis |
| **Reviewer** | Read-only | dbt PR review with a signed, engine-backed verdict — see [dbt PR Review](../usage/dbt-pr-review.md) |
| **dbt-Optimizer** | Read + approval-gated writes | Scan a dbt project for fixable issues, propose fixes with cost/impact evidence |
Comment thread
coderabbitai[bot] marked this conversation as resolved.
| **Plan** | Minimal | Planning only, no edits or execution |

## Builder
Expand Down Expand Up @@ -191,15 +193,76 @@ Plan: [expands into a full detailed plan]

---

## dbt-Optimizer

**Scans a dbt project for concrete, fixable issues and proposes targeted fixes with cost and impact reporting.**

```bash
altimate --agent dbt-optimizer
```

The optimizer works in four explicit phases and never skips ahead:

1. **Scan (read-only)** — detects issues across six lanes: materialization & incremental processing (with a named strategy — `merge`, `delete+insert`, `insert_overwrite`, `microbatch` — and verified preconditions), warehouse physical design (clustering/partitioning/sort keys, proposed only with query-history evidence), SQL anti-patterns, DAG economics (fan-out views, duplicate scans, dead models), run-level orchestration (Slim CI, threads, full-refresh overuse), and tests/docs/storage. The scan produces a numbered **candidate list** — every candidate carries evidence, an impact estimate, and a confidence level, ranked by expected ROI. It then stops and asks which candidates to fix.
2. **Fix** — applies only the candidates you select, one focused change each. Every SQL rewrite is verified with the equivalence engine; an undecidable result is reported as *unproven* with a data-diff recommendation, never as safe.
3. **Impact report** — the combined effect of the batch, with cost estimates only where query-history evidence supports them ("not estimable" is a valid answer).
4. **Pull request** — on request, a branch + PR whose body is the impact report.

### Example: Scan a project

```text
You: Scan this dbt project for optimization candidates

dbt-Optimizer: Building the evidence base (manifest + query history)...

Candidates, ranked by expected ROI:

1. [materialization] fct_events — full-rebuild table over append-only data
Evidence: rebuilt 24×/day scanning 2.1B rows; event_id key + loaded_at cursor present
Impact: compute cost (est. from last 30 days of query history)
Fix: incremental with merge strategy on event_id, 3-day lookback
Confidence: medium (validate first run against a full-refresh baseline)

2. [dag] legacy_events_backup — dead model, no downstream consumers
Evidence: no model, exposure, or selector references it; rebuilt daily
Impact: compute + storage Fix: quarantine, confirm with owner, then remove
Confidence: high (report), deletion is propose-only

3. [testing] dim_customers — primary key untested
Evidence: no tests in schema.yml; customer_id is a merge key downstream
Impact: correctness Fix: add not_null + unique tests
Confidence: high

Which candidates should I fix?
```

### Permissions

- File edits and shell commands **prompt for approval** by default.
- The direct SQL write tool (`sql_execute_write`) is **denied non-overridably** — no global or per-agent config can enable it.
Comment thread
anandgupta42 marked this conversation as resolved.
- dbt builds mutate the warehouse, so they run only as user-approved shell commands, model-by-model (`altimate-dbt compile --model` / `build --model`); a full project build requires explicit approval. The agent is instructed to confirm the active target is a dev/CI target before building, but the runtime does not validate the target — review the command's target before approving, and keep production credentials out of your default target.
- Destructive DDL (`DROP DATABASE`, `DROP SCHEMA`, `TRUNCATE`) stays hard-blocked like every agent.
Comment thread
coderabbitai[bot] marked this conversation as resolved.

### Coming from builder

Builder's self-review points you here: when it notices optimizer-shaped issues during dbt work (wrong materialization, duplicated logic), it flags them and suggests switching to dbt-Optimizer for the project-wide, cost-evidenced scan instead of fixing them silently out of scope.

---

## SQL Write Access Control

All SQL queries are classified before execution using AST-based parsing:

| Query Type | Builder | Analyst |
|-----------|---------|---------|
| `SELECT`, `SHOW`, `DESCRIBE`, `EXPLAIN` | Allowed | Allowed |
| `INSERT`, `UPDATE`, `DELETE`, `CREATE`, `ALTER` | Prompts for approval | Denied |
| `DROP DATABASE`, `DROP SCHEMA`, `TRUNCATE` | Blocked (cannot override) | Blocked |
| Query Type | Builder | Analyst | Reviewer | dbt-Optimizer |
|-----------|---------|---------|----------|---------------|
| `SELECT` | Allowed | Allowed | — | Allowed |
| `SHOW`, `DESCRIBE`, `EXPLAIN` (classified ambiguous) | Prompts for approval | Denied | — | Denied — use `schema_inspect` / `sql_explain` instead |
| `INSERT`, `UPDATE`, `DELETE`, `CREATE`, `ALTER` | Prompts for approval | Denied | — | Denied (non-overridable) |
| `DROP DATABASE`, `DROP SCHEMA`, `TRUNCATE` | Blocked (cannot override) | Blocked | — | Blocked |

The classifier treats only plain `SELECT` as a proven read; `SHOW`/`DESCRIBE`/`EXPLAIN` fall into the ambiguous category and follow the write column. Use the dedicated read tools (`schema_inspect` for structure, `sql_explain` for plans) instead.

The Reviewer has no direct SQL execution tools at all — it works through the `dbt_pr_review` verdict engine and read-only analysis tools; see [dbt PR Review](../usage/dbt-pr-review.md).

The classifier detects write operations including: `INSERT`, `UPDATE`, `DELETE`, `MERGE`, `CREATE`, `DROP`, `ALTER`, `TRUNCATE`, `GRANT`, `REVOKE`, `COPY INTO`, `CALL`, `EXEC`, `EXECUTE IMMEDIATE`, `BEGIN`, `DECLARE`, `REPLACE`, `UPSERT`, `RENAME`.

Expand Down
2 changes: 1 addition & 1 deletion docs/docs/llms.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

## Data Engineering

- [Agent Modes](https://help.altimate.ai/code/data-engineering/agent-modes/): 7 specialized agents (Builder, Analyst, Validator, Migrator, Researcher, Trainer, Executive), each with scoped permissions and purpose-built tool access. Builder has full read/write; Analyst has read-only enforced.
- [Agent Modes](https://help.altimate.ai/code/data-engineering/agent-modes/): 5 specialized agents (Builder, Analyst, Reviewer, dbt-Optimizer, Plan), each with scoped permissions and purpose-built tool access. Builder has full read/write; Analyst has read-only enforced; Reviewer produces signed dbt PR verdicts; dbt-Optimizer scans dbt projects for fixable issues with cost/impact evidence.
- [Training Overview](https://help.altimate.ai/code/data-engineering/training/): How to teach altimate project-specific patterns, naming conventions, and corrections that persist across sessions and team members.
- [Team Deployment](https://help.altimate.ai/code/data-engineering/training/team-deployment/): How to commit training to git so your entire team inherits SQL conventions automatically.
- [SQL Tools](https://help.altimate.ai/code/data-engineering/tools/sql-tools/): 9 SQL analysis tools with 19 anti-pattern rules. 100% F1 accuracy on 1,077 benchmark queries.
Expand Down
2 changes: 1 addition & 1 deletion docs/docs/usage/tui.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ Switch between agents during a conversation:
- Press leader key + `a` to see all agents
- Use `/agent <name>` to switch directly
- Built-in agents: `general`, `plan`, `build`, `explore`
- Data engineering agents: `builder`, `analyst`, `plan`
- Data engineering agents: `builder`, `analyst`, `reviewer`, `dbt-optimizer`, `plan`

## Diff Display

Expand Down
104 changes: 103 additions & 1 deletion packages/opencode/src/agent/agent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import PROMPT_TITLE from "./prompt/title.txt"
import PROMPT_BUILDER from "../altimate/prompts/builder.txt"
import PROMPT_ANALYST from "../altimate/prompts/analyst.txt"
import PROMPT_REVIEWER from "../altimate/prompts/reviewer.txt"
import PROMPT_OPTIMIZER from "../altimate/prompts/dbt-optimizer.txt"
// altimate_change end
import { Permission } from "@/permission"
import { mergeDeep, pipe, sortBy, values } from "remeda"
Expand Down Expand Up @@ -220,7 +221,7 @@ export const layer = Layer.effect(
// altimate_change end

const agents: Record<string, Info> = {
// altimate_change start - 3 modes: builder, analyst, plan (replaces upstream single "build" agent)
// altimate_change start - 4 modes: builder, analyst, reviewer, dbt-optimizer (replaces upstream single "build" agent)
builder: {
name: "builder",
description: "Create and modify dbt models, SQL, and data pipelines. Full read/write access.",
Expand Down Expand Up @@ -377,6 +378,95 @@ export const layer = Layer.effect(
mode: "primary",
native: true,
},
// dbt-optimizer agent: dbt project optimization — scan (read-only allowlist),
// propose candidates, apply user-selected fixes (edit/bash prompt), report impact.
"dbt-optimizer": {
name: "dbt-optimizer",
description:
"Scan a dbt project for fixable issues — performance, materialization, repeated logic, missing tests/docs — and propose targeted fixes with cost and impact reporting. File edits and shell commands prompt for approval by default (explicit user config can relax them); the direct SQL write tool is denied non-overridably, and dbt builds run only as user-approved shell commands (the agent confirms a dev target before building).",
prompt: PROMPT_OPTIMIZER,
options: {},
permission: Permission.merge(
defaults,
Permission.fromConfig({
"*": "deny",
Comment thread
anandgupta42 marked this conversation as resolved.
// Read-only project access (scan phase)
read: "allow",
grep: "allow",
glob: "allow",
list: "allow",
question: "allow",
tool_lookup: "allow",
todowrite: "allow",
todoread: "allow",
webfetch: "allow",
websearch: "allow",
// Scans routinely need paths outside the worktree (e.g. dbt profiles,
// package dirs); "ask" instead of hard-failing on the "*" deny.
external_directory: readonlyExternalDirectory,
// SQL analysis + verified rewrites
sql_execute: "allow",
Comment thread
anandgupta42 marked this conversation as resolved.
Comment thread
anandgupta42 marked this conversation as resolved.
Comment thread
anandgupta42 marked this conversation as resolved.
sql_analyze: "allow",
Comment thread
anandgupta42 marked this conversation as resolved.
sql_optimize: "allow",
sql_explain: "allow",
sql_diff: "allow",
sql_format: "allow",
sql_fix: "allow",
altimate_core_validate: "allow",
altimate_core_check: "allow",
altimate_core_grade: "allow",
altimate_core_rewrite: "allow",
altimate_core_equivalence: "allow",
altimate_core_compare: "allow",
altimate_core_column_lineage: "allow",
altimate_core_parse_dbt: "allow",
Comment thread
anandgupta42 marked this conversation as resolved.
altimate_core_testgen: "allow",
// dbt project structure + blast radius
dbt_manifest: "allow",
dbt_lineage: "allow",
dbt_unit_test_gen: "allow",
Comment thread
anandgupta42 marked this conversation as resolved.
impact_analysis: "allow",
Comment thread
anandgupta42 marked this conversation as resolved.
Comment thread
anandgupta42 marked this conversation as resolved.
Comment thread
anandgupta42 marked this conversation as resolved.
lineage_check: "allow",
schema_inspect: "allow",
schema_search: "allow",
// schema_index crawls the warehouse and REWRITES the persistent
// global schema cache (~/.altimate-code/schema-cache.db) — a
// mutation the read-only scan must not run unprompted.
schema_index: "ask",
Comment thread
anandgupta42 marked this conversation as resolved.
schema_cache_status: "allow",
warehouse_list: "allow",
warehouse_test: "allow",
// Cost evidence
finops_query_history: "allow",
finops_analyze_credits: "allow",
finops_expensive_queries: "allow",
finops_warehouse_advice: "allow",
finops_unused_resources: "allow",
// Fix phase: every file change and shell command prompts for approval
edit: "ask",
bash: "ask",
// Warehouse writes never
sql_execute_write: "deny",
// Training: list freely, but mutations prompt — training writes
// persistent memory outside the edit permission, so an injected
// instruction in scanned SQL/YAML must not be able to silently
// poison future sessions during the read-only scan.
training_save: "ask",
Comment thread
anandgupta42 marked this conversation as resolved.
training_list: "allow",
training_remove: "ask",
}),
// Merge user config, THEN re-apply the warehouse-write invariant so a
// permissive global config (e.g. `"*": "allow"`) can't turn the scan
// into a silent writer, THEN safetyDenials LAST so DDL denies always win.
user,
Permission.fromConfig({
sql_execute_write: "deny",
}),
safetyDenials,
Comment thread
coderabbitai[bot] marked this conversation as resolved.
),
mode: "primary",
native: true,
},
// altimate_change end
plan: {
name: "plan",
Expand Down Expand Up @@ -547,6 +637,18 @@ export const layer = Layer.effect(
Permission.fromConfig(value.permission ?? {}),
safetyDenials,
)
// Evaluation is last-match-wins, so a per-agent `permission` override
// (merged just above) would outrank the invariants baked into the native
// definitions. Re-apply the optimizer's warehouse-write deny here so
// `agent."dbt-optimizer".permission.sql_execute_write: "allow"` cannot turn
// the scan into a warehouse writer.
if (key === "dbt-optimizer" && item.native) {
Comment thread
anandgupta42 marked this conversation as resolved.
item.permission = Permission.merge(
item.permission,
Permission.fromConfig({ sql_execute_write: "deny" }),
Comment thread
anandgupta42 marked this conversation as resolved.
Comment thread
anandgupta42 marked this conversation as resolved.
safetyDenials,
)
}
// altimate_change end
}

Expand Down
Loading
Loading