The Init Function for NeMo Guardrails

View as Markdown

If config.py contains an init function, it is called during LLMRails initialization. Use it to set up shared resources and register action parameters.

The init function must be synchronous (def init, not async def init). The framework calls it without await, so an async function would silently do nothing.

Any top-level code in config.py runs at import time, before init() is called. This can be used for provider registration that does not require the LLMRails instance.

Basic Usage

from nemoguardrails import LLMRails
def init(app: LLMRails):
# Initialize database connection
db = DatabaseConnection()
# Register as action parameter (available to all actions)
app.register_action_param("db", db)

Registering Action Parameters

Action parameters registered in config.py are automatically injected into actions that declare them. The runtime matches parameters by name, i.e., the parameter name in the action must match the name used during registration.

config.py:

import os
from nemoguardrails import LLMRails
def init(app: LLMRails):
# Initialize shared resources
db = DatabaseConnection(host="localhost", port=5432)
api_client = ExternalAPIClient(api_key=os.environ.get("API_KEY"))
# Register as action parameters
app.register_action_param("db", db)
app.register_action_param("api_client", api_client)

actions.py:

from nemoguardrails.actions import action
@action()
async def fetch_user_data(user_id: str, db=None):
"""The 'db' parameter is injected from config.py."""
return await db.get_user(user_id)
@action()
async def call_external_service(query: str, api_client=None):
"""The 'api_client' parameter is injected from config.py."""
return await api_client.search(query)

Built-in Action Parameters

In addition to parameters you register, the runtime automatically injects these built-in parameters into any action that declares them:

ParameterTypeDescription
configRailsConfigThe full rails configuration object
contextdictThe current conversation context
eventslistThe event history
llmLLM instanceThe main LLM (auto-registered during initialization)
llm_task_managerLLMTaskManagerManages LLM task execution

See Custom Data for details on accessing config.custom_data inside actions.

Accessing the Configuration

The app parameter provides access to the full configuration:

def init(app: LLMRails):
# Access the RailsConfig object
config = app.config
# Access custom data from config.yml
custom_settings = config.custom_data
# Access model configurations
models = config.models

Example: Database Connection

import os
import psycopg2
from nemoguardrails import LLMRails
def init(app: LLMRails):
# Create connection pool
conn = psycopg2.connect(
host=os.environ.get("DB_HOST", "localhost"),
database=os.environ.get("DB_NAME", "mydb"),
user=os.environ.get("DB_USER", "user"),
password=os.environ.get("DB_PASSWORD"),
)
app.register_action_param("db_conn", conn)

HTTP Client Lifecycle

The synchronous init function has no asynchronous teardown hook. Do not create a long-lived HTTP client in init unless another application component owns and closes it.

Create a shared canonical client at the surrounding application lifecycle boundary, register it as an action parameter, and close it at shutdown:

from nemoguardrails import LLMRails, RailsConfig
from nemoguardrails.http import create_http_client
async def run():
http_client = create_http_client(timeout=10.0)
config = RailsConfig.from_path("config")
app = LLMRails(config)
app.register_action_param("http_client", http_client)
try:
return await app.generate_async(
messages=[{"role": "user", "content": "Hello"}],
)
finally:
await http_client.close()

Actions that accept http_client: HTTPClient | None = None can use a shared injected client or let http_call create and close a call-scoped fallback. For details, refer to Outbound HTTP in Actions.