anda_brain 0.13.6

๐Ÿง  Anda Brain (ๅคง่„‘) โ€” Autonomous Graph Memory for AI Agents
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
# Anda Brain โ€” Technical Reference

`anda_brain` is the Rust library and service binary behind
[Anda Brain](../README.md): a dedicated, LLM-driven memory service that maintains a
persistent **Cognitive Nexus** on behalf of business agents through
[KIP 2.0](https://github.com/ldclabs/KIP). Business agents talk to it in natural
language over REST or MCP; they never write KIP.

| Document | Use it for |
| :--- | :--- |
| [API.md]API.md ยท [API_cn.md]API_cn.md | Every request/response shape, with TypeScript types |
| [SKILL.md]SKILL.md | Integration instructions for agents (served at `GET /SKILL.md`) |
| [RUNTIME.md]RUNTIME.md ยท [RUNTIME_cn.md]RUNTIME_cn.md | Runtime API, Watch scheduling, action callbacks, recovery, execution limits |
| [SEMANTIC_WATCH_RUNTIME.md]SEMANTIC_WATCH_RUNTIME.md, [LEARNING_RUNTIME.md]LEARNING_RUNTIME.md, [UTILITY_RUNTIME.md]UTILITY_RUNTIME.md, [TRUST_RUNTIME.md]TRUST_RUNTIME.md | Optional runtimes (each with a `_cn.md` edition) |
| [../CHANGELOG.md]../CHANGELOG.md | Release notes and known limits |

Version 0.13.5 tracks KIP `11a82ec` and `kip://profiles/cognitive-memory@2.0.0`
(content digest `sha256:734aa0fdโ€ฆ`), on the 0.14 AndaDB / KIP / Cognitive Nexus
stack and `anda_engine` 0.17. `Cargo.lock` records the resolved versions.

## Contents

- [Architecture]#architecture
- [Agents]#agents
- [Memory model]#memory-model
- [Memory Interface]#memory-interface
- [HTTP API]#http-api
- [MCP server]#mcp-server
- [Diagnostics and observability]#diagnostics-and-observability
- [Wiki]#wiki-wiki-feature
- [Optional runtimes and host contracts]#optional-runtimes-and-host-contracts
- [Space lifecycle]#space-lifecycle
- [Configuration]#configuration
- [Cargo features]#cargo-features
- [Running]#running
- [Embedding the library]#embedding-the-library
- [Prompts and the KIP reference]#prompts-and-the-kip-reference
- [Testing]#testing
- [Known limits]#known-limits

---

## Architecture

```
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚   Business agent    โ”‚  natural language, REST, MCP, Memory Interface
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
          โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ anda_brain                                                  โ”‚
โ”‚  HTTP / MCP handlers โ”€ auth (CWT, Space tokens) โ”€ payloads  โ”‚
โ”‚  Formation ยท Recall ยท Maintenance agents (LLM + KIP tools)  โ”‚
โ”‚  Host gates ยท settlement ยท self-test ยท attention scheduler  โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
          โ–ผ KIP 2.0 (KQL / KML / META)
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ Cognitive Nexus on AndaDB โ€” one database per Space          โ”‚
โ”‚ object store: local filesystem ยท AWS S3 ยท in-memory         โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
```

| Module | Responsibility |
| :--- | :--- |
| `src/agents/` | Formation, Recall and Maintenance agents and their prompts |
| `src/space.rs`, `src/space/` | Space loading, lifecycle, flushing/eviction, settlement hooks, self-test, shadow evaluation, attention, vocabulary |
| `src/handler.rs`, `src/handler/` | HTTP route handlers |
| `src/mcp.rs` | MCP server (stdio and Streamable HTTP) |
| `src/payload.rs` | JSON / CBOR / Markdown negotiation |
| `src/authz.rs` | Endpoint admission (public read, credentialed, management) |
| `src/types.rs` | API inputs/outputs and persisted configuration |
| `src/kip.rs` | KIP envelope builders, read-only gate, literal helpers |
| `src/kip_reference.rs` | The read-only `kip_reference` tool over the compiled reference |
| `src/memory_interface/` | KIP Memory Interface (`memory_basic`) |
| `src/vocabulary.rs` | Draft vocabulary and the Formation `DEFINE` gate |
| `src/settlement/` | Deterministic settlement: corrections, revised roots, Watch advancement, Commitments, retention |
| `src/assess/` | Recall traces, citations, probe |
| `src/recall_budget/` | Budgeted Recall packets and the pinned tokenizer |
| `src/attention/`, `src/action/`, `src/runtime_api/` | Watch scheduling, action gate and dispatch, authenticated runtime API |
| `src/consequence/`, `src/recall_receipt.rs` | Outcomes, Recall receipts, utility and trust |
| `src/product.rs`, `src/product/` | Trusted-host memory product contracts |
| `src/learning/` | Trusted paired-trial runtime (`learning` feature) |
| `src/wiki/` | Versioned wiki (`wiki` feature) |
| `src/legacy_upgrade.rs` | In-place upgrade of KIP 1.x Spaces |

---

## Agents

Every model call carries the complete, version-pinned KIP 2.0 syntax, the Cognitive
Memory Profile, the applicable role cards and the deployment contract in its system
prompt (see [Prompts and the KIP reference](#prompts-and-the-kip-reference)). The
model writes KIP; the host decides what it is allowed to write.

### Formation โ€” encoding (`formation_memory`)

`POST /v1/{space_id}/formation` and the Memory Interface `observe` / `revise` /
`feedback` intents queue a Formation conversation and return at once.

1. The input (messages, optional `context`, optional `timestamp`) becomes a tracked
   conversation: `submitted` โ†’ `working` โ†’ `completed` | `failed`. The host captures
   each message as Evidence before the model runs; the model cites it as `:msg1`,
   `:msg2`, โ€ฆ.
2. The model decides what is worth keeping, using the Profile's products: Evidence
   for what was observed, Proposition + Assertion for a claim and whose stance it is,
   Event for what happened, Experience for a process that can teach future behavior,
   Commitment for an obligation, Insight and SelfModel candidates. Writing nothing is
   a valid answer.
3. It grounds against existing memory (`SEARCH` before `CREATE`) and writes through
   `execute_kip`.

The Formation gate accepts KQL and META in full and only the cognition subset of KML.
Bulk administration โ€” `UPDATE`, `SET RETENTION`, `PURGE`, `MERGE CONCEPT`, and
`TRANSITION` to `archived` or `tombstoned` โ€” is refused, because the whole input is an
untrusted conversation. Other host rules:

- **World time.** An Assertion that cites a captured message must carry that message's
  observation time (`at` or `valid.from`); the Brain's own inferences are exempt. A
  message's `timestamp` (Unix ms) is its observation time; otherwise the request
  `timestamp` (RFC 3339, canonicalized to UTC milliseconds; unparseable values are
  rejected with 400), otherwise the conversation's creation time.
- **Draft vocabulary.** A command naming an undefined type or predicate fails with
  `SchemaSymbolNotFound`. Formation then sends `DEFINE CONCEPT TYPE` /
  `DEFINE PREDICATE` with literal names in a request of its own (at most eight).
  The host checks the name's shape, caps the Space at 512 symbols of its own, and
  queues one `review_schema` SleepTask per new symbol. The `declare_memory_symbols`
  tool remains as a deprecated shortcut that drafts bare names the same way.
- **Strength writes** must carry `last_metabolized_at` and the host-bound
  `strength_policy` pin (`kip:strength-half-life-30d`).
- **Scope.** A Memory Interface source with a task/context scope makes every claim
  carry that context set; the gate refuses one that does not.
- **Large inputs** (โ‰ฅ 10,000 estimated tokens) get one focused self-review within the
  same turn and time budgets. It checks for material omissions and misrepresentation;
  "no changes" is a valid result. This is not a completeness guarantee.

Formation processes a Space's queue sequentially and resumes after Maintenance. A
conversation that fails three rounds over at least 30 minutes is given up so the
queue can move on. Tools: `execute_kip`, `note`, `declare_memory_symbols`,
`memory_runtime`, `kip_reference`.

### Recall โ€” retrieval (`recall_memory`)

`POST /v1/{space_id}/recall`, `/recall_structured`, the MCP recall tool and the
Memory Interface `recall` intent run the Recall agent.

1. It loads a fresh Primer, analyzes the question (entity lookup, relationship
   traversal, event recall, pattern, โ€ฆ) and grounds names to graph nodes.
2. It reads with KQL and META. Belief questions go through `BELIEF` projection rather
   than raw `FIND`, because a Proposition existing is not the Proposition being true.
3. It deepens iteratively, up to the Space's `recall_max_rounds` (default 7).
4. It answers with what memory supports: contested as contested, insufficient as
   insufficient โ€” never "no" for "no basis".

Recall is strictly read-only. `execute_kip_readonly` enforces KQL/META on what each
command *parses to*, and reading never reinforces memory. Tools:
`execute_kip_readonly`, `kip_reference`, plus `wiki_search` / `wiki_read` with the
`wiki` feature and `check_procedure_status` with the `learning` feature.

`recall_structured` adds trace-derived citations, a `found` flag and the model's
self-reported uncertainty. An optional `budget` (or an enforced
`memory_policy.recall_budget`) switches Recall to a host-packed JSON memory packet
counted with the pinned `o200k_base@tiktoken-rs-0.12` tokenizer: required
constraints and warnings first, explicit coverage, fixed failure codes. See the
[Recall budget contract](API.md#recall-budget-contract).

### Maintenance โ€” metabolism (`maintenance_memory`)

Maintenance runs asynchronously, single-flight per Space, and returns a conversation
id immediately. It runs at three scopes:

| Scope | Automatic trigger | Work |
| :--- | :--- | :--- |
| `daydream` (default) | every 21 formed conversations | Salience scoring and micro-consolidation |
| `quick` | every 42 formed conversations | Assessment plus urgent SleepTasks |
| `full` | every 168 formed conversations, and when 24 hours have passed since the last cycle of a Space that has formed anything | All phases, plus the predicate census and retention expiry |

The clock trigger fires from the background flush pass for resident Spaces and on load
for evicted ones. `POST /v1/{space_id}/maintenance` runs one on demand.

**Settlement first.** Before the model runs, the host settles deterministically:
newly superseded Assertions are recorded as corrections and tallied per asserting
actor (`source_reliability`); each revised root is handed over with its bounded
`LIST DEPENDENTS` (`assessment.revised_roots`); structured Watches advance under
generation/version/coverage checks; each due `pending`/`blocked` Commitment without a
Watch is raised once per `due_at` with a `commitment_review` Activity; full cycles
refresh the predicate census and archive what passed `retention.expires_at`. The
result reaches the model as its `assessment` block, which the host overwrites โ€”
a request body cannot tell the Brain what its own graph looks like. The last report is
kept in the `memory_settlement` extension.

**Model phases** (full scope): assessment; SleepTask processing (`consolidate`,
`review_conflict`, `review_skill`, `resolve_identity`, `review_retention`,
`review_derived`, `refresh_self_model`, `inspect_quarantine`, `review_schema`);
semantic consolidation with Activity lineage; procedural consolidation into unproven
Skill candidates with immutable `SkillRevision`s; identity review and non-destructive
`MERGE CONCEPT`; contradiction and derivation review; mnemonic metabolism from
explicit signals; Commitment and Watch review; SelfModel / WorkingState refresh;
retention review with `SET RETENTION`.

What Maintenance cannot do: `PURGE` / `PURGE PAYLOAD`, `DEFINE`, promoting vocabulary,
writing WatchState / LeaseState, or writing trial, evaluation, attempt, outcome,
grading or lineage records. SleepTask work requires a five-minute lease from the
`memory_runtime` tool (`lease_task`) and commits terminal state and outputs in one
version-guarded `MUTATE`. A Watch is created `disarmed` and armed with
`memory_runtime`'s `arm_watch`, which captures an authorization view and starts a new
generation; a fired Watch is attention, never permission. Tools: `execute_kip`,
`note`, `memory_runtime`, `kip_reference`.

**Self-test.** After a cycle, the host samples recent memories with no usage
evidence, generates one probe query per memory (one model call, bounded by
`self_test_queries_per_cycle` and `self_test_token_budget`) and checks whether search
surfaces them. Unfindable ones become `review` SleepTasks that the next full cycle
re-encodes with aliases and richer descriptions. Self-test retrievals are counted
separately and never reinforce. The report lives in the `memory_self_test` extension.

---

## Memory model

| Element | Id | What it is |
| :--- | :--- | :--- |
| **Concept** | `C-*` | A referable entity: `schema_ref`, immutable `key`, mutable `name`, attributes |
| **Proposition** | `P-*` | A truth-neutral `(subject, predicate, object)` tuple |
| **Assertion** | `A-*` | One actor's stance on a Proposition: `asserted_by`, `mode`, `confidence`, valid time, Evidence |
| **Evidence** | `E-*` | An observed artifact: a message, a tool result, a document passage |
| **Activity** | `X-*` | Provenance of a process: formation, consolidation, revision, import |

- **Belief is projected**, never stored: `BELIEF` evaluates Assertions under a named
  policy. `insufficient` is never reported as "no".
- **Three histories.** A changed world is one new Assertion from the change; temporal
  succession ends the old value, which stays true for its time. A wrong claim is
  superseded by a new Assertion from the same actor. A misrecording is repaired by
  invalidating the extraction (Memory Interface `revise` with
  `change_kind: "misrecorded"`). Nothing rewrites an Assertion, and different actors'
  disagreement coexists.
- **Mnemonic state is not confidence.** `MnemonicState.memory_strength` is a base;
  the engine derives `effective_strength` at read time from the base, its anchor
  (`last_metabolized_at`) and the pinned strength policy. A missing input is unknown,
  never 0.5. There is no decay sweep, and Assertion confidence never decays.
- **Reading never reinforces.** Recall records what it surfaced in an off-graph usage
  ledger and the Nexus exposure log; neither raises strength. Maintenance may
  reinforce from explicit signals in bounded, version-guarded batches.
- **Schema is not graph state.** Types and predicates resolve from immutable,
  versioned Schema Packages. Each Space activates the Cognitive Memory Profile and
  its own draft package `kip://local/draft@0.0.0` (KIP ยง20.16). Drafts are additive
  and never change; `GET /v1/{space_id}/schema/drafts` lists them, and the owner
  promotes one onto an installed symbol with `POST /v1/{space_id}/schema/promote`.
  Spaces that grew vocabulary earlier keep their read-only `kip://anda-brain/memory`
  package. The Profile has no `Preference` type: an option is a Concept typed by its
  kind (`ColorScheme`, `Editor`).
- **Two expiry clocks.** An Assertion whose `valid_time.until` has passed is
  `expired` for later reads โ€” computed, never swept, still visible to `FOR TIME` in
  the past. An element whose `retention.expires_at` has passed is archived by a full
  settlement (out of ordinary recall, still readable). Legal holds stop the sweep;
  the report counts held and refused elements.
- **Pinning and forgetting.** `POST /v1/{space_id}/memory/pin` gives an element the
  `pinned` retention class. `POST /v1/{space_id}/memory/forget` physically purges
  explicit `C-*`, `P-*`, `A-*`, `E-*` and `X-*` ids (dry run first), subject to legal
  holds and reference checks, and scrubs saved previews that referred to them.
  Conversations, wiki documents and external copies have their own lifecycles.
  Governed, plan-based erasure is the Memory Interface `forget` intent.

---

## Memory Interface

Every Space serves the KIP 2.0 Memory Interface at the `memory_basic` level: one
request shape, five intents, one intent per request. It is the recommended path for a
business agent that needs receipts and barriers.

| Intent | Does |
| :--- | :--- |
| `observe` | Runs Formation over a staged source within the request's scope |
| `recall` | Returns a `Briefing`: final belief per item, seven coverage channels (`constraints`, `commitments`, `failures`, `experiences`, `skills`, `dependencies`, `evidence`), `action_eligible`, and a retained `basis_ref` that can be expanded later. `mode: "attention"` pages raised attention without a model call |
| `revise` | Writes the right history: `correction`, `world_change`, `misrecorded` (recording repair) or `unspecified` |
| `feedback` | Captures a self-report or a person's statement as Evidence; it grades nothing |
| `forget` | Runs an ErasurePlan: `payload_only`, or `semantic` (owner CWT) erasure of a claim and its closure, including the host's own copies |

Mutations take an `idempotency_key` scoped to `(caller, Space, operation)` and return
an immutable receipt whose progress moves `recorded` โ†’ `available` (with a
disposition of `formed`, `evidence_only`, `skipped` or `erased`) or `failed`. A
recall's `after` list waits for the caller's receipts until `budget.deadline_ms`.
Staged sources, keys, receipts, retained bases and plans belong to the caller and
survive restart. `memory_experience`, `memory_learning` and `durable_brain_runtime`
are not advertised; requiring them fails with `UnsupportedCapability`.

The descriptor appears on `GET /info` and `GET /v1/{space_id}/info` as
`memory_interface`. Full semantics: [API.md โ€บ Memory Interface](API.md#memory-interface);
host-side receipts and barriers: [RUNTIME.md](RUNTIME.md#memory-interface-receipts-and-barriers).

---

## HTTP API

### Conventions

- **Envelope.** Most endpoints return `{"result": โ€ฆ, "error": null}`.
  `POST /v1/{space_id}/memory` returns a Memory Interface `Response` instead and
  reports failures inside it with HTTP 200.
- **Content negotiation.** Request bodies: `Content-Type: application/json`
  (default), `application/cbor` or `text/markdown` (raw text for Formation/Recall).
  Success bodies follow `Accept` with the same three types. Handler errors are always
  JSON; load shedding (`429` / `503`) and unmatched routes may return plain text.
- **Sharding.** Send `Shard-Id: <n>` (or `X-Shard`) matching the instance's
  `SHARDING_IDX`; the default is `0`.
- **Admission.** Model-driving routes (formation, recall, recall_structured,
  maintenance, shadow_eval, wiki digest) share `LLM_MAX_CONCURRENCY` and answer `429`
  when it is exhausted; every route shares `HTTP_MAX_CONCURRENCY` and answers `503`.

### Authentication

Credentials are sent as `Authorization: Bearer <token>`:

- **CWT** โ€” a COSE Sign1 token signed by one of the `ED25519_PUBKEYS`, with claims
  `sub` (principal), `aud` (Space id or `*`) and `scope` (`read`, `write` or `*`).
  `anda-cli cwt` creates one.
- **Space token** โ€” minted by the Space's management endpoints, with scope `read`,
  `write` or `*`, an optional expiry, and optional wiki ACL `labels`. A
  label-restricted token cannot use agentic Recall or read conversations, because
  those span all labels.

Scopes don't nest: `*` satisfies every requirement, while `read` and `write` satisfy
only endpoints that require exactly that scope. An agent that writes and recalls a
private Space needs a `*` credential or one of each.

Endpoints admit callers in one of four ways: public read (a public Space is readable
anonymously), credentialed (`read` / `write` / `*` via CWT or Space token), management
(CWT only), and admin (a CWT whose subject is in `MANAGERS`). When `ED25519_PUBKEYS` is
empty, authentication is disabled for these endpoints โ€” never run like that in
production. The runtime endpoints always require verified credentials and explicit
mappings. The per-endpoint rules are in [API.md โ€บ Authentication](API.md#2-authentication).

### Endpoints

Public:

| Method | Path | Description |
| :--- | :--- | :--- |
| `GET` | `/info` | Service name, version, sharding and the Memory Interface descriptor |
| `GET` | `/SKILL.md` | Integration skill (Markdown) |
| `GET` | `/favicon.ico`, `/apple-touch-icon.webp` | Icons |

Memory (`/v1/{space_id}`):

| Method | Path | Auth | Description |
| :--- | :--- | :--- | :--- |
| `POST` | `/formation` | `write` | Queue messages for encoding; returns the conversation id |
| `POST` | `/recall` | `read`* | Natural-language answer |
| `POST` | `/recall_structured` | `read`* | Answer with citations, `found`, uncertainty (or a budget packet) |
| `POST` | `/maintenance` | `write` | Run a maintenance cycle (`trigger`, `scope`, `parameters`) |
| `POST` | `/probe` | `read`* | Model-free "do I know anything about this?" |
| `POST` | `/memory/pin` | `write` | Pin or unpin an element |
| `POST` | `/memory/forget` | `write` | Purge explicit elements (`dry_run` supported) |
| `GET` | `/memory/attention` | `read`* | Fired Watches and due Commitments after a kept cursor |
| `GET` | `/schema/drafts` | `read`* | The Space's draft vocabulary |
| `POST` | `/schema/promote` | management CWT | Promote a draft onto an installed symbol |
| `GET` | `/memory_status` | `read`* | Counters, rates, graph counts, latest settlement/self-test/shadow reports |
| `POST` | `/execute_kip_readonly` | `read`* | Read-only KIP (KQL and META) |
| `POST` | `/get_or_init_user` | `write` | Get or create a counterparty Concept |
| `GET` | `/info`, `/status` | `read`* | Space information and statistics |
| `GET` | `/formation_status` | `read`* | Lightweight formation/maintenance progress |
| `GET` | `/conversations` | `read`* | List formation / recall / maintenance conversations (cursor paging) |
| `GET` | `/conversations/{id}` | `read`* | One conversation |
| `GET` | `/conversations/{id}/delta` | `read`* | Messages and artifacts after given offsets |

\* Public Spaces allow anonymous reads; some endpoints additionally reject
label-restricted tokens or anonymous reads of recall transcripts. See [API.md](API.md).

Memory Interface (`/v1/{space_id}`):

| Method | Path | Auth | Description |
| :--- | :--- | :--- | :--- |
| `POST` | `/memory` | recall `read`*; mutations `write`; `semantic` forget owner CWT | One intent per request |
| `POST` | `/memory/sources` | `write` | Stage observed messages; returns a `source_ref` |
| `GET` | `/memory/sources/{source_ref}` | `read` credential | A staged source, for the caller that staged it |
| `GET` | `/memory/receipts/{receipt_ref}` | `read` credential | Receipt progress and result |
| `GET` | `/memory/plans/{plan_ref}` | `read` credential | A forget's ErasurePlan and host surfaces |

Wiki (`/v1/{space_id}/wiki`, `wiki` feature):

| Method | Path | Auth | Description |
| :--- | :--- | :--- | :--- |
| `POST` / `GET` | `/docs` | `write` / `read`* | Commit a document version / list documents |
| `GET` | `/docs/{doc_id}`, `/docs/{doc_id}/content`, `/docs/{doc_id}/versions` | `read`* | Metadata, content (TOC, section, range), history |
| `POST` | `/docs/{doc_id}/archive`, `/docs/{doc_id}/restore` | `write` | Archive or restore |
| `POST` | `/search`, `/verify` | `read`* | BM25 search with citations; verify a citation |
| `GET` | `/events` | `read` | Wiki audit events |
| `POST` / `GET` | `/import`, `/export` | `*` | OKF import / export |
| `POST` | `/digest` | `write` | Run WikiDigest graph extraction |

Management (`/v1/{space_id}/management`, CWT only):

| Method | Path | Description |
| :--- | :--- | :--- |
| `GET` | `/space_tokens` | List Space tokens |
| `POST` | `/add_space_token` | Mint a token (`*` needs a `*`-scoped CWT) |
| `POST` | `/revoke_space_token` | Revoke a token by value or name |
| `PATCH` | `/update_space` | Name, description, visibility, `memory_policy`, wiki settings |
| `PATCH` | `/restart_formation` | Restart a stuck formation |
| `GET` / `PATCH` | `/space_byok` | Read / set the Space's own model configuration |
| `POST` | `/shadow_eval` | Compare a candidate `MemoryPolicy` on forked copies |

Admin (CWT from a principal in `MANAGERS`):

| Method | Path | Description |
| :--- | :--- | :--- |
| `POST` | `/admin/create_space` | Create a Space: `{user, space_id, tier}` |
| `POST` | `/admin/{space_id}/update_space_tier` | Change a Space's tier |

Runtime (`/v1/{space_id}`, requires `BRAIN_RUNTIME_CONFIG` mappings; see
[RUNTIME.md](RUNTIME.md)):

| Method | Path | Description |
| :--- | :--- | :--- |
| `GET` | `/attention` | The caller's durable attention inbox (reading claims nothing) |
| `POST` | `/attention/{id}/responses` | Answer a clarification or record an agent statement |
| `POST` | `/outcomes` | Independent outcome from a signed, registered observer |
| `GET` | `/runtime/status` | Configured runtime capabilities and a bounded visible inventory |

Typical calls:

```bash
# Formation
curl -sX POST "$BRAIN/v1/my_space/formation" -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"messages": [{"role": "user", "content": "I prefer dark mode.", "name": "Alice"}],
       "context": {"counterparty": "alice", "agent": "settings_bot"},
       "timestamp": "2026-03-09T10:30:00.000Z"}'

# Recall
curl -sX POST "$BRAIN/v1/my_space/recall" -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"query": "What are Alice'\''s preferences?", "context": {"counterparty": "alice"}}'

# Maintenance
curl -sX POST "$BRAIN/v1/my_space/maintenance" -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" -d '{"trigger": "on_demand", "scope": "full"}'

# Read-only KIP
curl -sX POST "$BRAIN/v1/my_space/execute_kip_readonly" -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" -d '"DESCRIBE PRIMER"'
```

Business agents can register Recall as a function call; `RecallAgent::definition()`
is its definition.

---

## MCP server

With the `mcp` feature, the HTTP service mounts a Streamable HTTP MCP endpoint at
`{MCP_HTTP_PATH_PREFIX}/{space_id}` (default `/mcp/{space_id}`). Clients send the same
CWT or Space token as REST in `Authorization: Bearer โ€ฆ`. For local clients, run a
stdio server:

```bash
MCP_AUTH_TOKEN="$SPACE_TOKEN" ./anda_brain mcp --space-id my_space local --db ./data
```

Both transports share the HTTP service's model, auth and storage configuration and
the process-wide model concurrency budget. The storage subcommand after `mcp` is
optional (in memory when omitted).

| Tool | Purpose | Scope |
| :--- | :--- | :--- |
| `anda_brain_memory` | Memory Interface request (`{request}`) | recall `read`; mutations `write` |
| `anda_brain_stage_memory_source` | Stage observed messages; returns a `source_ref` | `write` |
| `anda_brain_memory_receipt` | Read a receipt's progress | `read` |
| `anda_brain_remember_conversation` | Encode conversation messages (Formation) | `write` |
| `anda_brain_recall_memory` | Ask memory a question (Recall, optional `budget`) | `read` |
| `anda_brain_run_maintenance` | Run a maintenance cycle | `write` |
| `anda_brain_get_space_info` | Space statistics and metadata | `read` |
| `anda_brain_get_formation_status` | Formation/maintenance progress | `read` |
| `anda_brain_execute_kip_readonly` | Read-only KIP (KQL/META, 15-second bound) | `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` | One conversation or its delta | `read` |
| `anda_brain_get_attention` | The caller's runtime attention inbox | verified `read` + mapping |
| `anda_brain_respond_attention` | Answer a clarification or record a statement | verified `write` + mapping |
| `anda_brain_get_runtime_status` | Configured runtime capabilities | verified `read` |
| `anda_brain_wiki_search` | Wiki search with verifiable citations | `read` |
| `anda_brain_wiki_read` | Progressive wiki reads (TOC, section, range) | `read` |
| `anda_brain_wiki_commit` | Commit a wiki document version | `write` |
| `anda_brain_wiki_verify` | Verify a wiki citation | `read` |

The wiki tools join when the `wiki` feature is on (always, for the service binary).
Read tools work on public Spaces without a token. Remote MCP checks the `Host` header
against `MCP_HTTP_ALLOWED_HOSTS` and browser origins against
`MCP_HTTP_ALLOWED_ORIGINS`; set them when serving behind a domain or proxy.
`MCP_HTTP_AUTO_CREATE_SPACE` creates a missing Space on first use, which requires
`ED25519_PUBKEYS` and a `write` CWT for that Space; `--mcp-auto-create-space` does the
same for stdio. No MCP tool schema uses `oneOf`, `anyOf` or `allOf`.

---

## Diagnostics and observability

- **Probe.** `POST /v1/{space_id}/probe` (`{"query", "limit"}`) answers "do I know
  anything about this?" with pure search โ€” no model call. Explicitly exhaustive misses
  enter a negative cache (cleared when Formation completes, 1-hour TTL). `found: false`
  is a retrieval result, not a rejected belief. Probe first; pay for Recall when
  `found` is true.
- **Memory status.** `GET /v1/{space_id}/memory_status` returns counters maintained at
  write time (recalls, probe hits/misses, self-test groundability, corrections,
  forgets), derived rates (probe hit rate, correction rate, mean self-reported
  uncertainty, maintenance tokens per recall), graph counts including
  `predicate_types`, and the latest settlement, self-test and shadow reports. Reading
  it never runs heavy queries. Correction discovery reports
  `correction_scan_incomplete`, `correction_scan_through_seq` and
  `correction_scan_error`.
- **Shadow evaluation.** `POST /v1/{space_id}/management/shadow_eval` forks the Space
  twice into isolated in-memory stores (current vs candidate `MemoryPolicy`), settles
  both, replays recent real recall queries on each and has a judge compare the answers
  blind, alternating A/B order. The live Space is only read. Set an independent judge
  with `JUDGE_MODEL_*`; otherwise the Space's own model judges. The report is stored in
  the `shadow_report` extension; promoting the candidate stays a human
  `update_space` decision.
- **Conversations.** Formation, Recall and Maintenance runs are kept as conversations
  (`collection=formation|recall|maintenance`), readable in full or as deltas.

---

## Wiki (`wiki` feature)

The wiki is a Space's versioned reference memory โ€” policies, manuals, SOPs, API docs.

- Writes are immutable Markdown versions with compare-and-swap on `parent_version`;
  a conflict returns 409 with the version to rebase on. Content is capped at 1 MiB.
- Documents may carry an `acl_label`. Label-restricted tokens see unlabeled content
  plus their labels; anonymous readers of public Spaces see unlabeled content only.
  ACL checks and content selection use one document snapshot.
- The TOC follows ATX headings independently of retrieval chunks; reads are capped at
  256 KiB and continue by byte range. Citations are verifiable `wiki://` URIs.
- OKF import/export round-trips unknown YAML values.
- **WikiDigest** (disabled by default) extracts graph claims from documents. It keeps
  per-document pending state, skips unchanged bodies, and withdraws an old claim only
  after an explicit absence review over every body batch or withdrawal of the source โ€”
  an omission is not negative evidence.
- Recall uses `wiki_search` / `wiki_read` alongside the graph.

See [API.md โ€บ Wiki](API.md#43-wiki-endpoints-v1space_idwiki).

---

## Optional runtimes and host contracts

None of these change behavior until a host configures them. Model output never
installs an executor, observer, evaluator or authority.

| Capability | What it adds | Guide |
| :--- | :--- | :--- |
| **Watch scheduling** | A persistent scheduler advances structured Watches across registered Spaces, independently of Maintenance, resuming after eviction or restart. Firing commits the transition, a `watch_fire` Activity and a protected wake atomically. | [RUNTIME.md]RUNTIME.md |
| **Action callbacks** | Trusted Rust hosts install `ActionBindings` for a four-way decision gate, clarification and fenced dispatch. None are installed by default. | [RUNTIME.md]RUNTIME.md#action-callbacks-and-authority |
| **Runtime API** | `BRAIN_RUNTIME_CONFIG` selects a compiled inbox adapter and explicit identity/observer mappings for `/attention`, `/outcomes` and `/runtime/status`. | [RUNTIME.md]RUNTIME.md#startup, [runtime.example.json]runtime.example.json |
| **Semantic Watches** | A pinned evaluator judges prose and mixed Watch conditions over immutable pages; unknown, missing or truncated judgments never advance coverage. | [SEMANTIC_WATCH_RUNTIME.md]SEMANTIC_WATCH_RUNTIME.md, [example]semantic.runtime.example.json |
| **Learning** (`learning` feature) | Frozen paired-trial contracts, a Nexus evaluator and a persistent trial/settlement/review runtime with a `workflow_http_v1` adapter. Requires a real executor, independently authenticated observers and reviewed calibration. | [Contracts]#native-learning-contracts, [LEARNING_RUNTIME.md]LEARNING_RUNTIME.md, [example]learning.runtime.example.json |
| **Memory utility** | Verifiable off-graph Recall receipts, independent contribution attribution, bounded utility calibration and optional ranking within existing Recall priorities. | [UTILITY_RUNTIME.md]UTILITY_RUNTIME.md, [example]utility.runtime.example.json |
| **Contextual trust** | Reviewable source-trust proposals from independently verified facts, applied only through current `manage_trust` authority. | [TRUST_RUNTIME.md]TRUST_RUNTIME.md, [example]trust.runtime.example.json |
| **Experiments** (`experiments` feature) | Isolated host runs, immutable snapshots, completion waits, business time, cost receipts with explicit unknowns, forced Recall budgets and evaluator-only procedure audits. | [Below]#isolated-experiments-and-mib-integration, [src/space/experiments.rs]src/space/experiments.rs |
| **Memory product contracts** | The Rust `product` module: Assertion-backed `MemoryRecord` views, source-backed ingestion, reviewed `Correct` / `WorldChange` changes, `Suppress` / `Delete` with source fences, and recipient-owned record Watches. The embedding host must enforce visibility. | [API.md โ€บ Trusted host contracts]API.md#trusted-host-memory-product-contracts |

Procedures stay **unproven** without the learning pipeline:
`Skill.current_revision` points at an immutable `SkillRevision`, shared `task_family`
only discovers candidate controls, and `skills.unsupported_reason` in the settlement
report says why no verdict ran. Mechanism tests use deterministic fixtures; they are
not evidence of empirical improvement.

### Native learning contracts

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

The `anda-brain:paired-bounded-v2` rule compares one candidate revision with a stable
task policy under the same factual memory, model, tools, budget and task/state/seed
pairs. It needs the whole predeclared cohort, a one-sided Hoeffding lower bound above
the practical-improvement margin and an absolute candidate failure-rate ceiling.
Missing treatment outcomes count as failures; missing or unknown control outcomes
leave the comparison insufficient. Duplicate pairs or observations, changed pins and
extra applied revisions are rejected. A monitoring trial keeps the original
acquisition through `AdoptionBasis`. Multi-Skill bundles, adaptive stopping and
windowed ledgers are not supported, and no parameter has a production default.

`ExecutionContract` pins tool/time/token ceilings, the cutoff and the review deadline;
call `validate_settlement()` before a final verdict. `workflow_contract()` supplies
the first resettable task-family contract
([workflow-contract-v1.json](assets/learning/workflow-contract-v1.json)).

`Space::learning()` is the persistent host runtime: explicit registration, frozen
enrollment, bounded `drive` steps, recovery after restart, separately authenticated
Outcome ingestion, fixed-cutoff `settle`, persistent `reviews` / `enroll_review`,
`submit_safety_signal` for independent revocation, and `procedure_status` /
`bind_application_context` for read-time eligibility. Native leases, executable
authority and dependency validity gate dispatch; finishing a cohort adopts nothing,
and a recommendation never grants execution permission. Configured learning Spaces
cannot be forked with their operational journal. Background advancement, the
`workflow_http_v1` adapter and archival are configured as described in
[LEARNING_RUNTIME.md](LEARNING_RUNTIME.md). Run the mechanism tests with:

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

<a id="mib-integration"></a>
<a id="isolated-experiments"></a>

### Isolated experiments and MIB integration

With the `experiments` feature, the host-only `Experiment` owner supplies isolated
stores, quiescent immutable snapshots, per-conversation completion waits, monotonic
business time (`advance_to`), session boundaries and cost receipts that keep unknown
values unknown. It enables the Nexus `simulation` API for lifecycle expiry only;
authentication, lease and audit clocks stay real, and no HTTP/MCP clock override
exists. Agent Notes persist under each Space's `engine/` prefix and are part of
snapshots. `Experiment::create_with_recall_budget` pins a forced Recall budget before a
run is exposed, across forks and session boundaries; `audit_procedures()` returns a
bounded evaluator-only native inventory (256 items per kind, 4 MiB) whose truncated
counts cannot prove absence. Neither enables learning or grants execution authority.

The sibling [Anda Bot](https://github.com/ldclabs/anda-bot) `mib` feature builds on
this for an isolated loopback host: `/mib-agent/v0.1` for the agent and
`/mib-memory/v0.1` for the memory backend. These are not routes of this service. See
the [Bot host contract](https://github.com/ldclabs/anda-bot/blob/main/docs/mib-integration.md),
the [MIB memory backend contract](https://github.com/ldclabs/MIB/blob/main/docs/harness/MIB-Memory-Backend.md)
and the [longitudinal harness](https://github.com/ldclabs/MIB/blob/main/docs/harness/MIB-Learning-Longitudinal.md).
The Bot currently provides persistent and no-memory modes; native normal/ungated
learning bindings remain pending.

---

## Space lifecycle

- **Creation** (`POST /admin/create_space`) creates an AndaDB database for the Space,
  initializes the Cognitive Nexus, activates the Cognitive Memory Profile and records
  the owner. Drafted vocabulary is Space state the engine keeps across activations.
- **Tiers.** Formation refuses new input once a Space holds more Concepts (or
  conversations) than its tier allows: 10^(tier+2) โ€” 100 at tier 0, 1,000 at tier 1.
- **Loading.** Spaces load lazily on first access and stay cached.
- **Background work.** Every 5 minutes the service flushes active Spaces and checks
  the maintenance clock; Spaces idle for 9 minutes are evicted, unless pinned,
  processing or still referenced. Owned native writes survive cancelled requests and
  drain before a database closes.
- **Shutdown** closes every Space so AndaDB flushes collections and metadata.
- **One writer per Space.** The usage ledger, settlement, self-test and cache guards
  are in-process. Sharding assigns each Space to exactly one process; never point two
  instances at the same Space's storage.

<a id="upgrading-a-space-written-by-a-kip-1x-build"></a>

### Upgrading KIP 1.x Spaces

A Space written by a KIP 1.x build migrates in place when first opened. Stop the old
writer, take a consistent backup and rehearse on a copy first; rollback needs that
backup. The migration checkpoints extraction and vocabulary so it can resume, keeps
the original rows in `kip_legacy_v1`, and maps conservatively:

| v1 data | v2 representation |
| :--- | :--- |
| `(type, name)` identity | Immutable Concept `key`; standard Person / Event / Insight / Commitment / SleepTask fields normalized; a 1.x `Preference` keeps an open legacy type |
| A recorded claim | Proposition + `mode: "imported"` Assertion, preserving confidence and resolvable author |
| Retracted or superseded claim | Native lifecycle where the same-actor revision is reconstructible; otherwise archived, never revived as current belief |
| `valid_from` / `valid_until`; `expires_at` | Assertion valid time; record retention |
| `pinned`; mnemonic values | Pinned retention class; `MnemonicState`, never copied from confidence |
| Unsupported learning/runtime artifacts | Distinct `Legacy*` types under `kip://legacy/nexus@1.1.0`, without standing or leases |

Old-id usage rows, miss caches, derived metrics and scan cursors reset once;
conversations, tokens, policies and wiki records are kept. Malformed identifiers can
stop the migration โ€” inspect the reported row and retry on the backup rather than
treating an unopened Space as empty.

Spaces activated under the KIP 2.1.0 draft are not migrated by the service. Use the
standalone [`tools/migrate-draft-space`](../tools/migrate-draft-space/README.md).

---

## Configuration

### Service options

Every option is a flag and an environment variable; a `.env` file is read at startup.

| Environment variable | Flag | Default | Description |
| :--- | :--- | :--- | :--- |
| `LISTEN_ADDR` | `--addr` | `127.0.0.1:8042` | Listen address |
| `ED25519_PUBKEYS` | `--ed25519-pubkeys` | โ€” | Comma-separated Base64 Ed25519 public keys for CWT verification; empty disables authentication |
| `MANAGERS` | `--managers` | โ€” | Comma-separated principals allowed to use `/admin` endpoints |
| `MODEL_FAMILY` | `--model-family` | `anthropic` | Provider protocol: `anthropic`, `openai`, `gemini`, โ€ฆ |
| `MODEL_API_BASE` | `--model-api-base` | `https://api.deepseek.com/anthropic` | Provider base URL |
| `MODEL_NAME` | `--model-name` | `deepseek-v4-pro` | Model for all three agents |
| `MODEL_API_KEY` | `--model-api-key` | โ€” | Provider key; empty disables the default model |
| `MODEL_CONTEXT_WINDOW` | `--model-context-window` | `400000` | Context window (tokens) |
| `MODEL_MAX_OUTPUT` | `--model-max-output` | `384000` | Max output (tokens); use โ‰ค 128000 for Claude |
| `HTTPS_PROXY` | `--https-proxy` | โ€” | Proxy for outbound model requests |
| `SHARDING_IDX` | `--sharding-idx` | `0` | Shard index served by this instance |
| `CORS_ORIGINS` | `--cors-origins` | โ€” | Empty = disabled, `*` = any origin, or a comma-separated list |
| `HTTP_MAX_CONCURRENCY` | `--http-max-concurrency` | `1024` | In-flight request cap; excess requests get 503 |
| `LLM_MAX_CONCURRENCY` | `--llm-max-concurrency` | `64` | Model-call cap across Spaces (background work included); excess model-driving requests get 429 |
| `BRAIN_RUNTIME_CONFIG` | `--runtime-config` | โ€” | Path to a versioned JSON runtime configuration (โ‰ค 1 MiB) |
| `MCP_HTTP_ENABLED` | `--mcp-http-enabled` | `true` | Mount Streamable HTTP MCP |
| `MCP_HTTP_PATH_PREFIX` | `--mcp-http-path-prefix` | `/mcp` | Clients connect to `{prefix}/{space_id}` |
| `MCP_HTTP_ALLOWED_HOSTS` | `--mcp-http-allowed-hosts` | โ€” | Allowed `Host` values for remote MCP (`*` = any) |
| `MCP_HTTP_ALLOWED_ORIGINS` | `--mcp-http-allowed-origins` | โ€” | Allowed browser `Origin` values for remote MCP |
| `MCP_HTTP_AUTO_CREATE_SPACE` | `--mcp-http-auto-create-space` | `false` | Create missing Spaces on first remote MCP use |
| `MCP_HTTP_AUTO_CREATE_TIER` | `--mcp-http-auto-create-tier` | `1` | Tier for those Spaces |
| `MCP_SPACE_ID` | `mcp --space-id` | โ€” | Space served by the stdio MCP server |
| `MCP_AUTH_TOKEN` | `mcp --mcp-auth-token` | โ€” | CWT or Space token used by stdio MCP tools |
| `MCP_AUTO_CREATE_SPACE` | `mcp --mcp-auto-create-space` | `false` | Create the stdio Space if missing |
| `MCP_AUTO_CREATE_TIER` | `mcp --mcp-auto-create-tier` | `1` | Tier for that Space |
| `JUDGE_MODEL_API_KEY`, `JUDGE_MODEL_FAMILY`, `JUDGE_MODEL_NAME`, `JUDGE_MODEL_API_BASE` | โ€” | family `openai` | Independent judge for shadow evaluation |
| `LOG_LEVEL` (or `RUST_LOG`) | โ€” | โ€” | Log level for structured JSON logs |

Logs go to stdout for the HTTP service and to stderr in stdio MCP mode.

### Storage

| Subcommand | Storage | Settings |
| :--- | :--- | :--- |
| *(none)* | In memory โ€” lost on exit; a warning is logged | โ€” |
| `local` | Local filesystem | `--db` / `LOCAL_DB_PATH` (default `./db`) |
| `aws` | AWS S3 | `--bucket` / `AWS_BUCKET`, `--region` / `AWS_REGION`, plus `AWS_ACCESS_KEY_ID` / `AWS_SECRET_ACCESS_KEY` |

`mcp` takes the same `local` / `aws` subcommands after its own options.

### Memory policy

Each Space carries an optional `MemoryPolicy` in its `memory_policy` extension, set
with `PATCH /v1/{space_id}/management/update_space`. An absent policy means the
compiled defaults. Explicit maintenance `parameters` override it for one cycle.

| Field | Default | Effect |
| :--- | :--- | :--- |
| `stale_event_threshold_days` | `7` | Events older than this are consolidation candidates |
| `unconsolidated_max_backlog` | `20` | Target for Events/Experiences not yet consolidated (alias `unsorted_max_backlog`) |
| `orphan_max_count` | `20` | Target for orphan Concepts |
| `self_test_queries_per_cycle` | `4` | Self-test probes per cycle; `0` disables |
| `self_test_token_budget` | `20000` | Token budget of one self-test pass |
| `recall_max_rounds` | `7` | Recall model turns, 1โ€“50 |
| `recall_budget` | `null` | Enforced Recall budget ceilings; a request may tighten, never raise them |
| `shadow_replay_sample` | `4` | Recall queries replayed by shadow evaluation (cap 16) |
| `memory_strength_decay_factor`, `decay_floor`, `recall_reinforcement`, `correction_penalty`, `recall_search_threshold` | โ€” | Accepted for stored-policy compatibility; nothing reads them |

### Per-Space models (BYOK)

`PATCH /v1/{space_id}/management/space_byok` gives a Space its own model
configuration; `GET` returns it (including credentials) to a management CWT.

---

## Cargo features

The library defaults to memory only โ€” Formation, Recall, Maintenance and their HTTP
routes.

| Feature | Adds |
| :--- | :--- |
| `wiki` | The wiki (documents, versions, ACL-scoped reads, OKF import/export), the `wiki_search` / `wiki_read` / `wiki_commit` agent tools, WikiDigest, the `/v1/{space_id}/wiki/*` routes and the `wiki_*` fields of `SpaceInfo` / `UpdateSpaceInput` |
| `mcp` | The MCP channel (stdio and Streamable HTTP); with `wiki`, the wiki tools join it |
| `experiments` | Isolated host runs, snapshots, business time, cost receipts, forced Recall budgets, procedure audits; enables the Nexus `simulation` feature |
| `learning` | Paired-trial contracts and evaluator, native records, persistent host trial runtime and the read-only `check_procedure_status` Recall tool |

The `anda_brain` binary is the full product and declares
`required-features = ["mcp", "wiki"]`; Cargo silently skips it without them.

---

## Running

```bash
# In memory (development)
cargo run -p anda_brain --features mcp,wiki

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

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

# Remote MCP behind a domain
MCP_HTTP_ALLOWED_HOSTS="brain.example.com" \
  cargo run -p anda_brain --features mcp,wiki -- local --db ./data

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

Docker (the image runs as UID/GID `10001`):

```bash
docker run --rm -p 8042:8042 \
  -e LISTEN_ADDR=0.0.0.0:8042 -e MODEL_API_KEY=your_key \
  -v "$(pwd)/data:/app/db" \
  ghcr.io/ldclabs/anda_brain_amd64:latest local --db /app/db
```

A systemd unit is in [`deploy/systemd`](../deploy/systemd), and the full walkthrough
is [deploy/quick_start.md](../deploy/quick_start.md).

---

## Embedding the library

```toml
# Memory only
anda_brain = "0.13"

# The full surface
anda_brain = { version = "0.13", features = ["mcp", "wiki"] }
```

`AppState` owns the Spaces, model configuration and background tasks; the binary in
[`src/bin/main.rs`](src/bin/main.rs) is the reference wiring (router, CORS,
concurrency limits, MCP mount, graceful shutdown). Builders configure it before it is
shared: `with_agent_prompts`, `with_judge_model`, `with_llm_concurrency`,
`with_runtime_config` and, for an embedded single-Space host, `with_audience_free_cwt`.

Trusted hosts may replace the deployment section of a prompt:

```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)?;
```

Only section A can be replaced (it must start with `# A.`, at most 128 KiB); the
compiled KIP reference prefix stays verbatim. The configuration is immutable, inherited
by agent instances and forks, and must be supplied again at every start. There is no
HTTP or MCP endpoint for prompts and no process-global override.

---

## Prompts and the KIP reference

Each `assets/Brain{Formation,Recall,Maintenance}.md` has two halves. Everything above
`# A.` is the KIP 2.0 reference policy vendored from `anda_kip`; `# A.` and below is
this deployment's contract. The system prompt of every model call assembles the full
`anda_kip` syntax (about 40 KiB), the Cognitive Memory Profile, the role cards and
that prompt. Budgeted Recall counts the whole system prompt toward its input budget
and reports `recall_context_budget_exhausted` rather than dropping the syntax.

All three agents can page through additional compiled-in documentation with the
read-only `kip_reference` tool (`document=index` lists documents, `section=index`
lists headings, pages are at most 8 KiB). Reference pages grant no capability and never
count as retrieved memory.

Do not hand-edit the reference halves or `assets/kip-reference/`; edit section A by
hand and regenerate the rest from the repository root:

```bash
node scripts/sync-kip-assets.mjs
pnpm --filter @ldclabs/anda-brain-worker run codegen:prompts
node scripts/sync-kip-reference.mjs --check
```

`sync-kip-assets.mjs` re-copies the reference halves of the Rust and Worker prompts
from a sibling `anda-db` checkout by default; set `ANDA_KIP_SOURCE` to a downloaded
`anda_kip` crate directory to sync from a published version. `sync-kip-reference.mjs`
regenerates `assets/kip-reference/` (or verifies it with `--check`) and refuses a
source that differs from the `anda_kip` in `Cargo.lock`.

---

## Testing

```bash
cargo fmt --check
cargo clippy -p anda_brain --all-targets --all-features -- -D warnings
RUST_MIN_STACK=16777216 cargo test -p anda_brain --all-features

# The lean builds must keep compiling
RUST_MIN_STACK=16777216 cargo test -p anda_brain --lib
RUST_MIN_STACK=16777216 cargo test -p anda_brain --lib --features wiki
RUST_MIN_STACK=16777216 cargo test -p anda_brain --lib --features mcp
```

Debug builds need the larger test stack; release code fits the default 2 MiB worker
stack. Tests use local or in-memory storage and never call a model provider; one bin
test binds an ephemeral localhost port.

- **KIP conformance**: [conformance/]conformance/README.md drives a real process
  through the Memory Interface with a controlled model.
- **Wiki retrieval corpus**: [evals/wiki/]evals/wiki.

<a id="offline-regression-and-instance-configuration"></a>

### Offline regression

The Rust `anda_brain::eval` API and the `anda_brain eval` CLI (including `--optimize`,
`--mine` and their fixture profiles) have been retired. Product regressions live in
the sibling [MIB](https://github.com/ldclabs/MIB) project; Brain keeps its online
instruments โ€” self-test, probe, citations, usage and correction ledgers, shadow
evaluation โ€” and the native learning tests. From a MIB checkout:

```bash
# Public regression contracts, without a model
python scripts/check-brain-product-regression.py --output-dir /tmp/brain-product-regression

# A configured business agent through the normal submission path
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
[MIB migration guide](https://github.com/ldclabs/MIB/blob/main/docs/harness/MIB-Brain-Legacy-Migration.md)
lists the removed Rust APIs. Instance configuration stays per Space
([memory policy](#memory-policy)) or host-owned ([deployment prompts](#embedding-the-library));
there is no process-global override.

---

## Known limits

- **Full-scan ceiling.** Correction discovery and self-test sampling use full-scan KQL
  that the engine caps at 65,536 solutions. Past that they fail loudly
  (`correction_scan_error` in the settlement report and `memory_status`);
  predicate-sharded scans are not implemented.
- **Memory Interface.** `memory_experience` and `memory_learning` are not advertised;
  `resume` has no maintained WorkingState; a Formation interrupted by a close is
  reported `failed` with an unknown outcome and is not re-run.
- **Erasure scope.** Forgetting removes graph records and the host's own copies; it
  cannot erase an embedding application's original data, backups or provider copies.
- **Learning claims.** Skills stay unproven without configured trials; runtime status
  and fixtures are not calibration or improvement evidence. Missing measurements and
  provider costs stay unknown, never zero.

## Dependencies

| Crate | Role |
| :--- | :--- |
| `anda_core`, `anda_engine` | Agent traits, engine, model adapters, notes |
| `anda_db`, `anda_object_store` | Embedded database and object-store layer |
| `anda_kip` | KIP 2.0 parser, envelopes, errors, syntax and reference documents |
| `anda_cognitive_nexus` | The Cognitive Nexus graph |
| `axum`, `rmcp` | HTTP and MCP servers |
| `tiktoken-rs` | The pinned Recall tokenizer (0.12.x) |

## License

Copyright ยฉ LDC Labs. Licensed under the Apache License, Version 2.0.