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
Section titled “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
Section titled “2. XML configuration”New modules and routes are registered via XML. Create a file 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)
Section titled “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)
Section titled “4. Frontend module (controller)”In Kernel/Modules/AgentHelloWorld.pm, you 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)
Section titled “5. Templates (TT)”Create the following template in Kernel/Output/HTML/Standard/AgentHelloWorld.tt:
[% Data.Text %]
<p>This is your self-created HelloWorld module!</p>6. Example workflow
Section titled “6. Example workflow”-
Reload:
Terminal window bin/otobo.Console.pl Maint::Config::Rebuild -
Clear cache:
Terminal window bin/otobo.Console.pl Maint::Cache::Delete -
Open browser: Agent interface → Menu → “HelloWorld”
7. Tips & Best Practices
Section titled “7. Tips & Best Practices”- Declare ObjectDependencies cleanly (e.g., DB, Layout).
- Don’t forget POD documentation in Perl modules.
- Maintain translations under
Kernel/Language/en_*.pm. - Set up unit tests with Mojolicious (optional).
- After every change, perform a Config rebuild & Clear cache.
With this, you have a solid template for implementing further core extensions in OTOBO. Have fun developing!
Frequently asked questions
Where do OTOBO core customizations live?
Customizations go under the Kernel/ directory: Config/Files/XML for registrations, System for business logic, Modules for frontend controllers, and Output/HTML/Standard for templates.
How are new OTOBO modules registered?
New modules and routes are registered via XML files in Kernel/Config/Files/XML/, for example a HelloWorld.xml frontend module setting.
What does the HelloWorld example demonstrate?
It shows how to add a core Perl module, register it in XML, and render it with a Template Toolkit template in the agent interface.