$npx -y skills add rudderlabs/rudder-agent-skills --skill rudder-profiles-projectCreates a new RudderStack Profiles project with discovered warehouse resources and validated YAML. Use when creating a Profiles project, bootstrapping identity resolution, generating pb_project.yaml, or building inputs and features from scratch.
| 1 | # RudderStack Profiles Project Creation |
| 2 | |
| 3 | Create a new Profiles project by discovering real warehouse resources first, then generating the three core YAML files with explicit user confirmation at each decision point. |
| 4 | |
| 5 | ## Workflow |
| 6 | |
| 7 | 1. **Verify setup** — Check that Profiles MCP tools are available. If not, send the user to `/rudder-profiles-setup`. |
| 8 | 2. **Discover connections** — Call `get_existing_connections()`. |
| 9 | - If connections exist, present the list and let the user pick one. |
| 10 | - If no connections exist, instruct the user to run `pb init connection` in their terminal, wait for confirmation that it completed, then re-check with `get_existing_connections()`. |
| 11 | 3. **Discover tables** — Call `input_table_suggestions()` for candidate tables. Call `describe_table()` on each candidate to confirm columns, types, and timestamps. |
| 12 | 4. **Confirm with user** — Present discovered resources and get explicit approval (see confirmation gates below). |
| 13 | 5. **Generate YAML** — Write `pb_project.yaml`, `models/inputs.yaml`, and `models/profiles.yaml` using only discovered names and the exact shapes in `references/basic-yaml-templates.md`. Derive `schema_version` from the installed binary (scaffold with `pb init pb-project` or MCP `setup_new_profiles_project()`; verify with `pb version`) — do not hardcode a remembered number. For each event-stream input set `contract: { is_event_stream: true, is_append_only: true }` plus `app_defaults.occurred_at_col` (the contract unlocks later incremental migration without a checkpoint-invalidating schema change, and `is_append_only` is rejected without `occurred_at_col`). Start with the **default ID stitcher** (no explicit `id_stitcher` model) unless the user needs custom edge sources. Add `filters:` on id_types to exclude junk values (`"unknown"`, `"NaN"`, `""`, internal test IDs) — the cheapest over-stitching prevention available. |
| 14 | 6. **Pre-compile review** — Run through the validation checklist in `references/validation-checklist.md`. |
| 15 | 7. **Validate access** — Run `pb validate access` to confirm the warehouse role can read the inputs and write to the output schema. Fix permission gaps here, before compiling. |
| 16 | 8. **Compile** — Run `pb compile`. If it fails, fix one issue at a time and re-compile. |
| 17 | 9. **Pilot run** — Offer `pb run --begin_time <ISO-8601>` only after compile succeeds and the user confirms. |
| 18 | |
| 19 | ## Confirmation Gates (5 mandatory) |
| 20 | |
| 21 | Never proceed past a gate without explicit user approval: |
| 22 | |
| 23 | 1. Which warehouse connection to use? |
| 24 | 2. Which tables to include as input sources? |
| 25 | 3. Which columns for ID types and timestamps? |
| 26 | 4. Entity name and which features to create? |
| 27 | 5. Final YAML review before writing files? |
| 28 | |
| 29 | ## Critical Rules |
| 30 | |
| 31 | These are the most common sources of broken projects. Violating any of them will cause compile or run failures: |
| 32 | |
| 33 | - **No placeholders.** Never use names like `my_database`, `example_table`, `my_connection`, or `sample_schema`. Every resource name must come from MCP discovery or the user. |
| 34 | - **Aggregation requirement.** If an entity var has a `from` key, its `select` MUST use an aggregation function: `count`, `sum`, `max`, `min`, `avg`, `first_value`, or `last_value` (order-dependent ones need a `window:` with `order_by`). A bare column reference in `select` with `from` will fail. |
| 35 | - **Var reference syntax.** Reference another entity_var with the dot form `{{<entity_name>.<var_name>}}` — e.g., `'{{user.order_count}}'` for an entity named `user`. The first segment is the **entity's name from pb_project.yaml**, not the literal word `entity`. Quote the whole `select:` with single quotes. (The `{{user.Var("order_count")}}` function form also works but the dot form is preferred.) |
| 36 | - **Model paths, not ref().** `from:` takes a path to a model — `inputs/<input_name>`, `models/<model_name>`, or `packages/<pkg>/...`. pb has no dbt-style `ref('...')` function. |
| 37 | - **No date filters in YAML.** Never add `WHERE` clauses with date filters in input or profile definitions. Use `pb run --begin_time` at runtime instead. |
| 38 | - **Verify before using.** Always confirm table and column existence with `describe_table()` before writing them into YAML. Do not trust user-provided names without verification. |
| 39 | |
| 40 | ## Writing Strategy |
| 41 | |
| 42 | - Discover first, then draft YAML. |
| 43 | - Prefer the smallest correct project that compiles over a broad first draft. |
| 44 | - Show the final YAML or diff to the user before writing files. |
| 45 | - If `pb compile` fails, fix one issue at a time and re-run compile before making more edits. |
| 46 | |
| 47 | ## Credential Security |
| 48 | |
| 49 | - Do not request secrets in chat during connection setup. |
| 50 | - If `pb init connection` prompts interactively, let the user complete that step in their |