Skip to main content

Architecture overview

🚧Documentation Under Construction

We are actively working to improve this documentation. The content you see here may be incomplete, subject to change, or may not fully reflect the current state of the feature. We appreciate your understanding as we continue to enhance our docs.

The AI plugin provides the fundamental building blocks for AI-powered features, including:

  • Site-specific plugin configuration
  • Text chunking for handling large content
  • Text embedding generation for semantic search
  • Chat conversations with AI assistants
  • Tool calling for agentic workflows

Ingestion​

Content is chunked and embedded on save via AiRecordData:

Chat completion​

ChatClient completes a single turn, mapping to the provider's API:

Agent orchestration​

Agent loops over ChatClient, executing tool calls until the model produces a final response:

Plugin configuration​

AiPlugin​

The main plugin entry point that provides global AI configuration.

  • Configures the TextEmbeddingGenerator and TextChunker used for embedding generation
  • Defines additional content types for AI indexing
  • Provides system instructions for Create with AI and Ask AI features
  • Handles legacy configuration migration

AiPluginConfig​

Site-specific configuration for the AI plugin.

  • Configures the ChatClient for AI conversations
  • Configures a list of AiFeature instances, each with its own agent and instructions
  • Enables/disables Create with AI and Ask AI features
  • Defines brand guidelines, prompt suggestions, and author personas
  • Configures generation timeout and AI-generated content detectors
  • Sets Ask AI search parameters (max records, min similarity score, max tokens)

Features​

AiFeature​

Abstract base class for AI features. Each feature holds an optional Agent and defines a createDefaultAgent() fallback. Configured per-site via AiPluginConfig's feature list.

1
var askAi = AiFeature.get(AskAiFeature.class);
2
var agent = askAi.getAgent();
3
var instructions = askAi.getInstructions();

AiFeature.get(Class) resolves the configured instance for the current site context, or creates a default instance if not configured.

AskAiFeature​

The Ask AI feature. Provides default system instructions for agentic tool-calling behavior (readOnly tools act silently, destructive tools require confirmation, etc.) and defaults to a ToolCallingAgent.

Instructions fall back through: feature instance → AiPlugin global setting → built-in default.

CreateWithAiFeature​

The Create with AI feature. Provides default system instructions for content generation and defaults to a ToolCallingAgent with readOnly enabled.

Instructions fall back through: feature instance → AiPlugin global setting → built-in default.

Text chunking​

TextChunker​

An abstract base class for splitting text into smaller chunks suitable for embedding generation. Part of the RAG pipeline for improved precision in semantic search. Typical use might look like:

1
List<String> chunks = TextChunker.get().chunk(
2
"This is a very long piece of text that needs to be split...",
3
countTokens,
4
10);

If not configured, defaults to RecursiveJsonTextChunker.

FixedLengthTextChunker​

Splits text into fixed-length chunks with configurable overlap (default 10%).

RecursiveTextChunker​

Splits text using a recursive document splitter (via LangChain4j) with configurable overlap (default 10%).

JsonTextChunker​

An abstract base class for chunkers that work on JSON data directly.

RecursiveJsonTextChunker​

Recursively splits large JSON data while preserving context. Uses a two-stage approach: small fields serve as context, large fields are individually split and combined with context to create chunks. Configurable context ratio (default 40%) and string chunker (default RecursiveTextChunker).

Embedding generation​

EmbeddingGeneratable​

An interface that marks content types for automatic embedding generation. For example:

1
public class Article extends Content implements EmbeddingGeneratable {
2
private String title;
3
private String body;
4
}

The default shouldGenerateEmbedding() method returns true when the record is visible, but can be overridden for custom logic.

@ExcludeFromEmbedding​

A field-level annotation that excludes specific fields from embedding generation. For example, this is how to exclude sensitive data from an embedding:

1
public class Article extends Content implements EmbeddingGeneratable {
2
private String title;
3
4
@ExcludeFromEmbedding
5
private String internalId;
6
}

Common use cases are:

  • Personally identifiable information (PII)
  • Internal system identifiers
  • Administrative metadata (creation dates, flags)
  • Large binary data or encoded content

TextEmbeddingGenerator​

An abstract base class for generating text embeddings (vector representations of text). Typical use might look like:

1
TextEmbeddingGenerator generator = TextEmbeddingGenerator.get();
2
int tokens = generator.countTokens("This is some text");
3
float[] embedding = generator.generate("This is some text");

Implementations must provide getModel(), getMaxTokens(), getDimension(), and generate(List<String>).

AiRecordData​

A modification class that adds AI-specific data and behaviors to all Brightspot records.

  • Automatically generates embeddings when records are saved
  • Deletes embeddings when records are deleted
  • Extracts embedding-ready content by filtering excluded fields
  • Extracts filterable metadata for vector records

Whenever a record is saved, it follows these steps to generate an embedding:

  1. Checks if the record type should generate embeddings
  2. Chunks the content using TextChunker
  3. Generates embeddings for each chunk using TextEmbeddingGenerator
  4. Saves embeddings to the vector database

AiFieldData​

A modification class for field-level AI configuration. Tracks whether a field should be excluded from embedding generation.

Chat​

ChatClient​

An abstract base class for clients that complete a single turn of conversation with an AI model. Each provider (OpenAI, Bedrock) implements this to handle model-specific API calls. Providers always stream responses internally.

1
ChatClient client = ChatClient.get();
2
3
// Blocking
4
AssistantMessage response = client.complete(request, listener);
5
6
// Async (cancelable)
7
CompletableFuture<AssistantMessage> future = client.completeAsync(request, listener);

The listener parameter is an optional AssistantMessageListener that receives streaming events as the response is built. Provider errors are translated to TransientAiException (retryable) or NonTransientAiException (permanent).

Agent​

An abstract base class for multi-turn orchestration. The default ToolCallingAgent implements a tool-calling loop: it calls ChatClient#completeAsync, checks if the model requested tool calls, executes them, feeds results back, and repeats until the model produces a final text response. If the maximum iteration limit is reached, the future completes exceptionally with ToolIterationLimitException.

1
var feature = AiFeature.get(AskAiFeature.class);
2
3
// Blocking
4
List<Message> messages = feature.getAgent().run(request, listener);
5
6
// Async (cancelable)
7
CompletableFuture<List<Message>> future = feature.getAgent().runAsync(request, listener);

The listener parameter is an optional AgentListener that extends AssistantMessageListener with tool execution events. The agent passes it through to ChatClient#completeAsync for text and tool call streaming, and calls AgentListener#onToolResultMessage after each tool execution.

Agents are configured per-feature via AiFeature. Each feature defines its own default agent (e.g., AskAiFeature defaults to ToolCallingAgent, CreateWithAiFeature defaults to a read-only ToolCallingAgent).

ChatRequest​

An immutable request containing instructions, messages, tools, and optional generation parameters. Built with a fluent builder:

1
var feature = AiFeature.get(AskAiFeature.class);
2
3
ChatRequest request = ChatRequest.builder()
4
.instructions(feature.getInstructions())
5
.addToolGroups(ToolGroup.getAll())
6
.addMessages(history)
7
.addMessage(userMessage)
8
.temperature(0.7)
9
.maxOutputTokens(4096)
10
.build();
11
12
var messages = feature.getAgent().run(request, listener);

AssistantMessageListener​

Listener for streaming events on an AssistantMessage as it is built by a ChatClient. Provides callbacks for text deltas and fully assembled tool calls:

  • onTextDelta(String delta) -- called when a text fragment is received from the model
  • onToolCall(ToolCall toolCall) -- called when a fully assembled tool call is received

AgentListener​

Extends AssistantMessageListener with tool execution events:

  • onToolResultMessage(ToolResultMessage result) -- called after a tool has been executed

Message​

A sealed base class for chat messages. Each message carries raw text and an optional templated variant that may include additional context for AI processing. The permitted subclasses are:

  • UserMessage -- a user-generated prompt
  • AssistantMessage -- an AI-generated response, with metadata for timing, token usage, completion status, and tool calls
  • ToolResultMessage -- the result of executing a tool, correlated to a ToolCall by ID

ToolCall​

An embedded record on AssistantMessage representing a tool call requested by the model. Each tool call has a provider-assigned correlation ID (toolCallId), the tool name, and raw JSON arguments.

ToolCall.Builder accumulates streaming tool call fragments (ID, name, argument chunks) and assembles them into a complete ToolCall. Used by ChatClient implementations to handle streaming responses.

Tool system​

ToolGroup​

An abstract base class for grouping related tool methods. Concrete subclasses are discovered automatically via ClassFinder and their @ToolMethod-annotated methods are registered as tools for use in agentic workflows and MCP.

ToolGroup.getAll() returns all tool groups discovered on the classpath, cached for performance. Each group exposes its tools via getTools() (lazily resolved from @ToolMethod annotations) and optional getInstructions().

Tool​

Schema definition for a tool that can be offered to an LLM. A concrete class with a builder, holding the tool's name, description, input schema, and behavioral annotations (readOnly, destructive, idempotent).

RunnableTool​

A Tool that can be executed. Extends Tool with run(), title, and outputSchema. Produced by ToolGroup from @ToolMethod-annotated methods.

@ToolMethod​

A method-level annotation that marks a method as an AI tool. Attributes include:

  • name -- tool name (defaults to method name, prefixed with group name)
  • title -- human-readable title
  • description -- description for AI tool selection
  • readOnly, destructive, idempotent -- behavioral hints

@ToolParam​

A parameter-level annotation for @ToolMethod method parameters. Provides metadata for schema generation including name, description, default value, and required status. Supports custom SchemaSupplier implementations for non-standard JSON schemas.

Was this page helpful?

This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.