skills/rai-configuration/SKILL.md
Covers PyRel v1 configuration including raiconfig.yaml, connection setup, programmatic config, model and reasoner settings, and engine management. Use when setting up or troubleshooting RAI connections and configuration.
npx skillsauth add RelationalAI/rai-agent-skills rai-configurationInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
What: PyRel v1 configuration — config files, connection setup, authentication, model settings, and reasoner settings.
When to use:
When NOT to use:
rai-pyrel-codingrai-prescriptive-solver-managementOverview: Reference skill. Key lookup areas: Config File (raiconfig.yaml structure), Connection Setup (Snowflake auth methods), Programmatic Config (create_config), Model Settings, Reasoner Settings (engine sizes, per-reasoner options).
pip install relationalai>=1.0.14
Requires Python 3.10+.
# Minimal Snowflake config (raiconfig.yaml)
default_connection: sf
connections:
sf:
type: snowflake
authenticator: username_password
account: my_account
warehouse: my_warehouse
user: my_user
password: ${SNOWFLAKE_PASSWORD}
# Programmatic config (no YAML file needed)
from relationalai.config import create_config
from relationalai.semantics import Model
config = create_config(connection_type="snowflake")
model = Model("my_model", config=config)
Verify connectivity: Run rai connect to check the connection before writing model code. Also use it to validate after changing any connection-related configuration.
Primary file: raiconfig.yaml (also accepts raiconfig.yml). TOML (raiconfig.toml) is deprecated with a warning.
Auto-discovery: create_config() walks upward from CWD to find the config file.
Full YAML structure:
default_connection: sf
active_profile: dev # or set RAI_PROFILE env var
connections:
sf:
type: snowflake
authenticator: username_password
account: my_account
warehouse: my_warehouse
user: my_user
password: ${SNOWFLAKE_PASSWORD} # env var substitution
role: my_role # optional
database: my_database # optional
schema: my_schema # optional
reasoners:
backend: sql # "sql" (default) or "direct_access"
logic:
name: team_logic # optional; identifier for this reasoner
size: HIGHMEM_X64_S # used when creating the reasoner
use_lqp: true
emit_constraints: false
predictive:
name: team_predictive # optional
size: HIGHMEM_X64_S
prescriptive:
name: team_prescriptive # optional
size: HIGHMEM_X64_S
data:
wait_for_stream_sync: true # wait for streams before queries (default true)
data_freshness_mins: 5 # allow queries if data is within N mins (default unset = must be fully synced; max 30240 = 3 weeks)
query_timeout_mins: 10 # client-side timeout (default unset = no timeout)
ensure_change_tracking: false # auto-enable change tracking on tables read (default false; requires OWNERSHIP)
check_column_types: true # validate column types on load (default true)
download_url_type: external # "internal" (default) or "external" (accessible outside Snowflake)
compiler:
strict: false
soft_type_errors: false
model:
schema: analytics # install schema for SQL views/tables
implicit_properties: true # allow undeclared properties on first access
keep: true
isolated: true
execution:
metrics: false # collect SDK timing/counter metrics (default false)
logging: false # emit structured execution logs to Python logger (default false)
retries:
enabled: false
max_attempts: 3 # total attempts including first try
base_delay_s: 0.25
max_delay_s: 5.0
jitter: 0.2 # random jitter fraction added to each delay
debug:
show_full_traces: false
profile:
dev:
connections:
sf:
warehouse: dev_warehouse
prod:
connections:
sf:
warehouse: prod_warehouse
Environment variable syntax: Use ${VAR_NAME} in any string value.
Profile overlays: Profile selection priority (highest wins): create_config(active_profile=...) > RAI_PROFILE env var > active_profile in YAML. The selected profile's values merge on top of the base config.
Fallback sources (when no raiconfig.yaml found): raiconfig.toml (deprecated) -> ~/.snowflake/config.toml -> ~/.dbt/profiles.yml.
Transition note (as of Feb 2026): Use raiconfig.yaml for all new projects. See the Both raiconfig.toml and .yaml present pitfall below for the precedence gotcha.
Six authenticators, selected via the authenticator field:
| Authenticator | Class | Key Fields |
|---|---|---|
| username_password (default) | UsernamePasswordAuth | user, password |
| username_password_mfa | UsernamePasswordMFAAuth | user, password |
| externalbrowser | ExternalBrowserAuth | user |
| jwt | JWTAuth | user, private_key_path or private_key |
| oauth | OAuthAuth | token |
| programmatic_access_token | ProgrammaticAccessTokenAuth | token |
All Snowflake authenticators share: account, warehouse, and optional role, database, schema.
When running inside Snowflake (notebooks, stored procedures, UDFs), PyRel auto-detects the active Snowpark session. No config file needed -- create_config() returns a ConfigFromActiveSession that wraps get_active_session().
from relationalai.config import create_config
cfg = create_config() # finds raiconfig.yaml walking up from CWD
import os
cfg = create_config(
connections={
"sf": {
"type": "snowflake",
"authenticator": "username_password",
"account": os.environ["SNOWFLAKE_ACCOUNT"],
"warehouse": os.environ["SNOWFLAKE_WAREHOUSE"],
"user": os.environ["SNOWFLAKE_USER"],
"password": os.environ["SNOWFLAKE_PASSWORD"],
}
},
default_connection="sf",
reasoners={"logic": {"size": "HIGHMEM_X64_S"}},
)
from relationalai.config import create_config, UsernamePasswordAuth
cfg = create_config(
connections={
"sf": UsernamePasswordAuth(
account="my_account",
warehouse="my_warehouse",
user="my_user",
password="my_password",
)
}
)
session = cfg.get_session() # default connection
session = cfg.get_session(SnowflakeConnection) # typed, default
conn = cfg.get_connection(SnowflakeConnection, name="sf") # by name
# Or from the model (session is lazy — triggers on first job):
model = Model("MyModel")
session = model.config.get_session() # get session from model
session.sql("SELECT 1").collect() # verify connection works
# Force a fresh session (e.g., after rotating credentials):
conn = model.config.get_default_connection()
conn.clear_session_cache()
from relationalai.semantics import Model
# Auto-discovers raiconfig.yaml
model = Model("my_model")
# Explicit config
model = Model("my_model", config=cfg)
Set in raiconfig.yaml under model: or pass via create_config(model={...}):
| Field | Default | Purpose |
|---|---|---|
| schema | None | Install schema for SQL views/tables |
| implicit_properties | true | Allow undeclared properties on first access |
| keep | true | Keep model after execution |
| isolated | true | Run model in isolated mode |
reasoners:
backend: sql # default -- uses Snowpark SQL
# backend: direct_access # HTTP-based; requires direct_access_base_url (mandatory when using direct_access)
# direct_access_base_url: https://reasoners.example.com
| Platform | Valid Sizes |
|---|---|
| AWS | HIGHMEM_X64_S, HIGHMEM_X64_M, HIGHMEM_X64_L |
| Azure | HIGHMEM_X64_S, HIGHMEM_X64_M, HIGHMEM_X64_SL |
reasoners:
logic:
name: team_logic # optional; if named reasoner exists, PyRel uses it as-is (ignores size)
size: HIGHMEM_X64_S # used only when auto-creating (name set but reasoner doesn't exist)
use_lqp: true # LQP for rule execution (default true)
emit_constraints: true # emit constraint reports
incremental_maintenance: "off" # "off" (default), "auto", or "all"
lqp:
semantics_version: "1" # opt into hard validation errors
predictive:
name: team_predictive # optional
size: HIGHMEM_X64_S
prescriptive:
name: team_prescriptive # optional
size: HIGHMEM_X64_S
Reasoner name/size behavior: If
nameandsizeare both set and the named reasoner doesn't exist, PyRel creates it with the configured size. If the named reasoner already exists, PyRel uses it as-is and does not resize it. If the reasoner is later deleted and re-created automatically, it uses the default size (HIGHMEM_X64_S), not the previously configured size.
Note:
auto_suspend_minsandawait_storage_vacuumare managed via the CLI only — they are not config fields.
- Set auto-suspend after creation:
rai reasoners:alter --type Logic --name <name> --auto-suspend-mins <value>- Set await-storage-vacuum at creation time:
rai reasoners:create --type Logic --name <name> --size <size> --await-storage-vacuum
Gurobi requires three Snowflake objects and a named prescriptive engine:
SOLVERS.SECRETS.GUROBI_LICENSE)gurobi_integration)name, PyRel uses an anonymous engine that does not receive the solver settingsreasoners:
prescriptive:
name: my_prescriptive_engine # required for Gurobi — must reference an existing engine
size: HIGHMEM_X64_S
settings:
gurobi:
enabled: true
license_secret_name: solvers.secrets.gurobi_license
external_access_integration: gurobi_integration
If problem.solve("gurobi") returns Solver 'gurobi' is not enabled or not properly configured, check:
name field is set and the engine exists (rai reasoners:list --type Prescriptive)SHOW SECRETS IN SCHEMA SOLVERS.SECRETS)DESCRIBE INTEGRATION gurobi_integration)For solver selection guidance, see rai-prescriptive-solver-management.
Controls how aggressively the client polls for long-running operations:
reasoners:
poll_initial_delay_s: 0.05
poll_overhead_rate: 0.2 # +20% per poll (exponential backoff)
poll_max_delay_s: 2.0
cfg = create_config(
connections={"sf": {...}},
reasoners={
"backend": "sql",
"logic": {
"size": "HIGHMEM_X64_M",
"use_lqp": True,
"emit_constraints": True,
},
"prescriptive": {
"size": "HIGHMEM_X64_L",
},
},
)
Controls SDK-level behavior: observability, retries, compiler strictness, and data loading defaults.
# View collected metrics after running a query
from relationalai.client import connect_sync
client = connect_sync()
model = Model("MyModel")
model.select("hello world").to_df()
print(client.execution_metrics.counters)
print(client.execution_metrics.timings_ms)
# Enable structured logs (configure Python logging to display output)
import logging
logging.getLogger("relationalai.client.execution").setLevel(logging.INFO)
Enable both in raiconfig.yaml:
execution:
metrics: true
logging: true
Automatic re-attempts on transient failures. max_attempts is the total count including the first try:
execution:
retries:
enabled: true
max_attempts: 5
base_delay_s: 0.25
max_delay_s: 5.0
jitter: 0.2
compiler:
strict: true # fail fast on ambiguous types — recommended for CI/production
soft_type_errors: true # treat type errors as warnings — use in notebooks only
Use strict: true in CI. Use soft_type_errors: true only during rapid iteration — it hides real type problems.
data:
wait_for_stream_sync: true # wait for streams to sync before queries (default: true)
data_freshness_mins: 5 # allow queries if data is within N mins (default: unset = fully synced; max 30240 = 3 weeks)
query_timeout_mins: 10 # client-side timeout in minutes (default: unset = no timeout)
ensure_change_tracking: false # auto-enable change tracking on tables (requires OWNERSHIP; default: false)
check_column_types: true # validate column types on load (default: true — keep enabled in CI)
download_url_type: internal # "internal" (default) or "external" (for access outside Snowflake)
Caution: check_column_types: false speeds up loading but silently allows type mismatches. ensure_change_tracking: true modifies tables — only enable if you have OWNERSHIP.
rai reasoners:*)All commands accept --type (Logic / Prescriptive / Predictive) and --name. Both are optional — interactive prompts fill missing values.
| Command | Purpose |
|---------|---------|
| rai reasoners:create --type Logic --name <name> --size <size> | Create a reasoner |
| rai reasoners:delete --type Logic --name <name> | Delete a reasoner |
| rai reasoners:suspend --type Logic --name <name> | Suspend (stop billing) |
| rai reasoners:resume --type Logic --name <name> | Resume a suspended reasoner |
| rai reasoners:list | List all reasoners (filterable by --type, --name, --size, --state) |
| rai reasoners:get --type Logic --name <name> | Get details for one reasoner |
| rai reasoners:alter --type Logic --name <name> --auto-suspend-mins <N> | Change settings |
Resize pattern: No in-place resize — delete and recreate: suspend → delete → create with new size.
Resources)Use the Resources class to list, create, delete, resume, and suspend engines programmatically. Each engine has a name and a type (LOGIC, SOLVER, or PREDICTIVE). Note: SOLVER in the Python API corresponds to Prescriptive in the CLI. A typical deployment has both a LOGIC and a SOLVER engine under the same name — they are independent.
See engine-management.md for full API reference, engine states, and the delete-and-recreate pattern.
| Mistake | Cause | Fix |
|---------|-------|-----|
| raiconfig.yaml not found | File not in CWD or any parent directory | Place raiconfig.yaml in project root; create_config() walks upward from CWD |
| First invalid config raises error with no fallback | PyRel validates the first source found; if invalid it stops | Fix the file — it does not fall back to lower-priority sources after a parse error |
| direct_access with no direct_access_base_url | URL is required when backend: direct_access | Set reasoners.direct_access_base_url or switch to backend: sql |
| execution.logging: true produces no output | Python logging must be configured separately | Add logging.getLogger("relationalai.client.execution").setLevel(logging.INFO) |
| Auth fails with externalbrowser in CI | Browser auth requires interactive session | Use jwt or username_password for non-interactive environments |
| Both raiconfig.toml and .yaml present | Toml may take precedence in some code paths | Remove .toml and use .yaml as canonical |
| Engine not provisioned | Reasoner config references an engine size not available on account | Check reasoners.prescriptive.size matches available sizes for your platform |
| Unicode errors on Windows (UnicodeEncodeError in output) | Windows console defaults to a non-UTF-8 encoding | Set PYTHONIOENCODING=utf-8 before running. PowerShell: $env:PYTHONIOENCODING = "utf-8". cmd: set PYTHONIOENCODING=utf-8 |
| rai CLI or scripts fail to run on PowerShell | PowerShell execution policy blocks scripts | The user should run Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy RemoteSigned. RemoteSigned allows local scripts while still requiring signatures on scripts downloaded from the internet |
| Reference | Description | File | |-----------|-------------|------| | Engine management | Engine provisioning, sizing, and lifecycle management | engine-management.md |
data-ai
Configure and train graph neural network (GNN) models, generate predictions, evaluate results, and manage trained models. Use when ready to train, generate predictions, evaluate, or manage models; for concepts, data loading, edges, and feature configuration, see `rai-predictive-modeling`.
development
Build graph neural network (GNN) models — concepts, Snowflake data loading, task relationships, graph edges, and PropertyTransformer features. Use for node classification, regression, and link prediction tasks; for training, predictions, and evaluation, see `rai-predictive-training`.
development
Setup and configuration for RelationalAI — first-time install walkthrough and all raiconfig.yaml tuning. Use when installing RAI, connecting to Snowflake, or editing raiconfig.yaml. Not for writing PyRel model code (see rai-pyrel-coding) or solver usage and diagnostics (see rai-prescriptive-solver-management).
testing
Converts natural language business rules into PyRel derived properties — validation, classification, derivation, alerting, and reconciliation. Use whenever a task assigns each entity a new tier, segment, score, or flag, or derives a new property; author it here as a derived property, then query it with rai-querying.