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/ # Translations2. XML Configuration
New modules and routes are registered via XML. Create a file named HelloWorld.xml in Kernel/Config/Files/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:
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:
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:
[% Data.Text %]
<p>This is your custom HelloWorld module!</p>6. Example Workflow
Reload:
bashbin/otobo.Console.pl Maint::Config::RebuildClear Cache:
bashbin/otobo.Console.pl Maint::Cache::DeleteOpen 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!