Skip to content

Page and entity context

Entity-dependent scopes only work when CCC can see the request entity or request page. Configuring Specific Entities, Entity Types, Taxonomy Terms, or Site Sections on a context item is not enough by itself.

This matters most for AI Assistants and the DeepChat chatbot. Those UIs can look fully configured while the agent still has no page awareness.

What needs a request entity or page

These built-in scopes fail closed when their detected value cannot be resolved:

Scope Needs If missing
Specific Entities The exact entity being worked on Targeted items are left out
Entity Types The request entity type and bundle Scoped items are left out
Taxonomy Terms Taxonomy references on the request entity Scoped items are left out
Site Sections The URL path of the page being viewed Scoped items are left out

Items that leave those scopes empty stay unrestricted by that scope. Global, Always include, and subscription matches can still be selected alongside a Specific Entities item. See Context Selection.

How the request entity reaches CCC

CCC accepts a request entity from any of these sources.

1. The current Drupal route

When the agent runs on a page that already has an entity in the route -- for example viewing or editing /node/123 -- CCC reads that entity automatically. No extra integration is required. Only content entities count. A config entity on the route, such as the Editor on the CKEditor request endpoint, is ignored.

This is the happy path for Canvas, node forms, and other in-place agent UIs.

2. Agent token contexts

On the push-injection path (context appended to the system prompt), CCC also reads entity hints from the BuildSystemPromptEvent tokens:

  • entity_type plus entity_id
  • An entity object in a known token (node, media, taxonomy_term, canvas_page, and similar)

Canvas AI passes these tokens. A custom integration can do the same.

3. Generic chat entity_context metadata

On the generic PreGenerateResponseEvent path, CCC reads the entity from structured entity_context metadata on the provider event or chat input. Consumers on API-proxy routes, such as AI CKEditor, send this because their route and path describe the endpoint, not the content being edited.

Accepted shapes:

  • entity_type plus entity_id
  • entity_type_id plus id
  • type plus id
  • entity_type plus bundle (any type key above) for an unsaved entity, for example a node add form. Entity Types matches the bundle; Specific Entities and Taxonomy Terms have nothing to match. A loaded entity wins over the bundle hint.
  • path: the page being edited, used by Site Sections. See Site Sections on API-proxy routes.

See Events.

4. Explicit tool parameters

When context is pulled through tools instead of pushed into the prompt, ai_context:get_relevant_ai_context_items and ai_context:list_ai_context_items accept optional entity_type and entity_id parameters. See Function calls.

If those parameters are omitted, entity-dependent scopes have nothing to match.

Integrations and request hints

Modules can also set the request entity through:

  • Request attributes ai_context_entity_type and ai_context_entity_id (AiContextRequestInfoResolver::setEntity())
  • BuildSystemPromptEvent payload values via AiContextRequestInfoResolver::applyRequestInfo()
  • POST or JSON body fields entity_type and entity_id (content entity types only; a body naming a config entity such as an Editor is ignored)

Request-body values are untrusted client hints used only for string matching. They do not grant entity access.

Chatbots and AI Assistants

A chatbot or assistant setup is not the same as running an agent on a node form. Assistants that are not backed by an agent receive no automatic context push in 1.x. The generic path excludes the ai_assistant_api tag.

Typical DeepChat traffic is a POST to /api/deepchat, not to /node/123. The page the visitor is looking at is not the Drupal route of the agent request. Unless the assistant integration maps that page onto one of the sources above, CCC sees no request entity.

Until #3586681 is fixed, agent-backed assistants drop the page context that classic (non-agent) assistants already consume. Specific Entities, Entity Types, and Taxonomy Terms therefore have no page to match, even when the chatbot block is placed on that page.

For a chatbot or assistant to use entity-dependent scopes today, the integration must supply the request entity through token contexts or tool parameters. Waiting for the visitor's URL to appear in the Drupal route is not enough.

Consumer ID: push versus tools

CCC uses the consumer ID to merge that consumer's saved subscriptions, Always include / Never include lists, and selection mode.

  • Push injection receives the agent ID from BuildSystemPromptEvent and converts it to agent:{id}. Saved consumer configuration for that agent is applied automatically.
  • The tool path inherits it. When GetRelevantAiContextItems or ListAiContextItems runs inside an agent and consumer_id is omitted, AiContextAgentToolSubscriber sets consumer_id to agent:{id} from AgentToolPreExecuteEvent. Tools opt in via AiContextInheritsConsumerIdInterface. An explicit canonical consumer_id argument still overrides the inherited value.

Do not hardcode a consumer ID into a Pre Action Prompt. The tool now fills it server-side for agent-backed assistants.

getResult() and getRenderedContext() keep consumerId null on purpose for non-agent callers.

Site Sections on API-proxy routes

Site Sections matches configured path patterns against the effective page path, not only $request->getPathInfo().

Sources, in order:

  1. Request attribute ai_context_path (setPath() or a caller)
  2. Request body path (POST or JSON)
  3. A same-site Referer path, only on XMLHttpRequest or JSON requests
  4. $request->getPathInfo()

On chatbot and other API-proxy routes, getPathInfo() is the proxy endpoint (/api/deepchat), not the page the visitor is viewing (/node/1). Callers should supply the viewed page path, either on the request or as entity_context.path metadata on the generic chat path. When they do not, the Referer of an asynchronous browser call is used, because it names the page the visitor is working on. A normal page load never uses the Referer, because there it names the previous page. The fallback also depends on the browser sending a same-origin Referer; a no-referrer policy leaves only the endpoint path, so an explicit path hint is preferred. A supplied path is an untrusted context hint used for string matching only. Absolute URLs are reduced to their path, with the site base path removed.

On the push-injection path, AiContextBuildSystemPromptSubscriber passes BuildSystemPromptEvent payload values to AiContextRequestInfoResolver::applyRequestInfo(). A path-like path or route value is stored on the request before selection.

Until the assistant integration supplies that path -- see #3586681 -- Site Sections still cannot see /node/1 on DeepChat traffic by itself. Pairing Specific Entities with Site Sections does not restore page awareness unless both the entity and the path are supplied.

What to configure

  1. Publish the context item. Enable Dynamic Entity Reference if you use Specific Entities.
  2. Set Specific Entities (or Entity Types / Taxonomy Terms / Site Sections) on the item. Leave Global off unless the item should apply everywhere.
  3. Confirm the agent will actually receive a request entity or page path through one of the sources above.
  4. Do not override (use subscriptions) is the default inclusion setting. It does not make Specific Entities exclusive; the scope itself is the filter.
  5. On the matching entity, the item is an exact-match. Other published items can still appear (Global, Always include, subscriptions, Relevant or Broad fill).
  6. On any other page, with no fabricated entity_id, the targeted item must be absent.

Enable debug logging in General settings and check Reports → Recent log messages (type ai_context) to see whether selection received an entity and which items were chosen.

See also