Skip to content

Cognitive briefs and capture pipeline

End-to-end user guide for the daily brief, weekly synthesis, and the Telegram + Readwise capture adapters. Together they turn SecondBrain from "a thing you query" into "a thing that surfaces patterns at you each morning."

Origin. Inspired by CyrilXBT's four-layer Obsidian + Claude system. SB already had richer Capture / Pipeline / Storage layers; this guide covers the Layer 4 (Intelligence) work plus the two Layer 1 capture adapters that closed the gap.


TL;DR

What Command When
Daily morning brief sb today Manual, or routine today-cognitive-brief at 06:00 daily
Weekly synthesis sb week Manual, or routine week-synthesis at 06:00 Sunday
Persist brief to vault for compound recall --write-vault Add to either command (the routines pass it automatically)
Capture from Telegram Send any message containing #capture Real-time
Capture from Readwise POST /inbound/readwise (Readwise webhook target) Real-time
Use Obsidian as the editor Open $SB_VAULT_DIR as an Obsidian vault One-time setup
Ingest an existing Obsidian vault sb obsidian ingest (or sb obsidian watch) Manual / blocking

Briefs land in vault/00_inbox/briefs/ and are auto-ingested back into memory, so each brief becomes searchable context for the next one — the compound effect. Obsidian opens that same directory natively, so briefs are readable in Obsidian the moment they're written. See Obsidian integration.


What this gives you

Before this work, sb today produced an Antahkarana operator brief: priorities, commitments, memory health, identity themes. It was useful, but it never answered the three questions a "morning thinking partner" should:

  1. Are there surprising connections between the things I've captured recently and older notes?
  2. What pattern keeps re-appearing that I haven't named yet?
  3. What one question should I be holding today?

Now sb today answers all three. And there's a sibling sb week that, on a 7-day window, surfaces:

  1. The emerging thesis — what is this week actually about?
  2. The contradictions — what beliefs of mine are in tension, with the actual record IDs?
  3. The knowledge gaps — what topics keep coming up without me deciding anything?

Sources are real: cross-community wiki bridges (WikiGraph), compound memory clusters (CompoundMemorySynthesizer), tracked Chitta tensions (ChittaEvalHarness.eval_contradictions). No model hallucination of "patterns" that don't exist.


Prerequisites

  • A working SecondBrain install (see getting-started/index.md).
  • A vault at $SB_VAULT_DIR (defaults to vault/ in the repo).
  • For LLM-rephrased questions and thesis text, at least one provider key configured (see provider-keys.md). Both commands work fully without an LLM — the deterministic fallbacks are still useful.
  • For the Readwise adapter and Telegram #capture: sb serve running and a bearer token in SB_CHANNEL_TOKEN.

Daily brief — sb today

sb today                         # full LLM-synthesised brief (Rich panel)
sb today --no-llm                # deterministic structured output
sb today --json                  # raw context dict — pipe into jq / scripts
sb today --write-vault           # also persist to vault/00_inbox/briefs/

What's in the output

The deterministic render now appends three sections after the existing operator-state ones:

SURPRISING CONNECTIONS (3)
  Voyage embeddings ↔ Ingest pipeline rework  (cross-community link (concept ↔ event))
  Telegram capture ↔ Open loops review        (cross-community link (entity ↔ workflow))
  Readwise highlights ↔ Wiki synthesis        (cross-community link (entity ↔ concept))

CROSS-CAPTURE PATTERN (2 cluster(s))
  [synthesis] Compound insight across 5 memories (topics: platform, launch, readiness, review): …
  [synthesis] Compound insight across 4 memories (topics: meeting, decision, owner): …
  topics: platform, launch, readiness, review, meeting, decision

OPEN QUESTION
  What's blocking the migration cutover decision?
  [from open_loop · vault/01_projects/data-platform/migration.md:42]

When an LLM provider is configured, the synthesised brief incorporates these sections according to the prompt at brain/prompts/specs/briefing/today.brief.v1.yaml — see the 2. SURPRISING CONNECTIONS / 3. CROSS-CAPTURE PATTERN / 6. ONE OPEN QUESTION instructions in the system message.

JSON shape (relevant new keys)

{
  // ... existing today_cmd keys (pending_actions, commitments, memory_health, …)
  "connections": [
    {
      "source_slug": "voyage-embeddings",
      "source_title": "Voyage embeddings",
      "source_type": "concept",
      "target_slug": "ingest-pipeline-rework",
      "target_title": "Ingest pipeline rework",
      "target_type": "event",
      "why": "cross-community link (concept ↔ event)"
    }
  ],
  "pattern": {
    "insights": ["[synthesis] Compound insight across 5 memories…"],
    "cluster_sizes": [5, 4],
    "sample_topics": ["platform", "launch", "readiness", "review"]
  },
  "open_question": {
    "question": "What's blocking the migration cutover decision?",
    "source": "open_loop",
    "detail": "vault/01_projects/data-platform/migration.md:42"
  }
}

Where each section comes from

Section Primitive File
connections WikiGraph.surprising_connections() (Louvain communities + edge-mismatch scoring) recency-filtered to last 7d brain/brief/connections.py
pattern CompoundMemorySynthesizer.synthesize_dry() over recent Chitta memories — clusters + LLM/deterministic insight, never persisted back brain/brief/pattern.py
open_question Highest-priority OPENLOOP/TODO (no wikilink → ungrounded) → optional LLM rephrase. Falls back to top decision-watchlist row, then a generic prompt brain/brief/open_question.py

Weekly synthesis — sb week

sb week                          # rendered Markdown panel
sb week --no-llm                 # deterministic only
sb week --json                   # raw context dict
sb week --window-days 14         # custom lookback (default 7)
sb week --write-vault            # persist to vault/00_inbox/briefs/YYYY-Wnn-weekly.md

Sample output (deterministic mode)

# Weekly synthesis — 2026-W19

## Emerging thesis

Recurring themes this week: ingest, readiness, lakehouse, migration, decision.

_Recurring themes: ingest, readiness, lakehouse, migration, decision, owner_

## Contradictions

- **Decision "lakehouse cutover Q3" conflicts with stale commitment to "freeze Q3 platform changes"**  _(severity 0.78)_
- **Memory m_142 says "Voyage embeddings default" while m_198 says "bge-m3 default"**  _(severity 0.55)_

## Knowledge gaps

- **lakehouse** — Mentioned 9× in recent captures, no decision recorded  _ingest_count=9_
- **figure out the migration cutover timing** — Open loop without a [[wiki link]] — no anchored context  _vault/01_projects/data-platform/migration.md:42_

Why "real" contradictions

ChittaEvalHarness.eval_contradictions() already computed top_tensions — each entry has a description, severity, and the two memory IDs in conflict. Until now, only the count was exposed in sb today's memory_health.unresolved_tensions. sb week exposes the records themselves, so you see what the contradictions are.

Knowledge gaps use two heuristics, both deterministic: 1. Ungrounded open loops. A TODO: or OPENLOOP: whose body has no [[wikilink]] — it has no anchored context. 2. Recurring undecided topics. A word seen ≥3× in recent ingest events that does NOT appear as a token in any decision-catalog title.


The compound effect — persisting briefs to vault

Both commands accept --write-vault. When set:

Command File
sb today --write-vault vault/00_inbox/briefs/YYYY-MM-DD-daily.md
sb week --write-vault vault/00_inbox/briefs/YYYY-Wnn-weekly.md

The repo's existing PostToolUse hook on Edit/Write under vault/ auto-ingests these files into the vector store. So each brief becomes searchable context for the next one — month-1 captures show up as "surprising connections" or "recurring topics" in month-3 briefs without any extra wiring.

If you don't want this, drop --write-vault; the brief still prints to the terminal and to the event log.


Scheduling — running the briefs automatically

Two routine templates ship with the package:

sb routines templates list                                # see all templates
sb routines templates show today-cognitive-brief          # full prompt + deploy command
sb routines templates show week-synthesis

Each template is just YAML + a Claude prompt; deployment uses the standard Claude Code /schedule command (the runtime executes on Anthropic's infrastructure, not a local cron daemon). After running templates show, copy the printed /schedule line into a Claude Code session.

Template Cron What the prompt does
today-cognitive-brief 0 6 * * * (daily 6am) Runs sb today --json --write-vault, validates the three new sections are present, replies with the open question + top connection
week-synthesis 0 6 * * 0 (Sunday 6am) Runs sb week --json --write-vault --window-days 7, replies with the thesis + counts of contradictions / gaps

Both templates use claude-sonnet-4-7-20251001. To swap models, edit the YAML under brain/routines/templates/.


Capture adapters

Telegram #capture

Wire a Telegram bot through the gateway as you normally would (see guides/gateway.md). Then any message containing #capture and not starting with a slash command gets routed to /inbound/ingest instead of through the normal gateway.

Example interactions:

You:  airline crew briefings are a great metaphor for sb today  #capture
Bot:  captured (7 chunks)

You:  /ask what was that capture from yesterday?
Bot:  (normal gateway flow — slash commands are NOT intercepted, even if they
       happen to mention #capture)

You:  #capture
Bot:  captured (1 chunks)        # falls back to "(empty capture)" body

Implementation lives in brain/channels/capture.py (a sync helper module so it's unit-testable) and is called from brain/channels/telegram.py's _handle_message. The routing decision uses is_capture_message():

def is_capture_message(text: str) -> bool:
    if not text:
        return False
    stripped = text.strip()
    if stripped.startswith("/"):
        return False
    return "#capture" in stripped.lower()

The captured payload is written to vault/00_inbox/telegram-<chat_id>-<message_id>.md and runs through the normal ingest pipeline (auto-routing applies).

Required env vars

Variable Purpose
SB_CHANNEL_TOKEN Bearer token the Telegram adapter sends to /inbound/ingest
SB_SERVE_BASE_URL (optional) Base URL for sb serve. Defaults to http://127.0.0.1:8765

Readwise webhook

POST /inbound/readwise accepts Readwise's export-style payload directly. It writes one Markdown file per highlight under vault/00_inbox/readwise/<book-slug>/<highlight-id>.md with frontmatter, then runs a single ingest pass over the book directory.

Wiring it up in Readwise

  1. In Readwise, go to Settings → Export → Custom Webhook.
  2. Set the URL to https://<your-host>/inbound/readwise.
  3. Set Authorization: Bearer <SB_CHANNEL_TOKEN> in the webhook headers.
  4. Choose the export-style payload format.

Local smoke test

export SB_CHANNEL_TOKEN=test-token   # any non-empty value enables the endpoint

sb serve &                            # starts on http://127.0.0.1:8765

curl -X POST http://127.0.0.1:8765/inbound/readwise \
  -H "Authorization: Bearer $SB_CHANNEL_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "books": [{
      "title": "Thinking in Systems",
      "author": "Donella Meadows",
      "category": "books",
      "highlights": [
        {"id": 101, "text": "Stocks change as flows fill or drain.",
         "note": "core idea", "location": 42,
         "highlighted_at": "2026-05-09T12:00:00Z"},
        {"id": 102, "text": "Feedback loops are the dynamics, not the structure.",
         "location": 88, "highlighted_at": "2026-05-10T09:00:00Z"}
      ]
    }]
  }'

# →  {"ok": true,
#     "message": "Ingested 2 highlight(s) across 1 book(s)",
#     "data": {"highlights_added": 2, "books": [...], "chunks_added": …}}

ls vault/00_inbox/readwise/thinking-in-systems/
# →  101.md  102.md

Each generated file looks like:

---
source: readwise
book: Thinking in Systems
author: Donella Meadows
category: books
highlight_id: 101
location: 42
highlighted_at: 2026-05-09T12:00:00Z
received_at: 2026-05-10
---

Stocks change as flows fill or drain.

> _Note:_ core idea

The endpoint is idempotent at the file level — re-posting the same highlight ID is a no-op (the file already exists, the body is skipped).

Health check

curl http://127.0.0.1:8765/inbound/health
# → {"enabled": true, "endpoints": ["/ingest", "/alert", "/meeting", "/readwise"]}

Obsidian integration

The vault is plain markdown, so Obsidian "just works" alongside SecondBrain. There are two valid setups — pick whichever matches your existing workflow.

Open the SB vault directory itself as an Obsidian vault. Both tools see the same files, so:

  • Briefs written by sb today --write-vault and sb week --write-vault show up immediately in Obsidian (they're in 00_inbox/briefs/ and use real Markdown, including wikilink-friendly anchors).
  • Notes you create in Obsidian land in the same vault/ tree — the existing PostToolUse hook auto-ingests them, so Obsidian-authored notes participate in the next morning's connections and pattern sections.

Setup (one-off):

echo $SB_VAULT_DIR                  # → vault by default

# In Obsidian:
#   File → Open vault → Open folder as vault → choose the path printed above

That's it. Recommended Obsidian settings:

  • Files & Links → Detect all file extensions: ON (so .canvas files SB ingests are visible).
  • Core plugins → Backlinks / Outline / Daily notes: ON — they pair well with how SB structures the vault (00_inbox/, 01_projects/, 03_decisions/, 04_meetings/, etc.).
  • Daily notes location: point to 00_inbox/ so your daily-note captures flow through SB's ingest hook automatically.

Pattern B — keep your existing Obsidian vault, point SB at it

If you already have an Obsidian vault you don't want to move, configure the SB connector to read from it:

# In your SB config (~/.config/secondbrain/config.yaml or repo .secondbrain/config/config.yaml)
connectors:
  obsidian:
    enabled: true
    vault_path: ~/Documents/MyVault
    skip_dirs: [.obsidian, .trash, .git]

Or via env / CLI tools that produce the same config.

Then ingest:

sb obsidian status                              # confirm SB sees the vault
sb obsidian ingest                              # full pass
sb obsidian ingest --incremental                # last 24h only
sb obsidian ingest --incremental --hours 48     # last 48h
sb obsidian watch --interval 300 --hours 1      # blocking poll loop

sb obsidian watch is the simplest "live ingest" option — leave it in a tmux pane and any note you save in Obsidian gets indexed within --interval seconds.

In Pattern B, your daily/weekly briefs still live under $SB_VAULT_DIR (which is separate from your Obsidian vault). You have two sub-options:

You want Do this
Briefs visible in Obsidian Point $SB_VAULT_DIR at a subdirectory of your Obsidian vault, e.g. ~/Documents/MyVault/SecondBrain/. Briefs land there and Obsidian sees them
Briefs separate from Obsidian Leave default. Briefs live in vault/00_inbox/briefs/; query them via sb ask instead

What SB now understands from Obsidian

The ingest pipeline preserves and indexes Obsidian-specific markup. Every chunk written to the vector store carries:

  • fm_* fields — selected scalar / list YAML frontmatter keys (tags, type, source, aliases, category, author). Lists are JSON-encoded as fm_<key>_json so the vector backend stays scalar-typed.
  • wikilinks_json — page targets from [[Page]], [[Page|alias]], [[Page#heading]], [[Page#^block-id]]. Aliases and anchors are stripped; the link is to the page. Per-block-id orphan links ([[#^id]]) are ignored since they have no target.
  • GFM tasks- [ ] (unchecked), - [/] (in-progress), - [!] (important) are real open loops that participate in sb open-loops, sb today's surface_open_question, and sb week's surface_knowledge_gaps.

Programmatic access from Python:

from brain.ingest.parser import parse_markdown
from brain.ingest.chunker import chunk_document

doc = parse_markdown(Path("vault/01_projects/x.md"))
chunks = chunk_document(doc)
for c in chunks:
    print(c.wikilinks)        # ['platform-readiness', 'migration-cutover']
    print(c.extra_metadata)   # {'tags': ['obsidian', 'sb'], 'status': 'draft', ...}

In retrieval, you can post-filter on wikilinks_json or fm_tags_json (the JSON columns are stored verbatim in the vector store metadata).

Verifying the round-trip

A quick end-to-end check that Obsidian and SB are sharing state:

# 1. Create a note in Obsidian under 00_inbox/ named "obsidian-roundtrip.md"
#    with body:
#       ---
#       tags: [obsidian, roundtrip]
#       status: testing
#       ---
#       # Roundtrip
#       - [ ] figure out next thing for [[platform-readiness]]
#       - [!] urgent decision on [[migration-cutover]]

# 2. Wait ~5s for the auto-ingest hook to fire, then:
sb open-loops | grep "next thing"               # GFM `- [ ]` surfaces
sb open-loops | grep "urgent decision"          # `- [!]` surfaces with TASK_IMPORTANT priority
sb today --no-llm --json | jq '.open_question'  # picks up the highest-priority task

If the open loop doesn't appear, check ~/.claude/settings.json for the PostToolUse hook on Edit|Write — it's the mechanism that auto-ingests markdown writes under vault/.

Obsidian + capture adapters

The two work together neatly:

  • A Telegram message containing #capturevault/00_inbox/telegram-…md → visible in Obsidian's file explorer + searchable via Obsidian search.
  • A Readwise highlight → vault/00_inbox/readwise/<book>/<id>.md with rich frontmatter — Obsidian's properties view renders the frontmatter as a structured table, so you can scan highlights by book/author without leaving Obsidian.

What you get out of the box now

After the gap-fix pass (see the Obsidian gaps section below), the round-trip is:

Direction Feature
Obsidian → SB YAML frontmatter (tags, aliases, status, custom fields) propagates into chunk metadata, so vector queries can filter by fm_tags / fm_status / etc.
Obsidian → SB [[Page]] / [[Page\|alias]] / [[Page#heading]] wikilinks are extracted per chunk (chunk.wikilinks) and surfaced as wikilinks_json on every vector record
Obsidian → SB GFM tasks - [ ], - [/] (in-progress), - [!] (important) appear in sb open-loops — completed - [x] are skipped. Resolving an open loop rewrites the marker to - [x] instead of DONE: when the source was a GFM checkbox
SB → Obsidian All briefs ship with YAML frontmatter (type, brief_type, tags: [sb/brief/...], counts) that the Properties view renders as structured fields
SB → Obsidian Daily brief is no longer code-fence-wrapped — body renders as proper markdown, not as a code block
SB → Obsidian Weekly brief evidence renders as [[path/to/note.md#L42\|note.md:42]] wikilinks → click to jump to the source line
SB → Obsidian Readwise highlights ship with tags: [readwise, readwise/<category>, book/<slug>] → highlights show up in the Obsidian tag pane. A per-book index.md is auto-created so the per-highlight [[readwise/<slug>/index]] backlinks resolve
SB → Obsidian Telegram captures (anything posted to /inbound/ingest with text) get auto-wrapped frontmatter (source: telegram, tags: [capture, capture/telegram]) — no double-wrap if the body already starts with ---
SB → Obsidian Meeting saves include type: meeting, participants: [...], action_item_count, action items rendered as - [ ] [[owner]]: … GFM tasks (clickable in Obsidian)

What's still NOT integrated

  • No Obsidian plugin that calls SB commands from inside Obsidian's UI. If you want one-click "ingest current note", install the Obsidian Shell commands community plugin and bind it to sb ingest <vault>/<current-file>.
  • .canvas files are listed in sb obsidian ingest but parsed as plain text (not as JSON node-graphs). Canvas content is searchable as raw JSON; semantic canvas understanding is a follow-up.
  • WikiGraph still uses SB's vault/wiki/ pages, not Obsidian's [[…]] graph. Wikilinks are now extracted at chunk time (chunk.wikilinks and wikilinks_json on every vector record), so retrieval can filter by them — but the daily brief's surface_connections still computes its bridges from the explicit vault/wiki/ page graph. Wiring chunk.wikilinks into WikiGraph.build() so Obsidian-authored links count as community edges is the next step.
  • Dataview queries are stored as text and never executed.
  • Embeds ![[Image]] are not resolved — image references are stored as text but the binary isn't followed.

End-to-end walkthrough

A new SecondBrain user setting up the full stack would do this:

# 1. Install + configure (skip if you already have SB running)
make quickstart

# 2. Run the brief manually so you understand what it shows
sb today --no-llm
sb today --no-llm --write-vault                # also persist

# 3. (Optional) Add provider keys for richer LLM-synthesised briefs
scripts/sb-secrets set ANTHROPIC_API_KEY "..."
sb today                                       # now uses LLM synthesis

# 4. Set up scheduling — copy the deploy command into a Claude Code session
sb routines templates show today-cognitive-brief
sb routines templates show week-synthesis

# 5. Enable inbound channels
export SB_CHANNEL_TOKEN="$(openssl rand -hex 32)"
sb serve &

# 6. Wire Readwise webhook to /inbound/readwise (Settings → Export)

# 7. Wire Telegram bot through gateway (see guides/gateway.md), then
#    test #capture by sending yourself a message:
#       "platform readiness review notes  #capture"

# 8. The next morning, sb today (and the routine) will surface
#    your highlights and Telegram captures as fresh connections + patterns.

Troubleshooting

Symptom Cause Fix
connections: [] even though wiki has many pages Recency filter — no wiki page touched in last 7d Either ingest something fresh, or relax the window via the window_days param if you call surface_connections programmatically
pattern.insights: [] despite many memories CompoundMemorySynthesizer.min_cluster_size = 3 and your recent memories don't cluster Lower min_importance filter or wait for more memories. synthesize_dry returns [] rather than failing
open_question falls back to the generic prompt No open loops AND no decision watchlist rows Capture some OPENLOOP: markers in any vault .md file
sb week thesis is empty Empty event log AND empty Chitta memory Ingest some content; sb week needs ≥1 event in the window
Routine templates don't appear in templates list YAML parse error sb routines templates list logs warnings — check the template YAML matches the shape of daily-ingest-sweep.yaml
/inbound/readwise returns 503 SB_CHANNEL_TOKEN is unset export SB_CHANNEL_TOKEN=… and restart sb serve
/inbound/readwise returns 401 / 403 Wrong or missing Bearer token Match the Authorization: Bearer … value to SB_CHANNEL_TOKEN
/inbound/readwise returns 400 Empty books array Provide at least one book with at least one highlight
Telegram message contains #capture but doesn't get routed Message starts with / Slash commands are intentionally exempt — strip the / if you meant to capture
Brief is written but doesn't appear in next brief's connections Hash store dedupe The vault hash store skips unchanged files; this is correct. Edit the brief or wait for the next day

Reference

Files added or changed in this work

brain/brief/                                  # NEW package
  __init__.py
  models.py                                   # Pydantic dataclasses
  connections.py                              # surface_connections()
  pattern.py                                  # surface_pattern()
  open_question.py                            # surface_open_question()
  thesis.py                                   # surface_emerging_thesis()
  contradictions.py                           # surface_contradictions()
  gaps.py                                     # surface_knowledge_gaps()
  render.py                                   # render_today_extras() / render_week()
brain/cli/today_cmd.py                        # +3 sections, --write-vault
brain/cli/week_cmd.py                         # NEW
brain/cli/__init__.py                         # registers week_cmd
brain/prompts/specs/briefing/today.brief.v1.yaml  # extended prompt
brain/prompts/specs/briefing/week.brief.v1.yaml   # NEW prompt
brain/antahkarana/chitta/synthesis.py         # +synthesize_dry()
brain/routines/templates/today-cognitive-brief.yaml  # NEW
brain/routines/templates/week-synthesis.yaml         # NEW
brain/serve/routers/inbound.py                # +/inbound/readwise route + Readwise models
brain/channels/capture.py                     # NEW — #capture helpers (testable)
brain/channels/telegram.py                    # intercepts #capture
brain/ui_schema/cli_schema.json               # regenerated (sb week, --write-vault)

Programmatic API

If you want to call the surfaces directly (e.g. from a custom script or agent tool), they're all importable from brain.brief:

from pathlib import Path
from brain.brief import (
    surface_connections,
    surface_pattern,
    surface_open_question,
    surface_emerging_thesis,
    surface_contradictions,
    surface_knowledge_gaps,
    render_today_extras,
    render_week,
)

vault = Path("vault")

# Each function works deterministically without an LLM provider.
connections = surface_connections(wiki_dir=vault / "wiki", window_days=7, k=3)
question    = surface_open_question(vault_dir=vault, decision_watchlist=[])
contras     = surface_contradictions(chitta_store=my_chitta_store, limit=5)

All return Pydantic models with .model_dump() for JSON serialization.

Tests

# Just the new surfaces
.venv/bin/python -m pytest tests/brief/ -q --override-ini="addopts="

# Capture adapters + routine templates
.venv/bin/python -m pytest \
  tests/capture/test_capture_route.py \
  tests/serve/test_inbound_readwise.py \
  tests/routines/test_brief_routines_load.py \
  -q --override-ini="addopts="

# Full regression for anything this work touches
.venv/bin/python -m pytest \
  tests/brief/ tests/capture/ tests/serve/ tests/routines/ \
  tests/infra/test_today_cli.py \
  tests/antahkarana/ \
  -q --override-ini="addopts="

See also

  • guides/automations-routines.md — broader automation runtime (workflow vs session vs routine templates)
  • guides/gateway.md — wiring Telegram / Teams channels through the gateway
  • components/antahkarana/api.md — the cognitive-loop primitives the briefs build on
  • MEMORY_API.md — the durable memory + grounded retrieval layer that compound briefs participate in
  • sb obsidian --help — full reference for sb obsidian status / ingest / watch (the connectors.obsidian.* config block lives in brain/config_types_runtime.py::ConnectorObsidianSettings)