Configuration & Template Rendering 
Open Ticket AI allows you to create dynamic configurations using YAML plus Jinja2 template expressions like
{ { ... } } without spaces 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:
yaml
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:
yaml
steps:
  - id: fetch_tickets
    use: "base:FetchTicketsPipe"
    injects:
      ticket_system: "otobo_znuny"
    params:
      ticket_search_criteria:
        limit: 25Template Rendering 
All params and injects values support Jinja2 templating for dynamic configuration:
yaml
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
yaml
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 | Trueif 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 
yaml
api:
  token: "{{ get_env('API_TOKEN') }}"
  baseUrl: "https://api.example.com"Consume a previous pipe’s result 
yaml
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 
yaml
shouldRetry: "{{ has_failed('fetch_customer') }}"Read a parent parameter 
yaml
timeoutMs: "{{ get_parent_param('timeoutMs') }}"Emit an explicit failure marker 
yaml
result: "{{ fail() }}"Access nested data (dict or Pydantic model) 
yaml
userCity: "{{ at_path(user, 'address.city') }}"