Skip to content

API stability

This page defines which parts of AI Context are public (safe to depend on) and which are internal (implementation details that may change without a deprecation period). It exists so contrib developers and site builders can answer one question without reading selector internals: what am I allowed to depend on?

The default rule

If an API is not listed as public on this page, treat it as internal.

  • Public APIs follow Drupal's deprecation policy: behavior changes are announced and a deprecation path is provided across minor releases.
  • Internal APIs may change, move, or be removed in any release without notice. Depending on them couples your code to implementation details that are expected to evolve.

While the module is in beta, public APIs may still change between releases without a full deprecation cycle — check release notes when upgrading. Once the module reaches a stable release, the boundaries on this page describe the supported surface. See also Upgrade and compatibility policy.

Deprecated APIs

CCC 1.0.x does not currently ship @deprecated public APIs. When a supported entry point is deprecated, it will be listed here with its replacement and the release that removes it.

If you depend on classes or services marked @internal in code, migrate to the public surfaces on this page — those internals are not deprecated; they were never part of the supported API.

Beta upgrade: entity scope terminology

The entity scope APIs were renamed before the 1.0.0 stable release. There are no backward-compatibility wrappers for the old names. Deploy the new code and run drush updatedb in the same release window, then update custom code and configuration that uses the old identifiers.

Old New
Scope plugin entity_bundle / AiContextScopeEntityBundle entity_type / AiContextScopeEntityType
Scope plugin target_entity / AiContextScopeTargetEntity entity_item / AiContextScopeEntityItem
Cache context ai_context.target_entity ai_context.entity_item
Base field target_entities entity_items
Usage fields target_entity_type / target_entity_id entity_item_type / entity_item_id
Views field ai_context_target_entity_link ai_context_entity_item_link
Service ai_context.entity_target_resolver / AiContextEntityTargetResolver ai_context.current_entity_resolver / AiContextCurrentEntityResolver
Request factory parameter targetEntity currentEntity

The AiContextItem methods were renamed or replaced as follows:

Old New
getTargetEntities() getEntityItems()
hasTargetEntities() hasEntityItems()
getTargetEntityData() getEntityItemData()
buildTargetEntityRenderArray() buildEntityItemRenderArray()
getTargetEntityMarkup() buildEntityItemRenderArray() (render array, not markup string)
matchesTargetEntity() matchesEntityItem()

The AiContextUsage getters and setters now use EntityItem instead of TargetEntity, for example getEntityItemType() and setEntityItemId().

Updates 10015 through 10019 migrate stored scope values and revisions, scope configuration, usage storage and Views configuration, and the optional Dynamic Entity Reference field storage. Update hooks cannot rewrite custom PHP or render arrays, so custom cache-context tokens, plugin IDs, class names, and method calls must be changed during the deployment.

Beta upgrade: max_items removal

The Max context items to inject limit was removed before the 1.0.0 stable release. The token budget (max_tokens) is now the only user-facing limit on overall injected context; max_global_items still caps the Global group. There are no backward-compatibility wrappers.

Removed Replacement
max_items in ai_context.settings and per-agent overrides None; use max_tokens
maxItems parameter on AiContextRequest and AiContextRequestParamsData None
AiContextSelectionItemsSelectedEvent::getMaxItems() (constructor no longer takes a max-items argument) None
max_items parameter on the get_relevant_ai_context_items function call None
AiContextLimitsConstraint and its validator None; the cross-limit validation is obsolete

Update 10020 removes the obsolete max_items keys from active configuration, and legacy configuration exports are sanitized during import. Custom code that passes maxItems or calls getMaxItems() must be updated in the same release window.

Update 10023 installs the token_count base field on ai_context_item and backfills stored estimates. See Configuration: Upgrading.

Public API

Request factory service

Service ID ai_context.request_factory (Drupal\ai_context\Service\AiContextRequestFactory) is the supported entry point for running context selection from your own code.

API Purpose
getRenderedContext() One-liner returning the rendered context string for non-agent consumers
getResult() Full AiContextResult with cache metadata, selected IDs, and token usage
fromAgent() Build an AiContextRequest from a saved agent config entry
fromParameters() Build an AiContextRequest from typed parameters
findAgentConfig() Canonical reader for per-agent context config
isLoopAware() Whether an agent has loop-aware injection enabled

See Services for full signatures and examples.

Scope subscription form builder

Service ID ai_context.scope_subscription_form (Drupal\ai_context\Service\AiContextScopeSubscriptionFormBuilderInterface) is the supported way to build and process scope subscription widgets on non-agent forms.

API Purpose
hasSubscribableScopes() Whether any enabled scope supports subscriptions
getNonSubscribableScopeLabels() Labels for scopes that cannot be subscribed to
buildWidgets() Per-scope subscription form elements (same UI as agent form)
extractValues() Normalize submitted widgets into a scope map
buildSummary() Render-array summary of selected subscriptions

Do not depend on plugin.manager.ai_context_scope for subscription UI; use this service instead. See Services.

Request and result value objects

  • Drupal\ai_context\Model\AiContextRequestParamsData — validated parameter DTO for fromParameters(). Build instances with fromArray() when passing raw input from forms, plugins, or other loosely typed sources.
  • Drupal\ai_context\Model\AiContextRequest — the immutable request passed into selection.
  • Drupal\ai_context\Model\AiContextResult — the immutable result returned from selection (rendered text, selected item IDs, token usage, cache metadata).

The supported way to run a request is through ai_context.request_factory, which builds these objects and invokes selection for you. The params DTO getters, request fields, and result accessors — such as getRenderedText(), getSelectedItemIds(), and getCacheableMetadata() — are public.

Selector pipeline events

The ai_context.selection.* events are the supported way to inspect or alter selection without coupling to selector internals:

  • ai_context.selection.items_selected (AiContextSelectionItemsSelectedEvent)
  • ai_context.selection.text_rendered (AiContextSelectionTextRenderedEvent)

Event name constants live on Drupal\ai_context\Event\AiContextSelectionEvents. See the Supported extension model in Events for the full contract, subscriber constraints, and examples.

Scope plugins, hooks, and alters

  • AiContextScope plugins are a public extension point. Create your own scope plugins as described in Custom scopes and the Scope API.
  • The documented hooks and alter hooks are public. See Hooks.
  • 1.0 custom scope storage: supported custom scopes store values in the context item scope map field (scope[plugin_id] => string[]). Custom entity-field storage, cleanup, and form lifecycle integration are internal module concerns in 1.0; map-backed scopes are indexed automatically.
  • Entity scope helpers on AiContextItem are public for reading scope state. Resolve effective scope through getScopeItem() first; use stored accessors (getScope(), getScopeValues(), isStoredGlobal(), getStoredEntityItemScopeValues()) only when you need values saved on this item. See Scope API.

Do not inject plugin.manager.ai_context_scope from contrib modules; prefer the subscription form builder service for subscription widgets. The manager may gain orchestration methods in a future release without a deprecation period while marked @internal.

Function call plugins

The context_tools function call plugin IDs (ai_context:list_ai_context_items, ai_context:load_ai_context_item_by_id, ai_context:get_relevant_ai_context_items) are stable identifiers for agent configuration. See Function calls.

Internal implementation

The following are internal. They may change without deprecation; do not depend on them, decorate them, or replace them.

Selector and its pipeline

ai_context.selector (Drupal\ai_context\Service\AiContextSelector) and AiContextSelectorInterface — and the candidate pipeline (loading, scoring, priority merge, and subcontext resolution) — are internal. Extend selection through the selector pipeline events, not by depending on or replacing the selector.

Supporting services

These services support the selector and are not part of the public surface:

  • ai_context.scope_resolver — scope scoring and hard context filters
  • ai_context.scope_index — denormalized scope index used for prefiltering
  • ai_context.subcontext_resolver — child item resolution
  • ai_context.renderer, ai_context.token_estimator, and ai_context.subscription_budget — rendering, token budgeting, and agent settings budget summary internals
  • ai_context.current_entity_resolver, ai_context.scope_cleanup, ai_context.children, ai_context.item_validator, and the remaining services in Services

Event subscribers, route subscribers, access checks, cache contexts, and the scope plugin manager (plugin.manager.ai_context_scope) are likewise internal infrastructure. All entries under Support services in the services reference are internal — they are not labeled individually. Use the public extension points above instead.

Service decoration and replacement

Decorating, extending, or replacing internal services (for example ai_context.selector) in a services.yml file is not supported. The internal pipeline may change shape, argument order, or service graph between releases. Use the selector pipeline events and the request factory for supported customization.

See also