Documentation Open Ticket Automation Users Configuration & Template Rendering

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

AttributeTypeDescriptionExample
useTEXTIdentifies which component to create. Format: plugin-name:ComponentName"base:FetchTicketsPipe"
injectsname:value pairsMaps constructor parameter names to service IDs, connecting dependencies to this component{ ticket_system: "otobo_znuny" }
paramsname:value pairsConfiguration 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 services section
  • Reusable across multiple pipes
  • Must have an id field 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 id field to reference results
  • Use services via injects to 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.

PathTypeDescriptionExample
otaiOpenTicketAIConfigMain application config root.
otai.api_versionstrAPI version for compatibility."1"
otai.plugins[]list[str]Python module paths of plugins to load."otai_hf_local"
otai.infrastructureInfrastructureConfigInfra-level settings.
otai.infrastructure.loggingLoggingConfigLogging configuration.
otai.infrastructure.logging.levelstrMin log level."INFO"
otai.infrastructure.logging.log_to_fileboolEnable file logging.false
otai.infrastructure.logging.log_file_path`strNone`Log file path when enabled."/var/log/app.log"
otai.infrastructure.logging.log_formatstrPython logging format string."%(asctime)s - %(levelname)s - %(message)s"
otai.infrastructure.logging.date_formatstrDate format for logs."%Y-%m-%d %H:%M:%S"
otai.servicesdict[str, InjectableConfigBase]Map of service-id → DI config.
otai.services.<id>InjectableConfigBaseOne service definition.
otai.services.<id>.usestrPython class path to instantiate."pkg.mod.Class"
otai.services.<id>.injectsdict[str,str]DI bindings: ctor-param → service-id.{ "db": "ticket-db" }
otai.services.<id>.paramsdict[str,Any]Constructor params (templating allowed).{ "url": "{\{ get_env('DB_URL') }\}" }
otai.services.<id>.idstrOptional explicit identifier (when using InjectableConfig)."ticket-db"
otai.orchestratorPipeConfigOrchestrator pipeline root.
otai.orchestrator.idstrPipe identifier (for referencing). (inherits)"root"
otai.orchestrator.usestrPython class path of the Pipe. (inherits)"project.pipes.CompositePipe"
otai.orchestrator.injectsdict[str,str]DI to sub-pipes/services. (inherits){ "step1": "ticket-db" }
otai.orchestrator.paramsdict[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)

FunctionParametersReturnsErrors if…
at_pathvalue: Any, path: textNested value at "a.b.c" path; supports dicts + Pydantic modelsInvalid path format
has_failedpipe_id: textTrue if the given pipe result is marked failedUnknown pipe ID
get_pipe_resultpipe_id: text, data_key: text;default = "value"Value stored in previous pipe result under given data_keyPipe or key missing
get_parent_paramparam_key: textInherited parent parameter valueParent missing or key missing
get_envname: textValue of environment variableEnv 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

Config Examples.