skills/rai-cortex-integration/SKILL.md
Covers deploying RAI models as Snowflake Cortex Agents for Snowflake Intelligence. Use when deploying a model as a Cortex Agent or configuring Snowflake Intelligence.
npx skillsauth add RelationalAI/rai-agent-skills rai-cortex-integrationInstall 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: Operationalize a RAI knowledge graph by creating a deployment script that packages it as a Snowflake Intelligence (SI) agent. The deployment script is the primary output of this skill — a CLI that can deploy, update, test, and tear down the Cortex agent.
When to use:
DeploymentConfig (database, schema, optional agent_schema, warehouse, LLM, preview flags)SourceCodeVerbalizer, QueryCatalog, or default model toolsQueryCatalogagent_schema, preview flags, init_tools shape)When NOT to use:
rai-pyrel-coding/SKILL.mdrai-ontology-design/SKILL.mdrai-queryingPrimary output: A deployment script with CLI subcommands (deploy, update, status, chat, teardown) that manages the full agent lifecycle. See examples/deploy.py for the reference implementation.
Overview:
chat subcommandagent_schema or the UIThe deployment script is the primary artifact. It provides a CLI to manage the full agent lifecycle:
python -m <package>.deploy deploy # Create schema, stage, sprocs, and agent
python -m <package>.deploy update # Update sprocs without re-registering the agent
python -m <package>.deploy status # Print deployment status
python -m <package>.deploy chat "..." # Send a message to the deployed agent
python -m <package>.deploy teardown # Remove all agent resources
The script contains four key parts — see examples/deploy.py for the complete reference:
database/schema, optional agent_schema, warehouse_build_manager() — creates session and CortexAgentManagerinit_tools() — called inside each sproc; builds a ToolRegistrydeploy, update, status, chat, teardownExpected project layout:
<project_root>/ # CWD when running the deploy script
├── <agent_pkg>/
│ ├── __init__.py
│ ├── deploy.py # CLI entry — init_tools() lives here
│ └── queries.py # (optional) query functions for QueryCatalog
└── <model_pkg>/ # Your model code as a sibling package
├── __init__.py
├── core.py
└── ...
Invoke as python -m <agent_pkg>.deploy <command> from <project_root>. Every module referenced by init_tools() (model code, query functions) must live under this root — discover_imports() packages local imports relative to CWD and excludes anything outside it. See Step 6 for the full imports contract and non-standard layouts.
Leverage PyRel's inline docstrings by inspecting the code or running eg help(CortexAgentManager) or print(CortexAgentManager.__doc__)
The goal is to produce a deployment script (e.g., deploy.py) that operationalizes a RAI model as a Cortex agent. The script should expose CLI subcommands for the full lifecycle. Each step below corresponds to a section of the script.
Use create_config().get_session(SnowflakeConnection) to create a session from raiconfig.yaml. See _build_manager() in examples/deploy.py.
The deployer role must have these privileges:
| Privilege | Purpose |
|-----------|---------|
| CREATE STAGE on deployment schema | Store sproc dependencies |
| CREATE PROCEDURE on deployment schema | Register RAI tool sprocs |
| CREATE AGENT on the agent schema | Register the Cortex agent (schema by default, agent_schema if set) |
| USE AI FUNCTIONS on account | Access Cortex AI functions (granted to PUBLIC by default) |
| database role snowflake.cortex_user | Access Cortex services (granted to PUBLIC by default) |
| application role snowflake.ai_observability_events_lookup | Access monitoring traces |
| database role snowflake.pypi_repository_user | Install Python packages in sproc environment |
| rai_developer role | Access RAI (granted during native app install) |
| USAGE on the relevant databases and schemas | Access the deployment schema and, if different, the agent_schema target |
| Parameter | Required | Default | Description |
|-----------|----------|---------|-------------|
| agent_name | Yes | — | Unique name for the Cortex agent within the agent schema |
| database | Yes | — | Snowflake database where stored procedures and the stage are created |
| schema | Yes | — | Snowflake schema where stored procedures and the stage are created |
| agent_schema | No | None | Fully-qualified DATABASE.SCHEMA where the agent is created. Use SNOWFLAKE_INTELLIGENCE.AGENTS to place the agent directly in the SI schema. If omitted, the agent is created alongside the sprocs |
| model_name | No | Same as agent_name | Name for the Model instance created inside each stored procedure |
| warehouse | No | None | Warehouse for RAI tool execution. SI users need USAGE. If omitted, tools use the caller's session warehouse |
| stage_name | No | "rai_sprocs" | Name of the Snowflake stage for storing sproc dependencies |
| manage_stage | No | True | Automatically create/drop the stage during deploy/cleanup. Set False for a pre-existing stage |
| llm | No | "claude-sonnet-4-5" | LLM for agent orchestration. Must be available in Snowflake Cortex |
| query_timeout_s | No | 300 | Timeout in seconds for stored procedure execution |
| budget_seconds | No | None | Time budget for agent execution |
| budget_tokens | No | None | Token budget for model consumption |
| external_access_integration | No | "S3_RAI_INTERNAL_BUCKET_EGRESS_INTEGRATION" | External access integration for sprocs |
| artifact_repository | No | "snowflake.snowpark.pypi_shared_repository" | Artifact repository for Python packages |
| allow_preview | No | False | Enable preview capabilities (e.g., RAI_QUERY_MODEL sproc) |
See _build_manager() in examples/deploy.py for a complete construction example.
init_tools FunctionThe init_tools function is executed inside each stored procedure invocation. It must be self-contained — do not close over local runtime state (sessions, connections, dataframes). Import your model code inside the function so it resolves from the packaged sproc code and initializes within the sproc session. See init_tools() in examples/deploy.py.
Three configuration levels — each adds more capability via ToolRegistry.add():
allow_preview=True). See examples/cortex_verbalizer_queries.py.init_tools shapes:
init_tools() that imports module-defined model code and returns ToolRegistry().add(model=<imported module>.model, ...)init_tools(model) for codebases that already build the model by mutating a framework-supplied ModelPrefer the zero-argument form for new code. PyRel validates that init_tools accepts 0 or 1 required parameters; helper signatures with 2+ required parameters are rejected.
Verbalizers control how model structure is presented to the agent.
ModelVerbalizer (default) — returns relationship readings extracted from the model (e.g., "Customer has many Orders"). Used automatically when no verbalizer is specified.
SourceCodeVerbalizer — extends ModelVerbalizer. explain_model returns the standard relationship readings, while explain_concept returns Python source code from the modules you provide, filtered to definitions that reference the requested concept. Comments are included, so clarifications in your code benefit the agent. Pass the imported model modules that define the model. See examples/cortex_verbalizer.py.
Use SourceCodeVerbalizer when important domain logic is encoded in rule definitions, computed properties, subtype logic, or inline comments rather than being obvious from concept/relationship structure alone. This is what enables the agent to answer questions that go deeper than "what concepts exist and how are they related?", such as whether a Cancel Transaction can cancel another Cancel Transaction, or why a concept is derived under a particular set of rule conditions.
If the model is simple and the agent only needs schema-level understanding, the default ModelVerbalizer is usually enough. Add SourceCodeVerbalizer when the agent needs access to the reasoning encoded in the source.
The queries capability is in PREVIEW. Deployment requires
allow_preview=True.
Without QueryCatalog wired into ToolRegistry.add(..., queries=...), the agent can describe the model (via discovery and verbalization) but cannot execute any pre-defined queries — RAI_QUERY_MODEL is not registered.
Each query function must:
rai.Fragment (a rai.select(...) expression) or pandas.DataFrame__name__ attribute — used as the query identifierSee examples/model/queries.py for a complete query definition.
Prefer module-level zero-argument query functions imported inside init_tools(). This keeps __name__ and __doc__ intact for QueryCatalog without wrappers or partials.
Adding a new query:
queries.py that returns a rai.Fragment or pandas.DataFrame. Give it a clear docstring — it becomes the description shown to the agent.QueryCatalog(...) call inside init_tools() in deploy.py.deploy (or update if the agent already exists).Use QueryCatalog to expose a small set of curated, parameterized entry points into advanced analysis that the agent should invoke directly rather than reconstruct from scratch. Good candidates are things like community detection outputs, graph metrics, scenario summaries, or other pre-modeled analytical routines whose results you want surfaced reliably.
Do not use QueryCatalog as a general-purpose slicing-and-dicing layer for ordinary business exploration. For open-ended dimensional analysis and ad hoc filtering/aggregation, Snowflake Semantic Views are usually the better fit. QueryCatalog is for high-value, opinionated queries that expose complex analysis results cleanly to the agent.
Wire the manager methods into CLI subcommands using argparse. Each command maps to a single manager call. See examples/deploy.py for the complete implementation.
| Command | Manager method | Notes |
|---------|---------------|-------|
| deploy | manager.deploy(init_tools=..., imports=discover_imports()) | Creates schema, stage, sprocs, and agent |
| update | manager.update(init_tools=..., imports=discover_imports()) | Updates sprocs without re-registering agent |
| status | manager.status() | Reports what exists |
| chat | manager.chat().send(message) | Test the deployed agent |
| teardown | manager.cleanup() | Removes all resources — permanently loses SI conversation history |
imports — discover_imports() recursively discovers local Python imports and packages them into the stored procedure. It excludes standard library and installed packages; the relationalai package is included automatically. It uses the current working directory as the project root and filters out anything outside it. This is why the canonical layout (see Quick Reference → Expected project layout) keeps the agent package and model package as siblings under <project_root> and expects you to invoke python -m <agent_pkg>.deploy ... from that root — with that setup, no extra import wiring is needed.
For cases discover_imports() can't cover — e.g., a package that must be registered under a specific sproc-visible module name, or model code that cannot be relocated under the project root — build an explicit imports list:
from pathlib import Path
_AGENT_DIR = Path(__file__).resolve().parent
_PROJECT_ROOT = _AGENT_DIR.parent
def _imports():
return [
str(_AGENT_DIR / "queries.py"),
(str(_PROJECT_ROOT / "ontology"), "ontology"), # (path, module_name) tuple
]
Pass this in place of discover_imports(): manager.deploy(init_tools=init_tools, imports=_imports()). Directory entries use (path, module_name) tuples so Snowpark registers them as top-level importable packages inside the sproc. init_tools() itself stays self-contained per Step 3 — no sys.path manipulation inside init_tools(). The tuple form already makes the package importable in the sproc; mutating sys.path there is a no-op inside the sproc and masks the real fix for local invocation.
Workaround if you ignore the run-from-project-root guidance: if you must invoke the deploy script from somewhere else and local imports fail, add a one-time sys.path fix at the top of the deploy module — not inside init_tools():
import sys
from pathlib import Path
sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
This is a local-invocation crutch, not a deploy requirement. Prefer running from the project root.
extra_packages — optional parameter on deploy()/update() that specifies additional PyPI packages Snowflake installs in the sproc environment. httpx is a known required entry — it is a dependency of relationalai.agent.cortex but is not auto-installed as a transitive dependency in the sproc environment.
If agent_schema is set, deploy(), status(), chat(), and cleanup() operate on the agent in that schema while the stored procedures and stage remain in database.schema.
After a successful deploy, inform the user of these next steps:
status subcommand to confirm all sprocs are created.chat subcommand with a sample question (e.g., "What can I ask about?") to confirm the agent responds correctly.agent_schema if you set it, otherwise under database.schema.SNOWFLAKE_INTELLIGENCE.AGENTS via agent_schema, it is already in the SI schema. Otherwise, use Add to Snowflake Intelligence on the agent detail page to promote it.manager.chat()), including full tool-call traces for debugging.Four CALLER'S RIGHTS stored procedures are created in the deployment schema (database.schema), even if the agent itself is created elsewhere via agent_schema:
| Sproc | Purpose | Maturity |
|-------|---------|----------|
| RAI_DISCOVER_MODELS | Lists all registered RAI models and their concepts | GA |
| RAI_VERBALIZE_MODEL | Returns human-readable schema description for the LLM | GA |
| RAI_EXPLAIN_CONCEPT | Explains a specific concept using verbalizer context | GA |
| RAI_QUERY_MODEL | Executes a named pre-defined query from QueryCatalog | PREVIEW |
All sprocs run under the invoking user's privileges, not the owner's — Snowflake's existing RBAC is the single source of truth for data governance across all agent interactions. No privilege escalation is possible.
SI users need:
| Privilege | Purpose |
|-----------|---------|
| USAGE on warehouse | Execute sprocs |
| USE AI FUNCTIONS on account | Access Cortex AI functions (granted to PUBLIC by default) |
| database role snowflake.cortex_user | Access Cortex services (granted to PUBLIC by default) |
| database role snowflake.pypi_repository_user | Install Python packages in sproc environment |
| rai_developer role | Access RAI |
| USAGE on the relevant databases and schemas | Access the agent schema plus any deployment/data schemas it touches |
| SELECT on tables | Read data accessed by the model |
| EXECUTE on stored procedures | Invoke RAI tools in the deployment schema |
| Mistake | Cause | Fix |
|---------|-------|-----|
| use schema fails during deploy | Deployment schema doesn't exist | Run CREATE SCHEMA IF NOT EXISTS before deploying. If agent_schema is different, ensure that schema exists and the deployer can use it too |
| Object "does not exist" errors from Snowflake | Role lacks required privileges — Snowflake reports missing permissions as "does not exist" | Verify deployer and SI user privileges against the tables in Steps 1 and 6 (Deployed Stored Procedures) |
| Agent does not show up where expected in the UI | Agent was created in database.schema, not the SI schema | Set agent_schema="SNOWFLAKE_INTELLIGENCE.AGENTS" or promote the deployed agent from the UI |
| agent_schema validation fails | Value is not a two-part DATABASE.SCHEMA name | Use a fully qualified two-part name such as SNOWFLAKE_INTELLIGENCE.AGENTS |
| QueryCatalog rejects a query definition | Wrapped queries lost __name__ or __doc__ metadata | Prefer module-level query functions with docstrings; avoid functools.partial |
| Sproc fails at runtime with table-not-found | Model references a table unavailable in the sproc context | Restructure entity seeding to make that table optional |
| RAI_QUERY_MODEL not available | allow_preview not set | Set allow_preview=True in DeploymentConfig |
| init_tools is rejected or fails with stale state | Closed over local runtime objects or declared 2+ required parameters | Keep init_tools self-contained and use only the supported 0-param (recommended) or 1-param (legacy) forms |
| Agent can't explain business rules | No verbalizer configured | Add SourceCodeVerbalizer with all relevant model modules |
| discover_imports() misses model code | Model package lives outside CWD, or needs a specific sproc-visible module name | Run the deploy script from the project root; for exceptions, use an explicit _imports() list with (path, module_name) tuples — see Step 6 |
| Sproc fails with ModuleNotFoundError: httpx | httpx is a transitive dependency not auto-installed in sproc environment | Add "httpx" to extra_packages on deploy()/update() |
| Pattern | Description | File |
|---------|-------------|------|
| Deployment script | Complete CLI with deploy/update/status/chat/teardown — primary reference | examples/deploy.py |
| Default deployment | Minimal CortexAgentManager with model tools only | examples/cortex.py |
| Verbalizer deployment | Adds SourceCodeVerbalizer for concept explanation | examples/cortex_verbalizer.py |
| Full deployment | Verbalizer + QueryCatalog with pre-defined queries | examples/cortex_verbalizer_queries.py |
| Model modules | Core, computed, and query modules for the recommended zero-arg init_tools() pattern | examples/model/ |
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.