Configuration & Template Rendering
Understand Open Ticket AI's configuration lifecycle, template rendering with Jinja2, dependency injection, and how YAML transforms into runtime objects.
Configuration & Template Rendering
Open Ticket AI allows you to create dynamic configurations using YAML plus Jinja2 template expressions like
{{ ... }} without spaces
This lets you reuse values, read environment variables, and reference results from other pipes — all while keeping configuration clean and declarative.
Key Concepts
Injectable Configuration Structure
Both Services and Pipes in Open Ticket AI use the same configuration structure called
InjectableConfig. Understanding these three core attributes will help you configure any component
in the system.
Configuration Attributes
| Attribute | Type | Description | Example |
|---|---|---|---|
use | TEXT | Identifies which component to create. Format: plugin-name:ComponentName | "base:FetchTicketsPipe" |
injects | name:value pairs | Maps constructor parameter names to service IDs, connecting dependencies to this component | { ticket_system: "otobo_znuny" } |
params | name:value pairs | Configuration parameters specific to this component. Each component type expects different parameters | { limit: 25, queue: "Support" } |
Key Differences: Services vs. Pipes
While both use InjectableConfig, they differ in usage:
Services
- Defined once in the
servicessection - Reusable across multiple pipes
- Must have an
idfield for reference - Usually represent external systems
Example:
services:
otobo_znuny:
use: 'otobo-znuny:OTOBOZnunyTicketSystemService'
injects: {}
params:
base_url: 'https://helpdesk.example.com'
password: "{{ get_env('OTOBO_PASSWORD') }}"
Pipes
- Defined inside pipeline
steps - Execute actions in sequence
- Also have an
idfield to reference results - Use services via
injectsto perform work
Example:
steps:
- id: fetch_tickets
use: 'base:FetchTicketsPipe'
injects:
ticket_system: 'otobo_znuny'
params:
ticket_search_criteria:
limit: 25
Template Rendering
All params and injects values support Jinja2 templating for dynamic configuration:
params:
api_key: "{{ get_env('API_KEY') }}"
queue: "{{ get_pipe_result('classify', 'label') }}"
**Related: ** Template Rendering · Dependency Injection
Config Reference
Here is the Markdown table describing the full config structure clean and ready for your docs.
| Path | Type | Description | Example | |
|---|---|---|---|---|
otai | OpenTicketAIConfig | Main application config root. | ||
otai.api_version | str | API version for compatibility. | "1" | |
otai.plugins[] | list[str] | Python module paths of plugins to load. | "otai_hf_local" | |
otai.infrastructure | InfrastructureConfig | Infra-level settings. | ||
otai.infrastructure.logging | LoggingConfig | Logging configuration. | ||
otai.infrastructure.logging.level | str | Min log level. | "INFO" | |
otai.infrastructure.logging.log_to_file | bool | Enable file logging. | false | |
otai.infrastructure.logging.log_file_path | `str | None` | Log file path when enabled. | "/var/log/app.log" |
otai.infrastructure.logging.log_format | str | Python logging format string. | "%(asctime)s - %(levelname)s - %(message)s" | |
otai.infrastructure.logging.date_format | str | Date format for logs. | "%Y-%m-%d %H:%M:%S" | |
otai.services | dict[str, InjectableConfigBase] | Map of service-id → DI config. | ||
otai.services.<id> | InjectableConfigBase | One service definition. | ||
otai.services.<id>.use | str | Python class path to instantiate. | "pkg.mod.Class" | |
otai.services.<id>.injects | dict[str,str] | DI bindings: ctor-param → service-id. | { "db": "ticket-db" } | |
otai.services.<id>.params | dict[str,Any] | Constructor params (templating allowed). | { "url": "{\{ get_env('DB_URL') }\}" } | |
otai.services.<id>.id | str | Optional explicit identifier (when using InjectableConfig). | "ticket-db" | |
otai.orchestrator | PipeConfig | Orchestrator pipeline root. | ||
otai.orchestrator.id | str | Pipe identifier (for referencing). (inherits) | "root" | |
otai.orchestrator.use | str | Python class path of the Pipe. (inherits) | "project.pipes.CompositePipe" | |
otai.orchestrator.injects | dict[str,str] | DI to sub-pipes/services. (inherits) | { "step1": "ticket-db" } | |
otai.orchestrator.params | dict[str,Any] | Pipe parameters (templating allowed). (inherits) | {} |
Tiny example
otai:
api_version: '1'
plugins: []
infrastructure:
logging:
level: 'INFO'
services:
ticket-db:
use: 'plugin_name:Database'
params:
url: "{{ get_env('DB_URL') }}"
orchestrator:
id: 'root'
use: 'base:CompositePipe'
injects:
step1: 'ticket-db'
params: {}Available helper functions (for config.yml templates)
| Function | Parameters | Returns | Errors if… |
|---|---|---|---|
at_path | value: Any, path: text | Nested value at "a.b.c" path; supports dicts + Pydantic models | Invalid path format |
has_failed | pipe_id: text | True if the given pipe result is marked failed | Unknown pipe ID |
get_pipe_result | pipe_id: text, data_key: text;default = "value" | Value stored in previous pipe result under given data_key | Pipe or key missing |
get_parent_param | param_key: text | Inherited parent parameter value | Parent missing or key missing |
get_env | name: text | Value of environment variable | Env var missing |
fail | (none) | A “FailMarker” sentinel object to signal explicit failure paths | — |
Usage examples in config.yml
Read an environment variable
api:
token: "{{ get_env('API_TOKEN') }}"
baseUrl: 'https://api.example.com'
Consume a previous pipe’s result
classification:
label: "{{ get_pipe_result('classify_ticket', 'label') }}"
confidence: "{{ get_pipe_result('classify_ticket', 'score') }}"
isLowConfidence: "{{ get_pipe_result('classify_ticket', 'score') < 0.6 }}"
Check if a pipe failed
shouldRetry: "{{ has_failed('fetch_customer') }}"
Read a parent parameter
timeoutMs: "{{ get_parent_param('timeoutMs') }}"
Emit an explicit failure marker
result: '{{ fail() }}'
Access nested data (dict or Pydantic model)
userCity: "{{ at_path(user, 'address.city') }}"
Full Examples / Templates
See full working examples of config.yml
