Skip to main content
Week of July 6, 2026
APIBreaking ChangeBug FixComposable IdentityDashboardData StudioImprovementIntegrationsNew FeatureWorkflows

Exchange an app token for an installation-scoped access token

Applications using client-credentials authentication can now mint installation-scoped access tokens directly, without needing a user-bound token from the installing company. POST /installations/{id}/token accepts either a user bearer token (as before) or an app client-credentials token obtained from POST /oauth/token with grant_type=client_credentials, and returns an access token carrying the permissions granted to the app at installation. Use this flow when an app needs to act on behalf of a company that has installed it — for example, to run a scheduled sync — outside of any user session.To support the same flow, GET /installations and GET /installations/{id} also now accept app client-credentials tokens. With an app token, GET /installations lists installations across every company that has installed the app, optionally narrowed to one company via the new company_id query parameter, and GET /installations/{id} returns a single installation the app owns. The typical sequence is: exchange client credentials for an app token, call GET /installations (optionally with company_id) to discover the installation id, then call POST /installations/{id}/token to mint the installation-scoped token used for subsequent API calls. Requests for installations that do not belong to the authenticated app return 404, matching the behavior for user tokens accessing another company’s installations.The command palette (⌘K / Ctrl+K) is now a general-purpose navigation surface. Open it from anywhere in the dashboard and jump straight to the Graph Studio tabs — Graph Builder, Edge Builder, Match Report Builder, and Addressable Graph Builder — as well as Datasets, Graph Studio Help, or Create New Dataset without clicking through the sidebar.Your five most recently used commands surface at the top under a Recent section, each command has an icon, and the wider top-anchored palette scrolls with a No matching commands empty state when a search returns no results. Arrow-key navigation now wraps at the ends of the list, moves across sections, and keeps the highlighted command in view as you scroll.

Compute pools: instance-storage size variants

Every AWS EMR compute pool size now has a *_storage sibling — x_small_storage, small_storage, medium_storage, large_storage, x_large_storage, 2x_large_storage, 3x_large_storage, 4x_large_storage, 5x_large_storage, and 6x_large_storage — selectable via the size field on POST/PUT /data-planes/{id}/compute-pools.Storage variants match their base size’s memory budget and node counts but run core+task workers on rXgd instances with local NVMe SSD (Graviton instance-storage families) instead of the EBS-only default. Use them for shuffle- or scratch-heavy jobs that would otherwise spill to EBS and fail with “No space left on device”. The master node stays on m6g because it does no shuffle.

Compute pools: timeout defaults now applied on update

PUT /data-planes/{id}/compute-pools/{poolId} now applies the same timeout defaults as POST when the request omits idle_timeout_seconds or job_execution_timeout_seconds. Previously, only create ran the defaults helper — update wrote the supplied aws_emr provider verbatim. Because provider is replace-not-merge, a size-only update (for example switching to a *_storage variant) that omitted the timeouts persisted null, silently dropping the 4-hour job-execution cap and letting jobs run without a launch-time limit.Both endpoints now go through a shared defaults helper: an omitted or null timeout resolves to the default (15-minute idle, 4-hour job execution) on both create and update. Explicit values — including the -1 sentinel that disables idle-termination — are preserved as-is. This matches the tri-state semantics already documented on the AwsEmrProvider schema for compute pools.

Real provider error messages in connector dialogs

Connector dialogs now surface the actual error returned by the provider when a save, connect, or delete action fails. Previously, the Facebook, TikTok, Pinterest, PubMatic, and Yahoo DSP profile dialogs — along with Pinterest app invites and The Trade Desk taxonomy operations — replaced the response body with a generic “Failed to…” message, hiding the reason the request was rejected. Failures now propagate the provider’s response (including Facebook’s error_user_title/error_user_msg and standard error_description fields) straight to the dialog, so you can act on the real cause without checking network logs.

Create AWS EMR compute pools from the data plane page

You can now create a new compute pool directly from a data plane’s page in the dashboard. A Create Compute Pool button opens a side drawer where you fill in the pool’s name, size, collaboration policy, and optional idle and job-execution timeouts, then provision it without leaving the page. Creation from the UI is available for AWS EMR data planes; Snowflake compute pools continue to be registered through the Snowflake Native App.The Edit drawer now shares the same form, validation schema, and field layout as Create, so editing an existing pool gives the same tighter validation and clearer error messages — including a friendlier surface for name conflicts. The underlying POST /data-planes/{id}/compute-pools and PUT /compute-pools/{id} endpoints are unchanged.

Open in Data Studio now shows the current materialized view definition

Opening a materialized view dataset from Open in Data Studio now preloads the reconstructed CREATE MATERIALIZED VIEW statement that reflects the dataset’s current refresh schedule, description, tags, and write mode — the same query shown on the dataset’s read-only NQL tab. Previously the editor loaded the raw stored query (either the materialize job’s input.nql or the underlying MERGE INTO), which could be stale relative to the dataset’s current metadata. The reconstructed statement is treated as a verbatim query, so Run executes it as-is and the wrap actions (“Create dataset”, “Forecast”) remain hidden to prevent double-wrapping.

Dataset sample endpoints now require a pre-computed sample

Dataset sample reads no longer fall back to scanning the underlying dataset files on the fly — they are served exclusively from the sample store that the data plane populates. When no sample has been produced yet, GET /datasets/{id}/sample, GET /datasets/{id}/sample/mappings, and mapping-creation validation now return a 400 with a No Sample Available error that points callers at POST /datasets/{id}/request-sample to generate one. Previously these endpoints could return a 200 (sometimes with an empty result) by reading dataset files directly from the API. If your integration calls any of these endpoints against a dataset that may not yet have a stored sample, request a sample first via POST /datasets/{id}/request-sample and handle the new 400 response as a signal to do so.

Datasets listing no longer returns materialized-view refresh schedules

GET /datasets now returns an nql-only materialized_view_config for each materialized-view dataset. The refresh_schedule_config field has been removed from the listing response — the listing endpoint no longer fetches per-dataset refresh schedules.If you need the active refresh schedule (cron expression, timezone, next-run timestamp), call GET /datasets/{id} for the specific dataset. That endpoint still returns the full materialized_view_config including refresh_schedule_config.

Graph Builder now runs on AWS data planes

The Graph Builder in Graph Studio now builds identity graphs on AWS data planes in addition to Snowflake. Under the hood, step 2 of the graph build now runs the platform’s LabelConnectedComponents workflow task — the same algorithm as before, but executed as a series of independent NQL jobs instead of a single Snowflake UDF. The change removes the monolithic-query timeout that previously stalled large graph builds and enables graph creation for AWS-hosted data.

MCP server: compute pool config surfaced on data plane tools

The narrative_data_planes_list and narrative_data_planes_describe tools now return richer detail for each compute pool in the compute_pools section. Alongside the pool id and name, the tools emit status, size, idle_timeout_seconds, and a derived always_on flag (true / false for AWS EMR pools based on the idle-termination setting, n/a for Snowflake warehouses that use auto-suspend/resume).Both tool descriptions also carry new guidance telling connected AI assistants that always-on pools skip cold-start cluster spin-up, making small always-on pools ideal for lightweight jobs such as narrative_dataset_request_sample. Reconnect your MCP client to pick up the new fields and guidance.

MCP server: mapping expression dependencies surfaced in describe output

The narrative_datasets_describe tool now tells AI assistants how to read the dependencies.properties field it already returns for each mapping expression. When you call the tool with include=["mappings"], every mapping expression continues to carry the server-computed set of dataset fields it references — the updated tool description now explicitly instructs the model to use dependencies.properties to see which dataset columns feed each mapped attribute property.The wire response is unchanged; agents connected to the MCP server just get clearer guidance for reasoning about Rosetta Stone mappings without having to re-parse each NQL expression. Reconnect your MCP client to pick up the updated tool description.

S3 Connector column sort control for CSV deliveries

You can now control column ordering in CSV deliveries from the S3 Connector. Toggle Sort columns alphabetically on any S3 dataset connection to either keep the connector’s alphabetical default or preserve the delivering dataset’s schema column order. Existing connections keep their current behavior — the setting defaults to enabled to match the previous connector default. See the Amazon S3 Connector reference for details.

Split identity components on exclusive attributes

Identity graphs can now split resolved components that disagree on an attribute that should be exclusive to one identity — for example, an SSN token or an exact date of birth — targeting known overmerge cases without dropping legitimate connections.
  • Graph Builder UI: The Algorithm parameters step now includes an Exclusive attributes selector. Pick one or more first-party target ID types that must hold a single value per identity; after the connected-components pass converges, any resolved component whose vertices disagree on a declared attribute is split apart. Only first-party target ID types present on your input edges are selectable, and leaving the field empty preserves the previous behavior. See Building an identity graph.
  • Workflow DSL: The LabelConnectedComponents task gains a matching exclusiveAttributeCols parameter — a list of edge-table columns whose values are exclusive to one identity. The field is opt-in and defaults to an empty list, so existing workflows are unaffected until they declare it.
Records without a value in the declared column deterministically follow their edges into the fragment they remain connected to.
Week of June 29, 2026
APIBreaking ChangeBug FixDashboardImprovementIntegrationsNew FeaturePlatform

Filter access rules by data plane

GET /v2/access-rules now accepts an optional data_plane_id query parameter. Set it to a data plane UUID to return only rules whose dataset lives on that plane; omit it to keep the previous behavior of returning rules across every plane. The filter composes with the existing owned_only, shared_only, tag, dataset_id, and company_id parameters.The Narrative Model Context Protocol (MCP) server’s narrative_access_rules_search tool exposes the same data_plane_id argument and counts it as a narrowing filter, so it can be used on its own to scope a search to a single plane. Discover plane ids with narrative_data_planes_list. Reconnect your MCP client to pick up the updated tool schema.Newly created access rules also persist the data plane of their referenced dataset so this filter returns consistent results going forward; the field is not yet surfaced on access rule responses.

Access Rules API: data_plane_id on responses

Access rule responses now include the data_plane_id of the plane each rule belongs to, so you can tell which plane will serve a rule without a separate lookup.
  • v2 read endpoints return data_plane_id as a required field on both the owned and shared response variants.
  • v1 read endpoints also surface data_plane_id on every rule. The v1 update endpoint continues to respond with the legacy shape that omits it, so the field is documented as optional on the shared v1 schema.
  • The MCP narrative_access_rules_describe tool renders data_plane_id in the rule metadata block alongside the owning company.

Row TTL retention on AWS data planes

Row TTL retention policies now run on AWS-based data planes in addition to Snowflake. Previously, the API rejected row_ttl policies for datasets stored on AWS; that restriction is lifted.Row TTL deletes rows whose event-time clock exceeds the policy’s interval. On AWS, the scheduler compiles the retention DELETE against the dataset’s Iceberg table and the data-plane operator executes it via Spark on EMR. Cross-cutting policy validation — redundant policies and max_event_time interactions — still applies the same way it does on Snowflake.Underlying file reclamation is deferred: rows are removed from the table immediately, and the storage footprint shrinks when Iceberg snapshots later expire. No changes are required to existing policy definitions — the same row_ttl policy schema and clock semantics apply on both data planes. See Configuring retention policies for the UI workflow.

Consistent state panels across builders

The Classifier, Label, Model, and Lookalike builders now use the same state-panel styling as Graph Studio, Edge Builder, Match Report, and Prompt Studio, giving every builder a consistent look and behavior. Required-step warnings in the Lookalike builder and the Match Report source card now appear as inline messages with a Fix button that jumps you directly to the step that needs attention, replacing the previous action-menu pattern.

Compute pools: default idle and job timeouts on create

New AWS EMR compute pools now default to a 15-minute idle timeout (idle_timeout_seconds: 900) and a 4-hour job execution timeout (job_execution_timeout_seconds: 14400) when the caller omits either field on POST /data-planes/{id}/compute-pools. This applies to pools created through the API and the UI (which hits the same endpoint).Explicit values are preserved as-is, including the -1 sentinel that disables idle-termination. The per-customer x_small_default pool seeded at company registration now uses the same 4h/15m defaults (previously 1h job timeout with no idle timeout). Existing production pools are unchanged by this release.

Choose the compute pool that runs a dataset’s scheduled refreshes

The dataset Overview screen now lets you view and change the compute pool used to run a materialized view’s scheduled refreshes, right next to the Refresh Schedule field. The picker is limited to active, company-owned pools in the dataset’s data plane, mirroring backend validation. Previously the refresh-schedule API accepted a compute pool, but there was no way to set or change it on an existing materialized view from the dashboard.

Inline edit affordances for Extended Stats and Data Expiration

The Extended Stats and Data Expiration rows on the dataset Overview now show the same pencil edit icon as the other editable rows. Clicking the Extended Stats pencil opens the statistics configuration drawer, and the Data Expiration pencil opens the retention policy drawer in new-policy mode. The dataset actions menu also gains a Configure retention policy item that opens the same retention drawer.

Label Studio: auto-label unlabeled rows with multi-model LLM consensus

The Label Studio workspace can now pre-populate its labeling queue with LLM-generated suggestions, so you only review and confirm — instead of typing every label from scratch. The new Auto-label action lives alongside Train Model in the workspace header and runs entirely client-side against the inference layer that already powers Prompt Studio and LLM Studio.One adaptive action button. The workspace header now exposes a single split button whose default action follows the project’s state: Add Labels when you have staged changes pending, Train Model once the project has enough labeled examples to be trainable, and Auto-label otherwise. The other actions remain available from the button’s dropdown at any time, so you can always reach Auto-label or Train Model regardless of which one is currently primary.Pick one model or several for consensus. Clicking Auto-label opens a model picker listing every classifier model available in the current data plane — on Snowflake that’s Claude Opus 4.6, GPT-4.1, and o4-mini; on AWS it’s Claude Opus 4.6, Claude Sonnet 4.6, and Claude Haiku 4.5. Selecting a single model takes its recommendation directly; selecting two or three runs the same classification prompt across all chosen models in parallel and takes a strict majority vote (floor(n/2) + 1). Suggestions are validated client-side against the project’s allowed classes, so off-list answers are dropped rather than staged. Labels written from a multi-model run are marked with source = 'llm_3x' in the label dataset; single-model runs are still marked human once you confirm them, since you remain the final reviewer.Review, then commit in one pass. Auto-labeled rows appear with a subtle highlight on the class dropdown so unconfirmed suggestions are easy to spot at a glance, and a per-row sparkle indicates a row that’s still being labeled in the background. A per-row kebab menu lets you re-run Auto-label for just that row, dismiss the current suggestion, or clear a staged change. Bulk Assign from the selection toolbar now stages the chosen class into the same pending set as individual picks and Auto-label suggestions, so a single Add Labels click commits everything — manual picks, bulk assignments, and accepted suggestions — in one atomic write. A result toast summarizes each Auto-label pass with the number of rows suggested, the models used, and the average consensus agreement across rows.Auto-label complements the existing Train Model handoff: use it to bootstrap a labeled dataset quickly, scan and correct any rows the models disagreed on, and hand off to Classifier Studio once the project crosses the train-ready threshold.

Login response no longer returns the legacy DSM token

The dsm_token field has been removed from the response body of POST /authentication/login, POST /authentication/exchange-token, and POST /authentication/exchange-mcp-token. The response now contains only the authenticated user profile and the api_token (access token, refresh token, and their expiries).The DSM token was a legacy bearer credential carried alongside the access token for compatibility with older internal services. Those services have all migrated to the access token, so the field is no longer issued. If you were reading dsm_token from any of these endpoints, switch to api_token.access_token — it is the credential used everywhere else in the platform and is what you should send in the Authorization: Bearer … header.Session cookies, the user object, and the api_token shape are unchanged.

MCP access-rules search now returns data_plane_id

The narrative_access_rules_search MCP tool now includes each rule’s data_plane_id in its results, closing the last gap where an access rule’s data plane was visible everywhere except in search output. The field is on by default and can be toggled via the tool’s include= argument, matching how the describe tool surfaces it inside its default-on metadata block. Combined with the existing data_plane_id search filter, you can now both filter access rules by data plane and see each result’s data plane id in one call. Reconnect your MCP client to pick up the updated tool schema.

MCP server: create Rosetta Stone mappings from an AI assistant

The Narrative Model Context Protocol (MCP) server now exposes a narrative_mapping_create tool, letting AI assistants create Rosetta Stone mappings from a dataset to an attribute without leaving the conversation. The tool wraps the private-mapping create endpoint and is scoped to the session’s active company, so the assistant can pick a dataset, pick an attribute, draft the NQL expressions, and submit the mapping in a single turn.Pass attribute_id, dataset_id, and a mapping body of one of two shapes:
  • object_mapping for object-valued attributes: a list of property_mappings, each with a path (dotted path to the attribute property, e.g. product.brand) and an expression (NQL over dataset columns, e.g. itemBrand). Provide a mapping for every required property.
  • value_mapping for scalar attributes: a single expression that produces the attribute’s value.
cached_mapping is not supported through this tool. The dataset must be active and owned by the current company, and the caller must have map permission on the attribute. The response includes the created mapping’s id, scope, source, status, and creation timestamp.Reconnect your MCP client to pick up the new tool. See the MCP server reference for the full parameter schema.

NQL builders now quote Calcite reserved keywords automatically

Builders across the platform — Lookalike, Classifier Studio, Composable Identity edge and graph builders, and Match Report — now emit valid NQL when a column name collides with a Calcite reserved keyword such as order, value, or timestamp. The NQL printer double-quotes identifiers against a shared canonical keyword list, so datasets that use these column names no longer produce invalid queries at generation time.Builder settings cards also handle long auto-generated names more gracefully: dataset, column, report, and model names scroll on a single line instead of wrapping and breaking the card layout, and the actions ellipsis stays clickable even when a long value would otherwise run under it.

Table TTL reclaims storage immediately

Table TTL on Iceberg data planes now physically deletes the underlying data files in the same run that empties the table, instead of waiting for the separate snapshot-expiration flow to reclaim them later. Because Table TTL is opt-in and signals that the data should be gone now, this removes the previous grace window and frees S3 storage as soon as the policy fires. Table TTL datasets are also skipped by the downstream snapshot-expiration flow to avoid redundant work. See Dataset retention policies for the full policy model.
Week of June 22, 2026
Bug FixComposable IdentityDashboardData StudioImprovementIntegrationsNQLNew FeaturePlatform

Forms in drawers and dialogs now autofocus the first field

Opening a drawer or dialog that contains a form now automatically places the cursor in its first input. You can start typing immediately instead of clicking into the field first — a small but pervasive ergonomics win across the dashboard, from creating access tokens to configuring datasets, compute pools, and taxonomy actions.

Compute pool edit drawer fixes

Resolved a set of bugs in the compute pool page and edit drawer. The drawer now correctly pre-selects the pool’s current warehouse size, warehouse type, and scaling policy when reopened — previously some provider-specific fields could appear blank even when set on the underlying pool. The drawer also more reliably renders only the fields that belong to the pool’s provider (AWS EMR vs. Snowflake warehouse) so edits submit cleanly against the right schema.

Data Studio Query Builder emits dataset names in NQL

Queries assembled in Data Studio’s Query Builder now render the FROM clause using dataset names instead of numeric IDs. Toggling into the NQL editor view of a builder query now shows readable references like company_data.my_dataset instead of company_data."40390", making generated NQL easier to read and review.Numeric IDs remain fully supported, and dataset references in the company_data schema can use either form. Where a stable identifier is required, Narrative I/O still uses IDs internally — for example, the NQL persisted with a newly created access rule is always ID-qualified, since dataset names can be reused after a dataset is archived.See SQL comparison and NQL syntax for the updated reference.

Edge Builder warns when a first-party dataset has no data

Graph Studio’s Edge Builder now catches empty first-party datasets up front instead of letting you wander into a downstream “Invalid Mapping” error. When you pick a dataset that has no stored records, the First-Party Data step surfaces a warning with a deep link to the dataset’s statistics page, the Source IDs Select button is disabled, and the flow no longer auto-advances into Source ID selection — keeping you on the step where the problem actually lives.

/llms.txt discovery file at app.narrative.io

The Narrative app now serves a machine-readable llms.txt at the site root, giving LLMs and AI agents a single entry point that describes what Narrative is and where to go next. The file summarizes the platform’s core building blocks — datasets, access rules, NQL, Rosetta Stone, data planes, connectors, and the marketplace — and links out to authoritative resources rather than app internals, since most of the app is auth-gated.From llms.txt, agents can discover the documentation site (including its own llms.txt index), both public MCP servers — the platform MCP server at mcp.narrative.io/mcp and the no-auth agent feedback MCP server at narrative.support/mcp, with an explicit pointer to submit_feedback for stuck agents — and the public marketplace catalogs for models, apps, skills, MCP servers, and data plane providers. The file is served as text/plain from the CDN with no auth required.
Week of June 15, 2026
Bug FixDashboardData StudioImprovementNew Feature

Credit-limit errors now surface across AI generation flows

When a company hits its AI credit limit, the Company Credit Limit Exceeded toast now appears consistently across every AI-powered flow in the dashboard, instead of failing silently in some places and only toasting in others.Previously, only the dataset-description generator surfaced the credit-limit error. The Create Attribute name and description generators, attribute property rows, access token helpers, Audience Studio prompts, and dataset statistics generators all suppressed the toast as a side effect of their inline progress UI — so a credit-limit failure looked like a generic glitch with no explanation. AI field generation now distinguishes “suppress the in-progress toast” from “suppress all toasts,” so the underlying RFC 7807 error is still raised even when the start-of-action spinner is hidden.The Rosetta AI chat also no longer degrades credit-limit errors into a generic “Request failed” toast. The chat now recognizes an RFC 7807 error body by its title and status fields alone, treating log_id as optional — matching how the rest of the dashboard parses platform errors — so credit-limit responses (which omit log_id) render with their real message.

Label Studio: bulk select and assign labels

You can now label many rows at once in Label Studio instead of working through the queue row by row. Each row in the Label tab grid has a checkbox, plus a header checkbox to select every row currently in view. Once you’ve selected at least one row, a selection-aware action bar appears with a class picker, an Apply button, and a Clear action — pick a class, hit Apply, and the chosen label is staged on every selected row in a single batched write.The bulk path reuses the same atomic commit as per-row labeling, so all rows in a bulk apply land together or not at all. On success, the grid updates optimistically and the selection clears; if the write fails, your selection and chosen class stay intact so you can retry without rebuilding it. Bulk apply and the per-row Add Labels action are guarded against overlapping writes, so you won’t accidentally double-commit while a batch is in flight.

Label Studio: Train Model hands off to Classifier Studio

The Train Model action in the Label Studio workspace is now wired up. Previously a disabled stub, it now hands a labeled project off to Classifier Studio without leaving the product or duplicating training configuration.Readiness gate. Train Model becomes active once a project has at least 10 labeled rows across at least 2 distinct classes — the minimum a classifier needs to learn a boundary. Readiness is checked with a cheap sample read against the project’s label dataset, so the action reflects current state without running the heavier distribution workflow. If the read fails, the button stays disabled rather than opening a half-configured builder.Pre-seeded handoff. Clicking Train Model navigates to Classifier Studio with the builder pre-filled:
  • Dataset — the project’s label dataset
  • Label columnlabel
  • Featureinput_string, the same source NQL expression Label Studio already materializes over the source dataset, so no extra column materialization or backend work is needed before training
You still pick the algorithm, hyperparameters, test/train split, and finalize the model name and tags in Classifier Studio — only the dataset, label, and feature steps are seeded.Data plane scoping. Label Studio is now scoped to your selected data plane in two places:
  • The Label Studio listing only shows projects whose dataset lives on the currently selected plane, matching the dataset pickers used elsewhere. Opening a project from a different plane no longer fails on the cross-plane write.
  • Label Studio (and Classifier Studio) are hidden from the side navigation on non-Snowflake data planes, since their seed, write, and distribution workflows rely on Snowflake-only DML.

Marketplace skills catalog: 3 new skills and per-skill icons

The Skills marketplace now lists every skill published in the public catalog and gives each one a distinct visual identity.Three new skills. Profile Dataset (narrative-common), Generate Match Report (narrative-identity), and Create Lookalike (narrative-audience) are now discoverable and installable from the Skills page. Create Lookalike also introduces the new narrative-audience plugin category, which automatically appears in the Plugin filter on the catalog grid.Per-skill icons. Every skill in the catalog now displays its own line-art glyph on a Narrative-blue tile instead of the shared generic icon, so the catalog grid reads as a set of recognizable tiles at a glance.

Non-admin context company defaults to own company

Fixed an issue where non-admin, single-company users could end up with an undefined context company, causing downstream requests (such as the exchange-token endpoint) to fail with Missing required field. The dashboard now defaults the context company to the user’s own company whenever no “View As” override applies, ensuring authenticated requests always carry a valid company id.

CREATE MATERIALIZED VIEW and EXPLAIN now run verbatim

The NQL editor in Data Studio now sends CREATE MATERIALIZED VIEW and EXPLAIN statements to the query engine exactly as written, instead of rewriting them through the standard query transformer.Previously, the editor’s pre-flight formatter could normalize casing, collapse whitespace, or reshape the surrounding query — which mattered for materialized views, where the stored statement is later round-tripped back into a CREATE MATERIALIZED VIEW for editing and recreation. CTEs, window functions, identifier casing, and metadata options (TAGS, PARTITIONED BY, EXTENDED STATS, refresh schedules) are now preserved end-to-end, so the query you see in the editor is the query that runs and the query that comes back when you reopen the view. EXPLAIN plans likewise reflect the exact statement you submitted.
Week of June 8, 2026
APIAudience StudioBreaking ChangeBug FixDashboardData StudioImprovementIntegrationsNew FeaturePlatform

Lookalike Studio

Lookalike Studio is a new guided builder for creating lookalike audiences from a seed audience, available at My Audiences → Lookalike Studio. It uses the same two-column layout as Audience Studio and walks you through the full workflow:
  • Seed and population — Start from a seed dataset, then choose the larger population to model against. The picker only allows joinable pairs, hiding any population that lacks a join-key Rosetta Stone mapping to the seed.
  • Similarity attributes — Candidate features are classified automatically and shown in a searchable list with categorical/continuous, source, and cardinality badges. Identity attributes are surfaced separately as the join keys.
  • Configure output — Size the audience by count (top N highest-scoring users) or by a similarity-score threshold, and choose whether to include your original seed users.
  • Connections (optional) — Attach destination connectors to the output using the same eligibility checks and per-connector configuration as Audience Studio. The output is automatically mapped to the unique_id attribute, so it can be delivered to connectors and reused as a future seed audience.
  • Finalize — Name the audience (with an auto-generated, collision-free dataset slug), add a description and tags, and review a summary of the full configuration before building.
Clicking Create Lookalike Audience assembles and submits the workflow for immediate execution, with a live progress dialog that continues server-side if you close it and a success drawer on completion. Intermediate build checkpoints are hidden from dataset listings so the catalog only shows the finished audience.Read more →

Attributes API: filter semantic search by minimum relevance score

GET /attributes now accepts a min_score query parameter that bounds results by the cosine similarity between the search term’s embedding and each attribute’s embedding. min_score is a number in the interval [0, 1]; attributes scoring below the threshold are excluded from both the returned records and the total count, so weakly related attributes no longer dilute search results. Setting min_score=0 disables the threshold entirely and returns the top per_page matches ranked purely by relevance — useful when a search comes back empty and you want to widen the net.The Narrative Model Context Protocol (MCP) narrative_attributes_search tool exposes the same min_score argument and applies a sensible default so loosely related attributes are dropped without the caller having to specify a threshold on every query. Reconnect your MCP client to pick up the updated tool schema.

Cached mappings for NQL

Mappings now support a new cached_mapping expression type alongside the existing SQL expression type. A cached mapping references a separate cache dataset whose output column holds pre-computed attribute values; at query time, rows from the source dataset are joined to the cache using the configured input_expressions as the join key. This lets you reuse expensive attribute computations across queries without recomputing them inline.Cached mappings can be created and read through the company-scoped Mappings API (for example, POST /mappings/companies/{company_id}). The referenced cache dataset must already exist, be owned by the same company, and have an output column whose type matches the target attribute.A few constraints apply while the feature rolls out:
  • Cached mappings are not permitted on opt-out attributes (data_privacy_request_identifier, unique_id, identifier_relation).
  • Materialized fields cannot be backed by a cached mapping, and an existing mapping cannot be converted to a cached mapping while an active materialized field on the same dataset references it.
  • DELETE statements that filter on a cached mapping are rejected with DELETE on cached mappings not yet supported.
See Mapping types for the full schema and validation rules.

Compute pool idle-timeout disable sentinel changed to -1

For AWS EMR compute pools, the sentinel value that disables idle-termination on idleTimeoutSeconds is now -1 instead of 0. Validation accepts null, -1, or any value in the [60, 604800] range; 0 is now rejected.Existing AWS EMR pools that used 0 to disable idle-termination have been migrated to -1 automatically, so no action is required for currently running pools. Callers that create or update compute pools should switch to -1 (or omit the field) to disable idle-termination going forward.

Dataset mutations now propagate across Data Studio tabs

Fixed an issue in Data Studio where dataset changes made in one tab did not reach other open tabs. Deleting a dataset in one tab no longer left a stale name-uniqueness error in another, and renaming or otherwise updating a dataset from one surface now syncs into the kept-alive Dataset Details page without requiring a manual refresh. Datasets auto-created from file uploads are also pushed into the shared datasets store immediately, so every open tab sees the new dataset as soon as ingestion finishes.

Default user token permissions now include read on connections

Fixed a gap in the default permissions granted to user-owned access tokens. Tokens minted on a user’s behalf — through platform login, MCP server bootstrap from a Stytch Connected Apps token, and the control-plane conversations worker — already carried write access to connections but were missing the matching read scope. As a result, requests that listed or fetched connection details could fail with an authorization error even though the same token could create or update connections.These tokens now include read:connections by default, so connection list and detail endpoints work out of the box without needing a token with custom permissions.

Job mutation endpoints now documented

The public OpenAPI reference now documents the full set of job mutation endpoints alongside the existing GET /jobs and GET /jobs/{job_id}. The newly documented endpoints are run, complete, fail, request-cancellation, cancel, and reschedule, each with their request body schemas.The JobResponse state enum also gained the previously undocumented pending_cancellation value, which is returned by the request-cancellation endpoint while a job is winding down.

Jobs API pagination and filtering improvements

The GET /jobs endpoint now returns full pagination metadata alongside the existing records array. Responses include current_page, total_pages, and total_records, making it straightforward to build paginated UIs and iterate through large result sets. The change is additive — existing clients that only read records continue to work unchanged.Job listings can now be filtered by multiple state and type values in a single request, so you no longer need to issue separate calls per state or job type. The endpoint also enforces a maximum page size to keep responses predictable.Job responses now include the default data plane ID rather than returning null when no data plane is explicitly set, simplifying client logic that previously had to handle the missing-value case.

Jobs dashboard fixes: tab rendering, status filter, and data plane scoping

Three fixes to how jobs are listed and filtered in the dashboard.
  • Dataset Jobs tab renders correctly. Fixed an issue on the dataset detail page where the Jobs tab showed a blank table body and a large empty space even when jobs existed — the pagination control reported the correct count (for example, “1 to 1 of 1”), but the rows themselves were clipped to invisibility by a collapsed container. Job rows now render as expected.
  • Dataset Jobs tab shows jobs across all data planes. Fixed the dataset Jobs tab dropping jobs when viewing a dataset under a non-default data plane. Because a dataset is a global object, its jobs are now fetched by dataset_id only — independent of the selected data plane — so the tab consistently lists every job for the dataset. The standalone Jobs page continues to scope by data plane as before.
  • Jobs Status filter keeps all options visible. Fixed an issue on the Jobs page where selecting a value in the Status filter caused the other status options to disappear from the dropdown, making it impossible to switch to or add another status without clearing the filter first. The Status filter now always lists the full set of job states regardless of which option is currently applied, so you can freely change selections or combine multiple statuses.

Label Studio: build labeling projects from your datasets

Label Studio is a new studio for creating and running labeling projects against the datasets already in your platform, joining Prompt Studio, Classifier Studio, and LLM Studio under My Models.Create a project. Launch the builder from My Models → Label Studio → New and walk through four steps: pick the source dataset, choose the attribute whose values define your label taxonomy, configure how each row’s source input is presented for labeling, and give the project a name and optional description. The attribute picker lists every Rosetta Stone attribute in your workspace, grouped into Eligible (primitive attributes that define an enumerated set of allowed values — valid label taxonomies) and Not eligible (shown disabled so you can see why an attribute can’t be picked), with the allowed values previewed inline. If your workspace has no attributes yet, the step links straight to Rosetta Stone → Attributes so you can define one without leaving the flow. Hitting Create project provisions a label dataset in your currently selected data plane, seeds it with the distinct source inputs from your chosen attribute, activates the dataset, and drops you into the project workspace.Label your data. Each project opens into a dedicated workspace whose Label tab renders the labeling queue as a sortable grid — input string, assigned label, source, and labeled-at timestamp — with unlabeled rows surfaced first. A filter bar lets you toggle between Unlabeled, Labeled, and All rows, narrow to a specific class, and refresh from the server without losing staged work. Each row exposes a searchable inline dropdown bound to the target attribute’s allowed values, so the only labels you can assign are ones the schema already understands. Selections stage locally until you click Add Labels, which commits every pending change in a single atomic write; if the write fails, staged selections are preserved so you can retry without losing work. While a newly created project’s seed sample is still generating server-side, the grid shows a spinner and polls for completion.Track distribution. The Distribution tab shows what your labeled data actually looks like: KPI cards for Total Labels, distinct Classes, and an Imbalance indicator that highlights when the gap between your largest and smallest class crosses the threshold, plus a per-class bar chart and a donut chart splitting labels by source — human review, LLM-assisted labeling, and imports. Aggregations run server-side, and saving labels in the Label tab refreshes the distribution view automatically. A Train Model action in the workspace header becomes active once a project has accumulated enough labeled examples.Manage the lifecycle. Archiving a project from the Label Studio listing cascades the cleanup — the label dataset, the project’s seed, write, and distribution workflows, and its distribution materialized views are all removed, with success and failure toasts so you know the result. Opening an unknown or inaccessible project ID renders a friendly not-found state with a link back to the listing.

MCP server: better typo handling and broader fuzzy search coverage

The Narrative Model Context Protocol (MCP) server’s fuzzy matcher has been rewritten to align with the reference fuzzywuzzy WRatio algorithm, so search tools recover more reliably from typos, word-order differences, and partial substring matches. Each candidate is now scored on a 0–100 scale by combining four ratios — raw Levenshtein, token-sort, token-set, and a sliding-window partial ratio — with scaling and gating that mirror fuzzywuzzy’s defaults. Per-tool score thresholds have been tuned so legitimate near-matches (conversion against convesion_events3, edge vs edges, myAttributeName vs my attribute name) clear the cut while unrelated candidates do not.Fuzzy ranking now backs every MCP search tool, not just narrative_datasets_search and narrative_access_rules_search. The narrative_attributes_search, narrative_jobs_search, and narrative_context_search_companies tools all rank search_term against their primary text fields (name, display name, description, and similar) and return results ordered by descending match score. Tag, status, and data-plane filters continue to work as exact-match constraints alongside search_term. Queries longer than 200 characters are rejected up front to keep per-call latency bounded on large corpora. Reconnect your MCP client to pick up the updated tool descriptions.

Force-reschedule terminal jobs

POST /jobs/{id}/reschedule now accepts an optional body with a force flag. By default the endpoint remains a no-op for terminal jobs (Completed, Cancelled, Failed). Setting force: true reschedules the job even when it is in a terminal state, resetting it to Pending and clearing its executor so the operator re-dispatches it onto a fresh cluster — useful for re-running a job that already finished.The endpoint now returns a RescheduleJobResponse whose outcome field reports what happened (rescheduled or skipped_terminal) alongside the job’s current state. The body is optional, so existing callers that send no body are unaffected.

Rosetta AI Chat: redesigned chat surface, @-mention constructs, and artifacts sidebar

Rosetta AI Chat has been rebuilt end to end around how multi-step agent runs actually feel. The chat surface, message bar, transcript, and toolbar all moved at once, so the experience reads as a single coherent conversation instead of a stream of disconnected tool outputs.Live progress, grouped by round. Tool calls now render in-flight from the run’s live messages — you can watch each step of a Rosetta turn as it executes instead of waiting for the final answer. Related steps are grouped into round summaries with a unified progress component, so a multi-step investigation (chained dataset lookups, NQL refinements, knowledge base searches) reads as one coherent unit rather than a wall of individual tool invocations. The legacy “thinking…” placeholder has been replaced by this richer round-progress UI.@-mention datasets, attributes, and NQL. The message bar now supports typed constructs: press @ to mention a dataset (with a virtualized, filterable picker), an attribute, or an NQL query. Mentions render as inline chips in both your message and the transcript, and hovering one reveals a details popover so the agent — and you — can see exactly which object you meant. New conversations also surface a quick-action row (“Normalize Data”, “Create Identity Graph”, “Create an Audience”, “Classify Data”) that seeds the message bar with a starter prompt.Artifacts sidebar. Charts, tables, datasets, attributes, and other agent-produced objects are now split out of the transcript into a dedicated Artifacts sidebar, oldest first, so you can scan everything Rosetta produced during a conversation without scrolling back through the chat. References stay inline in the message where they were introduced; only the heavier produced artifacts collect in the drawer.Polish across the surface. Messages submit optimistically and animate in, agent responses fade between states, collapsed agent messages get a subtle bottom shadow so longer turns are easier to scan, and the chat container width, header, and conversation history have all been tightened to the redesign. A new per-message hover toolbar exposes message actions in place. Mobile gets dedicated layout and behavior tweaks so the chat works in narrow viewports.The legacy Rosetta “About” page has been removed in favor of this surface.
Week of June 1, 2026
APIAgent ConversationsBreaking ChangeBug FixComposable IdentityDashboardData StudioImprovementIntegrationsMarketplaceNew FeaturePlatformWorkflow DSLWorkflows

Rosetta AI Chat now runs on the Narrative MCP servers

Ask Rosetta AI Chat anything about your data or the Narrative platform — your datasets, attributes, NQL, access rules, security posture, or how to do something in the product — and get current, accurate answers grounded in the live state of your account.
Rosetta AI Chat — Hi! I'm Rosetta, your big data assistant. I can help you query, forecast, and buy data; build audiences; explain security policies; and use the Narrative platform.
Rosetta is also easier to find: it’s now a top-level entry in the side navigation, promoted out of the old Tools submenu.Why answers are better now. Rosetta AI Chat has been rebuilt on top of the Narrative Data Collaboration MCP server and the Narrative Knowledge Base MCP server — the same servers your team can connect to from Claude Code, Claude Desktop, Cursor, or any other MCP-aware client. Instead of running on a bespoke tool layer that only Rosetta could see, every question goes through the live MCP tool catalog: dataset, attribute, and access-rule lookups use the same fuzzy search and pagination, and how-to and platform answers ground against the live Knowledge Base instead of a snapshot embedded in the chat.Every new MCP capability shows up in chat for free. New tools, skills, and fixes that land on the MCP servers — workflow orchestration, access rules, dataset operations, NQL execution, schema-compatible tool input, persistent sessions, auto-auth, fuzzy search, and the rest of this month’s launches — appear in Rosetta the moment they ship. There is no longer a separate “chat backend” to keep in sync with what external agents see, so every investment in the MCP surface compounds across every Narrative-aware harness at once — Rosetta AI Chat, Claude Code, Claude Desktop, Cursor, and anything else you connect.The migration also fixes a class of session-lifecycle bugs: conversations are created server-side on the first message and their ids are adopted into the URL in place, so refreshing the page resumes the same conversation and in-flight responses are no longer cancelled by client-side navigation. The embedded Rosetta tab updates its path without remounting, keeping a single tab per chat instead of spawning a new one for every session.

Public /health endpoint no longer exposes infrastructure details

The public Open API /health endpoint now returns a detail-free response by default to avoid leaking infrastructure information (database hostnames, S3 bucket names, per-dependency error messages). Unauthenticated callers receive {"success": true|false} with the same 200 (healthy) or 500 (unhealthy) status code as before, so existing uptime probes, load balancer checks, and synthetics canaries that rely on the HTTP status keep working unchanged.To retrieve the full HealthCheckResult with per-dependency details, send the stage-specific secret in the X-Narrative-Health-Check-Secret header. The secret is stored in SSM at /${stage}/open-api/health-check/secret and can be rotated independently per stage. The internal API’s /health endpoint is unchanged, as it is only reachable through a private VPCE.

Rosetta AI Chat: playful thinking messages and richer tool call rendering

Rosetta AI Chat now keeps you company while it works. Instead of a single static “Thinking…” line, the chat cycles through a rotating set of short, on-topic loading messages that riff on what you actually asked — so a question about churn might surface “Churning the butter…” while a question about your budget might surface “Counting the beans…”. When Chrome’s on-device language model is available, the messages are generated locally and tailored to your prompt; otherwise the chat falls back to a curated set of generic messages. Nothing about your request leaves the browser to power the animation.Tool calls render more consistently as well. Every tool invocation now flows through a single, unified renderer, so MCP tool activity in the conversation looks coherent across the catalog rather than varying tool by tool. Submitting a message is also more responsive — your turn appears in the transcript optimistically the moment you hit send, instead of waiting for the server round-trip. And the previous cap on how many tool-call iterations a single Rosetta turn could take has been lifted, so longer multi-step investigations (chained dataset lookups, NQL refinements, knowledge base searches) can run to completion without being cut short.

Auto-titled agent conversations

Agent conversations now generate a human-readable title automatically on the first user turn. When you call POST /agents/conversations/{id}/runs on an unnamed conversation, the platform enqueues a one-shot, schema-constrained inference over the first user message and writes the result to agent_conversations.name — no extra request needed and no impact on the agent run itself (no extra messages, no version bump).Naming is idempotent: it only fires while name is null, and the underlying workflow rejects duplicate IDs, so retries and concurrent first runs converge on a single title. Once a conversation has a name — whether set by auto-titling or by an explicit update — subsequent runs leave it alone.Run responses now include a current_name field that reflects the conversation’s title at the time the run was observed, so clients can render the latest name alongside run state without a separate GET /agents/conversations/{id} round trip.

In-flight progress for agent runs

GET /agents/runs/{id} now streams an agent run’s progress while it’s still executing through a new live.messages field. As the agent loop produces each turn — tool calls, tool results, and intermediate model responses — it appends them best-effort so you can render activity in real time instead of waiting for the run to reach a terminal state.Live messages only appear while the run is non-terminal. Once the run finishes (or fails), the live entries are cleared and the committed message log under messages becomes authoritative, so live turns never get a sequence_no and never bump the conversation version. The streaming path is best-effort and never fails the run itself.

Compute pool lookups tolerate transient errors

Jobs running on compute pools no longer fail permanently when the compute-pool lookup hits a transient error. Previously, the AWS data plane operator collapsed every lookup failure — 5xx responses, timeouts, connectivity blips, and genuine 404s — into a single “compute pool could not be resolved (it may have been archived or does not exist)” failure, which terminally killed the job even when the pool was active the whole time.The operator now classifies lookup outcomes three ways: active pools dispatch as before, genuinely missing or archived pools still fail fast with the same actionable message, and transient errors (HTTP 429, 5xx, or connectivity/timeout) leave the job untouched so the next poll retries the lookup. The “could not be resolved” message is now only surfaced when the pool is actually gone, so it accurately reflects the situation when you see it.

Dashboard updates: dataset picker, refreshed logo, and Yahoo connector fix

  • Horizontally scrollable dataset picker. The dataset picker used across the Composable Identity builders — Edge Builder, Graph Studio input configuration, and Match Report Builder — now scrolls horizontally instead of squeezing its columns into the available width. The ID, Display Name, Unique Name, and Created At columns each render at their natural width and stay legible regardless of how narrow the surrounding panel is, making it easier to identify the right dataset when selecting first-party sources, graph inputs, or match report sources.
  • Refreshed Narrative logo. The Narrative logo has been updated across the dashboard. The new mark renders inline as an SVG, so it inherits the surrounding text color and stays crisp at every size — from the top navigation bar to compact in-app badges.
  • Yahoo connector shows all opt-out and PXID connections. Fixed an issue in the Yahoo DSP connector where some opt-out and PXID (partner match) connections were missing from the connector’s settings view. All existing opt-out and partner match connections now appear, so you can review and manage every connection tied to your profile.

Data Studio: interactive runs deliver previewable results

Clicking Run in Data Studio now produces a previewable sample on every data plane, including Snowflake Native App data planes where the Preview Results panel previously stayed empty. Behind the scenes, an interactive run is now submitted as a two-task workflow — CreateMaterializedViewIfNotExists followed by CreateDatasetSample — so the sample is orchestrated server-side and is guaranteed to exist by the time the run resolves. NQL is still pre-validated client-side, so the detailed error dialog continues to surface syntax and binding problems before any work is scheduled.The result dataset is still a temporary materialized view tagged _nio_interactive with a one-day retention policy, and still appears on the Queries page under Interactive queries. Two refinements make it easier to find:
  • Human-readable names and descriptions. When Chrome’s on-device model is available, Data Studio generates a display name and description for the result dataset from the NQL you ran. Generation is best-effort — unsupported browsers, an undownloaded model, or a timeout all fall back to the previous unnamed view, and the underlying dataset name stays a UUID so re-runs never collide with an existing view.
  • Refresh and auto-refresh on My Queries. Every tab on the My Queries page now has a refresh button, and interactive runs refresh the queries and datasets stores automatically when they complete. New runs show up in history without a page reload, and rows prefer the generated display name when one is present.

Datasets API: filter by data plane and tag

GET /datasets now accepts data_plane_id and tag query parameters so you can narrow the list without filtering client-side.
  • data_plane_id takes a single data plane UUID and returns only datasets stored on that plane.
  • tag is repeatable — pass it multiple times (e.g. ?tag=foo&tag=bar) to restrict results to datasets carrying any of the given tags. Unknown tag values return a 400 instead of a server error.
Both filters compose with the existing q keyword search and pagination parameters.Two improvements to the Narrative Model Context Protocol (MCP) server and its marketplace surface.
  • Narrative Conversations API snippet on MCP server pages. MCP server detail pages in the marketplace (/marketplace/mcp-servers/[slug]) now include a Narrative Conversations API option in the Configuration section, alongside the existing third-party client snippets for Claude Code, Cowork, Claude Desktop, ChatGPT, and Codex. The new option shows the defaults.mcp_servers fragment to drop into an Agent Conversations API request, with the selected server expressed as { alias, url, description } — the array shape the Conversations API expects, which is distinct from the mcpServers object used by the Claude harnesses. The alias, URL, and description are derived from the listing you’re viewing, so you can copy the snippet directly into a request without leaving the platform. Other defaults fields (such as model, data_plane_id, and execution_cluster) are elided as ... since they’re out of scope for adding a server. Claude Code remains the default-selected snippet.
  • Fuzzy matching for dataset and access-rule search. The narrative_datasets_search and narrative_access_rules_search tools now use token-aware fuzzy matching instead of plain substring matching, so agents recover gracefully from typos, word-order differences, and minor morphological variation (e.g. edge vs edges, myAttributeName vs my attribute name). Each candidate is scored on a 0–100 scale using a Levenshtein-derived combination of token-sort and token-set ratios, weighted across fields. For datasets, search_term now ranks against name, display_name, and description; for access rules, it ranks against name and description. Results are returned ordered by descending match score, and matches that don’t clear a per-tool score threshold are dropped. Tag and data-plane filters continue to work as exact-match constraints alongside search_term. Reconnect your MCP client to pick up the new tool descriptions.

Platform updates: credit limit enforcement and interactive query routing

  • Credit limit enforcement on usage-producing endpoints. Endpoints that start usage-producing work on Narrative-owned data planes now check the company’s credit limit before running. POST /nql/run, POST /openapi/model-inference/run, POST /agents/conversations/{id}/runs, and the workflow run and trigger endpoints reject requests with HTTP 403 and an RFC 7807 Company Credit Limit Exceeded response when the company has no credit account or has exceeded its limit. Runs targeted at customer-owned data planes are unaffected. If your account is blocked, reach out to your account manager to restore access.
  • Interactive queries open in Dataset Details. Clicking an interactive query on the Queries page now opens it in Dataset Details instead of Data Studio. Interactive queries are temporary materialized-view datasets with no editable query to load, so routing them to Data Studio produced an error. They now land on the dataset’s NQL tab, which shows the originating query. As part of this fix, the Queries page was rebuilt around the standard object browser pattern, with one tab per query type, live counts in the tab headings, and type-aware row actions (datasets offer both Dataset Details and Data Studio; access rules, forecasts, templates, and views continue to open in Data Studio).

RecalculateStatistics workflow task

You can now refresh a dataset’s column statistics from within a workflow using the new RecalculateStatistics task. This is useful after a step that loads or modifies data — for example, chaining it after an ExecuteDml task so downstream consumers see up-to-date statistics without a separate manual trigger.Specify the target dataset by either datasetId or datasetName (exactly one), with an optional computePoolId to control where the job runs. The dataset must already have a statistics configuration. The task waits for the recalculation to complete and outputs totalRows and columnCount, which downstream tasks can reference via export.as or ${…} expressions.

Cancel workflow executions via API

You can now cancel a running workflow execution through the public API. Two endpoints are available: POST /workflows/{workflowId}/cancel cancels the currently running execution of a workflow, and POST /workflows/{workflowId}/runs/{runId}/cancel cancels a specific run by its run ID.The run-level endpoint is the recommended option because it guarantees that only the intended execution is cancelled. Cancelling by workflow ID alone is subject to a race condition where the targeted execution finishes and a new one starts before the server processes the request, which would cancel the new execution instead. Both endpoints return 204 No Content once the cancellation request has been accepted.In addition, subscriptions can now be cancelled through POST /subscriptions/{subscriptionId}/cancel. Cancelled subscriptions cannot be reactivated.

Reference datasets by ID in workflow tasks

Workflow DSL tasks that operate on a dataset now accept either datasetId or datasetName, giving you more flexibility when wiring tasks together. Previously, datasetName was required.This applies to the RefreshMaterializedView, CreateDatasetSample, and CreateRosettaStoneMappingsIfNotExist tasks. Use datasetId when an upstream task outputs a dataset id (for example via export.as), or continue using datasetName when referencing a known dataset by name. Exactly one of the two must be supplied.
Week of May 25, 2026
APIBug FixComposable IdentityDashboardData StudioDeprecationImprovementIntegrationsNew FeaturePlatform

Composable AI Marketplace

Compose AI agents that work with your data — without writing custom code — by combining prebuilt building blocks from a single marketplace.
Narrative Marketplace landing page — Easily build agents that work with your data. Skills, models, apps, and MCP servers. Everything you need in one place.
Open /marketplace to browse and install skills, models, apps, MCP servers, data plane providers, and licensed datasets. Whether you want Rosetta AI Chat to draft an NQL query, Claude Desktop to build an identity graph, or an internal automation to activate an audience into Facebook, you assemble it from the same catalog instead of stitching infrastructure together yourself.Six catalog kinds, browsable from the new landing page and via the Browse all menu entry:
  • Models — the LLMs available for inference. Claude Opus, Sonnet, and Haiku via Bedrock on the Narrative Cloud data plane at launch, with additional providers reachable through other data planes.
  • Data Plane Providers — where workloads run. Narrative Cloud (first-party, auto-installed for every company) and Snowflake at launch. Each provider page lists its available models and the compatible app connectors that link to its app detail page.
  • MCP Servers — what AI agents can do with your data. Three always-available remote HTTP servers ship at launch: Narrative Data Collaboration (mcp.narrative.io, OAuth), Knowledge Base (docs.narrative.io), and Agent Feedback (narrative.support). Each detail page lists the available tools and a copyable client configuration you can paste into Claude Code, Claude Desktop, Cursor, or any other MCP-aware client.
  • Skills — harness-agnostic, prebuilt agent workflows (writing NQL, generating identity graphs, applying Rosetta Stone mappings, etc.) that orchestrate the MCP servers on top of your data. Filter by plugin, search published skills, and open a detail page showing Specifications, Dependencies, and Installation. Eight skills at launch. See Installing skills.
  • Apps — the connectors and integrations (Facebook, Google Ads, Snowflake, S3, The Trade Desk, TikTok, Pinterest, and more) that activate audiences and move data into and out of the platform. Rebuilt around typed app manifests, with search, sort, filter, and a unified Install / Launch flow.
  • Data — third-party datasets a data owner makes available through a Narrative access rule. Queried with NQL rather than installed: each detail page shows a copyable SELECT … FROM companySlug.ruleName snippet, a Schema table, the Rosetta Stone attributes the dataset surfaces, and CPM pricing inline. Access-gated — listings only appear when the active company can query the underlying rule.
Skills and MCP Servers are cross-linked: each skill lists the servers it requires under Requires MCP Servers, and each server lists the skills that depend on it under Used by Skills — so you can navigate between related listings without guessing.

List agent conversations

The Agent Conversations API now supports GET /agents/conversations to fetch a paginated list of the calling user’s conversations, newest first by created_at. Results are scoped to both the bearer token’s company_id and user_id — peers in the same company cannot see each other’s conversations.The endpoint uses the standard page / per_page query parameters (default per_page is 50) and returns the usual paginated envelope with prev_page, current_page, next_page, total_records, total_pages, and records. Callers with no conversations get an empty records array rather than a 404. Access requires the agent_conversations:read permission.

Structured outputs for agent runs

Agent runs now expose the model’s final answer through two mutually exclusive fields, removing the prior requirement that every caller-supplied output_format_schema declare a top-level text: string.On status: completed, the GET /agents/runs/{id} response populates exactly one of:
  • final_text — the plain-text answer, used when the caller did not supply an output_format_schema (text mode).
  • final_structured_output — a JSON object conforming verbatim to the caller’s output_format_schema (structured mode). The shape is whatever the caller defined — oneOf, extraction results, nested objects, etc. — with no top-level text field required or implied.
Previously, runs with custom output schemas that didn’t include a top-level text field failed post-inference with AgentLoopSchemaDecodeFailed. Existing text-mode callers see no change: final_text continues to be populated as before, with final_structured_output set to null.

Compute pools: default on registration and copy identifier

Two improvements to the compute pools surface.
  • Default compute pool on company registration. New companies are now provisioned with a usable compute target the moment registration completes. Every non-B2B register flow creates a private, x-small AWS EMR compute pool on the Narrative data plane and pins it as the company-level default for that data plane. Jobs that don’t pin a pool explicitly — and have no dataset-level or data-plane default to fall back to — now resolve to this seeded pool instead of failing with “no compute pool configured”. You can rename, archive, or replace the default at any time. B2B registration is unaffected since it maps to a pre-existing configured company.
  • Copy Identifier action. The Compute Pools tab on the Data Plane detail page now includes a Copy Identifier action in each row’s kebab menu, letting you grab a compute pool’s UUID without opening the Edit drawer. This matches the existing copy-identifier affordances on data planes, datasets, jobs, and workflows.

Marketplace polish: Home discovery, Data catalog fix, and standalone apps cleanup

Follow-up polish to the Composable AI Marketplace launched earlier this week.
  • Home page Browse Apps for zero-install users. Logged-out visitors and fresh tenants now see a Browse Apps row of up to eight marketplace apps on the Home page, alongside the Get Started cards. Cards link to each app’s marketplace listing, and a Browse all apps button routes to /marketplace/apps. Once you have at least one installed app, Home flips back to the installed-Apps section with Launch buttons. The View all apps button in the installed-Apps section now also routes to /marketplace/apps. Tab titles are now distinct: /apps reads Installed Apps and /marketplace/apps keeps Apps.
  • First-load fix for the Data catalog. Fixed a race condition that could cause the Marketplace Data catalog to render empty on a cold first load even when you had accessible products. The store backing accessible access rules now waits for the API service to initialize before fetching, so the catalog populates correctly on first paint without requiring a refresh. The fix also covers auth-state transitions (such as View As switches) that re-trigger service initialization.
  • Deprecated standalone apps removed. Legacy standalone apps already replaced by native Platform UI experiences are no longer accessible from the dashboard. This includes Touchless PII Hasher, Data Studio for Buyers, Data Studio for Sellers (Access Rules and Data Streams), and Shop Builder (Quick Start, Settings, and Site Pages). All functionality is available directly in the Platform UI — update any bookmarks pointing at /touchless-pii-hasher/hash, /buy/buyer-studio, /sell/access-rules, /sell/data-streams, or /shop-builder/* to the corresponding Platform pages.
  • Launch lineup mention. Five public-domain Data listings ship at launch: The Movies Dataset, US state polygons, German PLZ → lat/long, German PLZ polygons, and Germany polygon.

Match Report polish: builder, listing, and viewer

Polish across the Marketplace Match Report flow shipped earlier this month.
  • Automatic sample data for Graph Builder and Match Reports. Datasets created from the Graph Builder and Match Report builders now kick off a sample-generation job automatically as soon as the underlying workflow completes. Sample data is available immediately after the build finishes, so you can start exploring results without manually triggering a sample job. The Match Reports list and detail pages also now surface the sample job status alongside the workflow status, and handle the edge case where a workflow fails after the dataset has already been created — so partially built reports are still discoverable and recoverable.
  • Supplier access rule filtering and Match Report builder polish. Fixed an issue where eligible supplier access rules were filtered against their backing datasets’ Rosetta Stone mappings instead of the access rules’ own mappings — suppliers that exposed graph edge mappings through their access rules are now correctly listed. Access rule details now include a Mappings section showing the Rosetta Stone attributes and properties exposed through the rule, the supplier steps in the builder were retitled to Supplier Identity Access Rule and Supplier Enrichment Access Rule, and access rule names now fall back to a sensible default when missing.
  • Listing improvements. The Marketplace Match Reports listing page loads faster and only shows reports that are ready to view. The page no longer issues redundant requests for in-progress workflow runs, and reports backed by incomplete dataset outputs are hidden until they finish processing — so the reports you see are always ready to open.
  • Viewer refinements. The Marketplace Match Report viewer now focuses on the report itself: the NQL and Metadata tabs have been removed so the Report view is the single landing surface for evaluating a supplier match. The listing’s Dataset ID column links straight to the dataset details page with a tooltip clarifying the destination. Reports built on older, unsupported tag versions now show a clear error message instead of attempting to render, and Match Report builds tag the dataset with a schema version (_nio_ci_match_report:0.1) so future viewer updates remain backwards compatible with existing reports.

MCP server: auto-auth, persistent sessions, workflow tagging, schema compatibility, and access-rules fix

Five improvements to the Narrative Model Context Protocol (MCP) server.
  • Auto-authenticated MCP in agent conversations. Agent conversations now automatically authenticate to Narrative’s own MCP server. When mcp_servers[].url on a conversation points at https://mcp.narrative.io/mcp (or the dev equivalent), the platform mints a short-lived API token for the calling user and company and attaches it as a Bearer credential on every tools/list and tools/call issued during the run. Agents can now use the full Narrative MCP toolset — datasets, attributes, NQL, workflows, jobs, access rules, and the rest — without you needing to manage API tokens or wire authentication into your client. Public MCP servers outside the Narrative allowlist continue to be called unauthenticated. The minted token lives only for the duration of the in-flight HTTP call and is never persisted, returned in API responses, or logged.
  • Persistent MCP server sessions. The MCP server now persists sessions across reconnects, so AI assistants no longer have to re-bootstrap a fresh session on every request. Sessions are keyed by a hash of the bearer token and stored in the marketplace database with the bound Narrative API token encrypted at rest using a dedicated KMS key. Subsequent requests rehydrate the existing session, preserving the user’s selected company context across reconnects and process restarts. Server-minted API tokens are also refreshed automatically when they’re within five minutes of expiry, so long-running agent conversations no longer fail with token-expired errors mid-flight. Caller-provided API tokens remain pass-through and are not refreshed.
  • Auto-tagging for MCP-created workflows. Workflows created through narrative_workflows_create are now automatically tagged with created_by_mcp_server. The tag is appended to any tags an agent supplies (preserving their order) and is not duplicated if the agent already includes it, making it easy to identify and filter workflows that were authored by AI assistants.
  • Tool schema compatibility. Tool input schemas now use only the JSON Schema subset that Anthropic, Bedrock, and Cortex all accept — definitions that previously included unsupported keywords (such as $ref/$defs, oneOf, numeric minimum/maximum, string pattern/maxLength, or non-whitelisted format values) could be rejected with HTTP 400 by direct MCP clients like Claude Desktop, Cursor, and the Anthropic Messages API. All registered tools have been migrated to the safe subset, and a per-tool cap of 24 optional parameters (Anthropic’s limit, counted across nested objects) is now enforced by tests so future tools cannot regress. Reconnect your MCP client to pick up the new schemas.
  • Implicit-share access rules describe fix. Fixed a parsing error in narrative_access_rules_describe when describing rules of type implicit_share. The upstream GET /v2/access-rules/{id} endpoint omits dataset_ids for implicit-share rules, which previously caused the MCP client to fail decoding the response. The field is now optional and renders as _none_ when absent or empty.

Model Inference messages now use content blocks

The Model Inference RunRequest API now uses a structured content array on each message instead of a flat text string. Each content block is one of text, tool_use, or tool_result, so multi-turn conversations involving tool calls round-trip through the API without being flattened to prose. Responses always emit the new shape, and the assistant role is now accepted alongside system and user.The legacy { "role", "text" } request shape is still accepted for backwards compatibility — the API auto-canonicalizes legacy messages into a single text content block — but new integrations should send content blocks directly. See the updated RunRequest schema for examples.

Redesigned side navigation and Home page

The dashboard side navigation has been restructured to surface the most-used destinations directly. The Tools group is gone — Rosetta AI Chat is now a top-level entry, Secret Sharing has moved under Settings, and the collapsible Installed Apps sub-menu has been replaced with a single top-level link to a new /apps page that lists only the apps you have installed. The new order is Home → Installed Apps → Rosetta AI Chat → Rosetta Stone → My Data → My Models → My Audiences → Marketplace → Settings.The Home page has been redesigned to match the marketplace pattern. A new Get Started section offers three entry points into Normalize, Marketplace, and Explore, and an Apps section below it shows your installed app manifests as launchable cards. The Apps section is hidden when you have no installations, so fresh tenants land on a focused Get Started view.

Skill detail pages: arguments, examples, and npx skills install

Skill detail pages in the Marketplace now document each skill’s slash-command arguments and offer a faster install path. The Specifications section renders an Arguments table — Argument, Required / Default, and Description — for every skill that accepts flags, and each skill’s example prompts have been updated to show those arguments in use (for example, /write-nql --dataset 123 --run --limit 50 …). Skills without arguments hide the table.The Installation section now leads with the skills CLInpx skills add narrative-io/narrative-skills-marketplace — as the default install option, with the existing Claude Code /plugin commands available from the harness picker.Also in this release: added an Agent Conversations resource (Read + Write) under Query & Analytics in the API key create and edit drawer, and improved the resource label fallback so resources not yet in the SDK’s label map display as title case.

Bug fixes

  • Compute pool provider must match the data plane platform. Creating a compute pool now fails fast when the pool’s provider does not match its data plane’s platform — for example, a Snowflake pool targeting an AWS data plane, or an AWS EMR pool targeting a Snowflake data plane. Previously these mismatches were accepted and could silently be elected as defaults, surfacing only as runtime operator failures at job dispatch. The check runs at create time; provider type cannot drift afterward because ComputePoolUpdate has no externalId field.
  • AWS data plane job cancellation. Resolved two issues in the AWS data plane operator that could cause running jobs to be cancelled unexpectedly shortly after dispatch. The iteration-tail idle-cluster reaper now accounts for steps submitted earlier in the same iteration, so a cluster that just received fresh work is no longer terminated based on a stale snapshot showing only completed bootstrap steps. Additionally, operator-managed clusters are now segregated by deployment stage, preventing dev and prod operators running in the same AWS account from treating each other’s pending steps as orphans. Jobs running on EMR compute pools should no longer surface the “cancelled without a jobs-API cancellation request” failure caused by these races.
  • Snowflake SELECT struct/array results. Fixed an issue where NQL SELECT jobs against Snowflake-backed datasets returned struct and array columns in an unexpected shape. SELECT job results now use the same Spark JSON converter as the rest of the platform, so nested values are serialized consistently with other query and export paths.
  • Edge Builder dirty-state. Fixed an issue in the Edge Builder where existing graph edge mappings were incorrectly flagged as “dirty” on load, enabling the save controls even though no changes had been made. Hydrating a saved mapping now correctly reflects its persisted state, including nested object attributes that were previously normalized inconsistently.
Week of May 18, 2026
APIAgent ConversationsBug FixComposable IdentityDashboardData StudioImprovementIntegrationsNew FeaturePlatform

MCP server: workflows, access rules, and API token auth

The Narrative Model Context Protocol (MCP) server gained three significant expansions this week, broadening the agent surface from data exploration into orchestration and marketplace navigation.

Workflow and data plane tools

Five new tools let agents enumerate data planes, create workflows from YAML, and track their runs end-to-end:
  • narrative_data_planes_list / narrative_data_planes_describe — enumerate data planes accessible to the active company and describe one or more by id.
  • narrative_workflows_create — submit a workflow from a YAML specification with optional trigger_immediately, schedule_immediately, and tags.
  • narrative_workflows_describe — fetch one or more workflows by id; opt into include=["specification"] only when you need the full YAML.
  • narrative_workflows_list_runs — list a workflow’s runs with cursor pagination.
The recommended flow is data_planes_list → workflows_create → workflows_list_runs.

Access rule tools

Two new tools let agents discover and inspect access rules:
  • narrative_access_rules_search — search rules the active company owns or has been granted, with composable AND filters on search_term, exposed_attribute_names, tags, dataset_ids, company_ids, owned_only, and shared_only. At least one filter is required.
  • narrative_access_rules_describe — describe one or more rules with a selectable include= set (metadata, mappings, nql, schema, collaborators, pricing).
To reference a rule in NQL, use <owning_company_slug>.<access_rule_name>.

API token authentication

The MCP server now accepts opaque Narrative API tokens in the Authorization: Bearer header, alongside the existing Stytch OAuth JWT path. This enables server-to-server and scripted MCP clients to connect without a browser-based login flow. See Connecting to the Narrative MCP Server for the updated auth flow.

Agent Conversations API launch

Narrative now exposes a public Agent Conversations API for driving multi-turn LLM agent loops directly from your applications. A conversation is a long-lived container with a pinned system_prompt and a defaults block — model, data plane, max iterations, tools, and an output JSON schema — that every subsequent run inherits and can override per call.

Endpoints

Available under /agents:
  • POST /agents/conversations / GET /agents/conversations/{id} — create and inspect a conversation.
  • POST /agents/conversations/{id}/runs — start an asynchronous run with a user_message, or resume a paused run with tool_outputs. Runs use client_op_id for idempotency and expected_version for optimistic concurrency.
  • GET /agents/runs/{id} — poll a run through pending → running → completed | requires_action | failed. Response echoes effective_config, submitted_inference_job_ids, pending_tool_calls when paused, and final_text on completion.
  • GET /agents/conversations/{id}/messages — retrieve the transcript with assistant content blocks and tool calls. Supports since for incremental fetches.

Tool routing

The API uses a single routing rule: the dash in the wire name decides where a tool call goes.
  • MCP-resolved tools keep their {alias}-{name} wire form. The platform discovers each mcp_servers[] entry’s catalog at run start via the JSON-RPC tools/list method, so adding, removing, or changing a tool on the server is picked up automatically — no API change needed.
  • Caller-answered tools are declared as top-level tools[] entries with a bare, dash-free name and no alias. When called, the run pauses at status: requires_action; respond with a follow-up run carrying payload.kind: tool_outputs.
  • tool_choice accepts the bare name plus mcp_alias when pinning an MCP tool ({ "kind": "specific_tool", "mcp_alias": "docs", "name": "search_kb" }), or just name for caller-declared tools.
Access is gated by the new agent_conversations permission (read for the GET endpoints, write to create conversations and runs).

Composable Identity: builder, viewer refresh, and consistent pickers

A coordinated upgrade across the Composable Identity surfaces.
  • Match Report builder. A new guided builder at My Data > Reports > New report walks you through Source → Supplier → Match Identifiers → Supplier Enrichment → Finalize, generating the workflow that materializes a Marketplace Match Report — no hand-authored YAML required.
  • Viewer visual refresh. The Match Report viewer now uses a consistent card-based layout, with new breakdown cards for identifier-type summaries and identity enrichment.
  • Object Browser pickers. Dataset and access-rule selection across Composable Identity now uses the Object Browser, replacing the legacy dropdown.
  • Graph builder fix. Third-party source ID types are no longer grouped with first-party sources when constructing Label Connected Components arguments — graphs combining first- and third-party data now produce correct connected components.

Compute pool admin controls: delegated management and configurable timeouts

Compute pools gained two operator-grade controls this week.
  • Delegated management. Data plane owners can now grant other companies the right to create, update, and archive compute pools on a shared data plane via the new manage_compute_pools field on DataPlaneCollaborators. Previously any participant could provision pools just by being listed in participants; that permission is now governed separately, so owners can keep participation broad while restricting who may stand up infrastructure. Rights are re-evaluated on every call — revoking manage_compute_pools immediately removes a collaborator’s ability to mutate pools they previously created.
  • Configurable EMR timeouts. aws_emr pools now accept two optional knobs on the provider payload. idle_timeout_seconds overrides EMR’s AutoTerminationPolicy and the operator-side idle reaper (default 15 min, 0 disables auto-termination, range 60s–7d). job_execution_timeout_seconds caps how long a single job’s EMR step may stay in RUNNING before the operator cancels it (no enforcement by default, range 60s–7d). The shared Narrative pool ships with a 1-hour cap; pools you own can pick their own limit. Orphan steps left after an operator crash are also detected and cancelled on the next iteration.

Native Sources page in Data Studio

The My Data > Sources page has been rebuilt natively in the platform, replacing the legacy embedded experience. The page now loads faster, matches the rest of the platform UI, and exposes source management directly without an iframe wrapper.From the new page you can:
  • Browse your configured sources in a unified listing with an empty state for first-time setup
  • Create a new managed S3 bucket source from the New Source dialog, with inline validation of bucket configuration
  • View per-source authentication and configuration details in the auth config panel
Companies are currently limited to a single managed S3 bucket source; the New Source action is disabled with a tooltip once that limit is reached.

Per-route Open Graph previews

Links shared from the platform now render section-aware previews in Slack, Discord, iMessage, Twitter, LinkedIn, and other unfurling clients. Each route — Marketplace, Workspace, Rosetta, Connector, Rosetta AI, and the default app shell — resolves to a brand-aligned Open Graph image generated on the fly, so a shared Marketplace link no longer shows the same artwork as a Workspace or Rosetta AI link.The change wires og:image, og:url, og:title, and the matching Twitter card tags reactively for every page, with a worker-default image as a fallback for first paint. No action is required from you — existing links pick up the new previews automatically the next time they are re-scraped by a sharing client.
Week of May 11, 2026
APIBug FixDashboardData StudioDeprecationImprovementIntegrationsNQLNew FeaturePlatform

Compute pools: company defaults, self-service on shared planes, and aws_emr polish

Three changes broaden compute pools into a real multi-tenant primitive.
  • Company-level default. A new tier in the resolution chain — job-specific → dataset default → company default → data-plane default — covers operations with no dataset analog (model training, inference, healthchecks). Managed via PUT/DELETE /company/{id}/data-planes/{dpId}/default-compute-pool[/{poolId}], scoped per data plane.
  • Participants can create pools on shared data planes. POST /data-planes/{id}/compute-pools now permits any company allowed by dataPlane.collaborators, not just the owner — unlocking self-service compute on the Narrative-hosted data plane. Pool ownership stays with the creator; update/archive remain governed by strict pool ownership.
  • aws_emr create polish. external_id is now optional for the aws_emr provider (the server fills it in). AWS data planes never auto-promote the first pool to the data plane default — this is now the permanent steady state, not a migration-period restriction.

Installations API pagination and lookup

The public GET /installations endpoint now returns a paginated response and accepts page (1-based, default 1) and per_page (default 100) query parameters. Responses include currentPage, nextPage, prevPage, totalRecords, and totalPages alongside the records array. The App Invites list endpoint has been aligned to use the same page and per_page parameters in place of the previous page_number and page_size, and its response now includes the same pagination fields.A new GET /installations/{id} endpoint returns a single installation by ID for the authenticated company, and POST /installations now explicitly requires a user access token — app installation tokens and app client credential tokens are rejected with a 403 response.The private GET /companies/{id}/installations and POST /companies/{id}/installations endpoints are deprecated in favor of GET /installations and POST /installations.

Redesigned Marketplace Apps listing

The Marketplace Apps directory has been rebuilt around typed app manifests, giving you a faster, more consistent way to discover and launch apps.The listing page now supports search, sort by name or developer, and filtering — making it easier to find the right connector or app in a growing catalog. Each app card surfaces the publisher, a short description, and a primary Install or Launch action that adapts based on whether the app is already installed.Selecting an app opens a dedicated detail page with richer merchandising content, and installing an app now opens a permissions sidebar so you can review what the app will access before granting approval. Native apps and external apps share a unified launch flow, so opening an installed app behaves consistently across the marketplace.

Marketplace Match Report viewer

You can now view and interpret Marketplace Match Reports directly in the platform. The report viewer visualizes how your identity data overlaps with a third-party supplier, helping you evaluate supplier fit before committing spend.The viewer displays:
  • Identity Enrichment — a left-to-right flow showing your starting identifiers, which ones matched the supplier, and the net-new identifiers gained
  • Key Performance Metrics — headline KPIs including match rate, ID enrichment multiplier, and IDs per person
  • Demographic & Behavioral Enrichment — attribute-level distributions showing how the supplier characterizes your matched customers
Navigate to Identity Resolution > Marketplace Match Report and select a report to view it. Reports can be shared via link.For a detailed walkthrough of every section and the math behind each metric, see Viewing a marketplace match report.

MCP server: NQL tools and clearer dataset sample hints

The Narrative Model Context Protocol (MCP) server gained NQL execution and a smaller polish that removes a common agent confusion.
  • NQL tools. Three new tools — narrative_nql_validate, narrative_nql_run, and narrative_nql_get_job — let agents validate, submit, and poll NQL queries (including CREATE MATERIALIZED VIEW) without leaving the chat interface. Both _run and _get_job accept optional data_plane_id and compute_pool_id overrides. Recommended flow: validate → run → get_job.
  • Empty-sample hints. narrative_datasets_describe now distinguishes between a dataset with zero records and one whose sample simply hasn’t been requested yet. The rendered sample section appends either // dataset has no records yet or // no sample has been requested yet. Call narrative_dataset_request_sample to request one. so agents know what to do next.

Tool use in Model Inference

Model Inference on AWS data planes now supports tool use through the runModelInference SDK call and the RunModelInference workflow task.You can define tools the model is allowed to call and control how it selects them:
  • tools — a list of tool definitions, each with a name, description, and JSON Schema input_schema. Tools default to strict mode, which constrains sampling to match the input schema exactly.
  • tool_choice — controls tool selection: auto (model decides), any (model must call some tool), or specific_tool (model must call the named tool).
When the model invokes tools, the job result includes a tool_calls array (each with an id, tool name, and arguments) alongside a stop_reason that mirrors Bedrock’s Converse values (end_turn, tool_use, max_tokens, stop_sequence). The existing structured_output field is now optional and is omitted when the model stops to call a tool instead of producing a final response.The change is backward compatible: requests without tools behave exactly as before.

Bug fixes and enhancements

  • NQL UNION ALL usage collection — Fixed an issue in the NQL compiler where UNION ALL queries only collected field usages from the first branch of the union. Usages from subsequent branches were dropped, which could cause downstream graph edges and access checks to be incomplete.
  • AI-assisted mapping reliability — Fixed a validation error that could cause AI-powered features — including mapping generation, column normalization, dataset descriptions, and retention policy suggestions — to fail when the underlying model returned a discriminated-union response.
  • Dataset detail page reactivity — Fixed a bug where statistics, record counts, and last ingestion time on the dataset detail page could display stale values after the underlying data updated.
Week of May 4, 2026
APIBug FixImprovementIntegrationsNew FeatureWorkflow DSLWorkflows

Run NQL on AWS EMR compute pools

AWS data planes can now execute NQL jobs on Amazon EMR Spark clusters provisioned as compute pools. The compute pools API supports a new aws_emr provider type with a configurable size (x_small through 6x_large) that targets the equivalent Snowflake warehouse’s memory budget on EMR. Sizes x_large and above use EMR Managed Scaling so clusters expand and contract with load. Pair this with the existing context selector to direct NQL workloads to right-sized Spark clusters within your AWS data plane.

Claude Sonnet 4.6 and Opus 4.6 in Model Inference

Model Inference on AWS data planes now supports Anthropic’s Claude Sonnet 4.6 (anthropic.claude-sonnet-4.6) and Claude Opus 4.6 (anthropic.claude-opus-4.6). The new models are available wherever existing Claude models are accepted, including the runModelInference SDK call and the RunModelInference workflow task. Structured output via JSON Schema works the same as on prior generations. See Supported Models for the full list.

GenerateSample workflow task

You can now trigger sample-data generation for a dataset directly from a workflow with the new GenerateSample task. This is useful when you want to refresh sample data after a dataset is created or updated by an earlier task in the same workflow — for example, immediately after a RefreshMaterializedView step.The task takes a datasetName (and optional executionCluster) and outputs the generated sample’s datasetId and rowCount, which can be referenced by downstream tasks via export.as or ${…} expressions.

Dataset stats fixes

Two fixes to the dataset stats API:
  • Correct routing for Iceberg datasetsGET /datasets/{id}/stats now consistently routes by data plane: Iceberg datasets read from real Iceberg snapshots, while Snowflake datasets continue to read from synthetic stats history. Previously, when stats history rows existed for an Iceberg dataset, those synthetic values were served instead of the correct snapshot data.
  • Integer overflow for large cardinalitiesapproxCountDistinct and countDistinct values are now represented as 64-bit integers (int64) end-to-end, fixing an overflow that caused truncated values for columns with more than ~2.1 billion distinct values.

Expanded MCP server tooling

The Narrative Model Context Protocol (MCP) server gained a richer toolset and a clearer naming convention for AI assistants. All tools now use the narrative_* prefix (previously nio_*), and dataset and attribute tools follow a consistent ${entity}s_search / ${entity}s_describe pattern so assistants surface a recognizable namespace.

New tools

  • narrative_datasets_search and narrative_datasets_describe — find datasets by name, description, or tags, and fetch details with a selectable include= field set: metadata, schema, mappings, sample, stats, column_stats_config, retention_policy, and nql (defaults to metadata and schema).
  • narrative_attributes_search and narrative_attributes_describe — explore Rosetta Stone attributes by name or fetch full details for one or more attributes by id.
  • narrative_dataset_get_column_stats and narrative_dataset_set_column_stats_config — read per-column statistics and configure which columns have stats collected. Pass include= to opt into expensive payloads such as histograms; they are off by default to keep responses cheap on wide columns.
  • The existing narrative_context_* tools continue to list and switch the active company.
*_describe tools accept multiple ids per call and execute upstream fetches in parallel, with configurable concurrency and a per-request id cap to keep latency predictable.

Breaking changes

  • datasets_get_schema has been replaced by narrative_datasets_describe. Clients should switch to the new tool name and pass dataset_ids (array) instead of dataset_id (string); schema is still returned by default, so existing schema-only flows work with the swap.
  • The earlier access_rules_* tools have been removed. Use narrative_datasets_search / narrative_datasets_describe and narrative_attributes_search / narrative_attributes_describe to navigate datasets and attributes; equivalent access-rule functionality will return as part of the consolidated tool set.
  • Reconnect any MCP clients that have cached the older nio_* tool names.

Previous Release Notes

Q2 2026

April – June 2026

Q1 2026

January – March 2026

Q4 2025

October – December 2025