KIPSyntax.md

August 14, 2026 ยท View on GitHub

๐Ÿงฌ KIP (Knowledge Interaction Protocol) Syntax Reference

Full Spec: https://raw.githubusercontent.com/ldclabs/KIP/refs/heads/main/SPECIFICATION.md

KIP is a graph-oriented protocol for an agent's long-term memory brain. The graph contains Concept Nodes (entities) and Proposition Links (facts). LLMs read/write via KQL (query: FIND), KML (manipulate: UPSERT/UPDATE/MERGE/DELETE), and META (ground/introspect/round-trip: SEARCH/DESCRIBE/EXPORT). Data uses a JSON-compatible value model; KIP object literals allow unquoted identifier keys as shorthand for JSON string keys.


1. Data Model & Lexical Rules

ElementIdentityRequired fieldsOptional
Concept Nodeid OR {type, name}type (UpperCamelCase), nameattributes, metadata
Proposition Linkid OR (subject, predicate, object)subject/object (concept or link id), predicate (snake_case)attributes, metadata

subject and object may reference another Proposition Link, enabling higher-order facts.

1.2. Data Types (JSON)

  • Primitives: string, number, boolean, null.
  • Complex: Array, Object โ€” allowed in attributes / metadata; FILTER operates only on primitive comparison values.
  • Object keys: quoted JSON string keys and unquoted identifier keys are both accepted; unquoted keys are normalized as strings.

1.3. Identifiers & Prefixes

  • Syntax: [a-zA-Z_][a-zA-Z0-9_]*. Case-sensitive.
  • ? โ€” query variable (?drug).
  • $ โ€” system meta-type ($ConceptType, $self, $system).
  • : โ€” parameter placeholder in command text (:name, :limit).

1.4. Naming Conventions

ElementStyleExamples
Concept TypesUpperCamelCaseDrug, ClinicalTrial
Proposition Predicatessnake_casetreats, has_side_effect
Attribute / Metadata Keyssnake_caserisk_level, created_at
Variables? + snake_case?drug, ?side_effect

Required for schema-level names and variables; recommended for attribute / metadata keys. Wrong case on a type/predicate (e.g. drug vs Drug) โ†’ KIP_2001.

1.5. Dot Notation (data access)

In FIND / FILTER / ORDER BY:

  • Concept: ?var.id, ?var.type, ?var.name
  • Proposition: ?var.id, ?var.subject, ?var.predicate, ?var.object
  • Attributes: ?var.attributes.<key>
  • Metadata: ?var.metadata.<key>
  • Whole object: ?var.attributes / ?var.metadata โ€” full-object projection in FIND (not comparable in FILTER).

1.6. Schema Bootstrapping (Define Before Use)

KIP is self-describing: every legal type/predicate is itself a node.

  • {type: "$ConceptType", name: "Drug"} registers Drug as a concept type.
  • {type: "$PropositionType", name: "treats"} registers treats as a predicate.

Using an unregistered type/predicate โ†’ KIP_2001.

1.7. Data Consistency

  • Shallow merge: SET ATTRIBUTES and WITH METADATA overwrite only specified keys; unspecified keys remain. Array/Object values are overwritten at the key (no recursive deep merge) โ€” supply the full array when updating.
  • Proposition uniqueness: at most one link per (subject, predicate, object). Duplicate UPSERT โ†’ updates attributes/metadata of the existing link.
  • expires_at is a signal, not auto-filter: expired knowledge stays queryable until a background $system process cleans it. Add FILTER(IS_NULL(?x.metadata.expires_at) || ?x.metadata.expires_at > <now>) to skip expired entries.

1.8. Reserved System Metadata (_ namespace) & Optimistic Concurrency

Metadata keys starting with _ are engine-maintained and read-only to KML (writing them โ†’ KIP_2002). Readable via dot notation like any metadata:

FieldSemantics
_versionMonotonic mutation counter (starts at 1). Target of EXPECT VERSION.
_updated_atEngine-recorded ISO-8601 time of last mutation.
_scoreTransient normalized SEARCH relevance [0,1]; never persisted.
_merged_fromProvenance trail left by MERGE ("<Type>:<name>" entries).

EXPECT VERSION <n> (optional line in UPSERT CONCEPT/PROPOSITION blocks, right after the identity clause): block executes only if the element's _version equals <n>; EXPECT VERSION 0 = must-not-exist (create-only). On mismatch the whole UPSERT aborts with KIP_3005 โ†’ re-read, re-merge, retry. Use it for every read-modify-write of array/object values (e.g., $self attributes, logs).


2. KQL โ€” Knowledge Query Language

FIND( <variables_or_aggregations> )
WHERE { <patterns_and_filters> }
ORDER BY <expr> [ASC|DESC], <expr> [ASC|DESC], ...
LIMIT <integer>
CURSOR "<token>"

ORDER BY / LIMIT / CURSOR are optional.

2.1. FIND

  • Variables / dot-paths: FIND(?a, ?b.name, ?b.attributes.risk_level)
  • Aggregations: COUNT(?v), COUNT(DISTINCT ?v), SUM(?v), AVG(?v), MIN(?v), MAX(?v).
  • Implicit GROUP BY: when FIND mixes plain expressions with aggregations, all non-aggregated expressions form the grouping key. With only aggregations, the whole result set is one group.
  • Null handling: aggregations ignore null (unbound) values โ€” COUNT(?v) over an OPTIONAL-miss group returns 0.
  • Solution dedup: duplicate solutions (identical bindings) collapse (set semantics) before ORDER BY / LIMIT; distinct solutions projecting equal values are kept.

2.2. WHERE Patterns (AND-connected by default)

2.2.1. Concept Match {...}
?var {id: "<id>"}                       // by id
?var {type: "<Type>", name: "<name>"}   // exact
?var {type: "<Type>"}                   // broad
?var {name: "<name>"}                   // broad

When used directly as subject/object inside a proposition clause, omit the variable name: (?p, "treats", {type: "Symptom", name: "Headache"}).

2.2.2. Proposition Match (...)
?link (id: "<id>")                          // by id
?link (?subject, "<predicate>", ?object)    // structural
?link (?subject, ?pred, ?object)            // predicate VARIABLE โ€” associative recall
(?u, "stated", (?s, "<pred>", ?o))          // higher-order (object is a link)

The leading ?link is optional; endpoints are ?var, an unnamed {...} concept clause, or an unnamed nested (...) proposition clause. Do not attach a variable name to an embedded endpoint clause โ€” bind it in a separate clause first, then reference the variable.

Predicate variables: ?pred binds the predicate name (string); project it in FIND, test it in FILTER (string ops, IN), unify it across clauses. No quantifiers/alternatives on a variable (?p{1,3} invalid). Constrain at least one endpoint and add LIMIT โ€” engines MAY reject a fully unconstrained (?s, ?p, ?o) with KIP_4002. The ego-graph ("what surrounds X?") pattern:

FIND(?pred, ?neighbor)
WHERE {
  ?link ({type: "Person", name: "Alice"}, ?pred, ?neighbor)
  FILTER(?pred != "belongs_to_domain")
} LIMIT 50

Predicate path modifiers (literal predicates only):

  • Hops: "<pred>"{m,n}, "<pred>"{m,}, "<pred>"{n}. m == 0 includes a zero-hop reflexive match (subject == object, no edge traversed).
  • Alternatives: "<p1>" | "<p2>" | ....
2.2.3. FILTER(<bool_expr>)
CategoryOperators / Functions
Comparison==, !=, <, >, <=, >=
Logical&&, ||, !
MembershipIN(?expr, [v1, v2, ...])
Null checkIS_NULL(?expr), IS_NOT_NULL(?expr)
StringCONTAINS, STARTS_WITH, ENDS_WITH, REGEX
FILTER(?drug.attributes.risk_level < 3 && CONTAINS(?drug.name, "acid"))
FILTER(IN(?event.attributes.event_class, ["Conversation", "SelfReflection"]))
FILTER(IS_NOT_NULL(?node.metadata.expires_at))
FILTER(?event.attributes.start_time > "2025-01-01T00:00:00Z")  // ISO-8601 string compare
2.2.4. OPTIONAL { ... } โ€” Left Join

External vars visible inside; internal vars visible outside (null if no match). Dot-notation projection on an unbound var yields null, and IS_NULL(?var) is true.

?drug {type: "Drug"}
OPTIONAL { (?drug, "has_side_effect", ?side_effect) }
// ?side_effect == null when none exists
2.2.5. NOT { ... } โ€” Exclusion

External vars visible inside; internal vars are private (not visible outside). Discards the solution if the inner pattern matches.

?drug {type: "Drug"}
NOT { (?drug, "belongs_to_class", {name: "NSAID"}) }
2.2.6. UNION { ... } โ€” Logical OR

External vars are not visible inside UNION (independent scope). Internal vars are visible outside. Both branches run independently; rows are union-ed and deduplicated. Same-named variables in both branches are independent bindings; absent variables become null.

?drug {type: "Drug"}
(?drug, "treats", {name: "Headache"})
UNION {
  ?drug {type: "Drug"}
  (?drug, "treats", {name: "Fever"})
}
2.2.7. Variable Scope Summary
ClauseExternal vars visible inside?Internal vars visible outside?
FILTERYesN/A
OPTIONALYesYes (null on miss)
NOTYesNo (private)
UNIONNo (independent)Yes

2.3. Solution Modifiers

  • ORDER BY <expr> [ASC|DESC], <expr> [ASC|DESC], ... โ€” one or more comma-separated sort keys, left to right; default ASC. Each key: a variable, a dot-path, or an aggregation expression that also appears in FIND (e.g., ORDER BY COUNT(?n) ASC). null always sorts last regardless of direction. Memory-ranking idiom: ORDER BY ?e.attributes.salience_score DESC, ?e.attributes.start_time DESC. Bare ?var keys only for primitive bindings (e.g., predicate variables); otherwise sort by a dot-path.
  • LIMIT N or LIMIT :param.
  • CURSOR "<token>" or CURSOR :param โ€” opaque pagination token from a previous response's next_cursor.

2.4. Examples

// Optional + filter
FIND(?drug.name, ?side_effect.name)
WHERE {
  ?drug {type: "Drug"}
  OPTIONAL { (?drug, "has_side_effect", ?side_effect) }
  FILTER(?drug.attributes.risk_level < 3)
}

// Aggregation + NOT + ORDER BY + LIMIT
FIND(?drug.name, ?drug.attributes.risk_level)
WHERE {
  ?drug {type: "Drug"}
  (?drug, "treats", {name: "Headache"})
  NOT { (?drug, "belongs_to_class", {name: "NSAID"}) }
  FILTER(?drug.attributes.risk_level < 4)
}
ORDER BY ?drug.attributes.risk_level ASC
LIMIT 20

// Higher-order: confidence that a user stated a fact
FIND(?statement.metadata.confidence)
WHERE {
  ?fact ({type: "Drug", name: "Aspirin"}, "treats", {type: "Symptom", name: "Headache"})
  ?statement ({type: "Person", name: "John Doe"}, "stated", ?fact)
}

3. KML โ€” Knowledge Manipulation Language

Four statements: UPSERT (identity-addressed create-or-update), UPDATE (pattern-matched bulk mutation), MERGE (atomic entity consolidation), DELETE (targeted removal).

3.1. UPSERT (atomic, idempotent)

UPSERT {
  CONCEPT ?handle {
    {type: "<Type>", name: "<name>"}    // match-or-create
    // OR  {id: "<id>"}                 // match-only (must exist)
    EXPECT VERSION <n>                  // optional CAS guard (see ยง1.8)
    SET ATTRIBUTES { <key>: <value>, ... }
    SET PROPOSITIONS {
      ("<predicate>", ?other_handle)
      ("<predicate>", ?other_handle) WITH METADATA { <key>: <value>, ... }
      ("<predicate>", {type: "<T>", name: "<N>"})    // target must exist or KIP_3002
      ("<predicate>", {id: "<id>"})
      ("<predicate>", (id: "<link_id>"))
      ("<predicate>", (?s, "<pred>", ?o))            // higher-order
    }
  }
  WITH METADATA { ... }                 // local metadata (concept block)

  PROPOSITION ?prop_handle {            // ?prop_handle is optional
    (?subject, "<predicate>", ?object)  // endpoints: ?handle, {...}, or (...)
    // OR  (id: "<id>")                 // match-only
    EXPECT VERSION <n>                  // optional CAS guard (see ยง1.8)
    SET ATTRIBUTES { ... }
  }
  WITH METADATA { ... }                 // local metadata (proposition block)
}
WITH METADATA { ... }                   // global default for all items

Rules:

  1. Sequential, top-to-bottom. Handles must be defined before reference. Dependencies form a DAG (no cycles).
  2. Shallow merge for SET ATTRIBUTES / WITH METADATA.
  3. SET PROPOSITIONS is additive โ€” new links are added or updated; never deletes unspecified ones. Any item may append WITH METADATA { ... }.
  4. Metadata precedence: inner WITH METADATA overrides outer key-by-key (shallow); unspecified keys inherit from outer, and specified null still overrides. Lifecycle keys (expires_at, memory_tier) belong in the target block's own WITH METADATA, never in the statement-level default โ€” the default shallow-merges onto every element in the statement, silently stamping an episodic TTL onto matched durable nodes (e.g., a Person).
  5. Existing target refs: {type, name}, {id}, (id: ...), and nested proposition targets must already exist, or return KIP_3002.
  6. Provenance: always set source, author, confidence in WITH METADATA.
  7. EXPECT VERSION mismatch aborts the entire UPSERT atomically with KIP_3005 โ€” re-read, re-merge, retry.

Response: {"blocks": <n>, "upsert_concept_nodes": ["<id>", ...], "upsert_proposition_links": ["<id>", ...]} โ€” blocks counts executed UPSERT statements (a capsule may carry several); the arrays list every top-level CONCEPT / PROPOSITION block's ID in execution order. Links from SET PROPOSITIONS are not itemized (FIND them when IDs are needed); dry_run leaves the arrays empty.

3.1.1. Idempotency Patterns
  • Prefer deterministic identity {type: "T", name: "N"} for concepts.
  • Use deterministic Event names so retries do not duplicate.
  • Avoid random names/ids unless retries are guaranteed stable.
3.1.2. Safe Schema Evolution (sparingly)

When stable memory needs a new type/predicate:

  1. Define it as $ConceptType / $PropositionType.
  2. Assign it to the CoreSchema domain via belongs_to_domain.
  3. Keep definitions minimal and broadly reusable.

Common predicates worth registering early: prefers, knows, collaborates_with, interested_in, working_on, derived_from, belongs_to_class.

UPSERT {
  CONCEPT ?prefers_def {
    {type: "$PropositionType", name: "prefers"}
    SET ATTRIBUTES {
      description: "Subject indicates a stable preference for an object.",
      subject_types: ["Person"],
      object_types: ["*"]
    }
    SET PROPOSITIONS { ("belongs_to_domain", {type: "Domain", name: "CoreSchema"}) }
  }
}
WITH METADATA { source: "SchemaEvolution", author: "$self", confidence: 0.9 }

3.2. UPDATE (pattern-matched bulk mutation; never creates)

UPDATE ?target
SET ATTRIBUTES { <key>: <value_or_expr>, ... }   // โ‰ฅ1 of the two SET blocks
SET METADATA { <key>: <value_or_expr>, ... }     // `_` keys rejected (KIP_2002)
WHERE { <patterns binding ?target> }
LIMIT N                                          // optional blast-radius cap

Atomic: all matched elements update or none. Update expressions (numeric, computed per element from ?target's own state only): ADD(a, b), MUL(a, b), CLAMP(x, lo, hi), COALESCE(x, default). A null/non-number expression skips that key for that element. Scan bounds: LIMIT caps updates, not the scan โ€” a fully unconstrained (?s, ?p, ?o) pattern is a full-graph scan the engine may reject on large graphs (KIP_4002); shard sweeps by predicate, endpoint type, or domain. The memory-metabolism workhorse:

// Memory-strength decay across all predicates, one command โ€” small graphs only:
// past the engine's scan cap, shard per predicate ((?s, "prefers", ?o)) instead
// (spare structural links). Disuse decays metadata.memory_strength (accessibility);
// metadata.confidence (epistemic support) changes only on evidence, contradiction, or retraction.
UPDATE ?link
SET METADATA {
  memory_strength: CLAMP(MUL(COALESCE(?link.metadata.memory_strength, 0.7), :factor), 0.0, 1.0),
  strength_decay_applied_at: :now
}
WHERE {
  ?link (?s, ?p, ?o)
  FILTER(?p != "belongs_to_domain")
  FILTER(IS_NULL(?link.metadata.superseded) || ?link.metadata.superseded != true)
  FILTER(IS_NULL(?link.metadata.observed_at) || ?link.metadata.observed_at < :stale_cutoff)
  // Floor: skip fully decayed links so the sweep converges
  FILTER(IS_NULL(?link.metadata.memory_strength) || ?link.metadata.memory_strength > 0.05)
  // Idempotency guard: one decay per link per cycle; re-run until updated < LIMIT,
  // reusing the same :cycle_start across re-runs and crash-retries
  FILTER(IS_NULL(?link.metadata.strength_decay_applied_at) || ?link.metadata.strength_decay_applied_at < :cycle_start)
} LIMIT 500

// Reinforce without read-modify-write
UPDATE ?pref
SET ATTRIBUTES { evidence_count: ADD(COALESCE(?pref.attributes.evidence_count, 0), 1), last_observed: :now }
WHERE { ?pref {type: "Preference", name: :pref_name} }

Response: {"updated": <n>, "matched": <m>} โ€” matched by WHERE (after LIMIT), actually mutated.

3.3. MERGE (atomic entity consolidation)

MERGE CONCEPT ?source INTO ?target
WHERE { ?source {type: "<T>", name: "<dup>"} ?target {type: "<T>", name: "<canonical>"} }

Each variable must match exactly one node, same type (0 โ†’ KIP_3002; >1 โ†’ KIP_3003; type mismatch โ†’ KIP_2002). Atomically: repoints all of source's links to target (link ids preserved; (s,p,o) collisions keep target's link, fill its missing keys, drop the duplicate), fills target's missing attributes (target wins; aliases unioned + source name appended to target's aliases), deletes source, records _merged_from (the source's own _merged_from entries carry over). Re-running after success โ†’ KIP_3002 = "already merged" (engines SHOULD hint this when the target's _merged_from lists the source). Protected nodes โ†’ KIP_3004.

3.4. DELETE (smallest unit first)

Prefer: metadata โ†’ attribute โ†’ proposition โ†’ concept.

// Attributes
DELETE ATTRIBUTES {"risk_category", "old_id"} FROM ?drug
WHERE { ?drug {type: "Drug", name: "Aspirin"} }

// Metadata
DELETE METADATA {"old_source"} FROM ?drug
WHERE { ?drug {type: "Drug", name: "Aspirin"} }

// Propositions
DELETE PROPOSITIONS ?link
WHERE {
  ?link (?s, "treats", ?o)
  FILTER(?link.metadata.source == "untrusted_source_v1")
}

// Concept (DETACH is mandatory; removes all incident links)
DELETE CONCEPT ?drug DETACH
WHERE { ?drug {type: "Drug", name: "OutdatedDrug"} }

DELETE ATTRIBUTES / DELETE METADATA targets may be concept or proposition variables. Always verify with FIND before DELETE CONCEPT; DETACH cascades through higher-order propositions. KIP_3004 protects meta-types, the Domain type and belongs_to_domain definitions, core domains, $self/$system identity tuples, and their core_directives; ordinary $self attributes may evolve. Response: ATTRIBUTES/METADATA โ†’ {"updated_concepts": <n>, "updated_propositions": <m>} (key removal mutates, deletes nothing); PROPOSITIONS โ†’ {"deleted_propositions": <n>}; CONCEPT โ†’ {"deleted_concepts": <n>, "deleted_propositions": <m>} (cascade audit).


4. META โ€” Grounding, Introspection & Export

4.1. DESCRIBE (introspection)

DESCRIBE PRIMER                                 // Agent identity + Domain Map
DESCRIBE DOMAINS                                // top-level domains
DESCRIBE CONCEPT TYPES [LIMIT N] [CURSOR "<t>"] // list concept types
DESCRIBE CONCEPT TYPE "<Type>"                  // schema of one type
DESCRIBE PROPOSITION TYPES [LIMIT N] [CURSOR "<t>"]
DESCRIBE PROPOSITION TYPE "<predicate>"

4.2. SEARCH (index-driven grounding & associative retrieval)

SEARCH CONCEPT "<term>"|:term [WITH TYPE "<Type>"|:type]
  [MODE "keyword"|"semantic"|"hybrid"|:mode] [THRESHOLD <0..1>|:threshold] [LIMIT N|:limit]
SEARCH PROPOSITION "<term>"|:term [WITH TYPE "<predicate>"|:type] [MODE ...] [THRESHOLD ...] [LIMIT N|:limit]
  • Modes: keyword (lexical), semantic (meaning-based; engine owns embeddings โ€” text in, never vectors), hybrid (fused; recommended default). Omitted MODE โ†’ hybrid where supported, else keyword; engines without semantic capability silently degrade to keyword.
  • Grounding fields: engines MUST index name + attributes.aliases; SHOULD index description and salient text attributes.
  • Scoring: each hit carries transient metadata._score ([0,1], descending order); THRESHOLD drops weak hits โ€” a weak match is worse than an honest miss.
  • Use SEARCH to resolve fuzzy names โ†’ exact {type, name} before structured FIND; use MODE "semantic" when the probe is a meaning, not a name.

4.3. EXPORT (capsule round-trip; read-only)

EXPORT ?target WHERE { ... } [LIMIT N] [CURSOR "<t>"]

Serializes matched concepts/propositions into an idempotent UPSERT capsule for backup, migration, and agent-to-agent knowledge exchange. Bind everything the capsule needs: a nodes-only WHERE exports unconnected concepts โ€” also bind the links among them, their belongs_to_domain links, and the Domain node itself via separate UNION branches (each branch binds ?target independently; without the Domain node, importing into a fresh nexus fails with KIP_3002). Endpoints outside the export set become {type, name} refs (must exist on import); outside proposition endpoints become nested structural (s, "p", o) clauses (link IDs are not portable; must exist on import); reserved _ metadata is never exported; export needed $ConceptType/$PropositionType definitions separately if the destination may lack them. Response: {"capsule": "<KIP script>", "concepts": n, "propositions": m}, plus next_cursor when more remain โ€” re-issue with CURSOR to continue; each page is an independently valid capsule.


5. API (JSON-RPC)

5.1. Functions

  • execute_kip_readonly โ€” KQL (FIND) and META (DESCRIBE / SEARCH / EXPORT) only.
  • execute_kip โ€” full read/write (adds KML: UPSERT / UPDATE / MERGE / DELETE).

5.2. Parameters

  • command (String) OR commands (Array) โ€” exactly one MUST be provided.
  • commands element: a string (uses shared parameters) or {command, parameters} (independent).
  • parameters (Object): :name โ†’ JSON value substitution. Placeholders must occupy a complete KIP value position (name: :name, LIMIT :limit, SEARCH CONCEPT :term); never embed inside a string literal ("Hello :name" is invalid โ€” substitution uses JSON serialization).
  • dry_run (Boolean): validate only.

Batch error semantics: KQL / META / syntax errors are returned inline and execution continues. The first KML (UPSERT / UPDATE / MERGE / DELETE) error stops the batch.

5.3. Examples

// Single read-only
{
  "function": {
    "name": "execute_kip_readonly",
    "arguments": {
      "command": "FIND(?n) WHERE { ?n {name: :name} }",
      "parameters": { "name": "Aspirin" }
    }
  }
}

// Batch read/write
{
  "function": {
    "name": "execute_kip",
    "arguments": {
      "commands": [
        "DESCRIBE PRIMER",
        { "command": "UPSERT { ... :val ... }", "parameters": { "val": 123 } }
      ],
      "parameters": { "global_param": "value" }
    }
  }
}

5.4. Responses

  • Single response: { "result": ... } or { "error": { "code", "message", "hint"? } }, with optional next_cursor.
  • Batch response: { "result": [<single_response>, ...] }; KML stop-on-error may make the array shorter than submitted commands.
  • Result shapes: FIND โ†’ columnar โ€” one index-aligned column per expression (single expression unwrapped: FIND(?n) โ†’ array of node objects; bare ?var โ†’ full objects; non-grouped aggregation โ†’ scalar; grouped โ†’ aligned columns, e.g. [["DomainA","DomainB"],[15,3]]); SEARCH โ†’ array of hits (descending _score); DESCRIBE PRIMER โ†’ {identity, domain_map, total_domains}, TYPES lists โ†’ name arrays (+ next_cursor), single type โ†’ definition node; UPSERT โ†’ {"blocks", "upsert_concept_nodes", "upsert_proposition_links"}; UPDATE โ†’ {"updated", "matched"}; DELETE โ†’ {"deleted_*"} / {"updated_*"} counters; EXPORT โ†’ {"capsule", "concepts", "propositions"}.
// Single success
{ "result": [ { "id": "...", "type": "Drug", "name": "Aspirin" } ], "next_cursor": "token_xyz" }

// Batch (one entry per command)
{ "result": [
  { "result": { ... } },
  { "result": [...], "next_cursor": "abc" },
  { "error": { "code": "KIP_2001", "message": "...", "hint": "..." } }
] }

// Error
{ "error": { "code": "KIP_2001", "message": "TypeMismatch: 'drug' is not a valid type. Did you mean 'Drug'?", "hint": "Check Schema with DESCRIBE." } }

6. Standard Definitions

6.1. Bootstrap Entities (must exist)

EntityPurpose
{type: "$ConceptType", name: "$ConceptType"}Meta-meta (self-referential genesis)
{type: "$ConceptType", name: "$PropositionType"}Meta for predicates
{type: "$ConceptType", name: "Domain"}Organizational unit type
{type: "$PropositionType", name: "belongs_to_domain"}Domain membership predicate
{type: "Domain", name: "CoreSchema"}Holds core schema definitions
{type: "Domain", name: "Unsorted"}Holding area for uncategorized items
{type: "Domain", name: "Archived"}Deprecated/obsolete items
{type: "Domain", name: "System"}Operational home for memory-system nodes (e.g., SleepTask instances)
{type: "$ConceptType", name: "Person"}Actors (AI, Human, Org, System)
{type: "$ConceptType", name: "Event"}Episodic memory
{type: "$ConceptType", name: "Preference"}First-class stable preference facts
{type: "$ConceptType", name: "Insight"}Self-reflective lessons of the agent
{type: "$ConceptType", name: "Commitment"}Prospective promises & deadlines
{type: "$ConceptType", name: "SleepTask"}Background maintenance tasks
{type: "Person", name: "$self"}The waking mind (conversational agent)
{type: "Person", name: "$system"}The sleeping mind (maintenance agent)

Core predicates (pre-bootstrapped $PropositionTypes): belongs_to_domain, involves (Event/Experience โ†’ Person), mentions (Event/Experience โ†’ any), consolidated_to (Event/Experience โ†’ semantic), derived_from (semantic/Insight/Skill โ†’ Event/Experience), prefers (Person โ†’ Preference), learned (Person โ†’ Insight), committed_to (Person โ†’ Commitment), owed_to (Commitment โ†’ Person), assigned_to (SleepTask โ†’ Person); Experience-profile relations: has_step (Experience โ†’ ExperienceStep), caused_by (Step โ†’ Step, effect โ†’ cause), derived_insight (Experience โ†’ Insight), compiled_to (Experience โ†’ Skill).

6.2. Metadata Field Catalog

Provenance

FieldTypeDescription
sourcestring | arrayOrigin (conversation id, document id, url)
authorstringAsserter ($self, $system, user id)
confidencenumber[0, 1] โ€” epistemic support; changes on evidence, not disuse
evidencearray<string>References supporting the assertion
memory_strengthnumber[0, 1], optional โ€” mnemonic accessibility; reinforcement raises, disuse decays; never a truth proxy

Temporality / Lifecycle

FieldTypeDescription
created_at / observed_atstringISO-8601
expires_atstringISO-8601 โ€” signal for $system cleanup; not auto-filtered
valid_from / valid_untilstringISO-8601 validity window
statusstringactive | draft | reviewed | deprecated | retracted โ€” assertion lifecycle, distinct from a type's own attributes.status
memory_tierstringshort-term | long-term
supersededbooltrue for historical (state-evolved) facts
superseded_by / supersedesstringPointers across the evolution chain
superseded_atstringISO-8601 time when the assertion was superseded

Context / Auditing

FieldTypeDescription
relevance_tagsarray<string>Topic / domain tags
access_levelstringpublic | private
review_infoobjectStructured review history

Reserved System Fields (_ namespace โ€” engine-maintained, read-only to KML; see ยง1.8)

FieldTypeDescription
_versionnumberMonotonic mutation counter; target of EXPECT VERSION
_updated_atstringISO-8601 last-mutation time (engine truth)
_scorenumberTransient SEARCH relevance [0,1]; never persisted
_merged_fromarray<string>MERGE provenance trail

6.3. Error Codes

CodeNameMeaning
KIP_1001InvalidSyntaxParse or structural error
KIP_1002InvalidIdentifierIllegal identifier format
KIP_2001TypeMismatchUnknown type or predicate
KIP_2002ConstraintViolationSchema constraint violated (incl. writing _ reserved keys, cross-type MERGE)
KIP_2003InvalidValueTypeJSON value type mismatches schema
KIP_3001ReferenceErrorUndefined variable or handle
KIP_3002NotFoundReferenced node/link does not exist
KIP_3003DuplicateExistsUniqueness constraint violated; MERGE variable matched >1 node
KIP_3004ImmutableTargetProtected system structure modified/deleted
KIP_3005VersionConflictEXPECT VERSION mismatch โ€” re-read, re-merge, retry
KIP_4001ExecutionTimeoutQuery exceeded execution time
KIP_4002ResourceExhaustedResult/resource limit exceeded
KIP_4003InternalErrorUnknown internal system error

7. Best Practices (LLM-facing)

  1. Ground before structured query: use SEARCH CONCEPT "<term>" (and DESCRIBE for unknown types) before FIND โ€” names are ambiguous. When the probe is a meaning rather than a name, use MODE "semantic" / "hybrid" with a THRESHOLD.
  2. Cross-language: the graph stores English name/description with optional aliases; for non-English queries, send bilingual SEARCH probes in parallel via the commands array.
  3. Define before use: any new type/predicate must be registered via $ConceptType / $PropositionType first, then assigned to a Domain.
  4. Idempotent writes: prefer {type, name} identity; avoid random ids/names unless retries are stable.
  5. Always attach provenance: WITH METADATA { source, author, confidence, ... } โ€” knowledge without provenance is untrusted.
  6. State evolution > deletion: when a fact changes, mark the old proposition superseded: true (with superseded_by, superseded_at) and upsert the new one with supersedes. Keep history.
  7. Respect expires_at semantics: it is a signal, not a filter. Add explicit FILTER(IS_NULL(?x.metadata.expires_at) || ?x.metadata.expires_at > <now>) only when the query implies "currently valid". Hard deletion belongs to $system sleep cycles.
  8. Smallest delete that fixes the issue: metadata โ†’ attribute โ†’ proposition โ†’ DELETE CONCEPT ... DETACH. Always FIND first. Never modify/delete protected core: meta-types, the Domain type and belongs_to_domain definitions, core domains, $self/$system identity tuples, or core_directives.
  9. Batch independent operations in commands to reduce round-trips. Remember: KML errors stop the batch; KQL/META/syntax errors return inline.
  10. Mind variable scope: NOT hides internal bindings; UNION doesn't see external bindings; OPTIONAL projects null on miss.
  11. Use OPTIONAL for "may exist", NOT for "must not exist", UNION for "either branch", FILTER for value predicates.
  12. Higher-order propositions (?u, "stated", (?s, ?p, ?o)) are first-class โ€” use them for provenance, beliefs, and meta-claims rather than flattening into attributes.
  13. OPTIONAL projection of unbound variables yields null and IS_NULL returns true โ€” safe for downstream FILTER.
  14. Confidence transparency: when synthesizing answers, surface confidence and recency; prefer high evidence_count consolidated patterns over raw single Events.
  15. Explore with predicate variables: (?seed, ?pred, ?neighbor) is the one-query "what do I know about X?" primitive โ€” constrain the seed, exclude noisy predicates in FILTER, and always LIMIT.
  16. Bulk mutation belongs to UPDATE: decay, counters, status sweeps, salience refresh โ€” one pattern-matched UPDATE with ADD/MUL/CLAMP/COALESCE beats N per-element UPSERTs, and never needs a prior read for pure increments.
  17. Guard read-modify-write with EXPECT VERSION: read _version together with the value, merge in memory, write back guarded; on KIP_3005 re-read and retry. Required discipline for $self attributes and any shared array/object value.
  18. Deduplicate with MERGE, not by hand: one atomic MERGE CONCEPT ?dup INTO ?canonical repoints every link and preserves aliases/provenance; verify both nodes with FIND first.
  19. Reads are reads: the protocol keeps no access statistics (tracking reads would turn every query into a write, and recall frequency โ‰  importance). Decide decay and landmark promotion from author-maintained signals: evidence_count (observation), last_observed (recency), salience_score (impact), expires_at (declared intent).
  20. Memories are portable: use EXPORT for backup, migration, and sharing knowledge between agents โ€” and remember imports need the schema and referenced endpoints to exist first.