Skip to content

Nori Products

Agentic data operations: governance, health checks, and cleanup on a schedule

Nori runs data agents on a schedule or on webhooks against your warehouse and pipelines, using your own model subscriptions. They report in Slack, remember past incidents, and never apply a change without review.

Quick answer

Agentic data operations means the routine work of a data team is run by agents on a schedule or in response to events, with people reviewing the results. On Nori, a cron schedule or a webhook starts an agent in an isolated sandbox with scoped access to your warehouse and repositories. It checks freshness, tests and policy, investigates failures, and reports in Slack. Fixes arrive as pull requests. Nothing is applied until a person approves it.

The work that fits

Data teams carry a long list of jobs that are important, repetitive and usually late. Each one has a clear check and a clear output, which is what an unattended agent needs.

Data operations work that teams run as Nori automations.
JobTriggerWhat the agent returns
Pipeline healthNightly schedule, or a webhook when a dbt or orchestrator job failsRoot cause, affected downstream tables, a fix pull request
Data qualitySchedule after each loadFailed tests with first bad load, row counts, proposed test or model change
GovernanceSchedule, and a webhook on every pull request that touches a modelUnclassified columns, missing masked views, certification changes
CleanupMonthly scheduleUnused tables, stale exports and copies with owner and a recommendation
CostWeekly scheduleMost expensive queries and models, with a rewrite proposed as a pull request
Reference data upkeepBusiness-day schedule, late-file webhookMatched records, an exceptions queue for people

Three of these have full worked examples: bronze, silver and gold tables with dbt, a governance pipeline from raw to certified, and finding shadow data.

How it works

Every run, whether a person or a schedule started it, is the same kind of Nori session. That is the point: one history, one set of permissions, one place to look.

Triggers: schedules, webhooks and Slack

An automation is a prompt plus a trigger. The trigger is a cron line, a one-time reminder, or a webhook URL that your orchestrator, dbt Cloud, git host or file transfer job calls. The webhook payload is passed to the agent, so it starts with the failing job id or the pull request number. Anyone on the team can also start the same work by mentioning Nori in a Slack thread.

An isolated sandbox with scoped access

Each session gets its own cloud sandbox with your analytics repository cloned, dbt and your warehouse client installed by your setup script, and the credentials scoped to that agent. Give the data agent a warehouse role that reads production and writes only to a development schema. Connect catalogs, orchestrators and ticket systems as integrations or through any MCP server.

Shared skillsets and memories

Your conventions live in the team's skillset: layer rules, naming, test requirements, who owns which schema, what counts as an incident. Every session starts with them. Shared memories hold what was learned: that a vendor file arrives late on the first business day of the month, that a test on orders flaps when a backfill is running. The next run reads those notes before it raises an alarm.

Reports in Slack, changes in pull requests

The agent posts to the channel you name, and stays silent when a check passes if you ask it to. Anything that changes a model, a test, a policy file or a job definition arrives as a pull request with the build result attached. People reply in the thread to steer it, and the agent updates the branch.

Your models, your harness

Sessions run Jiro, Nori's own agent, or the harness your team already uses: Claude Code, Codex, Gemini CLI or any ACP agent. They run on your own Claude or ChatGPT subscription, API keys or LLM gateway. Nori never charges for tokens, so a hundred nightly runs cost a flat plan price plus whatever your own model plan charges.

Reversible, reviewed changes

An agent that can run at 3 a.m. needs firmer limits than a person at a desk. Four rules keep unattended runs safe, and they are enforced by permissions, not by asking the agent nicely.

  • Read production, write development. The agent's warehouse role cannot write to production schemas. Production changes when your deploy job runs after a merge.
  • Every change is a pull request. Branch protection and CODEOWNERS in your git host decide who must approve. The agent cannot approve its own work.
  • Destructive actions have two steps. For drops and deletes the agent prepares the statement and a dry-run count. A person approves in the thread and a person with the rights applies it. Where possible the first step is a rename or quarantine, so there is something to restore.
  • Every run is recorded. Run history keeps the prompt, the trigger payload, the commands and the result of each session, so you can answer what ran last night and why.

On Enterprise, the full stack, control plane included, deploys into your own AWS VPC or Azure VNet with your identity provider and LLM gateway, so warehouse credentials, query results and prompts stay inside your network.

Worked example: a failed dbt job at 02:14

A team runs its production dbt build from an orchestrator at 02:00 UTC. The orchestrator's failure callback calls a Nori webhook. The automation is defined once:

name:     dbt-failure-triage
trigger:  webhook  (called by the orchestrator's on-failure callback)
channel:  #data-alerts
prompt:   A production dbt job failed. The payload has the run id and
          failed nodes. Read the logs, find the root cause, and list the
          gold tables and dashboards downstream. Check shared memories
          for the same failure. Post a report. If the fix is a code
          change, open a PR against main and run `dbt build --select
          state:modified+ --target ci`. Do not rerun the production job
          and do not change production data.

What happens on the night:

  1. 02:14 The build fails on stg_payments__transactions. The orchestrator posts the run id and failed node to the webhook.
  2. 02:14 Nori starts a sandbox with the analytics repository, the team skillset and the data agent's read-only production role.
  3. 02:16 The agent reads the run logs. The error is a cast failure: Numeric value 'N/A' is not recognized on column fee_amount.
  4. 02:19 It queries bronze. 1,208 rows loaded at 01:47 have fee_amount = 'N/A'. All come from one new payment provider code, PAYX. No earlier load has the value.
  5. 02:21 It finds a shared memory from August: the same provider sent empty strings for a week, and the team chose to treat them as null and add a warning test.
  6. 02:27 It opens a pull request that uses try_to_number, adds a warn-severity test that counts non-numeric fees per provider, and attaches a passing CI build.
  7. 02:28 It posts the report below and stops.
Nori  02:28
Production dbt run 48213 failed at stg_payments__transactions.

Cause: 1,208 rows from provider PAYX (loaded 01:47 UTC) have
fee_amount = 'N/A'. The cast to numeric fails.

Downstream not refreshed: fct_payments, fct_monthly_revenue,
Finance daily dashboard. They still show data through 2026-11-09.

Seen before: PAYX sent empty strings in August. We decided then to load
them as null and warn (memory: payx-fee-format).

Fix: PR #531 casts with try_to_number and adds a warn test for
non-numeric fees. CI build passed. I have not rerun production.
@oncall-data: merge and rerun, or reply here if you want it handled
another way.

The on-call engineer reads one message in the morning, reviews a small diff, merges and reruns. The agent then saves a line to shared memory: PAYX can send N/A as well as empty strings.

How to start

  1. Pick one job from the table that already has a clear pass or fail, usually the nightly build.
  2. Create the scoped warehouse role and add it as an integration for your data agent.
  3. Write your conventions into the team skillset. A page is enough to begin.
  4. Run the job by hand from Slack a few times and correct the agent in the thread. Those corrections become memories.
  5. Turn the prompt into an automation with a schedule or webhook, and add the next job when the first is boring.

For how schedules work in general, see scheduled coding agents. For the role view, see Nori for data teams. Teams in fund operations use the same pattern for reference data; see AI agents for asset managers.

Frequently asked questions

Can a scheduled agent change production data?

Not in the recommended setup. The agent's warehouse role reads production and writes only to a development schema. Model and policy changes ship through reviewed pull requests and your own deploy job. Deletes and drops need a person's approval and a person to apply them.

Which warehouses and tools does it work with?

Anything the sandbox can reach with a client, API or MCP server: Snowflake, BigQuery, Databricks, Redshift, Postgres, dbt Core and dbt Cloud, Airflow, Dagster, and your catalog. Your setup script installs the tools, so every session starts ready.

Does this replace our orchestrator or dbt?

No. Your orchestrator still runs pipelines and dbt still builds models. Nori runs the agents that watch them, investigate failures, apply governance rules and propose fixes. The orchestrator calls a webhook when something needs attention.

How does the agent remember past incidents?

Through shared memories. When a thread ends with a decision or a root cause, the agent saves a short note. Later sessions search those notes before reporting, so a repeat failure arrives with the earlier cause and the fix the team chose.

What does it cost to run nightly agents?

Nori charges a flat plan price for machines: Developer is $99 per month and Team starts at $250 per month, with a 30-day free trial. Model usage runs on your own subscription, API keys or gateway. Nori never charges for tokens.

Can analysts who do not write code use it?

Yes. Anyone you allow can ask in Slack why a number changed or whether a table is fresh, and the agent answers with the query it ran. Changes still go through pull requests that a data engineer reviews.