[Feature] Add ExternalContextProviderInterface and ContextQueryInterface to support RAG/vector store integrations
<!--Please search existing work items before filing to avoid duplicates.-->
<!--Also check open feature request work items to avoid duplicating existing proposals.-->
## Summary
Follow-up to:
#3586257+s
<!--Briefly describe the feature or improvement you are proposing.-->
## Problem
We built an external RAG integration on top of CCC (AI Knowledge Connector — a vector store + semantic retrieval module for Drupal 11) and hit three specific API gaps that currently require workarounds. We're raising these before rc1 so the team can evaluate whether a formal API would be worth adding to make the integration pattern stable and documented for the ecosystem.
The current workaround path works (we're using `BuildSystemPromptEvent`) but it's fragile across agent types, bypasses CCC's token limit logic, and gives no observability into what external context was actually injected.
## Proposed solution _(optional)_
**1. ExternalContextProviderInterface**
A first-class plugin interface that CCC discovers and calls during context assembly, alongside native context items:
php
`interface ExternalContextProviderInterface {
public function getContext(ContextQueryInterface $query): string;
public function getPluginId(): string;
public function getLabel(): string;
}`
This would allow external modules to register RAG sources, vector stores, or any dynamic context provider without hooking into events that weren't designed for this. It would also let CCC apply its own token limit logic to external context the same way it does to native items.
**2. ContextQueryInterface — structured query object at injection time**
Right now external integrations have to extract the user's query from the event payload defensively, which breaks across different agent types. A structured object passed to external providers at injection time would fix this:
php
`interface ContextQueryInterface {
public function getUserInput(): string;
public function getAgentId(): string;
public function getTargetEntity(): ?EntityInterface;
public function getTokenBudget(): ?int;
}`
For RAG specifically, `getUserInput()` is the key — the vector store needs the actual user query to do semantic retrieval. Without it we're guessing.
**3. ContextAssembledEvent — post-assembly event for observability**
A lightweight event fired after CCC finalizes context for an agent call, carrying what was included, from which sources, and the token counts:
php
`class ContextAssembledEvent extends Event {
public function getAgentId(): string;
public function getItems(): array; // native CCC items included
public function getExternalSources(): array; // external providers called
public function getTotalTokens(): int;
public function getTokenBudget(): int;
}`
Currently the only way to log external context usage is via `kernel.response`, which is too late and too indirect for proper traceability.
---
**Additional context**
We're happy to contribute a proof-of-concept implementation for any of these if it would help move things forward. The integration module we built (ai_knowledge_connector_ccc) can serve as a real-world test case — it's already working via the event-based workaround, so we can validate any new API against it immediately.
None of these are blocking our current implementation. We're raising them because the foundation in Beta 2 is excellent and a small API surface addition before rc1 would make the integration pattern stable and reproducible for anyone else building RAG or external context sources on top of CCC.
Related module: https://www.drupal.org/project/ai_knowledge_connector _(once published)_
---
**Proposed change record**
New plugin interface `ExternalContextProviderInterface`, new value object `ContextQueryInterface`, new event `ContextAssembledEvent`. No breaking changes to existing API.
## Workaround _(optional)_
<!--Describe any workaround you are currently using, or state that none exists. This helps maintainers assess priority.-->
## Affected functional areas _(optional)_
<!--List the areas or sub-modules of the AI Context module this request relates to.
Examples: context items, scope plugins, context selection, subcontext, admin UI-->
<!--If this issue description was significantly AI-generated (entire sections, not autocomplete), please note it in a comment below. See https://www.drupal.org/docs/develop/issues/issue-procedures-and-etiquette/policy-on-the-use-of-ai-when-contributing-to-drupal-->
> [!note]
>
> Check the one that best describes your usage, or leave all unchecked if AI was not significantly used.
>
> * [ ] AI **Assisted Issue** \
> _Mainly written by a human; AI used for partial generation under full human supervision._
> * [ ] AI **Generated Issue** \
> _Mainly generated by AI, reviewed and approved by a human before this issue was created._
issue