Working with AI Agents
Working with AI Agents
Lettuce ships a built-in MCP server, so AI agents can
read, search, link, and edit the same .md files you’re working in. You stay in control:
every agent edit is attributed and revertible from the GUI, and any note you have
open in the editor is soft-locked against agent writes.
When Lettuce is running, the server is too. Point your MCP client at
http://127.0.0.1:51234/mcp (the banner prints the API key) and you’re done.
Headless from a terminal: lettuce serve ~/Notes.
Talking to agents inside notes
Two file-native conventions let the user address agents without leaving the editor:
@handlementions — type@claude(or any agent label) anywhere in a note. Agents pollagent_mentionsto find work addressed to them; the response includes the path, line, and the surrounding line as context. Filter byhandleto get a per-agent queue.[!ai]directive callouts — a Markdown callout asking for work:> [!ai] Summarize the section above and add a TL;DR at the top.Agents poll
pending_directivesfor unresolved ones, do the work (write_note, patch_section, etc.), then callcomplete_directive(path, line, response?)which flips the marker to[!ai-done]and optionally splices a response back into the same callout. The callout renders in a distinct violet style;[!ai-done]shows in green with a ✓.
Both signals are plain Markdown — they live in the file, not in a sidecar. Reverting an agent edit from the GUI’s timeline rolls them back like any other write.
The vault’s brief: AGENTS.md
Each vault may include an AGENTS.md file at its root with the user’s conventions
(folder structure, tag taxonomy, style preferences, do/don’t rules). Agents should
read it on every connect: get_vault_info surfaces its content automatically in the
agentsFile field, so a single tool call is enough. If agentsFile is null, suggest
that the user run lettuce agents init to scaffold one from their existing folders + tags.
What an agent can do
Tools fall into three groups: read (no risk), edit (writes, tracked and revertible),
and organize (folder operations). All write tools require valid auth scope.
delete_note and delete_folder require confirm: true so an agent can’t accidentally
trash your work.
Read & discover
| Tool | Purpose |
|---|---|
get_vault_info |
Root, note count, index time, AGENTS.md brief + capabilities (embeddings/llm configured, has index.md, propose-only) and liveness (pending-directive count, last log date, index-stale). |
list_notes |
Enumerate notes, optionally under a folder. Paginated. |
read_note |
Body, frontmatter, tags, outgoing links, file stat. |
search |
Full-text over titles and bodies. |
list_tags / notes_by_tag |
Browse by tag, incl. nested (#project/web). |
list_backlinks / list_outgoing_links |
Walk the graph from any note. |
suggest_links |
Unlinked mentions in a note: other notes’ names that appear as plain text. |
lint |
Vault hygiene findings: broken links, orphans, tag issues. |
list_folders |
All group paths, including empty ones, excluding .trash. |
agent_mentions |
@handle mentions across the vault; filter by handle for a per-agent queue. |
pending_directives |
Unresolved > [!ai] callouts; each is a task waiting to be done. |
read_outline |
Heading outline (level, title, anchor id) without the body — cheap navigation. |
link_graph |
BFS the link graph around a note up to depth hops; both directions. Use to build a context bundle. |
list_attachments / read_attachment |
Non-markdown files (images, PDFs, data); read one as base64. |
list_my_proposals / withdraw_proposal |
A propose-only key’s own pending proposals. |
Retrieve & answer (embeddings/LLM)
| Tool | Purpose |
|---|---|
semantic_search |
Vector search by meaning; hybrid fuses with keyword, plus prefer_recent / expand. |
answer |
Grounded, cited RAG answer; opt-in rerank / expand / use_graph / check_faithfulness. |
related_notes |
Notes semantically nearest to one that it isn’t already linked to. |
find_duplicates |
Near-duplicate page pairs (cosine ≥ threshold) — merge candidates. |
topic_map |
Cluster the vault into topics; flag clusters with no hub page. |
lint_semantic |
LLM health check: contradictions, stale claims, missing-concept, open questions, sources to ingest. |
suggest_tags |
LLM tag proposals for the untagged / missing-required notes. |
eval |
Score retrieval/answer quality (recall@k, MRR, faithfulness) against eval/questions.jsonl. |
wiki_health |
A single 0–100 health score (link health, lint cleanliness, tag coverage). |
recent_activity |
The log.md ledger as data + sources/ notes not yet compiled. |
reindex_embeddings |
Force-refresh the semantic index after a batch of writes. |
Edit
| Tool | Purpose |
|---|---|
write_note |
Create, overwrite, append, or prepend a note. |
patch_section |
Surgical edit: target a heading, block id, or frontmatter key. |
apply_edits |
Atomic find/replace edits to a note. Each find must match exactly once; the whole call rolls back if any edit fails. |
file_page |
File a NEW page + catalog it in index.md + append log.md, atomically (proposable as a batch). |
wiki_maintain |
Run the semantic health check and file each new finding as a > [!ai] directive. |
ingest_url / ingest_file |
Pull a web page / existing vault file into the raw sources/ layer. |
propose_batch |
Propose several writes as one reviewable batch (propose-only keys). |
move_note |
Rename or relocate a note; rewrites inbound links ([[wikilinks]] and [text](path.md) Markdown links). |
delete_note |
Soft-trash by default (confirm: true required). |
complete_directive |
Flip a [!ai] callout to [!ai-done]; optional response is spliced back into the same callout. |
Organize
| Tool | Purpose |
|---|---|
create_folder |
Create a group (intermediates allowed). |
rename_folder |
Rename or move a group; rejected if a contained note is open in the editor. |
delete_folder |
Soft-trash by default (confirm: true required). |
Suggestions mode
When the API key is configured as propose-only, every write tool above returns
{"status":"pending","proposalId":"…"} instead of the usual DTO — the change waits in
the user’s review queue. Two extra tools let the agent track its own queue:
| Tool | Purpose |
|---|---|
list_my_proposals |
Returns the calling key’s pending proposals (id, tool, path, operation, timestamp). |
withdraw_proposal |
Cancels a proposal the agent created. Refuses to touch other agents’ queues. |
See Suggestions mode for the full design + recipe.
Three example prompts
Triage my inbox: read every note in
Inbox/, summarize each in one line, and move drafts (frontmatterstatus: draft) intoArchive/.
Find every unlinked mention of “Project Lettuce” across the vault and patch them into
[[Project Lettuce]]wikilinks. Skip notes tagged#draft.
Pre-build next quarter: create
Projects/2026/Q1/with subgroupsRoadmap,Retro, andOKRs, and seed a placeholderRoadmap.mdin each.
How writes show up in the app
Every write tool records the edit in the coordinator that the GUI watches:
Attributed: the agent’s label is stored alongside the edit.
Revertible: undo from the GUI’s review panel, even hours later.
Lock-aware: opening a note in the editor soft-locks it; agents get a
userEditingerror until you stop typing or move on.
MCP vs CLI
| You’re doing… | Reach for |
|---|---|
| Interactive work mid-session (read, edit, search, link) | MCP tools (this page) |
| One-shot batch operations (publish, deploy, lint, scaffold) | CLI ([[CLI cookbook/00 Overview |
| Scripting folder layout from a shell | CLI (lettuce folder …) |
Both surfaces share the exact same code path, so semantics never drift.