Suggestion tools
Suggestion tools
Tools for agents to manage their own pending proposals and address mentions.
These are most useful for propose-only keys: their writes don’t commit, they queue as proposals for a human to accept or reject (see Suggestions mode/01 Overview). Both tools are scoped to read — they only touch the proposal store, never vault content — and both are filtered to the calling key’s own queue, so one agent can’t peek at or cancel another’s.
list_my_proposals
List the pending proposals authored by the calling key.
Input: none.
{}
Returns:
{
"proposals": [
{
"id": "ab12cd34-...-uuid",
"tool": "patch_section",
"path": "Inbox/note.md",
"operation": "patch",
"timestamp": "2026-05-28T09:12:34Z"
}
]
}
Each entry reports the tool that produced the proposal, the target path, the operation kind, and when it was filed. There is no server-side filter argument — filter client-side on the returned list if you need to.
withdraw_proposal
Cancel a pending proposal you authored. Refuses to touch other agents’ queues.
Input:
{"id": "ab12cd34-...-uuid"}
The id must be a lowercase UUID (the same value list_my_proposals returns); anything else is rejected before it reaches the store.
Returns:
{"ok": true, "id": "ab12cd34-...-uuid"}
ok is false if no matching proposal was found in your queue (already accepted/rejected, or never yours).
propose_batch
File several note writes as one reviewable batch — e.g. a multi-page ingest — so the user accepts or rejects the whole set together rather than approving pages one by one. Propose-only keys only (a commit key should just write each note directly). Each item is a write_note.
Input:
{
"items": [
{"path": "Pages/Vector databases.md", "content": "---\ntitle: ...\n---\n# ...", "mode": "create"},
{"path": "Pages/Embeddings.md", "content": "..."},
{"path": "index.md", "content": "...", "mode": "append"}
]
}
mode is create (default) / overwrite / append / prepend. Every item’s path is checked against the key’s folder allowlist; if any is out of scope the whole batch is rejected and nothing is saved.
Returns:
{"status": "pending", "batchId": "ab12cd34-...", "proposalIds": ["...", "..."], "count": 3}
The proposals appear grouped under the batch in the proposals UI, with Accept all / Reject all. Accepting a batch applies its proposals in order; if one has gone stale meanwhile it’s reported and skipped while the rest still apply (a batch isn’t a single atomic transaction across files).
complete_directive
Mark a > [!ai] directive (found via pending_directives) as done. It flips the callout marker at path line line from [!ai] to [!ai-done], so the directive disappears from future pending_directives calls. This tool needs the write scope.
Input:
{
"path": "Projects/Lettuce.md",
"line": 42,
"response": "Done; created Inbox/foo.md and tagged the source.", // optional
"fingerprint": "> [!ai] @agent draft the spec" // optional
}
lineis the 1-based line of the directive’s marker, as returned bypending_directives.response, if supplied, is spliced into the same callout below the directive.fingerprint, if supplied, is the marker line’s exact text. If the line has drifted (the file changed under you), the call is rejected rather than marking the wrong directive done.
Returns: {path, line, response} — the note path, the directive’s line, and the response text spliced in (or null if none).
Errors: directive not found at that line; fingerprint mismatch (line drifted).
Patterns
Self-cleanup on start
Useful for long-lived agents: clear out your stale proposals on each connection. Filter client-side on the fields the list returns.
import datetime
cutoff = datetime.datetime.now(datetime.timezone.utc) - datetime.timedelta(hours=24)
for p in client.tools.list_my_proposals().proposals:
if datetime.datetime.fromisoformat(p.timestamp) < cutoff:
client.tools.withdraw_proposal(id=p.id)
Address-and-acknowledge
for d in client.tools.pending_directives().directives:
# do the work...
result = do_the_thing(d)
client.tools.complete_directive(
path=d.path,
line=d.line,
response=f"Done: {result.summary}",
fingerprint=d.marker, # guard against the line drifting
)
Rotate a proposal when ground truth shifts
for p in client.tools.list_my_proposals().proposals:
if needs_resubmit(p):
client.tools.withdraw_proposal(id=p.id)
# re-submit with fresh context — the same write tool re-queues it
client.tools.patch_section(path=p.path, ...)
Advisors that pair with proposals
Two read-scoped LLM advisors are the natural source of what to propose. Both are documented in Agent reference/04 Read tools and both require an LLM provider configured (Settings → AI providers, or via env):
lint_semantic— a wiki health check: contradictions between pages, stale claims, important concepts that lack a page, data gaps. Advisory; nothing is applied.suggest_tags— tag suggestions for the untagged / missing-required notes thatlintflags. Propose-then-confirm; nothing is applied.
Run these, then turn the findings into actual write_note / patch_section / apply_edits calls (which queue as proposals under a propose-only key).
Related
Agent reference/05 Write tools — the write tools that produce proposals under a propose-only key
Agent reference/04 Read tools —
lint_semanticandsuggest_tagsadvisorsSuggestions mode/06 Withdraw and ownership — full ownership model
Suggestions mode/04 Staleness and conflicts — when proposals go stale