cortex
RelationalAI-Cortex Integration
Deploy Snowflake Cortex AI agents powered by RelationalAI semantic models for Snowflake Intelligence.
An agent answers questions from one model that you have already deployed with PyRel deploy mode (model.deploy() or rai models deploy). It reads that deployment and never deploys or refreshes the model.
Quickstart
from snowflake import snowpark
from relationalai.config import create_config, SnowflakeConnectionfrom relationalai.agent.cortex import ( AgentConfig, CortexAgentManager, DefaultTool, ModelDeployment, discover_imports)
# Create session using role for deploymentsession: snowpark.Session = create_config().get_session(SnowflakeConnection)
# Configure managermanager = CortexAgentManager( session=session, config=AgentConfig( agent_name="MY_ASSISTANT", # Unique name for the agent tools_schema="MY_DB.MY_TOOLS", # Schema for the agent's sprocs and stage (and the agent) warehouse="COMPUTE_WH", # Warehouse for RAI tool execution (SI users need USAGE) model_deployment=ModelDeployment(schema="MY_DB.CORE"))) # The model's deployment.schema
# Initialize RAI Tools# - This function is executed during each sproc invocation.# It must be self-contained — don't close over local# runtime state (sessions, connections, dataframes, etc.).def init_tools(): # IMPORTANT: import your RelationalAI Model and dependent code # inside init_tools so it runs within the sproc session. from my_project.model import core return DefaultTool( model=core.model, # The one model this agent serves description="...")
# Deploymanager.deploy( init_tools=init_tools, # Initialize RAI Tools imports=discover_imports()) # Specify local python modules to package into sproc
print(manager.status())After deployment, you can find the Cortex Agent in the Snowflake UI under AI & ML > Agents. The UI allows you to chat with the agent, preview or add it to Snowflake Intelligence, and view traces of conversations the agent participates in.
For programmatic access (testing, automation):
chat = manager.chat()response = chat.send("What can I ask about?")print(response.full_text())Conversations through the programmatic interface are persisted and available through the Monitoring tab for the agent in the Snowflake UI.
How It Works
The RelationalAI-Cortex integration
- operationalizes your RAI Model into Snowflake stored procedures
- configures a Cortex Agent with these tools, and instructions on how to explore your semantic model and answer questions about your data.
An agent serves exactly one model: init_tools returns one Tool for it, usually a DefaultTool. Deploy one agent per model; Snowflake Intelligence users can switch agents within a chat.
| Tool | Purpose |
|---|---|
RAI_DISCOVER_MODEL | Describe the agent’s model and its key concepts |
RAI_VERBALIZE_MODEL | Get detailed model structure and relationships |
RAI_EXPLAIN_CONCEPT | Understand business rules for specific concepts |
RAI_QUERY_MODEL | Execute catalog or dynamic queries (PREVIEW — requires allow_preview=True) |
RAI_QUERY_MODEL runs both pre-defined catalog queries and — when a
model is attached to the query catalog — dynamic queries the agent
authors at runtime. See Queries (PREVIEW) below.
RBAC: Caller’s Rights
All stored procedures are created with CALLER’S RIGHTS — they execute under the SI user’s Snowflake role, not the deployer’s role. This means:
- Data access is governed by the caller’s role. Users only see data their role can
SELECT. - No privilege escalation. The agent never operates with more permissions than the person using it.
This makes Snowflake’s existing RBAC the single source of truth for data governance across all agent interactions.
Reading the Model Deployment
AgentConfig.model_deployment names where the model was deployed: its deployment.schema, plus its object_name_prefix and object_name_suffix when several models share that schema. Deploy the model with the default compiler and the oplog enabled, which are PyRel’s defaults.
deploy() and update() read the deployment’s identity marker, deploy state and oplog from its meta schema, <schema>_META. They write nothing to the deployment. They fail before registering any procedure when the deployment can’t serve the agent. update() and deploy(skip_preflight=True) raise the code below as the error. deploy() otherwise raises PreflightFailed, whose report lists the code:
| Code | Cause |
|---|---|
ModelDeploymentNotFound | No model is deployed at that schema with that prefix and suffix, the identity marker there belongs to another deployment (as in a cloned database), or your role can’t read the meta schema. A model deployed by a PyRel version that didn’t record an identity marker is reported here too, and redeploying it adds the marker |
ModelDeploymentIncomplete | The model’s first deploy hasn’t finished, it was deployed with compiler.optimization: aggressive, or your role can’t read its deploy state |
ModelDeploymentFailed | The model’s last deploy failed. The message carries the recorded error |
ModelDeploymentHasNoOplog | The model was deployed with oplog.enabled: false, or your role can’t read its oplog |
deploy() also replays the oplog into the deployed model and compares it with the model init_tools builds. A difference is a DeployedModelMismatch warning naming what changed, not an error, so an agent can be redeployed while a model rollout is under way.
Each tool call runs one SQL statement against the deployed tables and views, through the caller’s session, and needs no RAI engine.
The agent’s model runs with PyRel’s default settings plus what was read from the deployment: its location, and its preserve_column_case as recorded in the oplog. Nothing comes from raiconfig.yaml or from a config passed to the Model. The one exception is column-name casing: a model built with Model(..., config=...) keeps that config’s preserve_column_case, so build the model without a config, or give it the value the model was deployed with.
The procedures carry the deployment’s source-table columns and preserve_column_case as read at agent deploy. After you redeploy the model, run manager.update() so the agent picks up the new model.
Limitations:
- The meta schema must be
<schema>_META. A model deployed with anotherdeployment.meta_schemais reported asModelDeploymentNotFound. - A query that reads a relation the deployment lacks fails when the agent runs it. The
DeployedModelMismatchwarning names such relations at agent deploy. - Deploy and update the agent from a process with one open Snowpark session. With more than one, they fail with “No active Snowpark session found”.
- For a branch deployment, the deployer also needs
SELECTon the parent deployment’s identity marker and oplog.print_setup_sqldoesn’t emit those grants.
Snowflake Privileges
The following permissions are required for two roles:
- deployer/admin who creates the Cortex Agent
- SI users who interact with it through the Snowflake Intelligence UI (or, programmatic users of the Cortex Agent)
Deployer / Admin
| Privilege | Purpose |
|---|---|
USAGE on the tools_schema database and schema, and on the warehouse | Access the deployment target |
CREATE STAGE on tools_schema | Store sproc dependencies (if manage_stage=True) |
CREATE PROCEDURE on tools_schema | Register RAI tool sprocs |
CREATE AGENT on tools_schema, or, if agent_schema is set, CREATE AGENT on it and USAGE on it and its database | Register the Cortex agent |
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 the sproc environment |
application role snowflake.ai_observability_events_lookup | Monitor AI observability events |
USAGE on the model’s meta schema (<schema>_META) and its database | Read the model deployment’s metadata |
SELECT on the meta schema’s _INTERNAL_MODEL_IDENTITY, _INTERNAL_DEPLOY_STATE and _INTERNAL_OPLOG tables, named with the deployment’s prefix and suffix | Find the deployment, check its last deploy, and replay its model |
The deployer needs no access to the model’s source tables or deployed outputs.
SI Users
Because sprocs use CALLER’S RIGHTS, SI users need privileges on the resources the agent accesses at runtime:
| Privilege | Purpose |
|---|---|
USAGE on warehouse | Execute sprocs (warehouse from AgentConfig, or session default) |
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) |
USAGE on the databases and schemas of tools_schema and agent_schema | Reach the sprocs and the agent |
USAGE ON ALL PROCEDURES in tools_schema | Invoke RAI tools |
USAGE on the agent | Chat with the agent |
USAGE on the model’s schema and meta schema, and their databases | Reach the model deployment |
SELECT on all and future tables, dynamic tables and views in both schemas | Read the deployed outputs, including outputs later model deploys add, and synthetic concepts, which are stored in the meta schema |
SI users need no grants on the model’s source tables: deployed views read them with the view owner’s rights. The schema-wide grants on the meta schema also let SI users read the deployment’s internal _INTERNAL_* tables.
Grant the SI block after the agent is deployed, because it grants on the agent and on the procedures that exist then. update() keeps those grants.
Example Role Definitions
manager.print_setup_sql(deployer_role="MY_DEPLOYER", si_role="MY_SI_USER", create_role=True) prints this block for the quickstart’s AgentConfig:
-- Cortex deployer role setupCREATE ROLE IF NOT EXISTS MY_DEPLOYER;GRANT DATABASE ROLE snowflake.cortex_user TO ROLE MY_DEPLOYER;GRANT DATABASE ROLE snowflake.pypi_repository_user TO ROLE MY_DEPLOYER;GRANT APPLICATION ROLE snowflake.ai_observability_events_lookup TO ROLE MY_DEPLOYER;GRANT USAGE ON DATABASE MY_DB TO ROLE MY_DEPLOYER;GRANT USAGE ON SCHEMA MY_DB.MY_TOOLS TO ROLE MY_DEPLOYER;GRANT CREATE STAGE ON SCHEMA MY_DB.MY_TOOLS TO ROLE MY_DEPLOYER;GRANT CREATE PROCEDURE ON SCHEMA MY_DB.MY_TOOLS TO ROLE MY_DEPLOYER;GRANT CREATE AGENT ON SCHEMA MY_DB.MY_TOOLS TO ROLE MY_DEPLOYER;GRANT USAGE ON WAREHOUSE COMPUTE_WH TO ROLE MY_DEPLOYER;-- Read the model deployment's identity, deploy state and oplogGRANT USAGE ON SCHEMA MY_DB.CORE_META TO ROLE MY_DEPLOYER;GRANT SELECT ON TABLE MY_DB.CORE_META._INTERNAL_MODEL_IDENTITY TO ROLE MY_DEPLOYER;GRANT SELECT ON TABLE MY_DB.CORE_META._INTERNAL_DEPLOY_STATE TO ROLE MY_DEPLOYER;GRANT SELECT ON TABLE MY_DB.CORE_META._INTERNAL_OPLOG TO ROLE MY_DEPLOYER;
-- Cortex SI-user role setupCREATE ROLE IF NOT EXISTS MY_SI_USER;GRANT DATABASE ROLE snowflake.cortex_user TO ROLE MY_SI_USER;GRANT USAGE ON WAREHOUSE COMPUTE_WH TO ROLE MY_SI_USER;GRANT USAGE ON DATABASE MY_DB TO ROLE MY_SI_USER;GRANT USAGE ON SCHEMA MY_DB.MY_TOOLS TO ROLE MY_SI_USER;GRANT USAGE ON ALL PROCEDURES IN SCHEMA MY_DB.MY_TOOLS TO ROLE MY_SI_USER;GRANT USAGE ON AGENT MY_DB.MY_TOOLS.MY_ASSISTANT TO ROLE MY_SI_USER;-- Read the model's deployment, including outputs later deploys add; synthetic concepts are stored in its meta schemaGRANT USAGE ON SCHEMA MY_DB.CORE TO ROLE MY_SI_USER;GRANT SELECT ON ALL TABLES IN SCHEMA MY_DB.CORE TO ROLE MY_SI_USER;GRANT SELECT ON ALL DYNAMIC TABLES IN SCHEMA MY_DB.CORE TO ROLE MY_SI_USER;GRANT SELECT ON ALL VIEWS IN SCHEMA MY_DB.CORE TO ROLE MY_SI_USER;GRANT SELECT ON FUTURE TABLES IN SCHEMA MY_DB.CORE TO ROLE MY_SI_USER;GRANT SELECT ON FUTURE DYNAMIC TABLES IN SCHEMA MY_DB.CORE TO ROLE MY_SI_USER;GRANT SELECT ON FUTURE VIEWS IN SCHEMA MY_DB.CORE TO ROLE MY_SI_USER;GRANT USAGE ON SCHEMA MY_DB.CORE_META TO ROLE MY_SI_USER;GRANT SELECT ON ALL TABLES IN SCHEMA MY_DB.CORE_META TO ROLE MY_SI_USER;GRANT SELECT ON ALL DYNAMIC TABLES IN SCHEMA MY_DB.CORE_META TO ROLE MY_SI_USER;GRANT SELECT ON ALL VIEWS IN SCHEMA MY_DB.CORE_META TO ROLE MY_SI_USER;GRANT SELECT ON FUTURE TABLES IN SCHEMA MY_DB.CORE_META TO ROLE MY_SI_USER;GRANT SELECT ON FUTURE DYNAMIC TABLES IN SCHEMA MY_DB.CORE_META TO ROLE MY_SI_USER;GRANT SELECT ON FUTURE VIEWS IN SCHEMA MY_DB.CORE_META TO ROLE MY_SI_USER;Diagnostics
Cortex deployments depend on a stack of grants that are easy to misconfigure. The diagnostics module turns cryptic Snowflake errors (“Object X does not exist or not authorized”) into one upfront list of named GRANTs, with a paste-ready SQL block.
Preflight
manager.deploy() runs manager.preflight() automatically. To inspect findings without raising:
report = manager.preflight()print(report.format(config=manager.config, role=report.role))
if report.has_errors: print(manager.print_setup_sql(deployer_role="MY_ROLE"))Preflight probes are read-only (SHOW/DESCRIBE/SELECT):
| Check | Severity |
|---|---|
tools_schema database and schema, and warehouse, exist + USAGE | error |
snowflake.pypi_repository_user granted (primary or secondary role) | error |
snowflake.cortex_user granted | error |
CREATE STAGE/PROCEDURE/AGENT on schema (direct grants) | warning |
Agent schema (if agent_schema set) | error/warning |
Model deployment can serve the agent (see Reading the Model Deployment); ModelDeploymentUnreadable if reading it fails otherwise | error |
The model init_tools builds matches the deployed model (DeployedModelMismatch) | warning |
DISCOVER / VERBALIZE / EXPLAIN payloads fit the response budget (Truncated*Payload) | warning |
The last two checks run only when init_tools is given, as deploy() does. Of the warnings, deploy() shows only DeployedModelMismatch; call manager.preflight(init_tools) to see the rest.
The database-role check uses IS_DATABASE_ROLE_IN_SESSION plus a fallback that walks CURRENT_AVAILABLE_ROLES() × SHOW GRANTS OF DATABASE ROLE, so secondary-role grants are recognized.
Setup SQL
Generate a GRANT block parameterized with this manager’s config:
print(manager.print_setup_sql( deployer_role="MY_DEPLOYER", si_role="MY_SI", # optional — also emit SI-user block create_role=False, # prepend CREATE ROLE IF NOT EXISTS))The block is the deployer-friendly version of the privilege table above — hand it to a Snowflake admin verbatim instead of writing it by hand.
Skip preflight
For fast iteration once you know the environment is correctly granted:
manager.deploy(init_tools=init_tools, imports=imports, skip_preflight=True)Skipping preflight skips the grant probes and the model comparison. Deploy still checks the model deployment before registering any procedure, and raises the ModelDeployment* code itself instead of PreflightFailed.
If deploy still fails, the underlying Snowflake error is post-processed: the diagnostic message includes the named GRANT that fixes the most common cases (missing pypi_repository_user, missing CREATE PROCEDURE, etc.).
Command-line diagnostics
For ad-hoc probing without writing Python:
python -m relationalai.agent.cortex.diagnostics \ --account MY_ACCT --user me@example.com \ --role MY_ROLE --warehouse MY_WH \ --tools-schema MY_DB.MY_TOOLS --model-schema MY_DB.CORE \ --agent-name MY_AGENT \ [--model-object-name-prefix SALES_] [--model-object-name-suffix _V2] \ [--preflight-only] # skip the deeper SQL/REST sweep [--no-rest] # skip Cortex REST API probes [--json-out FILE] # write the full report as JSONRead-only — never creates or drops resources.
Configuration
AgentConfig
| Parameter | Required | Default | Description |
|---|---|---|---|
agent_name | Yes | - | Unique name for the Cortex agent within its schema |
tools_schema | Yes | - | Fully-qualified DATABASE.SCHEMA for the agent’s sprocs and stage, and the agent unless agent_schema is set. Keep it separate from the model’s deployment schema |
model_deployment | Yes | - | ModelDeployment(schema=..., object_name_prefix=..., object_name_suffix=...) naming where the model of the Tool returned by init_tools was deployed with PyRel deploy mode. The model runs against it with default settings; its own config and raiconfig.yaml are not used. deploy() and update() also point the in-process model init_tools returns at it |
warehouse | No | None | Snowflake warehouse the Cortex agent will use when executing RAI tools. SI users need USAGE on this warehouse. If omitted, tools use the caller’s session warehouse. Stored procedures are created with CALLER’S RIGHTS |
stage_name | No | "rai_sprocs" | Name of the Snowflake stage for storing sproc dependencies |
manage_stage | No | True | If True, automatically create/drop the stage during deploy/cleanup. Set to False if using a pre-existing stage |
llm | No | "claude-opus-4-6" | Language model 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 in seconds for agent execution. Can be used with budget_tokens |
budget_tokens | No | None | Token budget for model consumption. Can be used with budget_seconds |
artifact_repository | No | "snowflake.snowpark.pypi_shared_repository" | Artifact repository for Python packages |
allow_preview | No | False | Allow Preview capabilities (e.g., queries) |
agent_schema | No | None | Fully-qualified DATABASE.SCHEMA where the agent is created. Sprocs and stage remain in tools_schema. Use SNOWFLAKE_INTELLIGENCE.AGENTS to expose the agent in SI. If not set, agent is created alongside sprocs |
procedure_prefix | No | None | Prefix for the stored-procedure names, so several agents can share one tools_schema. Agent-facing tool names don’t change |
ModelDeployment
| Parameter | Required | Default | Description |
|---|---|---|---|
schema | Yes | - | Fully-qualified DATABASE.SCHEMA the model was deployed to: its deployment.schema |
object_name_prefix | No | "" | The deployment’s deployment.object_name_prefix |
object_name_suffix | No | "" | The deployment’s deployment.object_name_suffix |
Verbalizers
Verbalizers control how model structure is presented to the agent.
ModelVerbalizer (Default)
Returns relationship readings extracted from the RAI model:
Customer has many OrdersOrder has one CustomerOrder contains many OrderItems...This is the default — no configuration needed.
SourceCodeVerbalizer
Extends ModelVerbalizer: explain_model returns the standard relationship
readings, while explain_concept returns the Python source code from the
modules you provide, filtered to those that reference the requested concept.
Pass the model as the first argument, followed by your model definition modules:
from relationalai.agent.cortex import DefaultTool, SourceCodeVerbalizer
def init_tools(): from my_project.model import core, computed return DefaultTool( model=core.model, description="Customers and orders", verbalizer=SourceCodeVerbalizer(core.model, core, computed) )The agent sees actual Python code for specific concepts, including business logic and computed properties.
Comments are included, so clarifications and justifications of your code will benefit the agent as well.
Queries (PREVIEW)
> Note: The queries capability is in PREVIEW. Deployment requires allow_preview=True. Please contact us first!
Two complementary surfaces ship under one capability:
- Catalog queries — pre-defined, vetted analytical queries built by
domain experts. The agent picks one by
idand supplies arguments. - Dynamic queries — the agent authors a JSON query spec at runtime against the model’s queryable schema. Use for narrow exploratory analysis when no catalog query matches.
Both are exposed through RAI_QUERY_MODEL. Catalog queries are preferred
when a question matches one; dynamic queries are the fallback. You opt
into either or both via the queries= parameter on DefaultTool.
Catalog queries
Define queries as module-level functions returning a rai.Fragment:
import relationalai.semantics as raifrom my_project.model.core import model, Customer, Order
def segment_summary() -> rai.Fragment: # Topline metrics per customer value segment customer = Customer.ref() segment = Customer.ValueSegment.ref() order = Order.ref() g = rai.per(segment) return model.select( segment.name.alias("segment"), g.sum(customer.ltv).alias("revenue"), g.sum(order.profit) .where(customer.order(order)) .alias("profit") ).where( customer.value_segment(segment) )Register them with QueryCatalog. The function name becomes the query
id and the agent picks it when a user’s question matches.
from relationalai.agent.cortex import ( AgentConfig, CortexAgentManager, ModelDeployment, discover_imports, DefaultTool, SourceCodeVerbalizer, QueryCatalog,)
def init_tools(): from my_project.model import core, computed, queries return DefaultTool( model=core.model, description="Customers and orders", verbalizer=SourceCodeVerbalizer(core.model, core, computed), queries=QueryCatalog(queries.segment_summary), )
# Deploy with preview enabled — set allow_preview on AgentConfigmanager = CortexAgentManager( session=session, config=AgentConfig( agent_name="MY_ASSISTANT", tools_schema="EXAMPLE.CORTEX", warehouse="COMPUTE_WH", model_deployment=ModelDeployment(schema="EXAMPLE.CUSTOMERS"), allow_preview=True, ))
manager.deploy( init_tools=init_tools, imports=discover_imports(),)Type-annotated parameters become the agent-visible args schema.
Function names must not be "dynamic" (reserved for dynamic queries).
Dynamic queries
Enable dynamic queries by passing model= to QueryCatalog. Discovery
then advertises a dynamic path alongside the catalog, and the agent
authors small queries at runtime against the model’s queryable schema
whenever no catalog query fits the user’s question.
def init_tools(): from my_project.model import core, queries return DefaultTool( model=core.model, description="Customers and orders", # Pass model= to enable dynamic queries alongside the catalog. queries=QueryCatalog(queries.segment_summary, model=core.model), )Catalog-only (QueryCatalog(queries.segment_summary)) and dynamic-only
(DynamicQueries(model)) tools are both supported. Use
CompositeQueries for advanced layouts (e.g. multiple catalog
providers).
Dynamic queries are intentionally a small-result, exploratory surface: narrow filters, counts, simple aggregations. They complement — they do not replace — catalog queries. Catalog queries should still cover the vetted analytical workload; dynamic queries are the fallback for ad-hoc questions the catalog doesn’t anticipate. The validator emits structured self-correction envelopes for common authoring mistakes so the agent can recover without a round-trip to a human.
Packaging Code for Deployment
When deploying, you need to provide code that runs inside Snowflake stored procedures. There are two parameters for this:
imports - Your Project Code
The imports parameter packages your local Python files (model definitions, queries, etc.) and uploads them to Snowflake. Use discover_imports() to automatically find all modules imported by your init_tools function:
manager.deploy( init_tools=init_tools, imports=discover_imports() # Packages your project code)discover_imports() recursively discovers all local imports starting from the calling file. It excludes standard library and installed packages.
extra_packages - PyPI Dependencies
The extra_packages parameter specifies PyPI packages that Snowflake will install in the stored procedure environment. Use this for third-party libraries your code depends on:
manager.deploy( init_tools=init_tools, imports=discover_imports(), extra_packages=["pandas==2.0.0", "numpy"] # Installed by Snowflake)Note: relationalai is included automatically.
Updating Agents
Update tool definitions without recreating the agent:
def init_tools_v2(): # Updated tool definitions ...
manager.update(init_tools=init_tools_v2, imports=discover_imports())Run update() after each model redeploy too, so the procedures read the deployment as it is now.
Lifecycle
Check deployment status or tear down all resources:
print(manager.status()) # Reports what exists (agent, stage, sprocs)manager.cleanup() # Drops agent, sprocs, and stage — permanently loses SI conversation historyAttributes
Attributes exposed by this module.
DynamicQueries. Re-exported from relationalai.agent.cortex.queries.Functions
Functions exposed by this module.
relationalai.agent.cortex.api.client.Classes
Classes exposed by this module.
relationalai.agent.cortex.cortex_agent_manager.relationalai.agent.cortex.deployment_config.relationalai.agent.cortex.deployment_config.relationalai.agent.cortex.model_deployment.relationalai.agent.cortex.tool.relationalai.agent.cortex.api.agent.relationalai.agent.cortex.api.agent.relationalai.agent.cortex.api.thread.relationalai.agent.cortex.chat.relationalai.agent.cortex.chat.relationalai.agent.cortex.tool.relationalai.agent.cortex.tool.relationalai.agent.cortex.verbalize.relationalai.agent.cortex.verbalize.relationalai.agent.cortex.verbalize.relationalai.agent.cortex.queries.relationalai.agent.cortex.queries.relationalai.agent.cortex.queries.Queries providers. Re-exported from relationalai.agent.cortex.queries.Modules and Subpackages
Submodules and subpackages available under this namespace.
discover_imports module provides utilities for discovering project imports for Snowflake stored procedure deployment.verbalize module provides verbalizers for presenting RAI model structure and semantics to Cortex agents.cortex_agent_manager module provides a unified interface for managing Cortex agents with RAI-powered tools.model_deployment module names the PyRel deploy-mode deployment a Cortex agent's model reads from.chat module provides a programmatic chat interface for interacting with deployed Cortex agents.queries module provides abstractions for managing pre-defined RAI queries that Cortex agents can discover and execute.tool module provides the tool abstraction for RAI-powered Cortex agent tools.deployment_config module provides configuration and status types for Cortex agents.