Skip to content

description: "Learn how to customize OTOBO directly in the core – via XML configuration, Perl modules, and templates. We'll show you step-by-step how to integrate your own 'HelloWorld' module into the system."

Internally Extending the OTOBO Core System

In this article, you will learn how to customize OTOBO directly in the core – via XML configuration, Perl modules, and templates. We will show you step-by-step how to integrate your own "HelloWorld" module into the system.


1. Directory Structure

All customizations are located below your OTOBO clone in the Kernel/ directory:


Kernel/
├─ Config/Files/           # XML registrations
│  └─ XML/
├─ System/                 # Business logic modules (Core)
├─ Modules/                # Frontend controllers (Agent/Customer)
├─ Output/HTML/Standard/   # Template Toolkit (TT) templates
└─ Language/               # Translations

2. XML Configuration

New modules and routes are registered via XML. Create a file named HelloWorld.xml in Kernel/Config/Files/XML/:

xml
<?xml version="1.0" encoding="UTF-8"?>
<otobo_config version="2.0" init="Application">

  <!-- 1. Register Frontend Module -->
  <Setting Name="Frontend::Module###AgentHelloWorld" Required="1" Valid="1">
    <Navigation>Frontend::Agent::ModuleRegistration</Navigation>
    <Value>
      <Item ValueType="FrontendRegistration">
        <Hash>
          <Item Key="Group"><Array><Item>users</Item></Array></Item>
          <Item Key="Description" Translatable="1">HelloWorld Module</Item>
          <Item Key="Title"       Translatable="1">HelloWorld</Item>
          <Item Key="NavBarName">HelloWorld</Item>
        </Hash>
      </Item>
    </Value>
  </Setting>

</otobo_config>

3. Core Module (Business Logic)

Create your logic in Kernel/System/HelloWorld.pm:

perl
package Kernel::System::HelloWorld;
use strict;
use warnings;
our @ObjectDependencies = ();  

sub new {
    my ($Type, %Param) = @_;
    return bless {}, $Type;
}

sub GetHelloWorldText {
    my ($Self, %Param) = @_;
    return $Self->_FormatText(String => 'Hello World');
}

sub _FormatText {
    my ($Self, %Param) = @_;
    return uc $Param{String};
}

1;

4. Frontend Module (Controller)

In Kernel/Modules/AgentHelloWorld.pm, integrate your logic into the Agent frontend:

perl
package Kernel::Modules::AgentHelloWorld;
use strict;
use warnings;

sub new { bless {}, shift }

sub Run {
    my ($Self, %Param) = @_;

    my $HelloObj    = $Kernel::OM->Get('Kernel::System::HelloWorld');
    my $LayoutObj   = $Kernel::OM->Get('Kernel::Output::HTML::Layout');
    my %Data;
    
    $Data{Text} = $HelloObj->GetHelloWorldText();

    return 
        $LayoutObj->Header(Title => 'HelloWorld')
      . $LayoutObj->NavigationBar()
      . $LayoutObj->Output(
          TemplateFile => 'AgentHelloWorld',
          Data         => \%Data,
        )
      . $LayoutObj->Footer();
}

1;

5. Templates (TT)

Create the following template in Kernel/Output/HTML/Standard/AgentHelloWorld.tt:

tt
[% Data.Text %]

<p>This is your custom HelloWorld module!</p>

6. Example Workflow

  1. Reload:

    bash
    bin/otobo.Console.pl Maint::Config::Rebuild
  2. Clear Cache:

    bash
    bin/otobo.Console.pl Maint::Cache::Delete
  3. Open Browser: Agent Interface → Menu → "HelloWorld"


7. Tips & Best Practices

  • Declare ObjectDependencies cleanly (e.g., DB, Layout).
  • Don't forget POD documentation in Perl modules.
  • Maintain translations under Kernel/Language/de_*.pm.
  • Set up unit tests with Mojolicious (optional).
  • After every change, rebuild config & clear cache.

With this, you have a solid template for implementing further core extensions in OTOBO. Happy developing!