Knowledge Preparation — Administration
Knowledge asset generation runs on its own — but it is the administrator who defines the tone, who may approve, how much AI capacity a batch consumes and the moment approved content starts counting for chat users. This guide gathers everything you control: permissions, per-context prompts, generation limits, priority relative to interactive chat, the consumption on/off switch, installation resources and what to do when something gets stuck.
Architecture: Architecture — Knowledge Preparation. External export API: Knowledge Export API. User guide: Knowledge Asset Generation — User Guide.
1. Permissions
The feature's permissions live in the platform's central permission catalog, under the KNOWLEDGE category, and come mapped like this in the default roles:
| Permission | Sensitive | ADMIN | ADVANCED_USER (steward) | ANALISTA | READ_ONLY |
|---|---|---|---|---|---|
KNOWLEDGE_ASSET_VIEW | no | ✅ | ✅ | ✅ | — |
KNOWLEDGE_ASSET_GENERATE | no | ✅ | ✅ | — | — |
KNOWLEDGE_ASSET_APPROVE | yes | ✅ | ✅ | — | — |
KNOWLEDGE_ASSET_DELETE | yes | ✅ | — | — | — |
KNOWLEDGE_EXPORT | no | ✅ | — | — | — |
The rule is enforced on the server, in two layers: the filter chain requires the matching authority before the request reaches the code, and a second permission check runs inside the service itself. The interface merely mirrors what the server already decides.
The platform's internal integrations — such as the cascade triggered when a document is superseded by a newer version — authenticate with the internal service token and receive a safe subset: view, generate and approve, never delete or export.
2. Knowledge prompts per context
Every context has four prompts of its own that govern generation:
| Prompt | What it controls |
|---|---|
Optimized document (KNOWLEDGE_DOC) | The rewrite into standardized sections and plain language |
FAQ (KNOWLEDGE_FAQ) | The question-and-answer pairs |
Glossary (KNOWLEDGE_GLOSSARY) | The extraction of terms, acronyms and definitions |
Tone of voice (KNOWLEDGE_TONE) | The persona and tone applied to every type |
- Automatic seeding: when a context is created, the four prompts are born with the default text. Seeding is idempotent and never overwrites an existing customization.
- Where they live: in the
datta_promptsindex, cached underdatta:prompts:{dominio}:{tipo}with a 30-minute TTL. - Customization: prompts are read with
PROMPT_VIEWand edited withPROMPT_EDITthrough the context's prompt interface, always with the option to restore the default. The three matching endpoints (read, customize, restore) are in the API reference. - Defaults: they come from the default texts embedded in the platform. There are no per-domain knowledge prompt files in the repository — every context uses the generic default until you customize it through the screen.
Care when customizing: the prompts require the model to return JSON with the source excerpt citations per item (
chunkIdsOrigem) — that is what makes source validation possible. Removing that requirement makes validation discard all the content, and the type fails with "nenhum item com citações válidas" ("no item with valid citations").
3. Generation capacity and limits
The defaults balance speed and AI consumption. All of them are adjustable at installation, under the datta.knowledge.* prefix:
| Parameter | Environment variable | Default | Effect |
|---|---|---|---|
| Documents in parallel per batch | KNOWLEDGE_MAX_CONCURRENT_GENERATIONS | 3 | More parallelism = faster batch, more pressure on the AI quota |
| Documents per batch | KNOWLEDGE_MAX_DOCS_POR_LOTE | 50 | Larger batches are refused with a message asking you to split them |
| Timeout per AI call | KNOWLEDGE_LLM_TIMEOUT_SECONDS | 300 | The internal reactive timeout is the value minus 10 seconds |
| Attempts per item | — (generation.max-tentativas-llm) | 3 | Automatic retry on a transient provider failure |
| Sections of the optimized document | — (generation.template-secoes) | Resumo, A quem se aplica, Principais regras, Prazos e condições, Como proceder, Referências normativas | The default section template, customizable through the prompt |
And on the export-to-external-systems side:
| Parameter | Environment variable | Default |
|---|---|---|
| Call limit per minute | KNOWLEDGE_EXPORT_RATE_LIMIT | 60 |
| Items per page | KNOWLEDGE_EXPORT_PAGE_SIZE | 500 |
| Service account status cache | — (export.status-cache-seconds) | 60 (this is the propagation ceiling of a revocation) |
| Manifest cache | — (export.manifest-cache-seconds) | 60 |
| Collections assembled in parallel | — (export.bundle-concurrency) | 4 |
Priority: interactive chat never waits
Batch generations run on a low-priority lane for AI access, separate from chat: a call only enters that lane when it is marked as batch — without the marking it is treated as interactive and goes straight through, no queue.
| Batch lane parameter | Environment variable | Default |
|---|---|---|
| Simultaneous calls per instance | LLM_LANE_BATCH_MAX_CONCURRENT | 2 |
| Queue size | LLM_LANE_BATCH_QUEUE_SIZE | 100 |
| Maximum wait in the queue | LLM_LANE_BATCH_QUEUE_TIMEOUT | 30s |
| Attempts on a provider refusal | LLM_LANE_BATCH_RETRY_MAX_ATTEMPTS | 3 (batch lane only) |
| Wait between attempts | — | 2s to 10s, with 0.5 random jitter |
When the lane saturates — full queue or a wait above the limit — the call receives HTTP 429 with Retry-After and a body stating the reason (queue_full or wait_timeout) and how many seconds to wait. Tracking lives in the llm_lane_wait_ms{lane=batch}, llm_lane_inflight{lane} and llm_lane_rejected_total{lane,reason} metrics.
Sizing in practice: with 2 simultaneous calls in the lane, 3 documents in parallel and up to 3 types per document, knowledge preparation queues at most ~9 calls — the 100-slot queue absorbs that comfortably. The bottleneck is intentional: it sits in the concurrency semaphore, and it exists precisely so that a chat user never waits behind a batch.
4. Consumption by chat (per-context on/off)
Approving an asset makes it eligible for chat search, but chat only starts querying it when the context has knowledge asset consumption turned on in its domain configuration (useKnowledgeAssets, off by default; the endpoint that updates the context is in the API reference).
- Publication to the retrieval index happens on every approval, item by item, with a deterministic identifier per asset and order; deprecating an asset removes all of its items.
- With the option off, the index list the search consults is byte-identical to the behavior before the feature — nothing changes for users.
- With the option on, approved assets join that context's retrieval; the change propagates within 5 minutes (the
datta:chat:knowledge-optin:{dominio}cache). - Wildcard searches across several contexts always exclude the knowledge indices — a context never inherits another context's knowledge without opting into it.
Master switch: publication is on by default (datta.knowledge.retrieval.enabled=true); set to false, it is suspended without blocking approvals (they simply log the intent). Publication is best-effort: an embedding or indexing failure does not undo the approval. Watch knowledge_retrieval_publish_total{outcome=error} and re-approve or republish once the vector generator is back — republishing overwrites, it does not duplicate.
5. Where the knowledge is stored
| Index | Role | How it is created |
|---|---|---|
datta-knowledge-assets | Master record of every asset, in any status | Automatically at service startup, with an explicit mapping (key fields declared before the first indexing) |
datta_{dominio} | The context index — source of the excerpts read during generation | Already exists, created by document ingestion |
datta_{dominio}_conhecimento | Retrieval of approved assets (optional consumption per context) | Automatically on the first approval of an asset in the domain, with an explicit mapping and a vector field (hnsw / cosinesimil / lucene; dimension of the active embedding model, with 1024 as the fallback) |
Both the retrieval index suffix (conhecimento) and the master index name are configurable at installation.
6. Installation and resources
| Parameter | Default value |
|---|---|
| Replicas | 1 |
| Service port | 8105 |
| CPU | 250m requested, 2 limit |
| Memory | 1Gi requested, 2Gi limit |
| Autoscaling | off |
Minimum memory of 1Gi, no exception: the application's startup with the telemetry agent takes around 190 seconds and does not fit in 512Mi — the service dies at boot. The readiness and liveness probes sit on the platform's standard health paths.
Cache prerequisite: knowledge preparation uses logical database 17 of the platform cache (the first free one — 1 through 16 are already allocated). The installation already configures 32 logical databases; older installations capped at 16 make the service fail to connect. To check how many databases the cache exposes, run CONFIG GET databases on the cache itself.
Relevant environment variables:
| Variable | What it is for |
|---|---|
OPENSEARCH_URL, OPENSEARCH_USER, OPENSEARCH_PASSWORD | OpenSearch access (default http://opensearch:9200, user admin, empty password) |
JWT_SECRET | Required — validated at service startup |
DATTA_INTERNAL_TOKEN | Token for internal communication between components (document supersede cascade, service account status) |
PROMPT_SERVICE_URL … AUTH_SERVICE_URL | Internal addresses of the components consulted: prompts, AI, embeddings, search, catalog, configuration and authentication — the defaults already point at the installation itself |
Note: the installation configuration exports
OPENSEARCH_URI, but knowledge preparation readsOPENSEARCH_URL. In practice the defaulthttp://opensearch:9200applies; to point at another OpenSearch, setOPENSEARCH_URLexplicitly.
The feature's calls arrive through the platform edge and are routed to knowledge preparation; the knowledge prompts have a route of their own, served by the prompt repository. All the endpoints are in the API reference.
7. Observability
| Metric | What it measures |
|---|---|
knowledge_assets_generated_total{tipo,outcome} | Assets generated per type and outcome |
knowledge_asset_generation_latency_ms | Generation latency |
| `knowledgegenerationlote_total{outcome=success\ | partial\ |
knowledge_retrieval_publish_total{outcome} | Publication and removal in the retrieval index, per domain |
knowledge_curation_mutations_total{op,outcome} | Curation mutations |
knowledge_curation_overview_latency | Latency of the curation indicators panel |
knowledge_export_requests_total{colecao,outcome} and knowledge_export_items_total{colecao} | Export per collection |
Audit events come out in structured logs (the otel-logs-* indices): KNOWLEDGE.EXPORTED, KNOWLEDGE.EXPORT_DENIED, KNOWLEDGE.ASSET_EDITED and KNOWLEDGE.ASSET_STATUS_LOTE. Asset lineage (ASSET_*) is published to the lineage:events stream and consumed by the platform catalog.
8. Troubleshooting
Chained 429 errors during generation
- Tell the origin apart. A batch lane 429 carries the reason in the body (
queue_fullorwait_timeout). A provider 429 (the Gemini per-minute quota) shows up in the logs of the model access layer and is retried automatically — first by the lane itself, then by knowledge preparation, with progressive backoff from 2s to 30s. - If it persists: lower
KNOWLEDGE_MAX_CONCURRENT_GENERATIONSfrom 3 to 1 or shrink the batch size; check the Gemini key's quota; in isolated environments, use the local provider (datta.llm.provider=vllm). - Confirm with data: growth of
llm_lane_rejected_totalonqueue_fullmeans the batch is too large for 2 simultaneous calls.
"Stuck" generation batch
- The state lives in the instance that created the batch, with a copy in logical database 17 of the cache (
datta:knowledge:task:{taskId}, 6-hour TTL). A service restart in the middle of a batch interrupts generation: the copy stops advancing, but the progress feed keeps answering the last state until the TTL expires. - Diagnosis: search the knowledge preparation logs for "Lote de geracao" and list the
datta:knowledge:task:*keys in logical database 17 of the cache. - Recovery: fire a new batch with only the missing documents. Persistence is idempotent per version — nothing gets corrupted, and the new run creates new versions only for what it processes.
datta-knowledge-assets index missing or with the wrong mapping
- The index is created at service startup; if OpenSearch is down, creation is retried on first access. Confirm the log line "Indice datta-knowledge-assets criado com mapping explicito".
- Never let the index be born through dynamic indexing: fields become a text type and exact filters silently stop matching. If it already happened, delete the empty index and restart the service, or recreate it with the correct mapping and reindex.
Generation returns a warning instead of content
- When AI is unavailable (missing Gemini key, local provider off), the model layer returns the unavailability as friendly content, not as an HTTP error. Knowledge preparation recognizes the authentication messages and fails the item with the original text — check the key under , which is the effective source.
Stale listings or indicators
- Caches: listings with 60 seconds in memory plus 5 minutes in the platform cache; indicators with 30 seconds in memory plus 60 seconds in the cache. Both are invalidated on any mutation.
- If a value stays stale beyond that, inspect the
datta:knowledge:*keys in logical database 17 and delete the domain's keys selectively — never flush the whole database without explicitly selecting 17.