awslabs / awslabs/cli-agent-orchestrator

[Feat] Use an Obsidian vault as a canonical CAO knowledge source

Open
#644 4 comments 0 reactions 0 assignees View on GitHub
enhancement feature
Dominant language
Python
Stars
1.3k
Forks
267
Avg merge
1d 23h
Merged PRs (30d)
70

Description

## Overview

Add an opt-in Obsidian vault-backed knowledge source for CAO.

Today CAO owns the memory corpus and can export snapshots or graph projections for
use in Obsidian. That works for interchange and visualization, but it leaves users
who already maintain knowledge in a vault with two sources of truth: existing vault
notes are not directly recallable, Obsidian edits do not reach agents, and
CAO-authored knowledge must be exported before it joins the user's normal workflow.

This feature makes a configured vault the canonical, human-editable knowledge
source. CAO should read allowed vault notes, write new memory only to a managed
folder, and reuse its existing retrieval, scope, relationship, security, audit, and
locking behavior around that source.

Obsidian itself does not need to be running. CAO integrates with the vault files and
documented Markdown conventions, without requiring an Obsidian plugin.

## User Stories

- As an Obsidian user, I want CAO to recall knowledge from selected vault folders so
that I do not maintain a separate agent-only knowledge base.
- As a user, I want edits and wikilinks made in Obsidian to become searchable and
visible in CAO's graph after reconciliation.
- As a user, I want `memory_store` to create ordinary notes in a CAO-managed vault
folder so that agent-authored knowledge is immediately inspectable and editable.
- As a security-conscious user, I want explicit folder-to-scope mappings and
exclusions so that private or ephemeral notes are not silently exposed to the
wrong agent or project.
- As an operator, I want the local index to be observable and rebuildable so that
the vault remains usable even if derived state is stale or deleted.

## Ownership Model

- Vault Markdown content is canonical.
- Standard wikilinks are canonical `relates_to` edges.
- A documented CAO-namespaced frontmatter schema or managed sidecar is canonical
for stable identity, typed relationships, provenance, and lifecycle state that
plain wikilinks cannot represent.
- SQLite metadata, BM25 indexes, graph projections, access counters, and caches are
derived state. They may be deleted and rebuilt from the vault.
- Existing native CAO memory remains available for scopes not mapped to a vault.
- After a scope switches to vault-backed writes, CAO must not maintain the legacy
wiki and vault as two writable replicas.

## Query Behavior

The vault changes the **corpus**, not the retrieval contract.

1. Reconcile allowed `.md` files into CAO's derived metadata and BM25 index.
2. Continue using the current CAO query path for scope filtering, ranking, access
controls, result limits, related-memory expansion, and observability.
3. Return source-aware results containing the vault path, mapped CAO scope, and
index freshness.
4. Resolve supported wikilinks into graph edges with documented behavior for
aliases, headings, duplicate names, missing targets, and excluded folders.
5. Detect out-of-band additions, edits, renames, and deletions through explicit
reconcile/rebuild operations in the first release.

SQLite and BM25 should therefore be reused rather than replaced by filesystem
scanning on every query. The key change is that index rows point to vault-backed
notes and are treated as disposable projections, not the content authority. The
initial product contract should not silently require an external search daemon or
embedding service.

## Store Behavior

The vault does change the write path.

1. `memory_store` writes only to a configured CAO-managed folder inside the vault.
2. New notes use a documented Markdown/frontmatter schema and stable CAO identity.
3. Updates are allowed for CAO-managed notes; arbitrary existing vault notes remain
read-only.
4. Writes reuse CAO's existing validation, secret controls, scope authorization,
path confinement, atomic-write/locking, and audit expectations.
5. After each successful write, derived SQLite/BM25/graph state is refreshed or
marked stale for reconciliation.
6. User-owned frontmatter fields in managed notes are preserved where possible,
and conflicts fail visibly rather than silently overwriting content.

Pointing `MEMORY_BASE_DIR` at a vault is not sufficient: arbitrary vault layouts do
not share CAO's scope structure or metadata format, and direct reuse would blur
ownership, indexing, relationship, and write-safety boundaries. This needs a
vault-source/reconciliation layer behind the existing memory service contract.

## Acceptance Criteria

- [ ] Vault access is opt-in and confined to a configured root with explicit
include/exclude rules.
- [ ] Folder-to-scope mappings are explicit; private and short-lived scopes are not
silently written to a broadly shared or synced folder.
- [ ] Existing allowed vault notes participate in `memory_recall` through a derived,
ranked index.
- [ ] Recall results identify the vault source, note path, mapped scope, and index
freshness.
- [ ] External create, edit, rename, and delete operations are reflected after a
bounded, observable reconciliation step.
- [ ] Resolvable wikilinks appear as graph relationships, with malformed or
ambiguous links reported rather than silently misresolved.
- [ ] `memory_store` creates and updates normal Markdown notes only in the managed
folder.
- [ ] Normal memory operations never modify an unmanaged vault note.
- [ ] CAO's derived SQLite/BM25/graph state can be deleted and deterministically
rebuilt from the vault.
- [ ] Existing scope, authorization, secret scanning, path traversal, symlink,
audit, and concurrent-write protections apply at the vault boundary.
- [ ] The workflow operates while the Obsidian application is closed.
- [ ] An explicit migration can move selected native CAO memory into the managed
folder, preserving representable metadata and reporting lossy fields.
- [ ] Focused tests cover malformed YAML, duplicate note names, excluded paths,
dangling links, symlinks, partial files, concurrent edits, and rebuilds.

## Proposed Solution

Add a vault-backed source/reconciliation adapter behind the existing memory service:

- configure one vault root, folder-to-scope mappings, exclusions, and a managed
write folder;
- parse a documented subset of Markdown, YAML frontmatter, and wikilinks;
- reconcile file identity and content changes into the existing SQLite/BM25
retrieval path;
- project supported wikilinks and CAO-namespaced typed relationships through the
existing relationship and graph services;
- expose explicit index/reconcile/status operations before adding continuous file
watching; and
- provide a dry-run migration from selected native scopes.

The first implementation should start with a compatibility spike against a
representative existing vault and validate rebuild determinism, retrieval quality,
scope isolation, and concurrent filesystem behavior before committing to a watcher
or broader write permissions.

## Alternatives Considered

- **Managed folder for both reads and writes:** safer, but does not make existing
vault knowledge recallable without moving or importing it.
- **Whole-vault read and write:** more seamless, but CAO cannot safely preserve every
user schema, plugin convention, attachment, or concurrent edit in a first release.
- **Bidirectional synchronization with native CAO memory:** creates two writable
replicas and requires conflict, deletion, provenance, and recovery semantics.
- **Improve export/import only:** retains snapshot lag and keeps co-curation as a
manual workflow.
- **Replace SQLite/BM25 with vault scans:** makes query latency and ranking worse and
discards CAO's existing scope, security, and retrieval behavior.

## Risks and Open Questions

- Vault notes may contain secrets, private material, stale claims, or prompt
injection. Index eligibility and automatic context injection must be separate,
explicit policies.
- Cloud-synced vaults introduce partial files, concurrent edits, rename races, and
platform-specific case behavior.
- Plain wikilinks cannot encode `contradiction`, `supersedes`, confidence,
provenance, or proposal status. The canonical CAO-namespaced representation needs
to be selected.
- The supported boundary for aliases, embeds, heading links, attachments, duplicate
titles, and plugin metadata must be documented.
- Decide whether the first release supports one vault or multiple vaults.
- Validate that whole-vault reads with managed-folder writes match user expectations
before allowing edits to arbitrary notes.

## Non-Goals

- Unrestricted writes to arbitrary existing vault notes
- Bidirectional synchronization with the legacy CAO wiki
- Two writable replicas for the same scope
- Requiring Obsidian, an Obsidian plugin, or an external search daemon at runtime
- Continuous file watching in the first release
- Cross-scope relationship semantics
- Replacing the existing memory API, BM25 ranking, or typed relationship service

## Additional Context

This is a follow-up to:

- #345, which added OKF export/import as an interchange boundary
- #348, which added a read-only graph layer and Obsidian export sink
- #511, which added durable typed memory relationships

Unlike those export and projection workflows, this proposal makes the configured
vault a canonical source while retaining CAO's database and indexes as rebuildable
query infrastructure.

Contributor guide

Open the contributing guide

Research direction

Start with a compatibility spike against a representative existing vault, then trace the existing memory service contract, memory_recall, memory_store, SQLite/BM25 retrieval path, and relationship and graph services. Validate deterministic rebuilds, retrieval quality, scope isolation, and concurrent filesystem behavior. Done means the acceptance criteria are met without replacing the existing memory API or requiring a watcher.

Written by the indexing model from the issue text.

Assessment

Tech stack
python, sqlite
Domain
backend, databases, search, security
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.