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:
| Field | Purpose |
|---|---|
topic_name | Searchable title; used for fuzzy matching by name |
topic_summary | Long-form content displayed when a topic is retrieved |
topic_facts | Discrete fact strings used for both fuzzy and semantic search |
confidence | Numeric score (1--100) indicating reliability of the information |
source | Provenance identifier; enables lookup by origin (e.g., menu01, rag_article_003) |
labels | Categorization tags for filtering search results (e.g., rag_context, rag_context_menu) |
persona_id | Scopes 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
CopyAndBuildAkbaction 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.
| Action | Description |
|---|---|
SetAkb | Create a topic automatically from context text using an LLM to extract facts and summary |
SetManualAkb | Create a topic with explicitly defined fields (name, summary, facts, labels, etc.) |
UpdateAkb | Update an existing topic by its ID |
DeleteAkb | Delete one or more topics by ID |
SearchFuzzyAkb | Perform text-based fuzzy search across specified topic fields |
SearchSemanticAkb | Perform meaning-based semantic search using vector embeddings |
CopyAndBuildAkb | Copy 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 topiclabels-- Labels to attach to the created topicpersonaId-- 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 topicsummary(required) -- Topic content or descriptionfacts(required) -- Array of fact strings for search indexingname-- Human-readable topic titleconfidence-- Confidence score (1--100)source-- Source identifier for provenance trackinglabels-- 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 searchquery-- Direct search query (can be combined withcontext)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, andcompleted(orerror/failed/expired).
API endpoints
| Endpoint | Method | Description |
|---|---|---|
v1/akb/topics | GET | List topics with filtering, fuzzy search, and pagination |
v1/akb/append-manual | POST | Create a single topic |
v1/akb/topics/{topicId} | PUT | Update a topic by ID |
v1/akb/topics/{topicId} | DELETE | Delete a single topic |
v1/akb/topics/batch-delete | POST | Delete multiple topics by ID |
v1/akb/export | GET | Export all topics for a persona |
v1/akb/import | POST | Import topics from JSON |
v1/akb/import/file | POST | Import topics from a text file (multipart) |
v1/akb/personas/{personaId} | DELETE | Delete all topics for a persona |
v1/akb/tasks | GET | List 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
contextand 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 usingSetManualAkb. Each topic receives labels including the business industry, scenario, andrag_contextfor 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:
- Topic index retrieval -- The system retrieves all AKB topics labeled
rag_contextfrom 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"]
) %}- 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"]
) %}- Context injection -- The retrieved topic names and summaries are concatenated and written to the user's
ragpersona 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:
| Label | Purpose |
|---|---|
rag_context | General RAG content eligible for retrieval |
rag_context_menu | Menu-specific RAG content |
attribute_template | Attribute 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.
Updated about 6 hours ago
