For the complete documentation index, see llms.txt. This page is also available as Markdown.

Personalization & Self-Learning

How OpenHuman learns your communication style, identity, tooling, vetoes, and goals from everyday use, then surfaces them as ambient defaults in every reply.

OpenHuman gets to know you the way a good assistant would: not by asking you to fill in a settings form, but by paying attention. As you chat, connect accounts, and correct it, it quietly collects evidence about how you like to work, scores that evidence for stability, and promotes the durable signals into your PROFILE.md and into the system prompt of every future turn.

Nothing is locked in from a single message. A preference has to keep showing up before it earns a place in your profile, and anything that fades stops being injected. You stay in control: the profile is a plain Markdown file you can edit, and you can pin or forget any learned fact.


What gets learned

Learning is organized into six facet classes. Each class has its own decay rate and its own budget so one noisy category can't crowd out the others.

Class
What it captures
Examples

Style

How you like replies written

verbosity=terse, format=bullets, emoji=skip

Identity

Stable facts about you

name=Alice, timezone=PST, role=engineer

Tooling

Your developer toolchain

package_manager=pnpm, editor=neovim, lang=rust

Veto

Things you've explicitly rejected

avoid em dashes, no nested bullets

Goal

Active goals and ongoing projects

free-form goal sentences

Channel

Your preferred place to talk

primary=desktop-chat

Recurring people, topics, and past threads are not stored here. Those live in the memory tree and are pulled in per-turn by memory_recall.


The learning pipeline

Evidence flows through four stages: capture β†’ score β†’ render β†’ inject.

 your activity                 candidate buffer            stability detector
 ────────────                  ────────────────            ──────────────────
 chat turns        ──┐
 corrections       ───
 email signatures  ──┼──→  LearningCandidate ──→  rebuild every 30 min
 connected accounts───      (class, key, value,    + event-driven (~60s
 LinkedIn (opt-in) β”€β”€β”˜       cue family, evidence)   after new data)
                                                          β”‚
                                                          β”‚  score each (class, key)
                                                          β”‚  resolve value conflicts
                                                          β”‚  apply per-class budgets
                                                          β–Ό
                                                   user_profile facets
                                                   (Active / Provisional /
                                                    Candidate / Dropped)
                                                          β”‚
                                          CacheRebuilt ────
                                                          β–Ό
                                  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                                  β–Ό                                        β–Ό
                            PROFILE.md                            system prompt
                       (managed blocks)                     ("Your standing preferences")

Capture. Producers watch your activity and push a LearningCandidate into a bounded buffer. Each candidate records the (class, key, value) it asserts, a pointer back to the evidence, and a cue family describing how strong the signal is: Explicit (you said it outright), Structural (from account data or a file), Behavioral (inferred from how you act), or Recurrence (a statistical pattern).

Score. A background stability detector rebuilds the cache roughly every 30 minutes, and sooner when new email or documents arrive. It aggregates every candidate for a given fact and computes a stability score: stronger cue families count for more, recent evidence counts for more than stale evidence (each class has a half-life), and an explicit statement from you doubles the weight.

Class
Evidence half-life

Identity

90 days

Veto

60 days

Tooling / Goal

30 days

Style

14 days

Channel

7 days

The score decides each fact's lifecycle state:

State
Meaning

Active

Strong enough to render in PROFILE.md and inject into the prompt

Provisional

Stored and tracked, but not yet shown

Candidate

Still gathering evidence

Dropped

Faded below the floor; removed

When two values compete for the same fact (e.g. verbosity=terse vs verbosity=detailed), the higher-stability value wins. The loser is dropped, and if it ever becomes true again it re-earns its place naturally.


Where it's stored: PROFILE.md

The learned profile is materialized into PROFILE.md in your workspace, a real, editable Markdown file. Each facet class owns a managed block (## Style, ## Identity, ## Tooling, ## Vetoes, ## Goals), and only Active facets are written, sorted by stability. Pinned entries are marked *(pinned)*.

The renderer only touches its own managed blocks. Anything you write by hand outside those blocks (and the separate ## Connected Accounts block owned by the integrations layer) is left untouched. Empty classes show a *(no entries yet)* placeholder rather than disappearing.

Per-session freeze. PROFILE.md is folded into the agent's system prompt at the start of a session and held stable for that session's lifetime, which keeps prompt caching fast. Edits you make mid-session are picked up on the next rebuild and the next session, not retroactively in the current one.


How it surfaces in replies

On every turn the agent reads the Active facets and injects them as a compact "Your standing preferences" section in the system prompt, alongside a standing instruction to call memory_recall before answering anything that leans on past sessions. The result is that the agent defaults to your verbosity, your tools, and your vetoes without being reminded, and it reaches into memory for the specifics.


Optional LinkedIn enrichment

During onboarding you can let OpenHuman bootstrap your identity from LinkedIn. The flow searches your connected Gmail for a linkedin.com/in/... profile URL, and (when available) scrapes the public profile, then compresses what it finds into PROFILE.md via the learning_save_profile step. It runs once, as a fire-and-forget pass. It is entirely opt-in and is skipped cleanly if no profile is found.


Reviewing and controlling what's learned

Everything learned is inspectable and reversible:

  • Edit PROFILE.md directly. It's your file. Correct, add, or delete anything; the next rebuild respects your edits.

  • The Brain page (raised center button in the bottom bar, /brain) is the home for memory and intelligence. The knowledge graph, goals, sources, and sync status all live here.

  • Pin a fact to lock it Active and shield it from decay, or forget a fact to drop it and block it from coming back. Under the hood these are the learning_pin_facet, learning_unpin_facet, and learning_forget_facet operations over the openhuman.learning_* RPC surface, alongside learning_list_facets and learning_rebuild_cache.


See also

  • Memory Tree, where recurring people, topics, and threads live and are recalled per-turn.

  • Goals & To-dos, the goal-tracking surface that pairs with learned goal/* facets.

  • Subconscious Loop, the background engine that keeps thinking about your workspace between turns.

Last updated