Skip to main content

Drupal Module Development Guide

Drupal Module Development Guide

Separation of Duties: See Separation of Duties - Drupal modules are responsible for Drupal-specific functionality. They do NOT own agent manifests, execution, or OSSA spec.

Comprehensive guide for developing custom Drupal modules in the LLM Platform ecosystem.

Table of Contents

Overview

The LLM Platform uses custom Drupal modules to provide AI-powered functionality, agent orchestration, and enterprise integrations. All modules follow Drupal coding standards and OSSA compliance requirements.

Key Principles

  1. OSSA Compliance: All AI agent modules must follow the Open Standard for Swarm Architecture
  2. Drupal Standards: Follow PHPCS and PHPStan standards (Drupal, DrupalPractice)
  3. Test Coverage: PHPUnit tests for all critical functionality
  4. API-First: REST, GraphQL, and JSON:API support
  5. Security: Input validation, access control, audit logging

Module Structure

Standard Drupal module structure with OSSA enhancements:

module_name/
 .agents/                      # OSSA agent manifests
    agent-name/
        manifest.json         # OSSA manifest
        README.md
        tools/
 .claude/                      # Claude Code configuration
    CLAUDE.md                 # Employment protection
 config/
    install/                  # Default config
    schema/                   # Config schema
 src/
    Controller/               # Route controllers
    Entity/                   # Entity definitions
    Form/                     # Form classes
    Plugin/                   # Plugin definitions
    Service/                  # Services
 tests/
    src/
       Unit/                 # Unit tests
       Kernel/               # Kernel tests
       Functional/           # Functional tests
 module_name.info.yml          # Module metadata
 module_name.module            # Hooks
 module_name.routing.yml       # Routes
 module_name.services.yml      # Service definitions
 module_name.permissions.yml   # Permissions
 composer.json                 # Composer dependencies
 README.md                     # Documentation

Development Workflow

1. Module Location

Source Location (edit here):

$LLM_ROOT/all_drupal_custom/modules/MODULE_NAME/

Deployment Location (Composer-managed, DO NOT EDIT):

$LLM_ROOT/llm-platform/web/modules/custom/MODULE_NAME/

2. Sync Modules

After making changes, sync to deployment:

buildkit drupal sync --modules

Or with dry-run to preview:

buildkit drupal sync --modules --dry-run

3. Module Creation

Create a new module:

buildkit drupal module:create my_module_name

This scaffolds:

  • Basic module structure
  • .info.yml with dependencies
  • Service definitions
  • OSSA compliance files
  • CLAUDE.md employment protection

4. Development Commands

# Clear cache buildkit drupal cache:clear # Export config buildkit drupal config:export # Run database updates buildkit drupal database:update # PHPCS validation buildkit drupal phpcs MODULE_PATH --fix # Design taste validation buildkit drupal taste MODULE_PATH

OSSA Compliance

All AI agent modules must be OSSA-compliant.

Manifest Structure

Every agent requires .agents/agent-name/manifest.json:

{ "name": "agent-name", "version": "0.4.9", "type": "worker", "description": "Agent description", "capabilities": [ "capability1", "capability2" ], "tools": [ { "name": "tool_name", "type": "function", "description": "Tool description", "parameters": { "type": "object", "properties": {}, "required": [] } } ], "dependencies": [], "security": { "isolation_level": "container", "permissions": [] } }

Validation

# Validate OSSA manifest ossa validate .agents/agent-name/manifest.json # Migrate old manifests ossa migrate .agents/old-agent/ --output .agents/new-agent/

Best Practices

1. Module Info File

name: 'Module Name' type: module description: 'Clear, concise description including OSSA compliance note' package: 'Package Name' core_version_requirement: ^10.3 || ^11 version: 0.1.1 dependencies: # Core dependencies only - drupal:system (>=10.3) - drupal:user suggests: # Optional enhancements - admin_toolbar:admin_toolbar configure: module_name.settings lifecycle: stable

2. Service Definitions

Use dependency injection:

# module_name.services.yml services: module_name.service_name: class: Drupal\module_name\Service\ServiceName arguments: - '@entity_type.manager' - '@logger.factory' - '@config.factory'

3. Entity Definitions

Use ECK (Entity Construction Kit) or custom entities:

<?php namespace Drupal\module_name\Entity; use Drupal\Core\Entity\ContentEntityBase; use Drupal\Core\Entity\EntityTypeInterface; use Drupal\Core\Field\BaseFieldDefinition; /** * Defines the Example entity. * * @ContentEntityType( * id = "example_entity", * label = @Translation("Example Entity"), * base_table = "example_entity", * entity_keys = { * "id" = "id", * "uuid" = "uuid", * "label" = "name", * }, * ) */ class ExampleEntity extends ContentEntityBase { public static function baseFieldDefinitions(EntityTypeInterface $entity_type) { $fields = parent::baseFieldDefinitions($entity_type); $fields['name'] = BaseFieldDefinition::create('string') ->setLabel(t('Name')) ->setRequired(TRUE); return $fields; } }

4. Plugin System

Use plugins for extensibility:

<?php namespace Drupal\module_name\Plugin\ActionType; use Drupal\Core\Plugin\PluginBase; /** * @ActionType( * id = "example_action", * label = @Translation("Example Action"), * description = @Translation("Description of action"), * ) */ class ExampleAction extends PluginBase { public function execute(array $context): array { // Implementation return ['success' => TRUE]; } }

5. API Endpoints

Provide REST/GraphQL endpoints:

# module_name.routing.yml module_name.api.endpoint: path: '/api/v1/module-name/{id}' defaults: _controller: '\Drupal\module_name\Controller\ApiController::getData' _format: 'json' requirements: _permission: 'access module name api' _method: 'GET'

6. Configuration Schema

Define configuration schema:

# config/schema/module_name.schema.yml module_name.settings: type: config_object label: 'Module Name settings' mapping: api_key: type: string label: 'API Key' timeout: type: integer label: 'Timeout (seconds)'

Testing

PHPUnit Setup

# Run all tests vendor/bin/phpunit modules/custom/module_name/tests # Run specific test suite vendor/bin/phpunit --testsuite Unit modules/custom/module_name

Unit Test Example

<?php namespace Drupal\Tests\module_name\Unit; use Drupal\Tests\UnitTestCase; use Drupal\module_name\Service\ExampleService; /** * @coversDefaultClass \Drupal\module_name\Service\ExampleService * @group module_name */ class ExampleServiceTest extends UnitTestCase { /** * @covers ::processData */ public function testProcessData() { $service = new ExampleService(); $result = $service->processData(['input' => 'test']); $this->assertEquals('expected', $result['output']); } }

Kernel Test Example

<?php namespace Drupal\Tests\module_name\Kernel; use Drupal\KernelTests\KernelTestBase; /** * Tests the Example entity. * * @group module_name */ class ExampleEntityTest extends KernelTestBase { protected static $modules = ['module_name', 'user', 'system']; protected function setUp(): void { parent::setUp(); $this->installEntitySchema('example_entity'); } public function testEntityCreation() { $entity = ExampleEntity::create(['name' => 'Test']); $entity->save(); $this->assertNotNull($entity->id()); $this->assertEquals('Test', $entity->label()); } }

Deployment

1. Pre-Deployment Checks

# Run tests buildkit golden test # Validate code buildkit drupal phpcs modules/custom/module_name --fix # Check design taste buildkit drupal taste modules/custom/module_name # Security audit buildkit golden audit

2. Sync and Deploy

# Sync to deployment location buildkit drupal sync --modules # Export configuration buildkit drupal config:export # Deploy to environment buildkit golden deploy --env dev

3. Post-Deployment

# Run database updates buildkit drupal database:update # Import configuration buildkit drupal config:import # Clear caches buildkit drupal cache:clear # Verify module status drush pm:list --type=module --status=enabled | grep module_name

Employment Protection

All modules include .claude/CLAUDE.md with employment protection:

# CLAUDE.md - module_name ## EMPLOYMENT PROTECTION ACTIVE - Claude Code BLOCKED from development branch - AI attribution BLOCKED in commits - Feature branch workflow ENFORCED ## TOKEN OPTIMIZATION MANDATORY Before writing ANY code > 500 tokens: - Check: buildkit agents list - Use: buildkit agents spawn --type worker Protected by Agent BuildKit v0.1.9

Common Patterns

AI Integration

// Use AI service $ai = \Drupal::service('ai.provider.manager'); $provider = $ai->createInstance('openai'); $result = $provider->chat($messages);

ECA Integration

# Workflow automation langcode: en status: true dependencies: module: - module_name id: example_workflow label: 'Example Workflow' modeller: bpmn events: - id: event_1 plugin: 'content:entity:save' conditions: [] actions: - id: action_1 plugin: 'module_name:custom_action'

Queue Processing

// Queue worker $queue = \Drupal::queue('module_name_tasks'); $queue->createItem(['data' => $data]); // Process in QueueWorker plugin

Resources

See Also