All jobs

Add a Customer Lifetime Value Model to a dbt Project from a Linear Issue

Yes. An agent picks up the Linear issue, adds a customer lifetime value mart to your dbt project with YAML tests and opens a pull request.

Run this on RushIn a Project that has your repository.

What the agent does

The run starts from the repository URL in resources: the agent clones it into its own cloud sandbox and reads the project the way a new analytics engineer would. In a project like dbt-labs/jaffle-shop, dbt_project.yml names the project jaffle_shop at version 3.0.0, requires dbt >=2.0.0, materializes staging as views and marts as tables, and points tests at data-tests/. packages.yml already pulls dbt-labs/dbt_utils at 1.4.1.

The agent maps the issue onto the existing marts before writing SQL. models/marts/customers.sql already joins stg_customers to an orders summary and exposes count_lifetime_orders, first_ordered_at, last_ordered_at and lifetime_spend, with matching column docs and tests in customers.yml. The issue still asks for a dedicated LTV mart with lifetime revenue, order count and first and last order dates, documented in YAML with tests, so the agent adds models/marts/customer_ltv.sql that selects those fields into a focused one-row-per-customer table rather than expanding the broader customers overview again.

The new model refs orders the same way the customers summary does, groups by customer_id, and names the columns the issue uses in reviews: lifetime revenue from order_total, order count, and the min and max of ordered_at. Alongside it the agent adds models/marts/customer_ltv.yml with a model description, not_null and unique on customer_id, and dbt_utils.expression_is_true style checks that lifetime revenue is non-negative when orders exist.

Proving it means a local DuckDB build. The agent installs dbt against the project's Python tooling from Taskfile.yml and requirements.txt, configures a DuckDB profile, runs dbt deps for dbt_utils, seeds or uses the sample data the project already ships under seeds/, and runs dbt build so the new mart and its YAML tests compile and pass before the pull request opens.

Start it with one API call

POST https://api.prix.dev/o/{org}/sessions with this body:

{
  "agent": "claude",
  "input": "A Linear issue labeled agent says: \"Add a Customer Lifetime Value Model to a dbt Project. Add a mart model with each customer's lifetime revenue, order count and first and last order dates, documented in YAML with tests.\" Do the work in this repository, add tests for it, run dbt build on DuckDB, and open a pull request that links back to the issue.",
  "resources": [
    {
      "url": "https://github.com/your-org/your-app"
    }
  ]
}
  1. Get an API key. In the console, open Settings, then API keys, and create a key for your org. Send it in the Authorization header as a Bearer token.
  2. Send the request. POST the body in request.json to https://api.prix.dev/o/{org}/sessions, with your repository as the resources URL. The run starts in its own cloud sandbox.
  3. Read what came back. Follow the run on its live stream or wait for the run.completed webhook, then read the result and its trajectory.

What comes back

What comes back is a pull request. Its diff adds models/marts/customer_ltv.sql and models/marts/customer_ltv.yml, and leaves the existing customers mart in place. The description quotes the issue and links back to it.

The checks on the pull request run dbt build on DuckDB with the same package versions packages.yml pins. A reviewer reads the SQL for one grain (one row per customer), confirms the four metrics match the issue, and confirms the YAML tests fail if customer_id duplicates or lifetime revenue goes negative. Staging models and seeds are untouched.

The session read keeps the record behind the pull request: dbt deps, the DuckDB profile the agent wrote, and the full dbt build output. Anyone who questions the mart can re-read those commands without re-running them locally.

Run it on every Linear issue labelled agent

The Project's automation turns the label into the run. In the console, add an automation with a Linear trigger on linear.issue.labeled filtered to the agent label and this prompt; each labelled analytics ticket starts its own run in its own sandbox and opens its own pull request on the dbt project.

If the automation is not wanted, a small server can do the same: receive Linear's issue webhook, put the mart definition from the issue into input, and POST to /o/{org}/sessions with the jaffle-shop style repository in resources. A run.completed webhook on the API key posts the pull request URL when dbt build has finished in the sandbox.

The use case this job follows, with its automation and trigger: Turn a Linear label into a PR.

Why run it on Rush?

On a laptop this job is a chain of Python and warehouse setup: a venv, pip install from requirements.txt, a DuckDB or warehouse profile, and dbt deps before dbt build will even resolve dbt_utils. Each run on Rush boots its own sandbox with that already in reach, runs the build itself, and keeps every command and its output, so the proof of the LTV mart is the run's own record.

Analytics backlogs stack up when several labelled issues wait on one engineer's laptop. Each labelled issue becomes one run, one sandbox and one pull request, so LTV, retention and revenue marts can move in parallel without fighting over a single dbt target directory.

Frequently asked questions

customers.sql already has lifetime spend. Why add another model?

The customers mart is a broad overview with customer type and tax breakdowns. The issue asks for a dedicated LTV mart with lifetime revenue, order count and first and last order dates. The agent adds customer_ltv for that contract and leaves customers alone so existing dashboards keep their columns.

Does it run against Snowflake or BigQuery?

The prompt asks for DuckDB in the sandbox so the build is self-contained. The SQL uses standard dbt refs and aggregations that port to the warehouse your profile already uses; change the profile when you merge if production is not DuckDB.

Which package provides the YAML tests?

packages.yml already depends on dbt-labs/dbt_utils 1.4.1. The agent runs dbt deps and uses those helpers for expression tests instead of inventing a second testing package.

Will the agent regenerate seed data?

Only if the existing seeds are missing in the sandbox. The Taskfile's gen and seed tasks exist for jafgen output; a normal LTV change reuses seeds/ and does not rewrite years of fake orders.