Skip to content

Extending

Add a vocabulary

A vocabulary is a serializer plugin: a class in a module's src/Plugin/AgentSurfaceSerializer directory with the #[AgentSurfaceSerializer] attribute, implementing Drupal\agent_surface\Serializer\SerializerInterface. Extend SerializerPluginBase, which returns nothing for each carrier, and override the carriers the vocabulary defines.

The module's own categories (training, inference, search, automated) are deliberately no specification's spelling. Translating them is the plugin's job, so a revised vocabulary is a new plugin rather than a change to stored configuration, and both can be enabled during a transition.

<?php

declare(strict_types=1);

namespace Drupal\my_module\Plugin\AgentSurfaceSerializer;

use Drupal\agent_surface\Attribute\AgentSurfaceSerializer;
use Drupal\agent_surface\Serializer\SerializerPluginBase;
use Drupal\agent_surface\Signal\Category;
use Drupal\agent_surface\Signal\Preference;
use Drupal\agent_surface\Signal\SignalSet;
use Drupal\Core\StringTranslation\TranslatableMarkup;

#[AgentSurfaceSerializer(
  id: 'example_training',
  label: new TranslatableMarkup('Example training header'),
  spec_version: 'Example spec, draft 1',
  description: new TranslatableMarkup('An X-Example-Training header.'),
)]
final class ExampleTraining extends SerializerPluginBase {

  public function toHeaders(SignalSet $signals): array {
    return match ($signals->get(Category::Training)) {
      Preference::Allow => ['X-Example-Training' => 'yes'],
      Preference::Disallow => ['X-Example-Training' => 'no'],
      Preference::Unstated => [],
    };
  }

}
Method Returns
toHeaders(SignalSet $signals) Header values keyed by header name. A value may be a list for repeatable headers such as Link. An empty array when nothing is stated.
toRobotsLines(SignalSet $signals, ?string $path = NULL) Complete robots.txt lines. $path is a path prefix to scope the rule to; return nothing for a path if the specification has no path-scoped form.
toFrontMatter(SignalSet $signals) Front matter values keyed by key.

New plugins appear under Vocabularies to emit on the settings form; nothing is emitted until a site enables them there. Plugin definitions can be altered with hook_agent_surface_serializer_info_alter().

Hooks

Defined in agent_surface.api.php.

hook_agent_surface_headers_alter(array &$headers, SignalSet $signals, array $context)
Alters the response headers built for a signal set. $headers maps header names to lists of values. $context may contain entity, request and response.
hook_agent_surface_robots_lines_alter(array &$lines, SignalSet $signals, ?string $path)
Alters the robots.txt lines built for a signal set. $path is the prefix the lines are scoped to, or NULL for the whole site.
hook_agent_surface_front_matter_alter(array &$keys, SignalSet $signals, array $context)
Alters the front matter keys built for a signal set. $context may contain entity.
hook_agent_surface_serializer_info_alter(array &$definitions)
Alters serializer plugin definitions, keyed by plugin ID.
function my_module_agent_surface_headers_alter(array &$headers, SignalSet $signals, array $context): void {
  $headers['X-Usage-Policy'][] = 'https://example.com/ai-policy';
}

Services

Service Class Use
agent_surface.signal_resolver Signal\SignalResolver The effective signals for the site (siteDefaults()), a bundle (forBundle()) or an entity (forEntity()), and their cacheability.
agent_surface.declarations Declaration\DeclarationBuilder Runs the enabled serializers: headers(), robotsLines(), frontMatter().
agent_surface.markdown_url_builder Url\MarkdownUrlBuilder The .md URL of an entity or the current page, or NULL when there is none.
plugin.manager.agent_surface_serializer Serializer\SerializerManager Serializer plugin discovery.

Cache tag

agent_surface_declarations is invalidated whenever a declared signal changes: on settings saves (through any route, configuration import included), on bundle override changes, and when modules are installed or uninstalled. Anything that renders a declaration should depend on it, and on config:agent_surface.settings; SignalResolver::cacheability() returns both, plus the bundle override's own tag for an entity.

Request attributes

During a request, $request->attributes->get('_agent_surface_rule') (AgentSurface::RULE_ATTRIBUTE) holds the rule that selected Markdown: suffix, format, accept or user_agent, or nothing for HTML. AgentSurface::isShareable() says whether a response for that rule may enter a shared cache.