Active Knowledge Base

The Active Knowledge Base (AKB) is a dynamic, per-agent vector database that stores structured knowledge as topics -- documents, conversation history, work instructions, and business context -- enabling agents to learn, remember, and retrieve information at runtime through fuzzy and semantic search.

Overview

Every agent on the Newo platform has access to one or more AKB collections, each scoped to a persona. The AKB serves as the agent's long-term memory: skills write topics into it during setup or conversation, and the RAG pipeline queries it to inject relevant knowledge into LLM prompts.

Unlike static configuration stored in attributes, the AKB holds rich, searchable content -- product catalogs, FAQ articles, operational procedures, menu items -- organized as topics with summaries, facts, confidence scores, labels, and source identifiers. Topics are created manually through the dashboard, programmatically through NSL actions, or by importing files.

The topic data model

Every entry in the AKB is a topic. Each topic has the following fields:

Each field serves a specific role in storage and retrieval:

FieldPurpose
topic_nameSearchable title; used for fuzzy matching by name
topic_summaryLong-form content displayed when a topic is retrieved
topic_factsDiscrete fact strings used for both fuzzy and semantic search
confidenceNumeric score (1--100) indicating reliability of the information
sourceProvenance identifier; enables lookup by origin (e.g., menu01, rag_article_003)
labelsCategorization tags for filtering search results (e.g., rag_context, rag_context_menu)
persona_idScopes the topic to a specific persona's AKB collection

::: 🗒️ NOTE When topics are returned by NSL search actions, field names use camelCase (topicId, updatedAt, createdAt) rather than the snake_case used in the API. Keep this in mind when accessing search results in skill scripts. :::

Persona-specific AKB collections

AKB topics are scoped to a persona -- the identity associated with an agent or user. Each persona has its own isolated collection of topics. This design enables several patterns:

  • Agent-level knowledge -- The GeneralManagerAgent stores RAG content, menu data, and business context in its persona's AKB. The ConvoAgent queries this knowledge during conversations.
  • User-level memory -- Topics can be stored under a user's persona ID, enabling per-user knowledge that persists across sessions.
  • Cross-agent transfer -- The CopyAndBuildAkb action copies topics from one persona to another, enabling knowledge sharing between agents.

In the Newo dashboard, the AKB page includes a persona selector that filters the topic list by persona. Select an agent's persona to view and manage that agent's knowledge base.

::: ❗❗ IMPORTANT Deleting a persona's AKB removes all topics for that persona. This operation is irreversible. The dashboard prompts for confirmation before proceeding. :::

Search modes

The AKB supports two distinct search strategies, each suited to different retrieval needs.

Fuzzy search

Fuzzy search (SearchFuzzyAkb) performs text-based matching against specified fields. It finds topics where the query string approximately matches field values, with results ranked by similarity score.

Fuzzy search is best for:

  • Exact or near-exact name lookups (finding a topic by its title)
  • Retrieving topics by source identifier
  • Listing all topics matching a label (using an empty query with scoreThreshold=0)
  • Situations where the query closely resembles the stored text
{# Find a topic by exact name match #}
{% set topic = SearchFuzzyAkb(
    query="golden retriever",
    searchFields=["name"],
    numberTopics=1,
    scoreThreshold=1.0,
    filterByPersonaIds=[agent_persona_id]
) %}

{# List all topics with a specific label #}
{% set all_rag_topics = SearchFuzzyAkb(
    query="",
    searchFields=["name"],
    numberTopics=300,
    scoreThreshold=0,
    filterByPersonaIds=[persona_id],
    labels=["rag_context"]
) %}

Semantic search

Semantic search (SearchSemanticAkb) uses vector embeddings to find topics based on meaning rather than exact text. It converts the query (or extracted conversation context) into an embedding and compares it against stored topic embeddings.

Semantic search is best for:

  • Finding relevant topics when the user's language differs from stored content
  • Matching conversational queries to knowledge base articles
  • Retrieving contextually relevant information for LLM prompts
{# Semantic search with a direct query #}
{% set results = SearchSemanticAkb(
    query="What are your business hours?",
    fields=["summary", "facts"],
    numberTopics=3,
    labels=["rag_context"],
    scoreThreshold=0.3
) %}

{# Semantic search using conversation context #}
{% set results = SearchSemanticAkb(
    context=GetMemory(count=10, maxLen=5000),
    fields=["summary"],
    numberTopics=1,
    labels=["rag_context"]
) %}

::: 🗒️ NOTE The scoreThreshold parameter works differently for each search mode. For semantic search, smaller values yield more precise results (default is 0.3, range 0--1). For fuzzy search, a threshold of 1.0 requires an exact match, while 0 returns all topics. :::

AKB actions reference

The platform provides seven NSL actions for working with the AKB. These are available in any skill script.

ActionDescription
SetAkbCreate a topic automatically from context text using an LLM to extract facts and summary
SetManualAkbCreate a topic with explicitly defined fields (name, summary, facts, labels, etc.)
UpdateAkbUpdate an existing topic by its ID
DeleteAkbDelete one or more topics by ID
SearchFuzzyAkbPerform text-based fuzzy search across specified topic fields
SearchSemanticAkbPerform meaning-based semantic search using vector embeddings
CopyAndBuildAkbCopy all topics from one persona's AKB to another persona's AKB

SetAkb -- automatic topic creation

SetAkb accepts raw context text and uses an LLM to extract facts and generate a summary, creating a fully structured topic automatically.

{{SetAkb(
    context="In mathematics, the Pythagorean theorem is a fundamental relation
             in Euclidean geometry between the three sides of a right triangle.",
    labels=["math", "geometry"],
    personaId=GetAgent(field="id")
)}}

Parameters:

  • context (required) -- The information to convert into an AKB topic
  • labels -- Labels to attach to the created topic
  • personaId -- Persona ID to scope the topic to

SetManualAkb -- explicit topic creation

SetManualAkb creates a topic with all fields defined explicitly, giving full control over the topic structure.

{{SetManualAkb(
    personaId=GetAgent(field="id"),
    summary="Golden Retrievers are one of the most popular dog breeds worldwide.",
    facts=["Origin: Scotland, mid-19th century", "Temperament: Friendly, gentle, patient"],
    name="Golden Retriever",
    confidence=100,
    source="dog_breeds_01",
    labels=["rag_context", "knowledge_base"]
)}}

Parameters:

  • personaId (required) -- UUID of the persona that owns this topic
  • summary (required) -- Topic content or description
  • facts (required) -- Array of fact strings for search indexing
  • name -- Human-readable topic title
  • confidence -- Confidence score (1--100)
  • source -- Source identifier for provenance tracking
  • labels -- Array of labels for filtering

SearchFuzzyAkb

SearchFuzzyAkb(
    query: str,
    searchFields: List[str] | None = None,
    fromPerson: Literal["Agent", "User", "Both"] = "Both",
    numberTopics: int = 1,
    fields: List[str] | None = None,
    labels: List[str] | None = None,
    scoreThreshold: float = 0,
    filterByPersonaIds: List[str] | None = None
)

Key parameters:

  • searchFields -- Which topic fields to search: "name", "summary", "facts", "source"
  • fields -- Which topic fields to return: "id", "personId", "topicId", "topic", "summary", "facts", "confidence", "source", "createdAt", "updatedAt", "labels"
  • filterByPersonaIds -- Restrict results to specific persona collections

SearchSemanticAkb

SearchSemanticAkb(
    context: str | None = None,
    query: str | None = None,
    fromPerson: Literal["Agent", "User", "Both"] = "Both",
    fields: List[str] | None = None,
    labels: List[str] | None = None,
    numberTopics: int | None = None,
    priority: Literal["searchFirst", "filterFirst"] = "filterFirst",
    scoreThreshold: float = 0.3,
    filterByPersonaIds: List[str] | None = None
)

Key parameters:

  • context -- Conversation excerpt from which facts are extracted for search
  • query -- Direct search query (can be combined with context)
  • priority -- "filterFirst" filters by labels then searches; "searchFirst" searches then filters

DeleteAkb

{# Delete a single topic #}
{{DeleteAkb(ids=topic_id)}}

{# Delete multiple topics #}
{{DeleteAkb(ids=[topic_id_1, topic_id_2, topic_id_3])}}

UpdateAkb

{{UpdateAkb(id=topic_id, summary="Updated summary text", labels=["new_label"])}}

CopyAndBuildAkb

{% set source = GetAgent(idn="GeneralManagerAgent", field="personaId") %}
{% set target = GetAgent(idn="ConvoAgent", field="personaId") %}
{{CopyAndBuildAkb(sourcePersonaId=source, targetPersonaId=target)}}

See AKB actions for complete parameter documentation and additional examples of each action.

Import and export

The AKB supports multiple import and export methods, accessible through both the dashboard and the API.

Dashboard operations

  • Export AKB -- Downloads the selected persona's entire AKB as a JSON file (akb-<persona_name>-<date>.json). The exported file contains an array of topic objects.
  • Import AKB -- Uploads a previously exported JSON file to restore or transfer topics to a persona. Labels can be added during import to tag all imported topics.
  • Import Facts -- Uploads a text file (such as a document or transcript) that the platform processes asynchronously into AKB topics. This operation creates a background task that progresses through the statuses: created, pending, processing, and completed (or error/failed/expired).

API endpoints

EndpointMethodDescription
v1/akb/topicsGETList topics with filtering, fuzzy search, and pagination
v1/akb/append-manualPOSTCreate a single topic
v1/akb/topics/{topicId}PUTUpdate a topic by ID
v1/akb/topics/{topicId}DELETEDelete a single topic
v1/akb/topics/batch-deletePOSTDelete multiple topics by ID
v1/akb/exportGETExport all topics for a persona
v1/akb/importPOSTImport topics from JSON
v1/akb/import/filePOSTImport topics from a text file (multipart)
v1/akb/personas/{personaId}DELETEDelete all topics for a persona
v1/akb/tasksGETList background import tasks

::: ⚠️ CAUTION Importing topics does not deduplicate against existing topics. If the same JSON file is imported twice, duplicate topics will be created. Delete the persona's AKB first if a clean import is needed. :::

Manual vs automatic population

AKB topics can be populated through two approaches, each suited to different use cases.

Manual population

Manual population gives direct control over topic content:

  • Dashboard -- Navigate to the AKB page, select a persona, and create topics through the topic form. Each topic's name, summary, facts, confidence, source, and labels can be set individually.
  • NSL with SetManualAkb -- Skills create topics with explicit field values. This is the standard approach for programmatic content ingestion such as menu parsing, document chunking, and configuration storage.
  • File import -- Upload JSON or text files through the dashboard or API.

Automatic population

Automatic population uses LLM processing to generate structured topics:

  • NSL with SetAkb -- Pass raw text as context and the platform uses an LLM to extract facts and generate a summary automatically. This is useful when ingesting unstructured content such as conversation messages or raw documents.
  • RAG append pipeline -- The platform's built-in RAG append flow (rag_append_create_akb_topics) takes structured markdown content, parses it into topic blocks, and creates labeled AKB topics using SetManualAkb. Each topic receives labels including the business industry, scenario, and rag_context for later retrieval.

AKB in the RAG pipeline

The AKB is the foundation of the platform's retrieval-augmented generation (RAG) system. During conversations, the RAG pipeline queries the AKB to find relevant knowledge and injects it into the LLM prompt context.

How the RAG flow works

The RAG pipeline operates in two stages:

  1. Topic index retrieval -- The system retrieves all AKB topics labeled rag_context from the GeneralManagerAgent's persona using a broad fuzzy search. This builds an index of available knowledge articles with their titles, facts, and source identifiers.
{% set rag_context_topics = SearchFuzzyAkb(
    query="",
    searchFields=["name"],
    numberTopics=300,
    scoreThreshold=0,
    filterByPersonaIds=[general_manager_agent_persona],
    labels=["rag_context"]
) %}
  1. LLM-powered article selection -- The topic index and conversation history are passed to an LLM search assistant that selects the 1--3 most relevant articles. The selected article IDs are then used to fetch full topic content via a second fuzzy search by source.
{# Fetch full content for each selected article #}
{% set rag_topics = rag_topics + SearchFuzzyAkb(
    query=article_id,
    searchFields=["source"],
    numberTopics=1,
    scoreThreshold=1.0,
    filterByPersonaIds=[general_manager_agent_persona],
    labels=["rag_context"]
) %}
  1. Context injection -- The retrieved topic names and summaries are concatenated and written to the user's rag persona attribute, where the ConvoAgent's main skill reads them as part of the LLM prompt context.
{% set rag = topic.topic + "\n" + topic.summary %}
{{SetPersonaAttribute(field="rag", value=rag, id=user_id)}}

RAG content labeling

The platform uses a labeling convention to organize RAG-eligible content:

LabelPurpose
rag_contextGeneral RAG content eligible for retrieval
rag_context_menuMenu-specific RAG content
attribute_templateAttribute templates stored as AKB topics

Topics without the rag_context label are not included in the standard RAG retrieval flow but remain available for direct search through NSL actions.

::: 🗒️ NOTE The RAG pipeline queries the GeneralManagerAgent's persona AKB by default. Business knowledge, FAQ content, and product information should be stored under the GeneralManagerAgent's persona for the RAG system to find them during conversations. :::

Common patterns

Store and retrieve knowledge by label

{# Store a topic with categorization labels #}
{{SetManualAkb(
    personaId=agent_persona_id,
    summary="We offer free delivery on orders over $50 within a 10-mile radius.",
    facts=["Free delivery over $50", "10-mile delivery radius"],
    name="Delivery Policy",
    confidence=100,
    source="policy_001",
    labels=["rag_context", "delivery", "policy"]
)}}

{# Later, retrieve all policy topics #}
{% set policies = SearchFuzzyAkb(
    query="",
    searchFields=["name"],
    numberTopics=100,
    scoreThreshold=0,
    filterByPersonaIds=[agent_persona_id],
    labels=["policy"]
) %}

Find and update an existing topic

{# Search for the topic by name #}
{% set results = SearchFuzzyAkb(
    query="Delivery Policy",
    searchFields=["name"],
    numberTopics=1,
    fields=["id"],
    scoreThreshold=1.0,
    filterByPersonaIds=[agent_persona_id]
) %}

{# Update if found #}
{% if results %}
    {{UpdateAkb(id=results[0].topicId, summary="Updated: Free delivery on all orders.")}}
{% endif %}

Bulk delete topics by label

{% set topics_to_delete = SearchFuzzyAkb(
    query="",
    searchFields=["name"],
    numberTopics=99999,
    labels=["outdated_content"],
    filterByPersonaIds=[persona_id],
    scoreThreshold=0.0
) %}
{% set topic_ids = [] %}
{% for topic in topics_to_delete %}
    {% set _ = topic_ids.append(topic.topicId) %}
{% endfor %}
{{DeleteAkb(ids=topic_ids)}}

See Attributes system for details on the persona attributes that the RAG pipeline writes to. See Skills for information about writing NSL skill scripts that interact with the AKB.