AgentSwarms 1.2.0
AgentSwarms 1.2.0
The semantic layer stopped being a place to write definitions and became a
compiler that refuses to produce a wrong one. On top of it sits a dedicated AI
Analyst that shows every step it took — the SQL, the result, its own check on
that result — and a verification badge that expires when the query underneath it
changes. Dashboards and the analyst itself can now be embedded per customer,
each viewer seeing only their own rows.
77 commits, 265 files, 15 migrations.
Highlights
A compiler that refuses to be wrong. Declare a measure's grain, a table's
primary key and a join's cardinality, and a query that would fan out is
refused at compile time — naming the join and suggesting the fix. Ask a
typical BI tool for revenue by campaign across orders ⋈ order_lines and it
returns a number; the number is wrong, because the join multiplied the rows.
Chasm traps are resolved by computing each fact at its own grain, and INNER
fanning joins keep their filtering scope through an EXISTS rewrite rather than
double-counting.
An AI Analyst that shows its work. Every question runs a transparent loop —
plan, write SQL, execute, self-check, synthesise — and every stage is stored and
shown. Where the planner can express a step against a semantic model, the
compiler writes the SQL, so a governed metric is authoritative rather than
advisory; steps say which were governed and which were raw SQL. It asks instead
of guessing. Driver contribution, trend slopes and median/MAD outliers are
computed, not narrated — and too little history means no forecast at all rather
than a confident line through noise.
Verification that expires. A human verdict is pinned to a fingerprint of the
SQL it reviewed. Edit a step and the green tick voids itself: a badge must not
outlive what it vouched for.
Row and column security that follows the viewer. A grant carries a row
filter and a field mask, enforced before compilation so the filter becomes a
governed IN-clause inside the SQL — identical on DuckDB and every warehouse.
Values may be {{user.attribute}} tokens resolved per caller, and an
unresolvable token refuses the query rather than compiling an empty filter,
because silent zero rows read as "there is no data".
Embedded analytics, per customer. Your backend mints a short-lived HMAC
token naming a viewer's attributes; we verify it and turn those attributes into
row filters. Every failure is a 403 stating the reason, never a fallback to the
owner's unfiltered view. Widgets that cannot be scoped — because they
aggregated the scope column away — are withheld with the reason and the fix,
rather than rendered blank, which would read as "no data".
Embed the analyst itself, streamed. The full reasoning loop runs server-side
as the analyst's owner, bounded by the analyst's configured data scope. Its
generated SQL never reaches the browser. A turn takes 30–95s, so it streams: the
named stage and the stated approach land at about six seconds.
Aggregate awareness. Declare a rollup and the compiler routes to it only when
it can prove the answer is identical — then tells the reader which table
answered.
Object storage as a first-class source. Parquet described from its footer
rather than skipped, ORC support, an honest account of Avro, and a Parquet/CSV
bucket queryable straight from the Workbench. Per-dataset storage modes and a
mirror budget with least-recently-used eviction, where eviction costs speed and
never correctness.
Also in this release
- Metrics catalog — every governed metric, searchable by synonym, with what
its certification actually covers and how fresh its data is. Usage never says
"unused"; it says what was searched. - Scan — trends, outliers and concentration across a dashboard's snapshots,
computed with no model call. A scan that finds nothing reports how many widgets
it examined, how many it could not, and the thresholds it applied. - Certification, versions and dependents for semantic models, with
certification blocked until validation passes clean. - Fiscal and custom 4-4-5 calendars, parameters, hierarchies, currency, and
period-over-period comparison across a multi-fact plan. - Scheduled analyses that re-run pinned SQL rather than re-asking the
question, with a digest that says plainly when nothing changed. - Credential key rotation with envelope/key-id support, a full
SECURITY.md,
and a design for external KMS.
Security fixes
- The local SQL engine could read the server's filesystem.
- Blocked PII was still written to the trace in full.
- Refused warehouse queries were not audited, only successful ones.
Notable fixes
- Dashboard charts silently drew 50 of 364 rows.
- Spend totals read only the first 1000 trace rows.
- Headless runs were not billed at all.
- The BI narrator added up averages.
- The embedded Ask-AI answered from row-less stubs, because that path never
hydrated the widget snapshots. - Dialogs had no height bound or overflow, so a tall form grew off both edges of
a laptop screen with no way to reach the submit button; and a popover inside a
dialog could not be scrolled with a mouse, because the dialog's scroll lock
cancelled wheel events outside its own subtree.
Upgrading
git pull
npx supabase db push # 15 migrations
docker compose up --buildNothing in this release requires a configuration change. Two optional
environment variables were added for dataset capacity, both unset by default:
PARQUET_MAX_ROWS (defaults to 5,000,000) and MIRROR_BUDGET_BYTES (defaults
to unlimited, so mirror eviction does not fire until you set a budget). See
.env.example.
Known limits
Stated plainly, because the alternative is you discovering them:
- Scale. Warehouse tables of any size are fine through the semantic layer,
and prep flows that fold are fine. Importing a billion rows into a local
dataset is not. There is no distributed in-memory engine; the warehouse is the
engine. Seedocs/SCALE_AND_LIMITS.md. - Embedded analyst latency. 30–95 seconds per question. It streams, so the
wait is legible, but it is still a wait — set expectations on the page you
embed it in. - Signed viewers are dashboard-only. They filter stored results; an analyst
writes fresh SQL each turn, so enforcement would cover the governed steps and
not the rest. Partial enforcement is a badge that vouches for less than it
appears to, so it is refused at the database rather than half-implemented.