Skip to content

Configuration knobs

AgenticMind runs with zero configuration beyond a database and (for synthesis) an LLM key. Everything below is optional and off / neutral by default — the defaults keep the deploy lightweight and the behaviour unchanged. Turn a knob on only when you want the capability it buys.

All knobs are environment variables read once at boot.

Profile

Env var Default What it does
AGENTICMIND_PROFILE standard standard keeps today's behaviour. strict turns the hardening checks below into refusals: the server and worker print the active profile at boot, and an unknown value (a typo such as Strict) refuses to start instead of silently running as standard.

What strict changes is listed in the security model. New deployments should start in strict; existing ones can switch once the checks it adds pass.

MCP input limits

Env var Default What it does
MCP_MAX_REQUEST_BODY_BYTES standard: no limit · strict: 2 MiB Caps the /mcp request body. It is read with a byte counter and answered 413 once the cap is crossed — before auth, parsing, schema validation or any model call. 2 MiB leaves room for a 200 000-character kl_ingest.text even from clients that escape non-ASCII as \uXXXX.
MCP_MAX_TOOL_INPUT_ELEMENTS standard: no limit · strict: 10 000 Caps array elements + object keys in one tool call's arguments (MCP SDK maxToolInputElements, GHSA-46jr-4wx8-v453). Over the cap the call gets an isError result and the schema never runs.

Both must be positive integers; any other value refuses to start, in both profiles. Behind a reverse proxy, set its body limit too.

Database TLS

Env var Default What it does
DATABASE_SSL false true connects over TLS. In standard the server certificate is not verified unless DATABASE_SSL_CA is set (a warning is logged at boot); in strict it is always verified.
DATABASE_SSL_CA unset CA bundle — PEM text or a path to a PEM file — to verify the server certificate against (e.g. your managed Postgres provider's CA). Setting it turns verification on in every profile; an unreadable or non-PEM value refuses to start.

sslmode / ssl parameters in DATABASE_URL override both (node-postgres behaviour); strict refuses sslmode=no-verify / ssl=no-verify and URL TLS parameters next to DATABASE_SSL=true.

Answer quality & trust

Env var Default What it does
KNOWLEDGE_FAITHFULNESS_TIER_B off Runs a semantic entailment judge over each cited claim (one extra LLM call per kl_ask_global). Adds semanticGroundedness + contradictedClaims to the answer. Tier-A structural groundedness is always computed for free.
KNOWLEDGE_CONTESTED_SOURCES off Runs a judge that surfaces facts where the retrieved sources disagree (one extra LLM call). Adds contested (each side tagged with source + date) instead of silently picking a winner.
KNOWLEDGE_ANSWER_POLICY unset A JSON policy that enforces the signals: minGroundedness, minSemanticGroundedness, blockOnConflict, blockOnNeedsReview, reviewOnConflict, reviewOnNeedsReview. blockOnNeedsReview is the single hard switch over all deterministic hallucination flags (fabricated figure/quote, mis-attributed citation, cited-but-unentailed claim, stale-only sources) — it turns detection into refusal. A blocked answer is replaced by a refusal; the decision (policy: { action, reasons }) is attached to the trace. requireSemanticVerification (review | block) handles a missing Tier-B signal (Tier-B off or the judge failed): review marks the answer needs_review, block refuses it — without it, minSemanticGroundedness is silently skipped when the signal is absent. missingGroundedness (pass | block) does the same for Tier-A against minGroundedness; strict defaults it to block. A malformed policy is ignored in standard and refuses to start in strict.
KNOWLEDGE_PII_REDACTION on Scrubs PII (email/phone/card/SSN/IPv4) from the answer and citation snippets before they leave the engine (and before caching). On by default — leaking PII is a defect. Set to false only when raw contact info is intended (e.g. an internal directory).

Every kl_ask_global answer carries a single status an agent can gate on, derived from the signals above (free, always present):

supported · partial · unsupported · conflicted · needs_review

Severity precedence: an honest decline → unsupported; conflicting sources → conflicted; a cited-but-unentailed claim, an answer resting only on stale (non-active) sources (staleSourcesOnly), an answer asserting a numeric figure absent from every cited snippet (ungroundedFigures), a cited claim that shares no salient word with its snippet (weaklyAttributedClaims), or a direct quotation absent verbatim from every snippet (ungroundedQuotes) — those deterministic no-LLM checks → needs_review; otherwise the grounded/partial/unsupported gradient.

Example policy (refuse weakly-grounded answers, flag conflicts for a human):

KNOWLEDGE_ANSWER_POLICY='{"minGroundedness":0.7,"reviewOnConflict":true,"reviewOnNeedsReview":true}'

Strict, zero-hallucination posture (hard-refuse on any deterministic flag — fabricated figure/quote, mis-attributed citation, unentailed claim, stale-only):

KNOWLEDGE_ANSWER_POLICY='{"minGroundedness":0.8,"blockOnConflict":true,"blockOnNeedsReview":true}'

Source trust

Each material carries a content lifecycle (active → deprecated → superseded → archived) and a trust tier (integer; higher wins on conflict). Retrieval down-weights stale/low-trust sources after the recency boost, so a signed policy outranks a historical note. Defaults (active, tier 0) change nothing. Set them at ingest via kl_ingest's optional lifecycle / trustTier, or later with updateMaterialLifecycle(). An answer that ends up resting only on stale sources is flagged (staleSourcesOnly, status → needs_review).

Retrieval & corpus

Env var Default What it does
RETRIEVAL_PARAMS engine defaults A tuned retrieval profile (hybrid weights / recency / topK / rerank) as JSON. Produced by scripts/tune.ts, which optimises against the eval corpus plus harvested real queries.
KNOWLEDGE_EVAL_HARVEST off Privacy-affecting. When on, the raw question is persisted on the telemetry row (default: only a hash) so signalled real queries can be replayed by the tuner. Leave off unless you want the closed read-path loop.
KNOWLEDGE_CARDS_ENABLED off Distil ingested text into reusable fact cards.
KNOWLEDGE_CACHE_ENABLED off Answer cache for repeated questions. Only supported answers are cached — a hallucinated / weakly-grounded / conflicted answer is never stored and then served back confidently to many agents (the cache amplifies whatever it holds). Staleness is enforced at lookup: TTL (default 7 d) plus source drift — if any cited material was edited, re-ingested, or deleted after the answer was cached, the entry misses. Accepted lag: a new material that would change an answer without touching its cited sources is not detected, so the old answer serves until the TTL expires — shorten the TTL on a fast-growing corpus.

Experimental

GraphRAG is experimental and agent-unproven. It is restored behind explicit flags after the v0.12.0 removal (which misdiagnosed an empty graph as a dead feature). The graph and multi-hop traversal work, but their value for agents (as opposed to human browsing) is not yet established — keep it off unless you are evaluating it.

Env var Default What it does
KNOWLEDGE_GRAPHRAG_ENABLED off Knowledge-graph context prelude + the kl_graph_neighbors tool. Entities/relations are extracted at ingest into the kg_* tables (Postgres recursive-CTE traversal, no extra service) and a best-effort neighbour prelude is prepended to retrieval.
KNOWLEDGE_GRAPHRAG_EXTRACTOR_MODEL unset → default chat model Required for the graph to populate. The extraction schema uses nullish fields, which OpenAI strict structured-output rejects → the default (OpenAI-strict) chat model extracts zero entities and the graph stays empty. Set this to a nullish-tolerant model (e.g. a Gemini id). The graphrag smoke check fails on an empty graph so this misconfiguration surfaces loudly instead of looking "dead".

Compounding loop (worker)

Env var Default What it does
KNOWLEDGE_ACCEPTANCE_EVALUATOR off A second-stage LLM gate over extracted cards at ingest (accept / reject / merge / human_review). One extra LLM call. In standard a card the judge returns no verdict for, and every card when the judge call fails, is admitted as approved (fail-open, today's behaviour). In strict both stay candidate with the reason recorded in confidence_reason.
KNOWLEDGE_DEMOTION_ENABLED off Anti-entrenchment brake. The worker sweep demotes a promoted resolution card to deprecated once its cluster's aggregate feedback score falls to/below a negative floor over enough signals — so a once-popular answer the community later rejects stops surfacing. The card is kept (audit trail intact), not deleted. Off by default; only meaningful once the promoter has run.

Multi-tenant

Env var Default What it does
DATABASE_APP_ROLE unset Downgrades each request transaction to a least-privilege Postgres role via SET LOCAL ROLE, so row-level security is enforced even on an owner/superuser connection. Set this whenever you rely on tenant isolation.

Tenant scoping itself is automatic: a token carries a tenant, every request runs in its tenant context, and RLS policies enforce isolation on read and write. See the security model.

Cost

Tier-B faithfulness and contested-sources each add one LLM call per kl_ask_global when enabled — both default off. The answer cache (when on) serves repeats without re-paying. Per-run output ceilings and per-call token usage are recorded in the trace.