Configuration
Akno separates machine settings, secrets, and knowledge-base-owned structure. The split makes configuration inspectable without turning credentials or private paths into repository data.
Precedence runs from lowest to highest:
packaged default.jsonc → platform machine config → checkout config/local.jsonc → AKNO_* environment| Layer | Purpose |
|---|---|
config/default.jsonc |
Committed, machine-independent defaults and comments for every setting |
| Platform machine config | ~/.akno/config.json on macOS; $XDG_CONFIG_HOME/akno/config.json on Linux |
config/local.jsonc |
Gitignored checkout-specific paths, endpoints, and model ids |
| Environment | Invocation-specific paths and credentials |
An installed package has no checkout config/local.jsonc. AKNO_CONFIG selects an explicit machine-config
path. Use akno config to see the resolved, redacted result and every contributing source.
knowledge_language: "en" selects English for new generated knowledge. The default null preserves previous
behavior. Source quotations and existing pages stay unchanged, and answers can independently request English
or Russian. See knowledge language and discourse for coverage, exact caller
attestations, typed failures, and evaluation.
The default private state is ~/.akno on macOS and $XDG_STATE_HOME/akno on Linux (falling back to
~/.local/state/akno). The default Linux socket is $XDG_RUNTIME_DIR/akno/akno.sock; when no runtime directory
is available it stays under private state. AKNO_STATE_DIR, AKNO_SOCKET, state_dir, and server.socket
remain explicit overrides; environment values win over files.
A config names the environment variable containing a credential; it never contains the credential itself:
{
"providers": {
"openai": {
"base_url": "https://api.openai.com/v1",
"api_key": { "env": "AKNO_OPENAI_API_KEY" },
"api": "responses",
},
},
}akno config, setup previews, diagnostics, benchmark artifacts, and dream receipts redact or omit resolved
secret values.
providers.<name>.api selects the provider’s generative transport. responses uses /responses,
max_output_tokens, reasoning.effort, Responses image parts, and text.format structured outputs;
chat_completions retains the existing OpenAI-compatible /chat/completions adapter. Providers that omit the
field default to chat_completions, so existing local and gateway configurations do not silently change.
auto is for an unfamiliar OpenAI-compatible endpoint. At the first handle or service startup, Akno sends a
single-word invented probe to Responses for every distinct configured generative model. It tries Chat
Completions only when Responses returns an absent-route status (404, 405, or 501); authentication,
rate-limit, timeout, malformed-response, and server failures leave the transport unresolved instead of being
misread as capability evidence. The successful selection is stored in
<state_dir>/provider-capabilities.json, keyed by a one-way fingerprint of the endpoint, authentication,
headers, and complete generative-model set. Changing any of those inputs invalidates the entry automatically. Run
akno doctor --refresh-api after an endpoint upgrades in place; akno doctor --no-probe never resolves a cache
miss or sends a model request. A failed probe stores no provider response: it records only a five-minute
content-free cooldown so repeated one-shot commands do not each wait on the same outage.
The guided OpenAI preset selects responses explicitly and sends store: false because Akno calls are
stateless and may contain private memory. A failed Responses call does not fall through to Chat Completions:
cross-transport retry could duplicate cost and change schema behavior. Automatic one-time capability resolution
uses only invented probe text. A real Akno request never falls through to the other transport.
Configuring a provider for a model role is the owner’s authorization to send that role’s necessary input to
that provider. Akno does not add per-page or per-call egress gates. It does keep the request on the exact
configured scheme, host, and effective port: model calls and api: auto probes refuse cross-origin redirects
before any authorization, custom header, or body can reach the target. Bounded same-origin 307/308
redirects preserve the POST; 301/302/303, loops, malformed or credential-bearing destinations, and
unsupported schemes fail with content-safe diagnostics. Retries and compatibility negotiation stay on the same
origin, and a failed configured provider never causes another provider block to be tried.
Inline merge blocks and duplicate stable page ids need no configuration. If a sync client creates recognizable conflict-copy filenames, declare only that deterministic shape in machine-owned configuration:
{
"index": {
"conflict_path_patterns": ["**/* (conflicted copy *).md", "archive/**/conflict-*.md"],
},
}Patterns match normalized relative paths, case-insensitively and with / or \ separators treated alike.
They cannot be absolute or traverse above the knowledge base. Page content and frontmatter cannot add or
disable them. A matching page is quarantined before Markdown parsing, so the pattern should describe only
actual conflict artifacts rather than a broad content folder.
Routine index and doctor output exposes only conflict classes and counts. Run
akno doctor --no-probe --quarantine-details locally when the source paths and known stable ids are needed to
repair the files; conflict bodies and neighboring text are never copied into quarantine state.
server.mcp_allow is the authoritative operation set for MCP. A stdio adapter that forwards through the
running service reads that policy from the service handshake. akno serve --mcp --allow ... may narrow the
set for one host, but cannot add an operation the service policy denied.
Loopback HTTP is usable without a credential and is limited to read operations in
server.http_public_allow; that list may narrow the public surface but cannot grant a write. Authenticated
identities are environment-backed secret references:
{
"server": {
"http_public_allow": ["recall", "answer", "read"],
"http_access": [
{
"name": "vulpine-agent",
"token": { "env": "AKNO_HTTP_AGENT_TOKEN" },
"actor": "agent",
"allow": ["recall", "answer", "read", "retain"],
},
],
},
}A missing token variable disables that identity and appears in akno doctor. A non-loopback HTTP bind is
refused unless at least one identity has a resolved credential. The credential selects both actor and
operations; an HTTP caller cannot supply actor: "user" itself. akno config redacts resolved tokens. The
built-in listener is plain HTTP, so carry non-loopback traffic through a trusted tunnel or TLS reverse proxy.
URL ingest denies loopback, private, link-local, multicast, unspecified, metadata, and other non-public IPv4
and IPv6 destinations after DNS resolution. Every answer must pass, the request is pinned to one validated
address, and redirects are resolved and checked again. A known internal service can be opted in by exact
scheme, hostname, and port—never by path or wildcard—with ingest.trusted_url_origins. The exception does not
authorize another port, protocol, or redirect origin on the same host.
Folder policy can travel with the notes in <akno_path>/akno.jsonc:
{
// The most specific matching glob wins.
"folders": {
"memory/**": { "role": "knowledge", "remember": "integrate" },
"topics/**": { "role": "knowledge", "observe": "integrate" },
"sources/**": { "role": "source", "remember": "deny", "ingest": "document" },
"templates/**": { "role": "ignored", "remember": "deny" },
"inbox/**": { "ingest": "auto", "route": true },
"notes/**": { "max_depth": 1, "relocate_to": "notes" },
},
}The .jsonc extension is deliberate: comments are valid and akno folder preserves them. The old
akno.json name is rejected with an exact rename instruction; if both names exist, Akno refuses to choose an
authority.
Knowledge-base rules override machine folder rules. They are configuration, not notes, and are never indexed as memory. A rule change fingerprints the affected policy, so the next index pass reconsiders matching pages even when their Markdown bytes did not change.
akno rules sources/example.mdThis explains the winning rule, its source, and page-specific maintenance authority without emitting page
content. With no page declaration or matching remember rule, a page remains searchable knowledge but is
read-only for fact injection. Observation authority is separate and also defaults to deny:
observe: integrate permits only Akno-owned L2 blocks on an existing exact-subject page, never retained-item
injection, page creation, or adjacent prose edits. Existing remember and dream settings do not imply it.
akno doctor reports admitted, read-only, and implicit read-only page counts so an upgrade can be reviewed
without adding a catch-all write rule. For the structural details, run:
akno doctor --no-probe --admission-previewThe opt-in preview groups implicit pages by top-level folder and prints exact { "remember": "deny" } patches.
Those patches merely make the current default-deny behavior explicit: they do not infer a role or grant write
authority. Root-level pages are counted separately because proposing a global ** rule would be broader than
the evidence. Routine doctor output omits folder names, and neither form writes configuration.
Every role is optional and degrades independently:
| Role | If configured | Without it |
|---|---|---|
embedding |
Semantic candidate generation | Lexical and exact-graph candidates only |
reranker |
Candidate ordering and optional irrelevance qualification | Rank-fusion order |
derive |
Summaries, facts, naming, remember, retain, and plans |
Those derived capabilities report unavailable |
expansion |
Query reformulation | Search the original query only |
answer |
Direct grounded synthesis and verification | answer reports not_answered; discovery still works |
vision |
Description of images with no readable text | OCR and ordinary document extraction still work |
One endpoint may host several roles, but embeddings still use a separate embedding model id. The qualified OpenAI minimum is therefore a single-endpoint, two-model setup—not a single-model setup.
The generative roles have separate reasoning and output settings because their latency and quality needs
differ. Expansion and reranking are interactive and can use reasoning_effort: "none"; derivation and
maintenance can use more effort off the hot path.
See config/default.jsonc for every field and
config/local.example.jsonc for a
specialist setup.
models.reranker.mode accepts decisions, llm, or endpoint. The guided OpenAI Luna setup defaults to
decisions with gpt-6-luna at /decisions. Set mode: "llm" to use the base model’s bounded listwise
JSON prompt, or mode: "endpoint" for a native /rerank endpoint. Provider api still selects generation
transport only; Decisions reuses the configured endpoint, credential, headers and retry policy.
Decisions batches one four-level relevance question per excerpt, ranks by expected grade, and uses
irrelevant_probability_threshold (default 0.8) to remove only confidently irrelevant excerpts when
exclude_irrelevant is enabled. Uncertain and marginal evidence remains available. Its returned relevance
is P(strong support or direct answer); automatic context admission requires at least 0.5 plus the ordinary
subject and temporal checks. Qualification reports model: "decisions" and its probability cutoff explicitly.
The complete named distribution must validate before any filtering. The role timeout bounds the whole
request including retries. Decisions failures report degradation without silently invoking generation.
This changes cloud exposure for a setup that previously used a local reranker: only enable the OpenAI role when sending its bounded memory excerpts to that configured provider is intended. The guided OpenAI setup already sends those excerpts to OpenAI in base-model mode. Successful reranking can remove candidates confidently judged irrelevant. A failed or invalid reranker response preserves fusion order and reports typed degradation; Akno never filters using an unvalidated result.
Native rerankers do not share a score scale. score_offset: "auto" calibrates a conservative boundary from an
invented anchor suite and caches it in derived state. If the model cannot separate the anchors, qualification is
disabled and recall keeps candidates rather than guessing a cutoff.
An optional exact page can catch durable claims when ordinary semantic routing and managed-page creation both fail:
{
"maintenance": {
"retain": {
"fallback_page": "memory/inbox",
"evidence_grace_days": 30,
},
},
}The default is null, so no fallback is used. This setting names a destination; it does not authorize one. An
existing page must itself resolve to role: knowledge and remember: integrate. A missing page can be created
only when its exact parent folder explicitly permits knowledge-page creation and remember integration. Reserved
paths, read-only pages, and existing Markdown files that are absent from the index are rejected rather than
overwritten. akno doctor reports the configured page as existing page, new page, or unavailable without
showing page content.
The fallback is deliberately last in the routing order: a separately qualified existing owner wins first, then
a qualified new managed page proposed by retention, then the configured fallback. Similarity only nominates
existing candidates. Without any authorized destination, remember returns a typed hold. During later
managed-item curation the fallback is a queue, not a canonical home: an item moves to one unambiguous supplied
existing page or remains held.
maintenance.retain.model_timeout_ms optionally sets the per-attempt deadline for retention model calls,
including extraction, structural repair, verification and support comparison. Null inherits the maintenance
or derive model deadline. It does not change reasoning effort or other workflows.
generation_max_output_tokens overrides extraction, structural-repair and verification output allowances; null keeps
each phase’s allowance, and the model role’s hard ceiling still wins. A larger allowance costs more tokens and allows
complete structured records to fit alongside hidden reasoning. verification_concurrency defaults to 1. Independent two-candidate verifier batches may run in parallel
(up to 16), with identical source frames, prompts, budgets and result ordering. With the default failure scope,
any failed batch withholds the complete candidate transaction; already launched calls are included in usage accounting.
verification_failure_scope defaults to source, preserving whole-source holds on a failed batch.
Opt-in batch mode keeps independently verified records, holds every record in a failed atomic batch,
and withholds all transitive relation dependents. Failure remains typed as retain_verification_failed;
all launched calls remain in usage accounting. Replacement corrections always retain source-wide failure.
These settings do not change evidence, admission or semantic acceptance checks.
evidence_grace_days defaults to 30. It applies only after retained support becomes inactive through exact
retraction or user forget; active support has no age limit. Nonterminal maintenance work that still names the
managed item also blocks pruning. A value of 0 permits immediate secure pruning once those dependencies are
gone. This removes bounded private quotes from local state, not Markdown, replay hashes, compact receipts, or
stored page/document bindings.
Interactive akno init can configure this boundary without examining page content. It classifies visible
top-level directories as managed memory, read-only knowledge, or source/reference material and can add a
dedicated fallback namespace. New setup writes an explicit decision for every directory it presents. An existing
installation keeps its current folder and fallback policy unless the user opts into reviewing it.
One profile defines the scheduled default:
{
"maintenance": {
"profile": "autonomous",
},
}| Profile | Decision owner |
|---|---|
audit |
Nobody; exact plans are retained without decisions or writes |
review |
A human decides each eligible item |
autonomous |
A separate curator model decides, then accepted items pass deterministic guards |
Transformation policies can lower individual classes:
{
"maintenance": {
"profile": "autonomous",
"policies": {
"hygiene": "auto",
"managed_item": "auto",
"broken_link": "auto",
"rule_drift": "auto",
"merge": "review",
"contradiction": "off",
},
"limits": {
"max_items": 30,
"max_files_changed": 40,
"max_bytes_written": 500000,
"max_high_risk_items": 3,
},
"plan_retention": {
"payload_days": 30,
"receipt_days": 180,
},
"max_revision_attempts": 1,
},
}Policy values are off, audit, review, and auto. Supported classes are observe, reflect, hygiene,
managed_item, synthesis, split, extract, merge, contradiction, broken_link, rule_drift,
timeline_history, and adopt. Page
opt-ins, folder restrictions, merge allowlists, feature switches, and write budgets remain additional ceilings.
max_revision_attempts is the number of correction calls permitted after an automatic curator returns
revise; it defaults to 1 and accepts 0 through 3. Each correction may replace complete after-state bytes
only for paths already sealed on the item, must pass deterministic preflight, and receives a fresh curator
decision. Another revision request at the limit becomes a rejection. Model or schema failure blocks the item
without writing or caching a semantic rejection, so a later cycle can retry from fresh planning.
managed_item is intentionally different from whole-page curation. It inspects only fragments introduced by
a strict akno:item marker on remember: integrate knowledge pages; those pages do not also need dream
authority. Its deterministic repair set removes empty markers and byte-identical payload/provenance duplicates.
Malformed or conflicting markers are counted as held findings and leave the page unchanged.
timeline_history starts from existing writable timeline declarations, including empty timeline.md
files. It can retain attributed temporal items from source evidence into a ledger-owned timeline-memories.md
companion, extract actual day-dated events from authored knowledge notes, or propose exact transfers
from an ancestor ledger to its owning descendant. It requires no whole-page dream opt-in: the declaration,
ledger-specific policy, and maintenance profile supply its bounded authority. A valid declaration grants
ledger authority independently of inherited source-folder or remember: deny policies; those policies
still protect ordinary documents. A timeline companion never authorizes edits to those sources. Explicit rules
naming the companion can deny its creation/use. Explicit rules naming the ledger and its frontmatter can restrict the
grant. The shared retention verifier, separate automatic curator, stale-input checks, journal, and apply
budgets still govern every write.
maintenance.curate.max_timeline_events defaults to 20 and bounds events and ownership calls per cycle;
extraction additionally uses max_pages. See folder timelines
for source eligibility, review, and undo behavior.
rule_drift is also independent from page-wide dream opt-in. It can replace an existing top-level scalar
type on a knowledge page only when a matching folder rule explicitly declares the exact expected type.
For an over-deep page, max_depth diagnoses the problem but does not authorize a guessed move. Pair it with
relocate_to in the same rule to name the exact destination folder; Akno preserves the basename and page
identity, moves the page’s complete owned document and rendition set with byte and identity checks, and rewrites
only source link addresses required to keep self-links, relative page links, and owned local-file references on
their original targets. It updates every inbound knowledge-page link and exact authored akno.about value in
the same high-risk item. Multiple references on one page compile into one replacement. The page, document
relations, reference updates, and full change remain undoable. It declines relocation when the target exists,
destination rules reject it, an owned document is missing, changed, externally related, or would collide, a
relative local-file reference is unowned or escapes the knowledge-base root, or a source/reference page points
to it. An inherited, malformed, or already-duplicated about value is also held because it is not one exact
page-owned rewrite. slug_pattern drift remains report-only because a pattern does not name one exact filename.
Source/reference pages are never rule-drift write targets.
maintenance.curate.max_rule_drifts bounds both forms per cycle; the default is 20.
Housekeeping does not leave an unplanned rule finding unexplained. Each displayed finding carries one typed
repair disposition: ready when the exact planner can seal it, plan_backed when a nonterminal item already
owns it, report_only when the rule does not determine one correction, or held with a deterministic safety
code such as document_unavailable, document_destination_occupied, reference_about,
about_unrewritable, reference_backlink, or location_dependent_reference. Ordinary JSON output
retains only aggregate disposition counts; page-specific codes and reasons require --private-details.
Canonical fragments are checked against the current rebuildable managed-memory projection: item id, page
identity, payload line, and exact payload hash must agree. This also covers reports, plans, questions, and other
items deliberately excluded from derived facts. Reusing an id on two pages or participating in a typed fact
conflict that excludes the claim from inference yields item_conflict; a stale or missing memory projection
yields source_unavailable rather than pretending verification passed. A fragment without one unique ##
section—or under the explicit ## Unsorted fallback—starts as misplaced_item. Qualified semantic placement may choose only keep,
move, or uncertain; an accepted move must name one existing unique ## section in the same page, and
deterministic code moves the complete owned block without rewriting it. If that block was the only content in
its unique source section, the now-empty source heading is removed with it; headings that retain authored or
managed content are preserved. placement_uncertain and
placement_unavailable are held. Verdicts are cached by exact content and model contract without storing page
text or headings. Cross-page routing separately retrieves at most three existing remember: integrate
knowledge pages and may move one exact owned block only to a supplied page. The destination may be an existing
unique ## section or the one plain heading deterministically derived from a fact attribute when available,
then the managed item’s current section or kind. The
classifier sees page identity and effective folder description; a second semantic pass independently confirms
that the proposed page and section own the item. Applied transfer history can nominate a previous owner but
repeating an earlier directed move is held to stop oscillation. The classifier cannot invent another label; creating the supplied heading is permitted only when no existing
section fits. Same-page placement uses the same rule. The operation is medium risk when it creates a section or
touches two pages, and it cannot create a page or replacement text. When the same page first needs deterministic
marker normalization, semantic placement is reported unavailable for that run and resumes against the canonical
bytes on the next cycle. The configured retain fallback is a queue: curation never accepts keep there, and
moves an item only to one unambiguous supplied canonical page; the fallback itself is never a curation
destination. Exact YYYY-MM buckets and exact or explicitly ledger-like YYYY-MM-DD pages reject memories
outside their period. A date-prefixed named event or trip is not a period bucket and may coherently own related
preparation or follow-up memories outside the event dates.
A cross-page move may empty the configured retain fallback queue. It may not reduce any other page to only
frontmatter and headings; that becomes the typed source_vacated hold. Existing heading-only pages are reported
as empty_knowledge_page for inspection rather than deleted.
Shareable JSON and durable run receipts keep only aggregate counts. Use akno dream --private-details during a
live run to see the exact slug:line for repairable or held findings.
Merge discovery remains exact by default. Enable the qualified semantic candidate source only after choosing explicit eligible folders:
{
"maintenance": {
"curate": {
"merge_folders": ["people"],
"merge_discovery": "semantic",
},
},
}exact uses authored aliases and conservative evidence-graph identity. semantic keeps those signals and may
also compare complete, compact, sibling pages that explicitly allow synthesis. Embedding similarity only
prefilters a bounded queue; the qualified same-subject classifier still cannot authorize a write. Every
selected pair must pass the lossless planner, independent verifier, curator or human policy, budgets, stale
checks, and atomic apply verification. Classifier verdicts are cached by content and model fingerprints, so an
unchanged rejected pair is not repeatedly sent to the classifier. Model outages appear as typed dream
degradation and exact discovery continues.
Complete-page semantic signatures are cached separately from retrieval chunks. An unchanged eligible page is therefore not sent to the embedding model again on every nightly cycle. The cache key includes the exact semantic input, page identity, embedding endpoint, and signature version; changing any of them re-embeds only the affected page. Stale signatures and pair verdicts are replaced instead of accumulating. The derived cache stores hashes and vectors, but no page text, slug, title, or classifier rationale.
Plan retention has two stages. payload_days removes exact private operations and evidence from terminal
plans while keeping compact decisions, hashes, and verification receipts. receipt_days then removes those
terminal plan rows; it must be at least as large as payload_days. Active review, apply, partial, and
verification states never expire through this policy. A zero-day value means immediate expiry at the end of a
writable dream run. Preview the current boundary with akno plan prune; apply it manually with
akno plan prune --apply. Full writable dream runs enforce the configured boundary automatically.
Read The dream cycle before raising authority.
Akno retries rate limits and selected transient 5xx failures with bounded exponential backoff. It does not retry a timeout: the attempt already spent the configured deadline, and repeating it would multiply latency without evidence that the endpoint recovered.
recall.expansion_timeout_ms bounds the entire interactive expansion sequence. A background role’s
timeout_ms applies per attempt because nobody is waiting on that request in the current turn.
Indexing leaves the knowledge base byte-identical by default. Explicit opt-ins include:
write_ids: true, which adds stable page ids to frontmatter;ingest.text_rendition: true, which maintains readable<document>.txtrenditions;create_reserved_paths: true, which permits configured reserved paths to be created.
Write commands and authorized maintenance plans naturally modify files and record journal entries. See Writing and ingestion and The dream cycle.