Skip to content

Wikilinks

Context

The citation and crosslinking contract for an agent-maintained wiki. When the agent answers a query from the wiki, it cites wiki notes — not raw URLs and not prose hand-waving. When the agent writes new wiki content, it wires every claim to a note. This note defines how those links are written so they resolve in Obsidian, survive MkDocs compilation, and stay greppable for lint passes.

Precedence: agents.md is the normative contract; this note elaborates its link rules with worked syntax and observed failure cases. On conflict, agents.md wins — update it first, then this note.

In the LLM Wiki pattern, the agent is a librarian: its answers must be auditable back to sources. Wikilinks are the right citation unit for three reasons:

  • Traceability is two-hop and stable. An answer cites a wiki note; the note cites the original URL (the vault's rule: synthesis note -> reference note -> original URL). When a source URL rots, exactly one note is repaired and every past answer that cited it remains valid.
  • The graph is the knowledge. Obsidian's link graph and backlink panes expose which notes are load-bearing and which are orphans — the primary signal for the weekly lint pass.
  • They compile. The mkdocs-roamlinks-plugin converts wikilinks to standard links in the published site, so one syntax serves both the local vault and the public knowledge base.

The Citation Chain

Agent answer
  └─ cites: [Wikilinks](<./wikilinks.md>)          <- wiki note (stable surface)
       └─ cites: [Karpathy's llm-wiki gist](https://gist.github.com/karpathy/442a6bf555914893e9891c11519de94f)  <- original URL

Rules for the agent when answering:

  1. Cite the narrowest note that supports the claim — a section anchor beats a whole note, a whole note beats a domain index.
  2. Cite the note, never the URL, in answers and in wiki prose. URLs live in the Sources section of a note, nowhere else.
  3. If no note covers the claim, create the note first (or add a reference note), then cite it. A claim with no citable note is not yet knowledge.
  4. When two notes disagree, cite both and flag the conflict in the newer note — do not silently pick a winner (that is the Conflict Resolution question in the index).

Scoping Rules

Wikilinks resolve by path-suffix matching: [ai-agents/llm-fundamentals/index](<../llm-fundamentals/index.md>) matches any file whose path ends with ai-agents/llm-fundamentals/index.md. Short links therefore resolve by accident today and break by rename tomorrow. The vault's contract:

Form Verdict Example
Folder-scoped required [ai-agents/llm-fundamentals/operations#speculative-decoding](<../llm-fundamentals/operations.md#speculative-decoding>)
Bare note name forbidden (ambiguous) [index](<../../tools-catalogue/index.md>), [architecture](<../../storage/ceph/architecture.md>)
Block reference forbidden [[note^abc123]] — breaks MkDocs compilation
Relative ([../note](<../../../note>)) forbidden use vault-scoped form instead
Unscoped with alias forbidden [[My Note]] — fine in generic Obsidian, ambiguous here

Bare [index](<../../tools-catalogue/index.md>) and [disclaimer](<../../disclaimer.md>) are the two accepted exceptions (vault-root pages). Anchors use the GitHub-style heading slug: ## Speculative Decoding becomes #speculative-decoding.

  • Backticks kill links. A wikilink inside inline code is dead text: `[ai-agents/llm-wiki/wikilinks](<./wikilinks.md>)` renders as literal text and lint tools count it unresolved. Write links as links.
  • Escape pipes in tables. Inside a Markdown table, the alias separator must be escaped or it splits the cell: [DFlash 2](<../../llm-inference/dflash2/index/.md>).
  • Case matters at build time. macOS (APFS) resolves [[Note]] to note.md; GitHub Pages and MkDocs do not. Write targets in their exact on-disk case.
  • Spaces in markdown-link targets need %20](ref - name.md) breaks, ](ref%20-%20name.md) resolves. Wikilinks handle spaces natively; prefer them for note-to-note links.
  • No trailing-slash directory links ([x](topic/)) — MkDocs cannot resolve them; always link the explicit index.md.

The public build only publishes knowledge/, compiles wikilinks via the roamlinks plugin, and uses awesome-pages navigation. Practical consequences:

  • Link targets must exist under knowledge/ — a wikilink into projects/ or meta/ publishes as a dead link.
  • Relative Markdown links must use explicit file paths ([Architecture](../../storage/ceph/architecture.md), [Comparisons](comparisons/dflash2-vs-eagle3-vs-mtp.md)), never directory paths.
  • Every new folder needs a .pages file or its pages are invisible in the sidebar.

Lint Hooks

The weekly lint pass (see Operations) checks exactly these invariants: every [[...]] target resolves by suffix match, every link is folder-scoped, no links inside code spans, no orphan notes, and every note cited by an answer exists. The vault-maintenance skill's audit checklist automates each check.

Sources

  • Vault conventions: agents.md (Wikilinks, SSG Compatibility, Interconnection Rules sections)
  • mkdocs-roamlinks-plugin — wikilink-to-markdown compilation used by the public build (v0.3.2, pinned in requirements.txt)
  • Obsidian help: Internal links — resolution and alias semantics