If you want to create a new page for developers, you should create it on the Moodle Developer Resource site.

External tool

From MoodleDocs

This page documents the External tool plugin in Moodle and its features.

LTI Source Plugins

The External tool supports sub plugins that live under the mod/lti/source directory with the plugin type of ltisource. The purpose of a LTI source plugin is to extend the functionality of the External Tool activity.

The LTI source plugins support the following standard plugin features:

  • Language file: mod/lti/source/pluginname/lang/en/ltisource_pluginname.php
  • Plugin upgrade API under the mod/lti/source/pluginname/db directory.

Extending the LTI protocol

The most powerful extension that the LTI source plugins can perform is to extend the LTI services provided by the External Tool activity. All incoming requests are handled by mod/lti/service.php and all standard LTI requests are automatically handled. But, if the request is non-standard, then a LTI source plugin can have an opportunity to handle the request.

The request is routed to the LTI source plugin by using the message type. For example, let's say this request was sent to the External Tool:

<?xml version="1.0" encoding="UTF-8"?>
<imsx_POXEnvelopeRequest xmlns="">
        <myCustomRequest><!-- LOOK HERE! -->
            <myRecord><!-- This can be named whatever you want -->
                <!-- You custom data in XML format -->

In the above request, the message type is myCustomRequest. Since this is not a standard request, a LTI source plugin can handle it. We can do this by adding a LTI source plugin and for this example, we will call it widget. Then, in our ltisource_widget plugin, we must define a specific function In order to handle the request. The function name takes on the form of component_messageType. So, for our above request example we would create mod/lti/source/widget/lib.php and add this function to the file:

 * Handle a custom widget request.
 * @param object $data The LTI request details
function ltisource_widget_myCustomRequest($data) {
    $data->body;         // The raw LTI request XML body.
    $data->xml;          // A SimpleXMLElement of the XML body.
    $data->messageid;    // The value of the <imsx_messageIdentifier> element in the request.
    $data->messagetype;  // The message type.
    $data->consumerkey;  // OAuth consumer key.
    $data->sharedsecret; // The shared secret used to verify the request body.

    // Do your custom work here.

    // Throw exceptions on error, they will be sent back appropriately.

    // When done, echo out your response XML.
    $responsexml = lti_get_response_xml(
        'Widget handled',

    echo $responsexml->asXML();

Word of warning: If more than one LTI source plugins implement a function for handling the myCustomRequest message, then an exception will be thrown. So, when coming up with names for your message types, try to keep them unique and perhaps prefix them with something unique about your service.

And that's about it! With this extension point, you can build deep integrations with external services all while communicating through the LTI protocol.

Addition to the add activities menu

Overall, the following has a narrow use case, but it might be expanded in the future.

A LTI source plugin can add itself to the add activities menu by implementing a component_get_types function in its lib.php file. So, for example, if our LTI source plugin was widget, then in mod/lti/source/widget/lib.php we would add the following function:

function ltisource_widget_get_types() {
    $types   = array();
    $types[] = (object) array(
        'modclass' => MOD_CLASS_ACTIVITY,
        'type'     => 'lti&amp;type=widget',
        'typestr'  => get_string('addwidget', 'ltisource_widget'),
        'help'     => get_string('addwidget_help', 'ltisource_widget'),
    return $types;

But, this on its own doesn't actually do much at the moment. You must also add another callback that gets called from the External Tool add instance form. The callback takes on the form of component_add_instance_hook. So, also add this function to mod/lti/source/widget/lib.php:

function ltisource_widget_add_instance_hook() {
    // Do custom work here.

At this point, the most common use case is to redirect to an external site to browse widget-like content. Then the Extending the LTI protocol section can be used to create widget-like content in Moodle.

LTI Content-Item

Support for the LTI Content-Item message type in mod_lti has been implemented since Moodle 3.2. The Content-Item message type enables tool consumers to select content from a tool provider that also supports the Content-Item message type. Content selection can range from LTI links, HTML content, and even multimedia data (e.g. images, video, audio, etc).

In Moodle 3.2, LTI Content-Item is being used to fetch tool configuration data from a tool provider that can be used to configure an external tool activity. This is done using the Select content button on the External tool configuration page which launches a modal dialogue containing an interface from the Tool Provider that allows the user to fetch the tool configuration data. Hopefully, in future releases, additional features will be added, such as fetching and attaching content to an editor.

Moodle 3.2


For developers who would like to send a ContentItemSelectionRequest to a Tool Provider, the function lti_build_content_item_selection_request() can be used. This function returns an object that contains the signed request parameters and the URL to the Tool Provider's Content-Item selection interface. It has the following parameters:

Required parameters

  • $id int - The tool type's ID (from in the lti_types table).
  • $course stdClass - The course object.
  • $returnurl moodle_url - The return URL in the tool consumer (TC) that the tool provider (TP) will use to return the response for the Content-Item selection request.

Optional parameters

  • $title string - The tool's title, if available.
  • $text string - The text to display to represent the content item. This value may be a long description of the content item.
  • $mediatypes array - Array of MIME types types supported by the TC. If empty, the TC will support ltilink by default.
  • $presentationtargets array - Array of ways in which the selected content item(s) can be requested to be opened (via the presentationDocumentTarget element for a returned content item). If empty, "frame", "iframe", and "window" will be supported by default.
  • $autocreate bool - Indicates whether any content items returned by the TP would be automatically persisted.
  • $multiple bool - Indicates whether the user should be permitted to select more than one item. False by default. any option for the user to cancel the operation. False by default.
  • $unsigned bool - Indicates whether the TC is willing to accept an unsigned return message, or not. A signed message should always be required when the content item is being created automatically in the TC without further interaction from the user. False by default.
  • $canconfirm bool - Flag for can_confirm parameter. False by default.
  • $copyadvice bool - Indicates whether the TC is able and willing to make a local copy of a content item. False by default.

For more information about the request parameters, see Content-Item Message - Information Model.

Sample implementation

// Prepare the request.
$request = lti_build_content_item_selection_request($id, $course, $returnurl, $title, $text, [], []);

// Get the launch HTML.
$content = lti_post_launch_html($request->params, $request->url, false);

See also