Skip to content

This feature is currently in Preview.

Deploy a model

Deploy a PyRel model to a Snowflake schema so its outputs are accessible as regular Snowflake objects: tables, views, or dynamic tables. This guide shows how to configure the target schema and role, validate and run the deployment in the CLI, inspect and query the model outputs in Snowflake with SQL, and troubleshoot common issues.

The outputs of a PyRel model are the concepts and relationships derived from its source tables via any of the supported reasoners. By mapping every concept to an object with a column for each of its properties, and every relationship to an object with a column for each of its fields, model outputs can be fully represented using familiar Snowflake objects. This makes deployed model outputs appear like any other governed data source in your organization.

To deploy, you pick a target Snowflake schema where the objects derived by your model should live. As long as your model remains the same, the generated schema stays stable so others in your organization can depend on it. PyRel also uses a meta schema (<target name>_META by default) to store model state and intermediate results that others should not depend on.

Deploying a model to a target schema does not move the model’s source tables. Source tables can come from any other schema and remain completely unaffected.

Each model output needs a refresh schedule, which tells PyRel when to refresh that output. You can configure a schedule to run periodically, or to run only when you trigger it manually or from an external pipeline.

PyRel marks the objects it creates with an ownership tag, named relationalai_managed by default. The tag value identifies the model that owns the object. PyRel rejects a deployment that would overwrite a foreign object, i.e., an existing object that doesn’t carry the model’s ownership tag. This protects both objects that are owned by other models and ones that were not created by PyRel.

A single model can be deployed to an arbitrary number of target schemas simultaneously. This is typically used to create separate development and production environments, or to support multiple tenants with isolated data sources. PyRel fits into your existing development and deployment processes.

In this section, you’ll set up a new, deployment-ready PyRel model. If you already have a model you want to deploy, skip to the next section.

  • You have a working PyRel installation and a working Snowflake connection.
  • You have access to a Snowflake account where the RelationalAI Native App is installed.

The steps below use the starter model to validate your deployment setup end to end.

  1. Initialize a new model

    In your working directory, run:

    Terminal window
    rai models init [your-model-name]

    For command details and options, see rai models init.

    This creates a folder your-model-name with a starter model and raiconfig.yaml. The generated raiconfig.yaml demonstrates a best practice: use separate dev and prod profiles in raiconfig.yaml. By switching profiles, you can keep using the same rai models deploy flow, whether you are developing against an isolated schema with test data, or releasing to a production schema widely used throughout your organization.

  2. Configure your development connection in raiconfig.yaml

    In the dev profile, fill in the connection fields for your Snowflake account and authentication method. You will also need to configure which warehouse to use for SQL execution. For example:

    default_connection: sf
    connections:
    sf:
    type: snowflake
    account: my_org-my_account
    warehouse: my_warehouse
    rai_app_name: relationalai # name of the RAI app in your Snowflake account
    authenticator: externalbrowser # SSO via browser; for PAT or JWT see README.md
    user: you@example.com
  3. Set the target schema and refresh schedule in raiconfig.yaml

    Again for the dev profile, fill in the model and deployment sections. For this first deployment, use a dedicated schema. No other applications should modify the objects created for this model, to avoid conflicts and unexpected results.

    model:
    path: model.py # path to the model entry point script
    deployment:
    schema: MY_DATABASE.MY_DEV_SCHEMA # fully-qualified <DATABASE>.<SCHEMA>
    role: MY_DEPLOYMENT_ROLE # Snowflake role used to deploy and refresh the model
    # auto_deploy: false # set to true to auto-deploy the model before queries
    schedules:
    standard:
    interval_s: 0 # run on deploy, but do not refresh on a fixed interval
    outputs:
    schedule: standard # assign all outputs to the `standard` schedule

    If the deployment database or schema is transient, configure a standard op log table before deploying. Snowflake can’t create the default Hybrid op log table in a transient database or schema.

  4. Load some sample data

    The starter model includes a script to load a few rows of test data that you can use to validate everything is working correctly:

    Terminal window
    python load_data.py

    If you have some source tables already, just skip this step and update model.py to use those.

  5. Deploy from the CLI

    Before your first deployment, you can validate your configuration and database connectivity with rai connect.

    With the data loaded, it’s time to trigger the deployment. In the model directory (the one containing your raiconfig.yaml), pick the dev profile and run:

    Terminal window
    RAI_PROFILE=dev rai models deploy --wait

    For command details and options, see rai models deploy. --wait makes the deploy command wait for the initial refresh of the model to finish.

  6. Inspect the deployed model

    Once the deployment and the initial refresh complete, your model outputs will be visible in the target schema. Use the Snowflake UI or CLI to inspect the target schema. It should now contain several dynamic tables corresponding to the Connection and Station concepts from the starter model.

    You can also query a deployed model through PyRel directly. For the starter model, run:

    Terminal window
    python queries.py

    This runs a few example queries. Note that PyRel queries return dataframes and are not themselves visible in the target schema.

You can configure the prod profile in the same way. When you’re ready to deploy to production, run RAI_PROFILE=prod rai models deploy. If you need to reset a development deployment and clean up its managed objects, see rai models teardown.

In this section, you’ll update your existing raiconfig.yaml so an existing model is ready for deployment. If you’re starting from scratch, see the previous section.

  • You have a working PyRel installation and a working Snowflake connection.
  • You have access to a Snowflake account where the RelationalAI Native App is installed.
  • You know which Snowflake schema to target for this workflow and can inspect that location in Snowflake.
  • You already know how to create a Model and run a query.

The steps below focus only on the deployment-specific configuration you need to add.

Eventually, any existing PyRel model will be deployable. However, the following limitations currently apply:

  • Deployment is currently supported only for models using rules-based reasoning.
  • Existing PyRel queries must be strictly separated from the model definition.

Your existing raiconfig.yaml will already have one or more Snowflake connections configured, which you can keep using. If you haven’t already, consider adding separate dev and prod profiles as a best practice. The steps below apply to any profile.

  1. Specify the entry path for your model

    Make sure that your model section specifies where your model can be found. This is done via the path field, which can point to a Python file or module.

    model:
    path: model.py
  2. Set the target schema in raiconfig.yaml

    Add a deployment section specifying the target schema and role.

    deployment:
    schema: MY_DATABASE.MY_DEV_SCHEMA # fully-qualified <DATABASE>.<SCHEMA>
    role: MY_DEPLOYMENT_ROLE # Snowflake role used to deploy and refresh the model
    # auto_deploy: false # set to true to auto-deploy the model before queries
    # suspend_after_mins: 60 # auto-suspend model refresh, useful in development

    This tells PyRel where to deploy the model and which Snowflake role to use for deployment and refresh tasks. If you omit deployment.role, PyRel uses the connection role or current session role.

  3. Define a refresh schedule

    Every model output must be assigned to a schedule. Extend your deployment section to create a schedule and use it as the default for all model outputs. Schedules are explained in more detail in Configure a model.

    deployment:
    schema: MY_DATABASE.MY_DEV_SCHEMA
    role: MY_DEPLOYMENT_ROLE
    schedules:
    standard:
    interval_s: 30 # outputs on this schedule refresh every 30s
    outputs:
    schedule: standard # set the `standard` schedule as the default
  4. Deploy from the CLI

    Select the right profile and trigger the deployment.

    Terminal window
    RAI_PROFILE=dev rai models deploy

    For command details and options, see rai models deploy.

Deployment behavior is configured in the deployment section of raiconfig.yaml. For the full set of options, see Configure a model:

After your model is correctly configured, you can trigger a deployment from the CLI. From the model directory that contains raiconfig.yaml, pick a profile and run:

Terminal window
RAI_PROFILE=dev rai models deploy

See rai models deploy for command details and options.

This validates your configuration and Snowflake connection, then deploys the model. Add --wait to wait for the initial refresh to finish before the command returns. Without --wait, deployment can finish while outputs are still refreshing. Refer to the troubleshooting section below if you run into issues.

Use deployment.object_name_prefix or deployment.object_name_suffix to give each model its own object names within a shared schema. You can use a prefix, a suffix, or both. The same settings apply to all objects created by PyRel, both model outputs and internal objects, except the ownership tag itself.

Start with two model projects that already have a working Snowflake connection, deployment role, and refresh schedules, as described above. In the first project’s raiconfig.yaml, set these fields in the existing deployment section:

deployment:
schema: MY_DATABASE.SHARED_MODELS
object_name_prefix: PRJ123_

In the second project’s raiconfig.yaml, use the same schema with a different prefix:

deployment:
schema: MY_DATABASE.SHARED_MODELS
object_name_prefix: PRJ456_

Keep each project’s existing role, schedules, and output settings. Deploy each model from its project directory with the configured profile.

If both models have an output named TRANSACTION, the shared schema contains PRJ123_TRANSACTION and PRJ456_TRANSACTION. Their status procedures are PRJ123_REFRESH_STATUS() and PRJ456_REFRESH_STATUS() in MY_DATABASE.SHARED_MODELS_META.

Prefixes and suffixes can coexist in a schema. PyRel will reject deployments that would overwrite existing objects that do not belong to the deploying model.

For defaults, naming rules, and suffix examples, see Configure object name prefixes and suffixes.

Once a deployment succeeds in the CLI, PyRel creates the target schema and meta schema if they don’t exist yet. By default, the meta schema is <target name>_META. You can override that default with deployment.meta_schema. PyRel then starts any refresh schedule whose run_on_deploy setting is true. Inspect the target schema to verify this.

  1. Check the target schema

    SHOW SCHEMAS LIKE '<YOUR_TARGET_SCHEMA>' IN DATABASE <YOUR_DATABASE>;

    Replace <YOUR_TARGET_SCHEMA> and <YOUR_DATABASE> with the target schema you set for deployment.schema.

  2. List installed objects

    During deployment, the PyRel compiler decides which type of Snowflake object to use for each output. It may choose regular tables, views, or dynamic tables. This can also be configured on a per-output basis.

    SHOW OBJECTS IN SCHEMA <YOUR_DATABASE>.<YOUR_TARGET_SCHEMA>;

    You should see objects corresponding to each of the concepts and relationships in your model.

  3. Check the model’s refresh status

    The meta schema exposes a REFRESH_STATUS procedure that returns one row per refresh schedule, showing each schedule’s current status. REFRESH_STATUS is the first place to check when a model is not refreshing as expected.

    CALL <YOUR_META_SCHEMA>.REFRESH_STATUS();

    You should see a row for each schedule. The status column can return:

    StatusMeaning
    DEPLOY_RUNNINGA deployment is currently updating the model.
    DEPLOY_FAILEDThe latest deployment failed.
    NEVER_RUNThe schedule exists but has not run yet.
    RUNNINGA refresh is currently running.
    SUCCEEDEDThe latest completed refresh succeeded.
    FAILEDThe latest completed refresh failed. The error column contains the failure message.

If you configured a prefix or a suffix, the refresh status procedure will carry this prefix or suffix. For example, with a PRJ123_ prefix, the procedure will be called PRJ123_REFRESH_STATUS().

If any of these steps fails or Snowflake does not show the expected objects, continue to the troubleshooting section below.

The outputs of a deployed model are eventually consistent with their source data. After a source table changes, deployed outputs will continue to show earlier results until a refresh reads the change and finishes successfully.

Within a refresh run for one schedule, PyRel updates outputs progressively in dependency order: dependencies first, then the outputs that depend on them. Outputs that do not depend on each other may refresh in parallel.

Refresh runs are not snapshot-isolated across all reads. If a refresh reads the same source table more than once, and the table changes between those reads, the refresh may read different versions of that table.

Different refresh schedules run independently. Dependency order is enforced within a schedule, but not between schedules. If dependent outputs are assigned to different schedules, queries may see a mix of older and newer output data while those schedules are refreshing.

For example, consider this model, with one source table S and three model outputs A, B, and C:

SsourceAoutputBoutputCoutput

If A, B, and C are assigned to the same schedule, a refresh submits updates for A and B first. After both finish, the refresh updates C.

If A, B, and C are assigned to different schedules, there is no cross-schedule ordering guarantee. For example, a query may see A after it has refreshed, B before it has refreshed, and C before it reflects both updates.

After you deploy a model, you manage it through a workflow built around the current model, its op log history, and any branches you create from it. The next sections explain how deployments are tracked, how to switch to the right model, and how to branch, collaborate, merge, and tear down models safely.

  • You already have a model deployed to a Snowflake schema.
  • Op log recording is enabled. In PyRel 1.28 and later, it is on by default. If you explicitly disabled it with oplog.enabled: false, remove the override or set it to true before using the branching, pull, and merge flows in this workflow. See Control op log recording below.

In PyRel 1.28 and later, op log recording is enabled by default. With recording enabled, a successful rai models deploy installs your model’s resources and outputs into the target schema and records the difference between your model and the previously deployed version as a series of operations in the schema’s op log. When recording is explicitly disabled, deploy still installs your model’s resources and outputs, but it records no history, and the branch, pull, and merge flows are unavailable.

The op log is your model’s history: an ordered record of how the model has changed from one deploy to the next. When a deploy records changes, PyRel tells you how many:

Recorded 3 change(s) to the snowflake oplog.

You never edit the op log directly. The rai models commands maintain it for you. Each model and branch keeps its own op log. That history is what the rest of this workflow builds on: deploy appends to the current model’s op log, branching forks a new branch from the parent’s history, and merging appends a branch’s changes back onto its parent’s op log.

You do not need to add an oplog section to record history in PyRel 1.28 or later. To deploy the model without recording change history, set oplog.enabled: false in raiconfig.yaml:

oplog:
enabled: false

oplog is a top-level section, alongside connections, model, and deployment. With recording disabled, rai models deploy installs your model without recording history, and the branch, pull, and merge flows are unavailable. To restore the default, remove the enabled: false override or set oplog.enabled: true.

The rai models commands read oplog.enabled from the raiconfig.yaml that PyRel discovers when the command runs, so set the override there for command-line workflows. For other ways to set it, including from Python, see Configure op log recording.

  • You’re comfortable with rai models deploy and with the deployment.schema setting in raiconfig.yaml.

To branch, pull, merge, or tear down a model, first make sure you’re pointed at the right one. Every command that manages a model acts on your current model: the model selected by schema, meta_schema, object_name_prefix, and object_name_suffix in the deployment section of your raiconfig.yaml. rai models deploy, branch, pull, merge, and teardown all target it.

Use rai models list to see the models that exist, and rai models switch to choose the one you want to work on:

Terminal window
rai models list
rai models switch MY_DATABASE.MY_DEV_SCHEMA

rai models switch validates that the model exists in the requested schema, then updates deployment.schema and its metadata location in your raiconfig.yaml, preserving its comments and layout. rai models list shows each model’s name, its parent if it is a branch, and its type: a base model, a live branch model, or a static branch model. For models with a prefix or suffix, the list also shows those values, and switch uses the values set in your configuration.

  • Your current model is already deployed to a Snowflake schema.
  • Op log recording has not been disabled. It is enabled by default in PyRel 1.28 and later. Branching relies on the op log, so rai models branch fails with Oplog recording is disabled (config.oplog.enabled = false) when it is off. See Control op log recording.

A branch is a fork of your current model into a brand-new Snowflake schema. Creating one is lightweight: it is a zero-copy fork that duplicates none of the parent’s data. The branch starts from the parent’s deployed state and history, then evolves on its own: you can deploy changes to it without touching the parent.

Because the parent is your current model, the schema you branch from must already be deployed. If the parent uses a prefix or suffix, the branch inherits it and can use an existing destination schema, provided its objects do not conflict with existing objects.

  1. Pick the model to branch from

    Confirm your current model, switching if needed:

    Terminal window
    rai models switch MY_DATABASE.MY_DEV_SCHEMA
  2. Create the branch

    Terminal window
    rai models branch EXPERIMENT_X

    For command details and options, see rai models branch.

  3. Switch into the branch and work in it

    Terminal window
    rai models switch EXPERIMENT_X

    Edit your model and deploy as usual:

    Terminal window
    rai models deploy

    Changes land in the branch’s schema. The parent is untouched.

Branches differ in how they track the parent as the parent changes:

  • Live branches (the default) stay connected to the parent. When you run rai models pull, the parent’s latest changes are reconciled into your branch automatically.
  • Static branches (rai models branch --static) are frozen at the fork point. A plain rai models pull does not bring in the parent’s later changes. You incorporate them explicitly, when you choose to, with rai models pull --from-parent.

Choose a live branch for short-lived work that should keep pace with the parent, and choose a static branch when you want a stable base that only changes when you ask it to.

  • Op log recording has not been disabled for the shared model. It is enabled by default in PyRel 1.28 and later, and every collaborator needs it enabled: rai models pull reconciles shared changes through the op log, and rai models deploy only records to the shared history when recording is on. With recording off, pull fails with Oplog recording is disabled (config.oplog.enabled = false) and deploy installs without contributing to the shared history. See Control op log recording.

Several developers can work against the same deployed model. The op log becomes the shared deployment history because each deploy appends to it.

A model has two parts, and they stay in sync in different ways:

  • The part you own: the model source you author. You can split it across as many files as you like and name them however you want. The op log records your changes to these entities too, but PyRel does not sync your source for you: you share it and resolve any conflicts the usual way, through version control (for example, git pull). When you deploy owned changes, PyRel reminds you to commit them to source control.
  • The shared part: entities contributed through the op log, including by your collaborators. PyRel projects these into a generated file named shared_model.py, written alongside your source. This file becomes part of the same model. It is not a separate, parallel model. PyRel wires it in automatically on deploy and pull. rai models pull keeps it current by regenerating it from the op log, so shared changes are reconciled for you automatically. You normally let PyRel maintain this file, but you can also edit it directly: as long as your copy is up to date, your edits are deployed and pushed to the op log just like a change to your own source.

In short, rai models pull reconciles shared changes for you automatically, while owned changes are yours to manage in version control.

The one exception to that automatic sync: if you have hand-edited shared_model.py, neither rai models pull nor rai models deploy will overwrite it unless you pass --force - both regenerate the file and refuse to clobber hand edits. With --force, your current file is backed up to a timestamped shared_model.py.<timestamp>.bak first.

To reference shared entities from your own code:

from shared_model import build_shared
shared = build_shared(m) # shared.Person, shared.orders, ...

A typical collaboration loop:

  1. Pull before you start

    Terminal window
    rai models pull

    For command details and options, see rai models pull.

  2. Make your changes and deploy

    Terminal window
    rai models deploy

    If a collaborator deployed since your last pull, the deploy is refused with a message telling you to pull first. Run rai models pull and deploy again to get back in sync.

For a static branch, a plain rai models pull only syncs the branch’s own changes. To incorporate the parent’s latest into the branch, run rai models pull --from-parent.

When a branch’s changes are ready, merge promotes them back into the parent and retires the branch.

A branch must sit on top of the parent’s latest changes before it can merge. In practice that means catching the branch up on the parent and re-deploying it first.

  1. Switch to the branch

    Terminal window
    rai models switch EXPERIMENT_X
  2. Catch up on the parent and rebase

    Terminal window
    rai models pull
    rai models deploy
  3. Merge

    Terminal window
    rai models merge

    For command details and options, see rai models merge.

rai models merge diffs the branch against its parent, appends the branch’s net changes to the parent’s op log, installs the merged model into the parent schema, and retires the branch. The parent is resolved automatically from the branch’s lineage, so you never name it.

A retired branch can no longer receive deploys. Add --delete to also clean up the retired branch in the same step. This removes the objects that PyRel created for this branch, and leaves the schema itself in place:

Terminal window
rai models merge --delete

rai models teardown removes the objects that PyRel created for the current model or branch. This includes model output objects and meta objects such as the model state, intermediate results, and refresh tasks. It leaves both the target schema and the meta schema in place, along with all the objects in them that were not created by PyRel, other models’ objects, and shared ownership tags.

By default, teardown is a dry run: it prints exactly what would be removed and stops. Re-run with --force to actually perform it.

Terminal window
rai models teardown # dry run: shows what would be removed
rai models teardown --force # actually remove them

Teardown leaves raiconfig.yaml untouched, so deployment.schema still names the model you just tore down. That pointer is now stale: deploying with it again redeploys into the same schema. You can update the pointer with rai models switch <name>. Teardown also leaves your model source and shared_model.py untouched.

Teardown protects you from losing work you may not have meant to lose:

  • It refuses to discard a branch that has unmerged changes. Override with --allow-unmerged to discard them.
  • It refuses to act when the model has downstream branches. Override with --allow-children to tear those branches down too, in a cascade: every child goes, merged or not. A child with unmerged changes also needs --allow-unmerged.

If a deploy, pull, merge, or teardown step does not behave as you expect, use the troubleshooting section below to narrow down the cause.

An administrator can prepare schemas or tags so that the deployment role does not need the corresponding creation privileges.

Have an administrator create the model schema and its meta schema, then grant the deployment role USAGE on the database and both schemas.

Have an administrator create the tag RELATIONALAI_MANAGED in the meta schema, then grant the deployment role APPLY on this tag. Create the tag without ALLOWED_VALUES so it accepts all string values. Do not apply the tag to the schemas.

For example, replace MY_DB, MY_MODEL_META, and DEPLOY_ROLE with your database, meta schema, and deployment role:

CREATE TAG MY_DB.MY_MODEL_META.RELATIONALAI_MANAGED;
GRANT USAGE ON DATABASE MY_DB TO ROLE DEPLOY_ROLE;
GRANT USAGE ON SCHEMA MY_DB.MY_MODEL_META TO ROLE DEPLOY_ROLE;
GRANT APPLY ON TAG MY_DB.MY_MODEL_META.RELATIONALAI_MANAGED TO ROLE DEPLOY_ROLE;

It is possible to create the tag outside the meta schema. To do so, create the tag as described, in the schema of your choice, and set deployment.managed_tag to that tag’s fully qualified name, such as GOV.TAGS.RELATIONALAI_MANAGED. Grant the deployment role USAGE on the database and schema that contain the tag, and APPLY on the tag itself. Configure deployment.managed_tag before the first deployment.

Deployment and model management commands can fail for several reasons. Start with the quick diagnostics below, then use the issue list to narrow down the most likely cause.

Many deployment issues come from missing or invalid model configuration or Snowflake connection settings. Start by running:

Terminal window
rai doctor

If the issue still looks configuration-related, also run:

Terminal window
rai config explain

When you need a deeper look or want to share diagnostics with RelationalAI support, generate a doctor report. It bundles the resolved configuration, connection and privilege checks, deployment state, and recent run traces into a single zip:

Terminal window
rai doctor report

This writes doctor_report_<timestamp>.zip to the current directory. Attach that zip to your support request. See rai doctor report for command details and options.

If you deploy programmatically by building a config in Python and passing it to Model(config=...) rather than using a raiconfig.yaml file, run the report from Python and pass the same config, so it reports on the configuration your deployment actually used:

from relationalai.tools.cli.doctor_report import run_doctor_report
run_doctor_report(config=config)

Inside a Snowflake Notebook, use download_doctor_report instead. It generates the report and renders a button to download the zip:

from relationalai.tools.cli.doctor_report import download_doctor_report
download_doctor_report(config=config)

No objects show up in the target schema

If rai models deploy succeeds but the target schema still looks empty, you’re most likely looking at a different schema than the one the model deployed to. Verify that deployment.schema is correct and that you’re using the expected profile.

Deployment cannot resolve a database

If neither the active Snowflake connection’s database nor the deployment.schema configuration option supplies a database, deployment reports a configuration error instead of selecting a placeholder database. Set deployment.schema to a fully qualified DATABASE.SCHEMA value, or set database on the active Snowflake connection in raiconfig.yaml. An unset connection database is fine when deployment.schema includes a database.

Snowflake raises a privilege error during model refresh

If deployment succeeds but the model refresh task fails with a privilege error, the deployment.role you configured most likely does not have permission to execute Snowflake tasks. Confirm the target schema and access configuration with your Snowflake admin or with RelationalAI support.

Source tables are not visible in the target schema

Only model outputs are deployed into the target schema. Source tables stay in their original schemas and aren’t affected by deployment. Check your tables configuration to confirm which schema your source tables come from.

Unexpected objects show up in the target schema

The PyRel compiler can choose tables, views, or dynamic tables for a given output. You can also override that behavior in raiconfig.yaml. If an expected dynamic table is missing, check whether PyRel used a table because the output cannot be represented as a dynamic table. If an expected table is missing, check whether PyRel created a view instead, or vice versa.

A deploy is refused because the remote has changes

Someone else or another session deployed since your last pull, so the remote is ahead of you. If the changes are shared deployment state, run rai models pull to reconcile them, then run rai models deploy again. If rai models pull reports code-owned changes, those changes live in a collaborator’s source files, so reconcile them through version control with git pull first, then pull and deploy. Pass --path so PyRel can verify that your source is in sync.

rai models merge reports the branch is behind its parent

The parent advanced after you branched. Switch to the branch, run rai models pull, then run rai models deploy to rebase it onto the parent’s latest state before you try the merge again.

rai models pull won’t overwrite shared_model.py

Pull protects a locally edited shared_model.py from being overwritten. Re-run rai models pull --force. PyRel backs up your current file to shared_model.py.<timestamp>.bak first.

rai models teardown refuses because of children or unmerged changes

A branch with downstream branches or unmerged work is protected. Merge or tear down the child branches first, or pass --allow-children or --allow-unmerged to override that protection. Note that --allow-children tears the child branches down too, and --allow-unmerged discards unmerged work.

rai models branch says the parent isn’t a provisioned model

You can only branch from a deployed model. Deploy the parent schema first with rai models deploy, then branch.