Keep API Schema Reference

Concise reference for the keep memory API. Covers the data model, tools, parameter types, and return formats.

Interface: MCP (keep_flow, keep_prompt, keep_help), CLI (keep <cmd>), or Python (Keeper).

The MCP boundary is keep_flow(state, params) — every operation is a state-doc invocation. Examples below show the JSON payload that goes into the params field.


Data Model

Item

Every piece of stored content is an item.

FieldTypeDescription
idstringUnique identifier (see ID Formats below)
summarystringGenerated or user-provided summary of the content
tags{key: value}Key-value metadata. Values are strings or lists of strings
scorefloat or nullSimilarity score (0-1), present only in search results

Items also carry system-managed timestamps in tags: _created, _updated, _accessed.

Versions

New archived versions are created when put updates an existing item's content. Tag-only updates (tag) and unchanged writes update in place.

SelectorMeaning
@V{0}Current version (default)
@V{1}Previous version
@V{N}N versions back
@V{-1}Oldest archived version

Append the selector to any ID: %a1b2c3@V{1}

Parts

analyze decomposes a document into structural parts — sections with their own summaries, tags, and embeddings.

SelectorMeaning
@P{1}First part (1-indexed)
@P{N}Nth part

Parts appear independently in search results. Retrieve with:

keep_flow(state="get", params={"item_id": "DOC_ID@P{1}"})

ID Formats

FormatExampleCreated by
%hexhash%a1b2c3d4e5f6Inline text when id is omitted (CLI, MCP, Python API)
URLhttps://example.com/docURI put
file:// URIfile:///path/to/doc.pdfLocal file put
Custom stringmy-notesUser-specified id parameter
nownowWorking context (singleton)
.tag/KEY.tag/actTag description (system doc)
.tag/KEY/VALUE.tag/act/commitmentTag value description (system doc)

Tags

Key-value pairs on every item. Keys are alphanumeric (plus _, -). Values are strings or lists of strings.

Setting and removing

keep_flow(state="tag", params={"id": "ID", "tags": {"topic": "auth"}})
keep_flow(state="tag", params={"id": "ID", "tags": {"old-tag": ""}})
keep_flow(state="put", params={"content": "text", "tags": {"project": "myapp"}})

Empty string value removes the tag.

Filtering

Tags on find and list are pre-filters — the search only considers matching items.

keep_flow(state="query-resolve", params={"query": "auth", "tags": {"project": "myapp"}})
keep_flow(state="list", params={"tags": {"status": "open"}})

Multiple tags use AND logic: all must match.

Built-in tags

KeyConstrainedSingularValues
actyesyescommitment, request, offer, assertion, assessment, declaration
statusyesyesopen, blocked, fulfilled, declined, withdrawn, renegotiated
typenonolearning, breakdown, gotcha, reference, teaching, meeting, pattern, possibility, decision
projectnonouser-defined
topicnonouser-defined

Constrained: only listed values accepted. Singular: new values replace old (not accumulate).

System tags (auto-managed, read-only)

_created, _updated, _updated_date, _accessed, _accessed_date, _source, _content_type

These are hidden from default display but accessible via --json or Python API. See SYSTEM-TAGS.md for the full list.


Time Filters

Both since and until accept two formats:

FormatExampleMeaning
ISO 8601 durationP3D3 days ago
P1W1 week ago
P1M~30 days ago
PT1H1 hour ago
P1Y~365 days ago
Date2026-01-15Specific date

since = items updated on or after. until = items updated before.


Tools

put (state doc)

Store text, a URL, or a document. For inline text without an explicit id, keep uses a content-addressed ID.

ParameterTypeRequiredDefaultDescription
contentstringone ofText to store
uristringone ofURI to fetch and index (http://, https://, file://)
idstringnoautoCustom ID. If omitted: URI inputs use the URI as ID; inline text uses a content hash
summarystringnoautoUser-provided summary (skips auto-summarization)
tags{str: str}nononeTags to set. Example: {"topic": "auth"}

Exactly one of content or uri is required. After storing, the after-write flow runs in the background to summarize, tag, analyze, and link the item — this is governed by .state/after-write and is not a parameter on put.

Returns: "Stored: %a1b2c3" or "Unchanged: %a1b2c3" (idempotent on same content)

Examples:

keep_flow(state="put", params={"content": "OAuth2 uses PKCE for public clients", "tags": {"topic": "auth"}})
keep_flow(state="put", params={"uri": "https://docs.example.com/api", "tags": {"kind": "reference"}})
keep_flow(state="put", params={"content": "My design notes", "id": "design-notes", "summary": "Architecture decisions"})

query-resolve (state doc)

Search memory by meaning. Returns items ranked by semantic similarity with recency weighting. This is the iterative entry point — it routes between query-branch and query-explore when results are ambiguous. See FLOWS.md for the state machine.

ParameterTypeRequiredDefaultDescription
querystringyesNatural language search query
tags{str: str}nononePre-filter: only search items matching all tags
sincestringnononeTime filter (see Time Filters)
untilstringnononeTime filter (see Time Filters)
deepboolnofalseFollow tags and edges to discover related items beyond direct matches
limitintno10Maximum results

Returns: Formatted list of results, one per line:

- ID  (score) date  summary text...

Examples:

keep_flow(state="query-resolve", params={"query": "authentication patterns"})
keep_flow(state="query-resolve", params={"query": "open tasks", "tags": {"project": "myapp"}, "since": "P7D"})
keep_flow(state="query-resolve", params={"query": "architecture decisions", "deep": true})

get (state doc)

Retrieve one note in note-first form, with attached context. The result starts with the requested note's tags and body, then may include contextual sections such as similar notes, meta sections, structural parts, linked items, and version navigation.

ParameterTypeRequiredDefaultDescription
item_idstringyesNote ID. Use "now" for current working context

Returns: YAML frontmatter for the requested note plus any available context sections:

---
id: %a1b2c3
tags:
  project: "myapp"
  topic: "auth"
similar:
  - %e5f6a7 (0.89) 2026-01-14 Related item summary...
meta/todo:
  - %d3e4f5 Open task related to this item...
parts:
  - @P{1} Section one summary...
edges/informs:
  - other-note  Related note surfaced via edge tags...
prev:
  - @V{1} 2026-01-13 Previous version summary...
---
Item summary or content here

The exact attached sections depend on what exists for the requested note. Tags are always part of the returned note shape; similar, meta/*, parts, edges/*, prev, and next appear when relevant.

Examples:

keep_flow(state="get", params={"item_id": "now"})
keep_flow(state="get", params={"item_id": "%a1b2c3"})
keep_flow(state="get", params={"item_id": "%a1b2c3@V{1}"})
keep_flow(state="get", params={"item_id": "%a1b2c3@P{1}"})
keep_flow(state="get", params={"item_id": ".tag/act"})

Updating now

The current working context is just an item with id="now". To update it, use put:

keep_flow(state="put", params={"id": "now", "content": "Investigating flaky auth test. Suspect timing issue."})
keep_flow(state="put", params={"id": "now", "content": "Fixed the bug. Next: add regression test.", "tags": {"project": "myapp"}})

Each call creates a new version of the now item. To read current context, use keep_flow(state="get", params={"item_id": "now"}).


tag (state doc)

Add, update, or remove tags on an existing item. Does not re-process content.

ParameterTypeRequiredDefaultDescription
idstringyesItem ID
tags{str: str}yesTags to set. Empty string "" deletes the tag

Returns: "Tagged %abc: set topic=auth; removed old-tag"

Examples:

keep_flow(state="tag", params={"id": "%a1b2c3", "tags": {"status": "fulfilled"}})
keep_flow(state="tag", params={"id": "%a1b2c3", "tags": {"topic": "auth", "obsolete": ""}})

delete (state doc)

Permanently delete an item and all its versions.

ParameterTypeRequiredDefaultDescription
idstringyesItem ID to delete

Returns: "Deleted: %a1b2c3" or "Not found: %a1b2c3"

keep_flow(state="delete", params={"id": "%a1b2c3"})

list (state doc)

List recent items. Supports filtering by ID prefix, tags, and time range. This is plain enumeration, distinct from query-resolve which does semantic search.

ParameterTypeRequiredDefaultDescription
prefixstringnononeID prefix or glob pattern (e.g. ".tag/*")
tags{str: str}nononeFilter by tag key=value pairs
tag_keys[str]nononeFilter by presence of tag keys (any value)
sincestringnononeTime filter
untilstringnononeTime filter
order_bystringnoupdatedSort key: updated, accessed, created, id
include_hiddenboolnofalseInclude system notes (dot-prefix IDs)
limitintno20Maximum results

Returns: List of items, one per line:

- ID  date  summary text...

Examples:

keep_flow(state="list", params={})
keep_flow(state="list", params={"tags": {"act": "commitment", "status": "open"}})
keep_flow(state="list", params={"prefix": ".tag/", "include_hidden": true})
keep_flow(state="list", params={"since": "P7D", "limit": 20})

move (state doc)

Move versions from a source item into a named target. Used to archive working context or reorganize notes.

ParameterTypeRequiredDefaultDescription
namestringyesTarget item ID (created if new, appended if exists)
sourcestringno"now"Source item to extract from
tags{str: str}nononeOnly move versions whose tags match (all must match)
only_currentboolnofalseMove only the tip version, not full history

Note: The MCP/flow parameter is source (matching the wrapper at .state/move). The Python API method kp.move() uses source_id= for the same field — historical name, same meaning.

Returns: "Moved to: my-notes"

Examples:

keep_flow(state="move", params={"name": "auth-work", "tags": {"project": "myapp"}})
keep_flow(state="move", params={"name": "design-log", "only_current": true})
keep_flow(state="move", params={"name": "topic-notes", "source": "old-doc", "tags": {"topic": "auth"}})

keep_prompt

Render an agent prompt template with live context injected from memory. Templates use {get} and {find} placeholders that expand to current item context and search results, plus any bindings from a state-doc-backed prompt's flow.

Signature comes from Keeper.render_prompt() in keep/_context_resolution.py.

ParameterTypeRequiredDefaultDescription
namestringnononePrompt name. Omit to list available prompts
textstringnononeSearch query for {find} placeholder / state doc text param
idstringno"now"Item ID for {get} placeholder / state doc item_id param
sincestringnononeLower-bound time filter for search context
untilstringnononeUpper-bound time filter for search context
tags{str: str}nononeTag filter for search context
limitintno10Max search results
deepboolnofalseFollow tags/edges to discover related items
scopestringnononeID glob to constrain search results
token_budgetintnotemplate defaultToken budget for rendered context

Returns: Rendered prompt text with placeholders expanded, or list of available prompts.

Bundled prompts (see keep list .prompt/agent --all):

NamePurpose
reflectStructured reflection on actions and outcomes
session-startContext and open commitments at session start
session-endEnd-of-session synthesis
subagent-startSubagent initialization context
queryAnswer a question using memory context
conversationConversation analysis
systemGeneric reflective-memory practice (host-agnostic system prompt)
system-hermesHermes-specific system-prompt wrapper around system
hermes-assembleHermes per-turn context assembly
openclaw-assembleOpenClaw per-turn context assembly

The system* and *-assemble prompts are intended for host integrations (Hermes, OpenClaw) rather than direct agent invocation, but they're discoverable here for completeness. Custom prompts can be added under .prompt/agent/.

Examples:

keep_prompt()
keep_prompt(name="reflect")
keep_prompt(name="session-start")
keep_prompt(name="query", text="what do I know about auth?")
keep_prompt(name="reflect", text="deployment", since="P3D")
keep_prompt(name="query", text="auth", tags={"project": "myapp"}, deep=true)
keep_prompt(name="query", text="api docs", scope="https://docs.example.com/*")

Common Patterns

Session lifecycle

keep_prompt(name="session-start")
keep_flow(state="get", params={"item_id": "now"})
keep_flow(state="put", params={"id": "now", "content": "Completed X. Next: Y."})
keep_prompt(name="reflect")

Store and retrieve

keep_flow(state="put", params={"content": "insight text", "tags": {"kind": "learning", "topic": "auth"}})
keep_flow(state="query-resolve", params={"query": "authentication insights"})
keep_flow(state="get", params={"item_id": "%returned_id"})

Track commitments

keep_flow(state="put", params={"content": "Will fix bug by Friday", "tags": {"act": "commitment", "status": "open"}})
keep_flow(state="list", params={"tags": {"act": "commitment", "status": "open"}})
keep_flow(state="tag", params={"id": "ID", "tags": {"status": "fulfilled"}})

Index a document

keep_flow(state="put", params={"uri": "https://docs.example.com/api", "tags": {"kind": "reference", "topic": "api"}})
keep_flow(state="query-resolve", params={"query": "API documentation"})

Archive and pivot

keep_flow(state="move", params={"name": "auth-work", "tags": {"project": "myapp"}})
keep_flow(state="put", params={"id": "now", "content": "Starting on database migration"})

See Also