anda_brain 0.12.1

🧠 Anda Brain (ε€§θ„‘) β€” Autonomous Graph Memory for AI Agents
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
# Anda Brain β€” Technical Documentation

Cloudflare Worker parity and limits are documented in the [commit audit](../anda-brain-worker/PORTING_AUDIT.md) and [trusted host contracts](../anda-brain-worker/PRODUCT.md). The Worker supports source records, reviewed changes, recovery and processing fences; budgeted Recall, Wiki and learning runtimes remain unavailable.

A dedicated LLM-powered memory management service that maintains a persistent **Cognitive Nexus** on behalf of business AI agents via [KIP 2.0 (Knowledge Interaction Protocol)](https://github.com/ldclabs/KIP).

Business agents interact entirely through natural language and a REST API β€” no KIP knowledge required.

Anda Brain is designed to be **self-hosted** (the hosted cloud service has been discontinued). For a complete agent built on Anda Brain, see [Anda Bot](https://github.com/ldclabs/anda-bot).

SleepTask and Watch are exempt from bulk mnemonic decay because all operational
record updates require version guards. Failed host passes reach the model in
assessment.settlement_errors.

## Trusted host memory product contracts (v0.12.1)

The Rust `product` module provides Assertion-backed `MemoryRecord` projections, stable native revisions, explicit stance/lifecycle/storage state and typed Evidence source references. `Space::product_records`, `product_record` and `product_source` do not authenticate a user. The embedding host must enforce owner/source visibility before returning any record, preview, dependent identifier or source quote. A matching source digest is provenance, not proof that an inference is correct.

`Space::ingest_product` accepts a bounded, trusted `SourceIdentity` with parent conversation/session keys. Natural-language input cannot set that identity. `product_prepare`, `product_commit`, `product_change` and `product_discard` implement caller/operation-scoped immutable requests, fixed revision/preview digests and ten-minute previews. Corrections retract the old Assertion and create a new claim with a user-statement Evidence and correction Activity; they never rewrite a Concept label or create an illegal cross-Proposition supersession. Undo is another conditional correction.

`Suppress` archives and `Delete` purges the declared bounded closure: selected Proposition/Assertions, cited inputs and recorded referrers. Unknown sources, Concept cascades, retention holds and closures above 128 elements are rejected. A durable source exclusion and processing epoch are admitted before mutation; tracked native work survives a cancelled API waiter and resumes before a reloaded Space is exposed. Stale Formation/Maintenance/Notes writes are fenced. Managed changes clear processing Notes and miss caches, stop old processor histories from entering new contexts and restrict automatic KIP readers to current active state. Trusted owner audit APIs remain distinct. Recall rechecks its captured epoch before returning context.

Managed changes also exclude history from budgeted Recall and fence timeout/turn-limit outputs. Pagination started before the change must restart; newer continuations remain usable. Deletion clears copies of erased content from saved previews/corrections and discards affected uncommitted intents while retaining operation identities and digests. An independent correction whose claim and Evidence survive keeps its source text. Correction-source reads check that the Evidence still exists with the matching payload.
Source-backed status verifies the captured conversation message and observation time, or a confirmed correction receipt; a matching client-key spelling alone is insufficient. Direct `/memory/forget` also clears saved previews that refer to the purged graph elements.

Removal does not erase an embedding application's original chat/files/logs/backups, other independent graph records, already delivered context or provider copies. Minimal source keys/digests survive for replay suppression. Replacing the database with an old backup without its current exclusions is not a supported deletion-preserving rollback. The host must also reset its own injected Notes and prevent excluded sources from being imported through later conversation chains.

`MemoryRuntime::{create_record_watch,record_watch,cancel_record_watch}` is a narrow recipient-owned subscription adapter using an opaque authenticated `RuntimeCaller`. Creation persists identity and arms only the initial generation. It provisions a cancellation grant restricted to that one Watch for the configured controller, with a durable no-regrant marker. Cancellation archives the Watch rather than forging its protected status; retries never re-arm it. Already delivered questions are separate work and remain visible. A revoked grant is not restored by subscription retry or bootstrap. These Rust methods are not new generic model tools or native HTTP product routes.

`RuntimeConfig::validate` performs static validation without loading a Space, running models, probing services or provisioning grants. The optional learning runtime reports `product_readiness` for installed isolated workflow bindings, including missing services, mismatched pins, missing reviewed calibration and approval gates. Ready is not business deployment authority; native per-item service/permission checks remain mandatory.

Anda Bot currently consumes these contracts through a temporary sibling patch. Replace it with the published 0.12.1 crate before removing the patch, while keeping the shared registry DB/KIP/Core type identity. No empirical learning improvement or full cost accounting is implied by these mechanism tests.


## KIP 2.0 / CognitiveMemory 2.1 update

Rust uses published `anda_kip`, Cognitive Nexus and AndaDB 0.13 packages;
the Worker uses published `@ldclabs/kip-do` 0.13. Skill behavior is an
immutable `SkillRevision`; Watch progress and task leases use protected Nexus
operations. The former family-rate Skill promotion rule has been removed. Without
configured independent observers, frozen trials and replayable evaluations,
procedures remain unproven and `skills.unsupported_reason` reports the limitation.
Existing Brain endpoints remain available. The optional five-intent Memory Interface
and its `memory_*` bundles are **not advertised** by these adapters.

## Architecture

```
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚   Business Agent    β”‚  ← Focuses on business logic & user interaction
β”‚  (No KIP knowledge) β”‚    Only speaks natural language
β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
         β”‚ Natural Language / REST API
         β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚      Brain          β”‚  ← The ONLY layer that understands KIP
β”‚   (LLM + KIP)       β”‚    Three agents: Formation / Recall / Maintenance
β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
         β”‚ KIP (KQL / KML / META)
         β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Cognitive Nexus    β”‚  ← Persistent Knowledge Graph (backed by AndaDB)
β”‚  (Knowledge Graph)  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
```

## Features

- **Zero KIP knowledge required** β€” Business agents interact through natural language and a simple REST API.
- **Persistent, structured memory** β€” Facts, preferences, relationships, events, and patterns encoded into a knowledge graph.
- **Three operational modes** β€” Formation (encoding), Recall (retrieval), and Maintenance (consolidation & pruning).
- **Multi-space isolation** β€” Each space has its own independent database, knowledge graph, and conversation history.
- **Triple serialization** β€” Supports JSON, CBOR, and Markdown for request/response payloads (negotiated via `Content-Type` / `Accept` headers).
- **Built-in MCP server** β€” MCP-capable agents can use Anda Brain through Streamable HTTP or stdio tools without writing REST glue code.
- **Pluggable storage backends** β€” Local filesystem, AWS S3, or in-memory (for development/testing).
- **MIB offline regression** β€” Product timelines and business outcomes are evaluated by the independent MIB runner; Brain retains online diagnostics and native learning-mechanism tests.

## Versioned wiki (`wiki` feature)

Wiki stores immutable Markdown versions with CAS updates and verifiable byte-range citations. ACL checks and content selection share one document snapshot; search candidates are checked against current document state. Published parent chains define history. Native wiki writes survive cancelled request waiters and drain before Space close or eviction.

Document outlines follow ATX headings (`#`–`######`) independently of BM25 chunks. Sections include child headings, and all text reads are capped at 256 KiB. OKF import/export preserves unknown YAML values through edits; comments, ordering and formatting are canonicalized. Imports replace file-owned fields and preserve native ACLs and unrelated host metadata.

Optional WikiDigest remains disabled by default. It reconciles durable document generations, including archive/restore and ACL changes, and reports failed documents without retiring their pending work. Metadata-only edits reuse prior results. Old claims are withdrawn only after explicit absence reviews covering every body batch, or withdrawal of the source; omitted or unknown model output is not negative evidence. Concurrent edits fence out stale writes. This is a mechanism contract, not a real-model quality claim. See the [English API](./API.md#43-wiki-endpoints-v1space_idwiki) and [δΈ­ζ–‡ζŽ₯口](./API_cn.md#43-wiki-ζŽ₯口v1space_idwiki).

## Agents

### Formation β€” Memory Encoding (`formation_memory`)

Receives conversation messages and encodes them into structured memory within the Cognitive Nexus via KIP.

**System prompt:** [BrainFormation.md](https://github.com/ldclabs/anda-brain/blob/main/anda_brain/assets/BrainFormation.md)

**Processing pipeline:**
1. Receives `FormationInput` (messages + optional context + timestamp).
2. Creates a tracked `Conversation` record (status: `Submitted` β†’ `Working` β†’ `Completed` | `Failed`).
3. LLM classifies what the conversation is worth keeping, into the products the
   Cognitive Memory Profile defines: `Evidence` for what was observed,
   `Proposition` + `Assertion` for a truth-sensitive claim and whose stance it
   is, `Event` for what happened, `Experience` + steps when the process itself
   can teach future behavior, `Commitment` for a future obligation, and
   `Insight` / `SelfModel` candidates. The empty write is a valid answer.
4. Grounds against existing memory before writing (SEARCH before CREATE).
5. Encodes it through the `execute_kip` tool, which on this path accepts KQL and
   META in full and only the cognition subset of KML β€” administering memory in
   bulk (`UPDATE`, `SET RETENTION`, `PURGE`, `MERGE CONCEPT`, and `TRANSITION`
   to `archived` or `tombstoned`) is refused to a pass whose whole input is an
   untrusted conversation.

**Key behaviors:**
- Sequential processing with automatic queue draining β€” new conversations are picked up after the current one completes.
- Atomic single-conversation processing via `processing_conversation` flag.
- Inputs of at least 10,000 estimated tokens receive one focused semantic
  review before completion, within the same turn/time budgets. It reuses tool
  receipts, reads only unresolved records, and repairs demonstrated omissions
  or misrepresentation. No changes is a valid result; missing source context
  is reported as a coverage limit. This self-review does not guarantee
  exhaustive processing or establish measured accuracy gains.
- New vocabulary enters through the host, never through KML. KIP 2.0 makes
  Schema protected control state, so a command naming an undeclared type or
  predicate is refused with `SchemaSymbolNotFound`; the model asks for one
  through the `declare_memory_symbols` tool, and the host validates the name's
  shape, caps how many a space may hold, and versions the result.

### Recall β€” Memory Retrieval (`recall_memory`)

The optional `RecallInput.budget` (or an enforced `memory_policy.recall_budget`)
selects a host-packed JSON memory response instead of free-form synthesis.
The whole packet and cumulative normalized planning input use the pinned
`o200k_base@tiktoken-rs-0.12.0` counter. Required commitments/warnings precede
optional items, failed coverage is explicit, and diagnostic histories/artifacts
cannot bypass the packet limit. Existing requests without a budget policy keep
the normal flow below. Question-specific search supplies candidates before
selection. Compact views keep provenance and detail references; terminal
commitments no longer consume mandatory space. Small budgets can deliver
partial candidates with explicit coverage/warnings while preserving required
constraints. See [Recall budget contract](API.md#recall-budget-contract).

Translates natural language queries into knowledge graph lookups and returns synthesized answers.

**System prompt:** [BrainRecall.md](https://github.com/ldclabs/anda-brain/blob/main/anda_brain/assets/BrainRecall.md)

**Processing pipeline:**
1. Receives `RecallInput` (query + optional context).
2. Analyzes query intent (entity lookup, relationship traversal, attribute query, event recall, pattern detection, etc.).
3. Grounds entities to actual graph nodes (resolves ambiguity).
4. Executes structured KQL/META reads; belief questions go through `BELIEF`
   projection rather than raw `FIND`, because a Proposition existing is not the
   Proposition being true.
5. Iterative deepening β€” follows up with additional queries if needed, up to
   the space's `recall_max_rounds` (default 7).
6. Synthesizes results into a coherent natural language answer, reporting
   contested as contested and insufficient as insufficient.

**Available tools:**
- `execute_kip_readonly` β€” KQL and META only, enforced on what each command
  parses to. Recall has no write tool at all, and reading never reinforces what
  it read.
- `wiki_search` / `wiki_read` β€” with the `wiki` feature; absent otherwise.

### Maintenance β€” Memory Metabolism (`maintenance_memory`)

Consolidates, prunes, and optimizes the knowledge graph during scheduled or on-demand cycles.

**System prompt:** [BrainMaintenance.md](https://github.com/ldclabs/anda-brain/blob/main/anda_brain/assets/BrainMaintenance.md)

**Processing phases (full scope):**
1. **Assessment** β€” Audit memory health (read-only): `DESCRIBE PRIMER`, pending SleepTasks, unconsolidated Events and Experiences, orphans, stale events, plus the runtime's own `assessment` block (per-predicate census, correction tallies, armed and fired Watches, the current `space_seq`).
2. **SleepTask Processing** β€” Handle queued work under the Profile's classes: `consolidate`, `review_conflict`, `review_skill`, `resolve_identity`, `review_retention`, `review_derived`, `refresh_self_model`, `inspect_quarantine`.
3. **Semantic consolidation** β€” Compress clusters of Events, Experiences and Evidence into derived Assertions, keeping Activity lineage back to the sources. A summary is not a new epistemic root.
4. **Procedural consolidation** β€” Compare successful and failed Experiences and compile an unproven Skill with an immutable SkillRevision. Its task_family identifies comparison candidates; only a configured trial/evaluation pipeline can confer validated standing.
5. **Identity review** β€” Review `same_as` suspicions, then `MERGE CONCEPT`, which is non-destructive: the source survives as merged historical identity.
6. **Contradiction and derivation review** β€” Different actors' disagreement coexists; only an actor's own revision supersedes. After a revision, the settlement walks `LIST DEPENDENTS` and hands the agent each revised root with its dependents (`assessment.revised_roots`); the agent flags what no longer holds `stale`.
7. **Mnemonic metabolism** β€” run by the runtime settlement before the cycle, not by the agent: `MnemonicState.memory_strength * decay_factor` on Concepts due for it. Never `confidence`; a fact nobody has asked about lately is no less credible. `salience` and `utility` stay with the agent β€” the sweep cannot make a per-memory judgement.
8. **Commitments and Watches** β€” Review outstanding obligations and attention. Nexus advances structured Watches under generation/CAS/coverage checks; prose conditions remain deferred without a semantic evaluator. No model completion attests change-stream consumption. See the Watch contract below.
9. **SelfModel and WorkingState refresh** β€” Consolidate identity from evidence rather than from the latest conversation, and rebuild the digest the next waking session resumes from, stamped with the `basis_seq` it was built at.
10. **Retention review** β€” Decide what should carry an expiry and write it with `SET RETENTION`; the full settlement's sweep is what makes that write mean something. See "Retention expiry" below.

Skill lifecycle transitions require the explicitly configured protected host evaluation pipeline. Standard model-driven maintenance does not grant standing. See "Procedural candidates remain unproven" below.

**Key behaviors:**
- Single-execution guard β€” only one maintenance cycle can run at a time per space.
- Non-destructive principle β€” archives before deleting, and weakens mnemonic accessibility rather than removing (never epistemic confidence).
- Async execution β€” returns immediately with conversation ID; actual processing in background.
- Two triggers, not one. Counting formation conversations paces a space that
  is being written to (daydream every 21, quick every 42, full every 168); a
  24-hour clock covers one that is not. Without the clock a space that stopped
  ingesting stopped metabolizing entirely β€” no Commitment review, no retention
  expiry, no self-test β€” which is not what "scheduled, threshold, or
  change-driven" means. The clock fires from the background flush pass for
  resident spaces and on load for spaces that had been evicted; a space that
  has never formed anything is never due.

**Memory policy:** each space carries an evolvable `MemoryPolicy` (stored in
the `memory_policy` extension, set via `update_space`) that holds the numeric
knobs of memory behavior β€” decay factor and floor, stale-event threshold,
backlog targets, and (from later phases) self-test and recall parameters.
Maintenance cycles without explicit `parameters` run under the space's
policy; an absent policy means the compiled-in defaults, so setting nothing
changes nothing. The policy is the evolution genome of
`docs/memory_evolution_plan_cn.md` (module M-P).

**Mnemonic metabolism:** before each maintenance cycle the runtime runs a
deterministic settlement that decays `MnemonicState.memory_strength` on
Concepts due for it, stamping `last_metabolized_at`. Pinned Concepts are
exempt. Every cycle sweeps; what paces it is the sweep's own weekly
`last_metabolized_at` filter, not the cycle scope, because scope decides how
much *cognitive* work a cycle does and gating metabolism on `full` as well
meant a Space forming slowly went months without any. Newly superseded
Assertions are recorded as corrections and aggregated per asserting actor into
the `source_reliability` extension; full cycles also refresh the per-predicate
census. Both reach the Maintenance prompt as its `assessment` block. What
decays is `MnemonicState.memory_strength` β€” how *available* a memory should be
β€” and never an Assertion's confidence: KIP 2.0 forbids letting time erode a
stance, because a fact nobody has asked about in a month is no less credible.
The LLM maintenance agent no longer runs bulk metabolism itself. The last
settlement report is stored in the `memory_settlement` extension.

**Reading does not reinforce.** Every completed recall still records which
graph entities it surfaced, into an off-graph usage ledger (`memory_usage`
collection) that the dream self-test, the health metrics and the scenario
diagnostic inspection reads. That record stops there. An earlier design closed the loop β€”
settlement raised the recalled Concepts' `memory_strength` by a
`recall_reinforcement` gain β€” and that is precisely what the reference Recall
policy forbids (Β§1 "MUST NOT ... change memory_strength, increment recall
counters", Β§32, invariant 2 "Read does not reinforce memory"). Deferring the
write to maintenance did not make reading stop reinforcing; it only moved
where the reinforcement was written from. So the writeback is gone: a recalled
memory earns no gain and buys no exemption from the next sweep. Retrieval is
observed, not rewarded β€” which is also the difference between a memory system
and a popularity contest. The `recall_reinforcement` policy knob is retained
for stored-policy compatibility and does nothing.

**Watch progress is protected Nexus state.** Create a Watch as `disarmed`, then
call the internal `memory_runtime` tool with `arm_watch`, its exact id and current
`_system.version`. Arming captures an authorization view and creates a fresh
`WatchState.arm_generation`. Settlement advances structured selectors through a
bounded authorized change page using the current overall version and generation.
Silence requires complete coverage through the deadline; a matching silence Watch
ends as `expired`, counted in the legacy `disarmed` report field. Native advancement
atomically commits `fired`, a `watch_fire` Activity and a protected wake in Nexus
0.13.1. Its response retains status/coverage/receipt and identifies the fire and
wake. Repeated native requests replay the same receipt; silence uses a fixed
deadline sequence. An independent, bounded scheduler now discovers registered
Spaces through a persistent directory, resumes after eviction/restart, and uses the
same service as the maintenance sweep. Explicitly installed `ActionBindings` add
bounded four-way decisions and fenced dispatch; without bindings there are no
action model calls or outward sends. Semantic Watch models have a separate explicit binding.
See [runtime setup, action contracts and recovery](RUNTIME.md).
The [runtime API](API.md#authenticated-runtime-inbox-and-observations) exposes authenticated inbox/response/outcome
routes plus MCP read/response tools. `BRAIN_RUNTIME_CONFIG` selects a compiled
durable inbox adapter; observation intake requires separately mapped signed
observer credentials and preserves learning's single-writer/cutoff rules.
Native wake leases and completion are trusted host
APIs. Spaces containing native attention state cannot be forked with those
operational identities; eviction/reopening the same Space remains supported.
Text conditions, including mixed selector/text objects, stay deferred without a
configured semantic evaluator. The semantic Watch runtime provides a bounded, pinned Chat Completions
adapter and trusted callback interface using immutable native pages outside the
Nexus lock. Unknown/omitted/timeout/truncated results retain the original coverage;
replay and purge follow native Artifact permissions. See
[SEMANTIC_WATCH_RUNTIME.md](SEMANTIC_WATCH_RUNTIME.md) and
[semantic.runtime.example.json](semantic.runtime.example.json).
A completed maintenance model call never advances a
Space-wide consumption watermark. Old Watches without WatchState need a reviewed
CognitiveMemory 2.1 replacement; the scheduler never auto-rearms them. Firing grants no external authority.

**Procedural candidates remain unproven.** `Skill.current_revision` selects an
immutable `SkillRevision` whose `revision_of` points back to the Skill. Both can be
created atomically. The internal `memory_runtime` tool computes the canonical
SHA-256 digest of all revision attributes except `behavior_digest`; Nexus verifies it.
No model plan can write TrialRecord, EvaluationRecord, AttemptRecord, OutcomeRecord,
TrialState or GradingState. Same-family outcomes are merely comparison candidates;
no automatic baseline or grade is inferred. Settlement preserves the historical
counter fields at zero because Full Maintenance does not execute business trials.
`skills.unsupported_reason` explains the boundary, while configured deployments
also return the independent scheduler's `skills.runtime` status. Historic counters or `adopted`
labels are not validated learning evidence.

### Contextual source trust

The optional `trust` startup binding uses independently verified, context-tagged
source Assertions to prepare reviewable calibration proposals. The first method
measures binary factual accuracy, not operational success or forecast probabilities.
There are no statistical defaults or implicit governance grants. A qualified governor
can apply one exact actor/predicate/context rule through the native atomic
proposal/control/audit API; other settings and Assertion confidence remain intact.
Duplicate roots/claims, missing material, corrections, revocation and version
conflicts cannot silently create another trust step. Restoration appends a new
protected version. See [TRUST_RUNTIME.md](TRUST_RUNTIME.md) and the
[disabled template](trust.runtime.example.json). Real instrument/method calibration
remains a separate MIB validation gate.

### Native learning contracts

With the Rust `learning` feature, `anda_brain::learning`
provides `PairedTrialPlan`, `ExecutionContract`, `PairedRule`, and `register_paired_rule`. A trusted
host freezes the plan as an artifact before baseline execution, uses its pin
for both arms' `AttemptRecord.selection_policy` and `TrialRecord.parameters`,
and registers the rule once per Nexus instance (including after restart).
`attempt_context()` and `comparability()` build the pinned KIP fields.

The `anda-brain:paired-bounded-v2` rule compares one candidate revision against a stable task policy with
the same factual memory, model, tools, budget and task/state/seed pairs. It
requires the entire predeclared cohort and a one-sided Hoeffding lower bound
above the positive practical-improvement margin, and an absolute candidate
failure-rate ceiling. The observer configuration binds the workflow contract
and the complete attempt budget. Missing treatment outcomes
count as failure; missing or unknown control outcomes leave the comparison
insufficient. Duplicate pairs/observations, changed pins, or extra applied Skill
revisions are rejected. A new monitoring trial retains the original acquisition
through `AdoptionBasis`; native tests verify adoption, subsequent revocation and
rejection of re-entry using the old trial. Multi-Skill bundles, adaptive stopping
and filtering a window out of one trial's ledger are not supported. Parameters have no production
defaults and require calibration.

`ExecutionContract` pins tool/time/token ceilings, cutoff and the review deadline.
The host must call `validate_settlement()` before a final verdict and enforce
expiry at read time: the current Nexus evaluator input does not contain the
EvaluationRecord cutoff. OutcomeRecord has no custom cost fields, so the trusted
verifier checks bounded success and retains measurements in Evidence payloads.
`workflow_contract()` supplies the first resettable task-family contract. See the
[frozen workflow contract](assets/learning/workflow-contract-v1.json).
The previous v1 evaluator digest is rejected rather than assigned these new semantics.

`Space::learning()` now provides explicit registration, frozen enrollment,
persistent dispatch/recovery and separately authenticated Outcome ingestion.
It uses native leases and dispatch authority checks; no executable authority or
Skill standing is assigned automatically. The host supplies the real executor
and observer. It can call the bounded `drive` step directly or install explicit
automatic bindings through runtime startup configuration. Compilation deploys no binding. The host's `settle` step now performs
fixed-cutoff native comparison and atomic standing updates. Persistent reviews,
new monitoring trials, independently authenticated safety revocation, and current
read-time recommendation checks are implemented. Recall's internal read-only
`check_procedure_status` tool reports these checks and does not grant execution
authority. The [learning runtime guide](LEARNING_RUNTIME.md) documents the compiled
HTTP adapter, calibration approval, separate scheduler, 1–32 hot job capacity,
retained history pages and terminal archival. Archived records remain available
for applicability, review and safety revocation. The [runtime implementation](src/learning/runtime.rs)
exposes the trusted host interfaces.
The native tests use deterministic fixture outcomes to verify KIP transactions,
not to claim empirical learning. Run them without a model provider:

```bash
RUST_MIN_STACK=16777216 cargo test -p anda_brain --lib --features learning learning::
```

### Isolated experiments

With the Rust `experiments` feature, the host-only
`Experiment` owner supplies isolated stores, quiescent immutable snapshots,
per-conversation completion waits, monotonic business time, session boundaries,
and cost receipts with explicit unknown values. It enables Nexus's non-default
`simulation` host API for lifecycle expiry; authentication, lease and audit
clocks remain real. No HTTP/MCP clock override or MIB adapter is exposed.
Notes now persist under each Space's `engine/` object-store prefix and are
included in experiment snapshots. See the [experiment API](src/space/experiments.rs) and [MIB integration](#mib-integration).

`Experiment::create_with_recall_budget` pins a forced Recall-budget policy before the run
is exposed, including across snapshot forks and session boundaries.
`audit_procedures()` supplies a bounded native inventory for evaluator-side
before/after checks. It does not establish applicability or execution permission.
See [validation and remaining bindings](#mib-integration).

### MIB integration

The sibling Anda Bot `mib` feature provides an isolated loopback host before
production home/daemon initialization. Its agent endpoint is
`/mib-agent/v0.1`; its memory backend endpoint is `/mib-memory/v0.1`.
Each run has a separate store and business clock. Formation/Maintenance wait
for exact terminal records, repeated requests preserve their original result,
and current-task tool replies remain available in no-memory mode. See the
[Bot host contract](https://github.com/ldclabs/anda-bot/blob/main/docs/mib-integration.md)
and [MIB backend contract](https://github.com/ldclabs/MIB/blob/main/docs/harness/MIB-Memory-Backend.md).

The [longitudinal harness](https://github.com/ldclabs/MIB/blob/main/docs/harness/MIB-Learning-Longitudinal.md)
requires explicit normal/no-memory/ungated capabilities, matched business
identities and fixed budgets. The current Bot provides persistent/no-memory
modes; native normal/ungated business bindings remain pending. Unknown costs
stay unknown, and engineering fixtures never establish model-learning success.
The evaluator-only `learning_audit` reads bounded native inventories (256 items
per kind, 4 MiB total projection); an incomplete count cannot prove absence.
It never grants applicability or execution permission and is not fed back to
Formation. Complete accounting and real provider calibration are separate
acceptance work.

**Task work requires a lease.** The internal tool's `lease_task` operation acquires
or renews a five-minute lease under the runtime Principal. After re-reading the
version, maintenance commits terminal task state and outputs in one guarded MUTATE.
WatchState and LeaseState cannot be written by model KML. External dispatch uses
explicit Rust host bindings and the separate action gate; none are installed by
default. `memory_runtime/status` reports current configuration. Runtime
authentication, tool capabilities and evaluator code never
come from model-generated content.

Operational records written against CognitiveMemory 2.0 cannot be armed or leased
in place: their exact `schema_ref` is immutable. Maintenance must create a 2.1
replacement, reconnect and verify its structural references, and only then archive
the legacy Watch or SleepTask. The runtime returns this migration instruction before
calling the protected operation.

**Current basis matters.** Recall loads a fresh Primer because policy, trust and
identity can change independently of vocabulary. A stored WorkingState/DerivationState
or bare `basis_seq` cannot override computed dependency validity. Derived refreshes
must retain their actual read pins, context and ProjectionBasis; incomplete coverage
or unavailable replay material remains explicit. Every Formation, Recall and
Maintenance model call includes the complete `anda_kip::KIP_SYNTAX`, Cognitive
Memory Profile, applicable role cards and deployment policy in its system prompt.
The same assembly applies to budgeted Recall and instance-specific section A
overrides; experiment prompt identities include this assembled static content.
The syntax comes directly from the pinned crate, without hand-maintained copies.
This adds about 40 KiB of syntax text to each request. Budgeted Recall counts the
entire system prompt on every planning pass toward its cumulative input budget;
if it cannot fit, it reports `recall_context_budget_exhausted` without calling the
model or dropping the syntax. The full language reference grants no additional
permissions: Recall remains read-only and model writes retain their host gates.
All three agents can read additional compiled-in KIP
documentation through the internal, read-only `kip_reference` tool. Markdown paths
are source citations; they do not require files beside the executable or network
access. `document=index` lists document IDs, `section=index` lists exact Markdown
headings, and `section=null` reads a document. Syntax topics also accept `kql`,
`kml`, `meta`, and `envelope`. Start at `offset=0`, then follow `next_offset` with
the same document/section; each page contains at most 8 KiB of UTF-8 text. The
catalogue includes the specification, consistency contracts, invariants, learning
architecture, grammars and wire schemas; unlisted background/translation links
are citations only. Reading a reference grants no host capability. Budgeted Recall
counts these calls and their planning input against its existing limits; reference
pages never become memory packet items or attest retrieval coverage. The legacy
`memory_runtime` syntax operation remains available to writing agents.

The reference supplement is pinned to `anda_kip =0.13.1`; public crate constants
are reused instead of copied. To refresh the supplementary files, set
`ANDA_KIP_SOURCE` to the matching published crate directory and run
`node scripts/sync-kip-reference.mjs` (or `--check` to verify without writing).
The generated manifest records source hashes, and tests check both the supplement
and exported crate documents against it. Do not hand-edit these reference assets.

**Retention expiry:** a full settlement also acts on the two clocks that say
when something should stop being kept, which are not the same clock. An
Assertion whose `valid_time.until` has passed is marked `expired` (Β§14.3) β€”
not retracted and not superseded, because nobody withdrew it and nothing
replaced it. An element whose `retention.expires_at` has passed is archived:
out of ordinary recall, still readable, still referenced. Purge is
deliberately unreachable from here β€” erasure over a set nobody enumerated is
the largest irreversible action this service can take, and a scheduled cycle
is not where that decision belongs; `POST /memory/forget` enumerates its
target and purges that. A legal hold stops the sweep that authorized it, and
the `retention` block of the settlement report says how many were held,
refused and left for the next cycle rather than reporting only what it
managed to archive.

The explicit forget endpoint accepts all five KIP element kinds (`C-*`, `P-*`,
`A-*`, `E-*`, `X-*`), including captured message Evidence. Its report counts each
purged kind and retains per-entity refusals such as legal holds. It erases selected
graph records; conversation, wiki and external copies retain their own lifecycles.

> **Known scale ceiling:** the bulk decay, correction discovery, and
> self-test sampling passes use unconstrained full-scan KQL, and the engine
> caps full-scan solutions at 65,536 regardless of `LIMIT`.
> On graphs past ~65k propositions these passes stop working; the failure
> is loud (`log::error` + `decay_error`/`correction_scan_error` in the
> settlement report and `memory_status`), but the fix β€” predicate-sharded
> scans β€” is not implemented yet. Watch those report fields in production.

> **Single writer per space:** the usage ledger, settlement, self-test,
> shadow, and negative-cache locks are in-process (`tokio::Mutex` /
> atomics), like the formation processing flag they follow. Sharding
> assigns each space to exactly one process β€” do not point two instances
> at the same space's storage: concurrent ledger writes can duplicate
> rows, and the miss-cache clear race guard does not cross processes.
> (The graph-side fences β€” `decay_applied_at`, `correction_settled` β€”
> stay safe either way.)

**Dream self-test (self-repair):** after each maintenance cycle completes,
the runtime samples recent memories with no usage evidence, generates one
natural probe query per memory (a single LLM call, budgeted by
`MemoryPolicy.self_test_queries_per_cycle`), and checks deterministically
whether search actually surfaces them. Unfindable memories become pending
`review` SleepTasks (source `memory_self_test`) that the next full cycle
re-encodes with aliases and richer descriptions. Self-test retrievals count
only into the ledger's isolated `self_test_count` β€” the brain testing itself
never reinforces its own memories. The pass report lives in the
`memory_self_test` extension and surfaces as the `groundability` graph stat.

**Metamemory:** `search_exhaustive` reports optional search-window coverage;
missing coverage is unknown. A search miss is not a negative BELIEF, and only
explicit exhaustive misses enter the cache. `POST /v1/{space_id}/probe` answers "do I know anything
about this?" with pure search β€” no LLM, no recall cost. Queries that find
nothing are remembered in a negative-knowledge cache (cleared whenever
formation completes, 1h TTL backstop), so agents stop paying to hit the same
wall. The intended contract: probe first, and only pay for a full recall
when `found` is true.

**Memory observability:** `GET /v1/{space_id}/memory_status` returns
incrementally-maintained counters (recalls, probe hits/misses, self-test
groundability, corrections, decay, forget) plus derived rates
(probe hit rate, correction rate, mean self-reported uncertainty,
maintenance tokens per recall β€” the memory-ROI proxy), graph counts
including the `predicate_types` schema-sprawl indicator, and the latest
settlement / self-test / shadow reports. Writers bump counters at write
time; reading the status never runs heavy queries. Full-scope settlements
also refresh a per-predicate link census, reported as `last_schema_audit`
and handed to the Maintenance prompt as `assessment.predicates` β€” with the
per-actor correction tallies as `assessment.source_reliability` β€” so the
predicate-merge and contradiction guidance has real numbers rather than the
model's impression of them.

**Shadow evaluation (safe policy canary):**
`POST /v1/{space_id}/management/shadow_eval` compares a candidate
`MemoryPolicy` against the current one on the **production distribution**:
the space is forked twice into isolated in-memory stores (baseline vs
candidate policy), both forks are settled, recent real recall queries are
replayed on each, and the judge blind-compares the answers with
deterministic A/B order alternation. The live space is only read β€” replays
can never pollute its conversations, usage ledger, or metrics. The report
(wins/ties/samples/usage) persists in the `shadow_report` extension;
promotion stays human: read the report, then `update_space` with the
candidate policy if it won.

## Offline regression and instance configuration

The Rust `anda_brain::eval` API and the `anda_brain eval` CLI, including
`--optimize`, `--mine`, validation/report modes and their fixture profiles,
have been retired. MIB owns the migrated product regressions. Brain retains
its online self-test, `/probe`, citations/metadata, usage and correction ledgers,
shadow diagnostics, isolated experiment controls and native learning runtime.
The separate wiki retrieval corpus remains at `evals/wiki/retrieval.json`.

From the sibling MIB checkout, run the public regression contracts without a model:

```bash
python scripts/check-brain-product-regression.py --output-dir /tmp/brain-product-regression
```

For a configured business Agent, use MIB's normal submission path:

```bash
python -m mib_runner benchmark \
  --profile profiles/MIB-Brain-Product-Regression-0.1-Dev.json \
  --schema schemas/mib-scenario.schema.json \
  --submission /absolute/path/agent.json \
  --output-report /tmp/product-real.report.json
python -m mib_runner verify-score /tmp/product-real.report.json
```

The contract fixture verifies the harness and its oracle, not model quality.
The actual normal/ungated learning bindings and three-arm provider runs remain
separate pending work. The [MIB migration guide](https://github.com/ldclabs/MIB/blob/main/docs/harness/MIB-Brain-Legacy-Migration.md)
records the nine product goals, removed Rust APIs and validation evidence.

Memory policies come only from each Space's persisted `MemoryPolicy` or the
compiled defaults. `UpdateSpaceInput.memory_policy` remains the configuration
entry point; there is no process-global policy override. Trusted Rust hosts can
configure deployment prompts before sharing an `AppState` or opening a Space:

```rust
use anda_brain::agents::prompts::{AgentPrompts, PromptTarget};

let prompts = AgentPrompts::default().with_deployment_section(
    PromptTarget::Recall,
    "# A. Deployment contract\nYour reviewed deployment instructions here.",
)?;
let app = app.with_agent_prompts(prompts)?;
```

The supplied text replaces only section A, is limited to 128 KiB, and must start
with `# A.`. The compiled KIP reference prefix is retained verbatim. The prompt
configuration is immutable and inherited by agent instances and isolated forks;
snapshot identity checks include its actual contents. `active_prompt()` now
returns compiled defaults only. No HTTP/MCP prompt mutation endpoint is added.
Prompt configuration is host-owned and must be supplied again at startup;
per-Space `MemoryPolicy` remains persisted.

## API Endpoints

Detailed API docs (with TypeScript request/response types):
- English: [API.md](https://github.com/ldclabs/anda-brain/blob/main/anda_brain/API.md)
- δΈ­ζ–‡: [API_cn.md](https://github.com/ldclabs/anda-brain/blob/main/anda_brain/API_cn.md)
- Agent Skill: [SKILL.md](https://github.com/ldclabs/anda-brain/blob/main/skills/anda-brain/SKILL.md)

| Method  | Path                                                   | Description                                                                   | Auth Scope                   |
| ------- | ------------------------------------------------------ | ----------------------------------------------------------------------------- | ---------------------------- |
| `GET`   | `/favicon.ico`                                         | Favicon                                                                       | β€”                            |
| `GET`   | `/apple-touch-icon.webp`                               | Apple touch icon                                                              | β€”                            |
| `GET`   | `/info`                                                | Service info (name, version, sharding)                                        | β€”                            |
| `GET`   | `/SKILL.md`                                            | Skill description (Markdown)                                                  | β€”                            |
| `GET`   | `/v1/{space_id}/info`                                  | Get space status & statistics                                                 | `read` (CWT or space token)  |
| `GET`   | `/v1/{space_id}/formation_status`                      | Get formation status (lightweight endpoint for monitoring formation progress) | `read` (CWT or space token)  |
| `POST`  | `/v1/{space_id}/formation`                             | Submit messages for memory encoding                                           | `write` (CWT or space token) |
| `POST`  | `/v1/{space_id}/recall`                                | Query memory with natural language                                            | `read` (CWT or space token)  |
| `POST`  | `/v1/{space_id}/recall_structured`                     | Recall with machine-readable provenance (citations, found, uncertainty)       | `read` (CWT or space token)  |
| `POST`  | `/v1/{space_id}/probe`                                 | LLM-free metamemory existence check with negative-knowledge caching           | `read` (CWT or space token)  |
| `POST`  | `/v1/{space_id}/memory/pin`                            | Pin/unpin a memory (pinned memories are exempt from disuse decay)             | `write` (CWT or space token) |
| `POST`  | `/v1/{space_id}/memory/forget`                         | Privacy-grade deletion (dry-run supported; physically removes, not archives)  | `write` (CWT or space token) |
| `GET`   | `/v1/{space_id}/memory_status`                         | Memory observability: usage/probe/self-test counters, rates, graph counts    | `read` (CWT or space token)  |
| `POST`  | `/v1/{space_id}/management/shadow_eval`                | Compare a candidate memory policy on forked copies (recent-recall replay)     | `write` (CWT)                |
| `POST`  | `/v1/{space_id}/maintenance`                           | Trigger maintenance cycle                                                     | `write` (CWT or space token) |
| `POST`  | `/v1/{space_id}/execute_kip_readonly`                  | Execute a KIP request (read-only mode, suitable for queries)                  | `read` (CWT or space token)  |
| `GET`   | `/v1/{space_id}/conversations/{conversation_id}`       | Get one conversation detail                                                   | `read` (CWT or space token)  |
| `GET`   | `/v1/{space_id}/conversations/{conversation_id}/delta` | Get incremental conversation updates                                          | `read` (CWT or space token)  |
| `GET`   | `/v1/{space_id}/conversations`                         | List conversations (cursor pagination)                                        | `read` (CWT or space token)  |
| `GET`   | `/v1/{space_id}/management/space_tokens`               | List space tokens                                                             | `write` (CWT)                |
| `POST`  | `/v1/{space_id}/management/add_space_token`            | Add a space token                                                             | `write` (CWT)                |
| `POST`  | `/v1/{space_id}/management/revoke_space_token`         | Revoke a space token                                                          | `write` (CWT)                |
| `PATCH` | `/v1/{space_id}/management/update_space`               | Update space information (name, description, public/private, memory policy)   | `write` (CWT)                |
| `PATCH` | `/v1/{space_id}/management/restart_formation`          | Restart a formation task                                                      | `write` (CWT)                |
| `GET`   | `/v1/{space_id}/management/space_byok`                 | Get BYOK (Bring Your Own Key) configuration                                   | `write` (CWT)                |
| `PATCH` | `/v1/{space_id}/management/space_byok`                 | Update BYOK (Bring Your Own Key) configuration                                | `write` (CWT)                |
| `POST`  | `/admin/{space_id}/update_space_tier`                  | Update a space tier (manager only)                                            | `write` (CWT)                |
| `POST`  | `/admin/create_space`                                  | Create a new space (manager only)                                             | `write` (CWT)                |

### MCP Server

When the HTTP service starts, Anda Brain also exposes a Streamable HTTP MCP endpoint:

```text
https://your-brain-host/mcp/{space_id}
```

Use this for multi-user deployments where each employee or agent team receives a dedicated Brain space. MCP clients should send the same CWT or space token used by REST as `Authorization: Bearer <token>`. Read-only tools can access public spaces without a token.

For local desktop or development clients, Anda Brain can also run as a stdio MCP server:

```bash
MCP_AUTH_TOKEN="$SPACE_TOKEN" \
  cargo run -p anda_brain --features mcp,wiki -- mcp --space-id my_space_001 local --db ./data
```

Both MCP modes use the same storage/model configuration as the HTTP service and expose these tools:

| Tool | Purpose | Scope |
| ---- | ------- | ----- |
| `anda_brain_remember_conversation` | Encode conversation messages into memory | `write` |
| `anda_brain_recall_memory` | Ask natural-language questions against memory | `read` |
| `anda_brain_run_maintenance` | Trigger memory consolidation/pruning | `write` |
| `anda_brain_get_space_info` | Read space statistics and metadata | `read` |
| `anda_brain_get_formation_status` | Read formation/maintenance progress | `read` |
| `anda_brain_execute_kip_readonly` | Run read-only KIP for advanced graph inspection | `read` |
| `anda_brain_get_or_init_user` | Get or create a counterparty concept | `write` |
| `anda_brain_list_conversations` | Page through tracked conversations | `read` |
| `anda_brain_get_conversation` | Read one tracked conversation or delta | `read` |

If authentication is enabled, pass a CWT or space token. Remote MCP reads it from the HTTP `Authorization` header; stdio reads it from `MCP_AUTH_TOKEN` or `--mcp-auth-token`. For local-only development with auth disabled, the token can be omitted. Remote MCP auto-create requires `ED25519_PUBKEYS` plus a `write` CWT for the target space before the missing space is created. Use `MCP_HTTP_ALLOWED_HOSTS` when exposing remote MCP behind a company domain or reverse proxy.

### Content Negotiation

Triple serialization via `Content-Type` / `Accept` headers:

- `application/json` β€” JSON (default)
- `application/cbor` β€” CBOR (binary, more compact)
- `text/markdown` β€” Markdown (human-readable text)

All responses use an RPC envelope:

```json
{"result": { ... }, "error": null}
```

### Authentication

All endpoints (except `/`, `/info` and `/SKILL.md`) require a Bearer token:

```
Authorization: Bearer <base64_encoded_cose_sign1_token>
```

If `ED25519_PUBKEYS` is not provided (empty), authentication is effectively disabled: API requests are accepted without signature verification.

Token format: COSE Sign1 message signed with Ed25519 keys, containing CWT claims:

| Claim   | Purpose                                                 |
| ------- | ------------------------------------------------------- |
| `sub`   | Principal ID (who is making the request)                |
| `aud`   | Audience β€” the space ID being accessed (or `*` for any) |
| `scope` | Permission level: `read`, `write` (or `*` for any)      |

### POST /admin/create_space

Create a new isolated memory space. Requires manager principal.

**Request:**
```json
{
  "user": "<owner_principal_id>",
  "space_id": "my_space_001",
  "tier": 0
}
```

**Response:**
```json
{
  "result": {
    "space_id": "my_space_001",
    "owner": "owner_principal_id",
    ...
  }
}
```

### POST /v1/{space_id}/formation

Submit conversation messages for memory encoding. Processing is asynchronous β€” returns immediately while encoding continues in the background.

RFC 3339 observation times are normalized to UTC milliseconds. Invalid or missing
timestamp strings use the durable conversation creation time, including on retries;
the original input is retained. Markdown raw text is captured as one user message
with the same Evidence binding. Looking up an existing counterparty without a name
preserves its current display name.

**Request:**
```json
{
  "messages": [
    {
      "role": "user",
      "content": "I prefer dark mode. My timezone is UTC+8.",
      "name": "Alice"
    },
    {
      "role": "assistant",
      "content": "Got it! I've noted your preferences."
    }
  ],
  "context": {
    "counterparty": "alice_principal_id",
    "agent": "customer_bot_001",
    "source": "source_123",
    "topic": "settings"
  },
  "timestamp": "2026-03-09T10:30:00.000Z"
}
```

| Field                  | Type        | Required | Description                                                     |
| ---------------------- | ----------- | -------- | --------------------------------------------------------------- |
| `messages`             | `Message[]` | Yes      | Conversation messages (`role`: `user` / `assistant` / `system`) |
| `context.counterparty` | `string`    | No       | User identifier                                                 |
| `context.agent`        | `string`    | No       | Calling agent identifier                                        |
| `context.source`       | `string`    | No       | Identifier of the source of the current interaction content     |
| `context.topic`        | `string`    | No       | Conversation topic                                              |
| `timestamp`            | `string`    | No (recommended) | RFC 3339; normalized, or receipt time if invalid/missing |

**Response:**
```json
{
  "result": {
    "conversation": 1,
    ...
  }
}
```

### POST /v1/{space_id}/recall

Query memory with natural language. Returns a synthesized answer from the knowledge graph and conversation history.

**Request:**
```json
{
  "query": "What are Alice's preferences?",
  "context": {
    "counterparty": "alice_principal_id",
    "topic": "settings"
  }
}
```

| Field                  | Type     | Required | Description                   |
| ---------------------- | -------- | -------- | ----------------------------- |
| `query`                | `string` | Yes      | Natural language question     |
| `context.counterparty` | `string` | No       | User identifier               |
| `context.agent`        | `string` | No       | Calling agent identifier      |
| `context.topic`        | `string` | No       | Topic hint for disambiguation |

**Response:**
```json
{
  "result": {
    "content": "Alice prefers dark mode and operates in UTC+8 timezone.",
    ...
  }
}
```

### POST /v1/{space_id}/maintenance

Trigger a memory maintenance cycle. Runs asynchronously with single-execution guard.

**Request:**
```json
{
  "trigger": "on_demand",
  "scope": "daydream",
  "timestamp": "2026-03-10T03:00:00.000Z",
  "parameters": {
    "stale_event_threshold_days": 7,
    "memory_strength_decay_factor": 0.95,
    "unconsolidated_max_backlog": 20,
    "orphan_max_count": 10
  }
}
```

| Field                                   | Type     | Required | Description                                               |
| --------------------------------------- | -------- | -------- | --------------------------------------------------------- |
| `trigger`                               | `string` | No       | `scheduled` / `threshold` / `on_demand` (default: `on_demand`) |
| `scope`                                 | `string` | No       | `full` (all phases) / `quick` (assessment + urgent tasks) / `daydream` (idle-time salience scoring & micro-consolidation, default) |
| `timestamp`                             | `string` | No       | Canonical UTC timestamp (`YYYY-MM-DDTHH:mm:ss.SSSZ`)      |
| `parameters.stale_event_threshold_days` | `u32`    | No       | Days before events are considered stale (default: 7)      |
| `parameters.memory_strength_decay_factor` | `f64`  | No       | Multiplier disuse metabolism applies to `MnemonicState.memory_strength` (default: 0.95). Never to `confidence`: KIP 2.0 forbids letting time erode a stance. Accepted under its KIP 1.x name `confidence_decay_factor` for stored-policy compatibility. |
| `parameters.unconsolidated_max_backlog` | `u32`    | No       | Events and Experiences that may sit without `consolidated_to` lineage (default: 20). Accepted as `unsorted_max_backlog`. |
| `parameters.orphan_max_count`           | `u32`    | No       | Max orphans to process (default: 10)                      |

The parameters are targets to work toward, not commands. The runtime fills an
`assessment` block into the same input β€” the per-predicate census, correction
tallies, armed and fired Watches, and the current `space_seq` β€” and overwrites
whatever a caller sent there: a request body must not be able to tell the Brain
what its own graph looks like.

**Response:**
```json
{
  "result": {
    "conversation": 8,
    ...
  }
}
```

### GET /v1/{space_id}/info

Get space statistics and health information.

**Response:**
```json
{
  "result": {
    "space_id": "my_space_001",
    "owner": "principal_id",
    "db_stats": { "total_items": 150, "total_bytes": 524288 },
    "concepts": 85,
    "propositions": 120,
    "conversations": 12,
    ...
  }
}
```

## Recall Function Definition

Business agents can register the Recall endpoint as an LLM tool/function call. See [RecallFunctionDefinition.json](https://github.com/ldclabs/anda-brain/blob/main/anda_brain/assets/RecallFunctionDefinition.json) for the OpenAI function-calling format.

## Memory Space Lifecycle

### Creation
1. Creates a new `AndaDB` instance.
2. Initializes `CognitiveNexus`.
3. Activates the KIP 2.0 Cognitive Memory Profile plus this space's own vocabulary package.
4. Stores creator/owner principal IDs.

### Upgrading a space written by a KIP 1.x build

Migration runs when a space is first opened, after the Brain activates its
Schema. Stop the old writer, take a consistent backup, and rehearse against a
copy before changing production. The two old graph collections are replaced in
place; rollback requires the pre-upgrade backup, not an older binary pointed at
the migrated store. Upgrade one space at a time and check its results before
opening the next.

The migration persists extraction and vocabulary checkpoints before switching
collections. It can resume between either collection deletion and between
loading records and committing the completion marker. Original rows remain in
`kip_legacy_v1`. `LegacyRecord` Facets preserve source data for audit, including
the published v1 `a` / `m` attribute and metadata fields.

| v1 data | v2 representation |
| --- | --- |
| `(type, name)` identity | Immutable Concept `key`; standard Person / Event / Preference / Insight / Commitment / SleepTask fields are normalized |
| Insight `description`; SleepTask `reason` / `requested_action` | Native summary / task class; interrupted tasks become blocked without a fabricated lease |
| A recorded claim | Proposition + `mode: "imported"` Assertion; recorded confidence and resolvable author are preserved |
| Retracted or superseded claim | Native lifecycle where the same-actor, same-Proposition revision is reconstructible; otherwise archived with its original annotations, never revived as current belief |
| `valid_from` / `valid_until`; `expires_at` | Assertion valid time; record retention, respectively |
| `pinned`; mnemonic values | Pinned retention class; `MnemonicState`, never copied from Assertion confidence |
| Unsupported old learning/runtime artifacts | Distinct `Legacy*` types under `kip://legacy/nexus@1.1.0`; they acquire neither learning standing nor operational leases |
| Legacy relation with incompatible native endpoints | A distinct legacy predicate for that tuple; compatible tuples keep the native predicate |

Unresolvable attribution and privacy annotations remain source data, not
verified identity, trust or Governance permission. Invalid optional native
values remain available in `LegacyRecord`. Malformed identifiers or dangling
references can still stop migration; inspect the reported source row and retry
on the backup copy rather than treating an unopened space as empty memory.

The service removes old-id usage rows and resets miss caches, derived metrics
and scan cursors once. It preserves conversations, tokens, policies, wiki
records and any already-recorded v2 usage. The migration is tested against a
complete object-store snapshot produced by the published v0.11 runtime packages;
see [the fixture generator](../scripts/fixtures/v0_11/README.md).

### Runtime
- Spaces are **lazy-loaded** on first access via `OnceCell`.
- In-memory cache with access tracking.
- **5-minute interval**: Flush active spaces to storage.
- **9-minute idle timeout**: Evict unused spaces from cache (skipped while a space is pinned, processing, or still referenced by requests).
- Graceful shutdown: Close all space databases before exit.

### Memory Elements in the Cognitive Nexus

KIP 2.0 separates things KIP 1.x kept in one graph. The distinction the rest
follows from is that **a Proposition existing is not the Proposition being
true**:

| Element         | What it is                                                                      |
| --------------- | ------------------------------------------------------------------------------- |
| **Concept**     | A referable entity: `schema_ref`, immutable `key`, mutable `name`, attributes    |
| **Proposition** | A truth-neutral `(subject, predicate, object)` tuple                            |
| **Assertion**   | One actor's stance about a Proposition: `asserted_by`, `mode`, `confidence`     |
| **Evidence**    | An observed artifact β€” a message, a tool result, a document passage             |
| **Activity**    | The provenance of a process: consolidation, revision, import                    |

What is *currently believed* is projected from Assertions under a named policy
(`BELIEF`), never stored. Mnemonic state β€” how available and how noteworthy a
memory is β€” lives in the `MnemonicState` Facet, and is not confidence.

**Schema is not graph state.** Types and predicates are resolved from immutable,
versioned Schema Packages, so a write cannot change what a type means. This
space activates the standard [Cognitive Memory
Profile](https://github.com/ldclabs/KIP) plus a `kip://anda-brain/memory`
package of its own. When Formation meets vocabulary the profile lacks, it asks
the host to publish it (`declare_memory_symbols`) β€” the host validates the
name's shape, caps how many a space may hold, and versions the result.

## Configuration

### CLI Arguments / Environment Variables

| Env Variable           | CLI Flag                 | Default                             | Description                                                                          |
| ---------------------- | ------------------------ | ----------------------------------- | ------------------------------------------------------------------------------------ |
| `LISTEN_ADDR`          | `--addr`                 | `127.0.0.1:8042`                    | Listen address                                                                       |
| `ED25519_PUBKEYS`      | `--ed25519-pubkeys`      | β€”                                   | Comma-separated Base64 Ed25519 public keys; if empty, API authentication is disabled |
| `MODEL_FAMILY`         | `--model-family`         | `anthropic`                         | Model family to use for encoding and recall (e.g., `gemini`, `anthropic`, `openai`)  |
| `MODEL_API_KEY`        | `--model-api-key`        | β€”                                   | API key for the configured model provider                                            |
| `MODEL_API_BASE`       | `--model-api-base`       | `https://api.deepseek.com/anthropic` | Model API base URL                                                                  |
| `MODEL_NAME`           | `--model-name`           | `deepseek-v4-pro`                   | LLM model for agents                                                                 |
| `MODEL_CONTEXT_WINDOW` | `--model-context-window` | `400000`                            | Model context window size (tokens)                                                   |
| `MODEL_MAX_OUTPUT`     | `--model-max-output`     | `384000`                            | Model max output size (tokens)                                                       |
| `HTTPS_PROXY`          | `--https-proxy`          | β€”                                   | HTTPS proxy URL                                                                      |
| `SHARDING_IDX`         | `--sharding-idx`         | `0`                                 | Shard index for this instance                                                        |
| `MANAGERS`             | `--managers`             | β€”                                   | Comma-separated manager principal IDs                                                |
| `CORS_ORIGINS`         | `--cors-origins`         | β€”                                   | CORS allowed origins: empty = disabled, `*` = allow all, or comma-separated origins  |
| `MCP_HTTP_ENABLED`     | `--mcp-http-enabled`     | `true`                              | Mount Streamable HTTP MCP with the HTTP service                                      |
| `MCP_HTTP_PATH_PREFIX` | `--mcp-http-path-prefix` | `/mcp`                              | Remote MCP prefix; clients connect to `{prefix}/{space_id}`                          |
| `MCP_HTTP_ALLOWED_HOSTS` | `--mcp-http-allowed-hosts` | β€”                                | Comma-separated Host allowlist for remote MCP; use `*` only behind trusted controls  |
| `MCP_HTTP_ALLOWED_ORIGINS` | `--mcp-http-allowed-origins` | β€”                            | Comma-separated browser Origin allowlist for remote MCP                              |
| `MCP_HTTP_AUTO_CREATE_SPACE` | `--mcp-http-auto-create-space` | `false`                    | Create remote MCP spaces on first use after a valid `write` CWT                      |
| `MCP_HTTP_AUTO_CREATE_TIER` | `--mcp-http-auto-create-tier` | `1`                         | Tier used for remote MCP auto-created spaces                                         |
| `MCP_SPACE_ID`         | `mcp --space-id`         | β€”                                   | Space exposed by the MCP stdio server                                                |
| `MCP_AUTH_TOKEN`       | `mcp --mcp-auth-token`   | β€”                                   | CWT or space token used by MCP tools                                                 |
| `MCP_AUTO_CREATE_SPACE` | `mcp --mcp-auto-create-space` | `false`                       | Create the MCP space if it does not exist                                            |
| `MCP_AUTO_CREATE_TIER` | `mcp --mcp-auto-create-tier` | `1`                            | Tier used for MCP auto-created spaces                                                |

`CORS_ORIGINS` examples:
- `""` (empty): CORS disabled
- `"*"`: allow all origins
- `"https://app.example.com,https://admin.example.com"`: allow specific origins

### Storage Backends

| Subcommand | Description                     | Key Env Variables                                                        |
| ---------- | ------------------------------- | ------------------------------------------------------------------------ |
| *(none)*   | In-memory storage (dev/testing) | β€”                                                                        |
| `local`    | Local filesystem storage        | `LOCAL_DB_PATH` (default `./db`)                                         |
| `aws`      | AWS S3 storage                  | `AWS_BUCKET`, `AWS_REGION`, `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY` |

## Cargo Features

The library ships memory only by default β€” formation, recall, maintenance, and
their HTTP routes. Everything else is opt-in:

| Feature | Adds                                                                                                                                                                                    |
| ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `wiki`  | The structured wiki (documents, versions, ACL-scoped reads, OKF import/export), the `wiki_search`/`wiki_read`/`wiki_commit` agent tools, WikiDigest graph extraction, and the `/v1/{space_id}/wiki/*` routes. Also adds the `wiki_*` fields of `SpaceInfo` and `UpdateSpaceInput`. |
| `mcp`   | The MCP channel: the stdio server and the Streamable HTTP service. With `wiki` on as well, the wiki tools join the MCP tool router.                                                        |
| `experiments` | Isolated Rust host runs, immutable snapshots, business time, session boundaries and cost receipts. Enables Nexus `simulation`, without changing production clocks or enabling learning. |
| `learning` | Paired contracts/evaluator, native records, persistent host trial/settlement/review runtime, and a read-only Recall applicability tool. Explicit executor/observer/source/calibration bindings and automatic switches are required; The learning runtime provides a compiled HTTP adapter and bounded scheduler, without model standing writes. |

```toml
# Embedding the library: memory only
anda_brain = "0.12"

# …or the full surface
anda_brain = { version = "0.12", features = ["mcp", "wiki"] }
```

To use development APIs before a crate release, build this checkout. Dependencies
resolve from published crates, including Nexus 0.13.4's legacy migration fixes;
a sibling `anda-db` checkout is only needed for optional local development overrides. Trusted experiment hosts add `experiments`; it is independent of the
`learning` feature.

The `anda_brain` **binary** is the full product and declares
`required-features = ["mcp", "wiki"]`, so every command below passes
`--features mcp,wiki`. Without them Cargo skips the binary target.

## Running

```bash
# Development (in-memory storage)
cargo run -p anda_brain --features mcp,wiki

# Local filesystem storage
cargo run -p anda_brain --features mcp,wiki -- local --db ./data

# HTTP service also serves remote MCP at /mcp/{space_id}
MCP_HTTP_ALLOWED_HOSTS="brain.example.com" \
  cargo run -p anda_brain --features mcp,wiki -- local --db ./data

# AWS S3 storage
cargo run -p anda_brain --features mcp,wiki -- aws --bucket my-bucket --region us-east-1

# MCP stdio server for local MCP clients
MCP_AUTH_TOKEN="$SPACE_TOKEN" \
  cargo run -p anda_brain --features mcp,wiki -- mcp --space-id my_space_001 local --db ./data
```

### Run with Docker image

```bash
# Pull image
docker pull ghcr.io/ldclabs/anda_brain_amd64:latest

# Run with ENV (in-memory by default)
docker run --rm -p 8042:8042 \
  -e LISTEN_ADDR=0.0.0.0:8042 \
  -e MODEL_API_KEY=your_key \
  ghcr.io/ldclabs/anda_brain_amd64:latest

# Override startup args (example: local storage)
docker run --rm -p 8042:8042 \
  -v $(pwd)/data:/data \
  ghcr.io/ldclabs/anda_brain_amd64:latest local --db /data

# Override startup args (example: AWS S3 storage)
docker run --rm -p 8042:8042 \
  -e AWS_ACCESS_KEY_ID=your_ak \
  -e AWS_SECRET_ACCESS_KEY=your_sk \
  ghcr.io/ldclabs/anda_brain_amd64:latest aws --bucket my-bucket --region us-east-1
```

## Dependencies

Key crates from the Anda ecosystem:

| Crate                  | Purpose                                                        |
| ---------------------- | -------------------------------------------------------------- |
| `anda_core`            | Core traits (`Agent`, `Tool`, `AgentContext`) and types        |
| `anda_engine`          | Agent engine, model integration, memory management             |
| `anda_db`              | Persistent database layer (`AndaDB`) with configurable storage |
| `anda_kip`             | KIP 2.0 protocol: parser, error registry, request envelope     |
| `anda_cognitive_nexus` | Cognitive Nexus knowledge graph implementation                 |
| `object_store`         | Object store abstraction                                       |

## License

Copyright Β© LDC Labs

Licensed under the Apache License, Version 2.0.

### Memory utility

`Space::recall_receipts()` retains delivery hashes, actual element versions, basis,
coverage and budgets outside the cognitive graph. Structured Recall returns a
`recall_receipt` handle; Action decisions can bind one through `ContextRequest`.
`Space::utility()` provides trusted attribution/calibration APIs. Startup config
selects `single_contribution_v1` or the paired-trial-backed `paired_revision_v1` and separate
automatic/apply/rank switches. Parameters and approval have no empirical defaults.
Required constraints, native uncertainty, procedure eligibility and execution
authority retain priority. Read the bilingual [utility guide](UTILITY_RUNTIME.md)
and disabled [configuration template](utility.runtime.example.json).