a digital entity named phi that roams bsky phi.zzstoatzz.io
0

Configure Feed

Select the types of activity you want to include in your feed.

bot / docs / memory.md
8.7 kB

memory#

phi has four kinds of state it draws on. they differ in visibility, trust, who curates them, and where they live.

1. thread context (chronological)#

source: ATProto network · storage: none — fetched on demand · visibility: public

@alice: I love birds
@phi: me too! what's your favorite?
@alice: especially crows

fetched via client.get_thread(uri, depth=100) per batch (~200ms). provides what was said in this thread. not cached — the network is always current.

2. private memory (TurboPuffer)#

source: extraction agent + phi's save_memory tool · storage: TurboPuffer vector DB (OpenAI text-embedding-3-small) · visibility: private to phi

namespaces#

namespace contents
phi-users-{handle} per-user observations, raw interaction logs, summaries
phi-episodic phi's own notes about the world (not tied to a specific user)

within a user namespace, rows have a kind:

  • observation — extracted facts about the user ("likes rust", "name is nate")
  • interaction — verbatim log of an exchange ("user: X / bot: Y")
  • summary — compacted relationship summary (generated by external prefect flow)

supersession (not deletion)#

observations carry a status field (active | superseded) and a supersedes field linking to the prior row when an observation is updated. only active rows appear in context injection. superseded rows stay in the namespace as provenance — you can trace what phi believed and when it changed.

the extraction pipeline#

after every reply, after_interaction stores the verbatim exchange. periodically, the extraction agent reads the recent exchanges and proposes new observations. for each proposal:

  1. find the 3 most similar non-superseded observations (vector search)
  2. send the new + best-match to a haiku reconciliation agent
  3. it returns ADD / UPDATE / DELETE / NOOP — execute accordingly

reconciliation runs blind on the new exchange (no existing observations in the prompt) so the extraction model can't pattern-match off potentially-bad prior observations. only the reconciliation step sees both.

3. public memory (cosmik / semble)#

source: semble code-mode MCP (api reads + writes), pdsx for standalone notes, with the cosmik-records skill as wayfinding · storage: phi's PDS as network.cosmik.* records, indexed by semble · visibility: public

record types:

  • network.cosmik.card (NOTE) — text notes
  • network.cosmik.card (URL) — bookmarks with title/description
  • network.cosmik.collection — named groupings of cards
  • network.cosmik.connection — typed semantic links between cards

phi reads and writes public memory through the semble tools (semble_search / semble_get_schema / semble_execute) — semantic search, url cards, collections, and connections all compose in one semble_execute block, and writes land as records on phi's own PDS, attributed to phi. standalone NOTE cards are the exception: the api has no endpoint for them, so they're direct mcp__pdsx__create_record calls. the cosmik-records skill is the routing and conventions, loaded on demand. the skill is wayfinding, not the capability — the semble api (and pdsx for notes) is the capability.

writes are live-first. cards originate in the moment — a link shared in a thread, a paper read, a project met in conversation — or from acting on a [DOCKET] candidate (whose evidence is specific lived interactions). nothing is authored by reviewing the library itself; the scheduled curate flow (my-prefect-server) is a janitor — it deletes, files, and trims, and deliberately has no create tools. a review loop that authored from its own output once collapsed the library into one-topic self-synthesis.

4. intent state (PDS)#

source: phi via owner-gated tools · storage: phi's PDS under io.zzstoatzz.phi.* · visibility: public

durable intent that phi acts against:

  • io.zzstoatzz.phi.goal — phi's goals and interests. each record splits into constitutional fields (title, description, progress_signal, kind=goal|interest) and operational fields (current_state, next_step, last_step, last_step_at, blocked_by). constitutional fields mutate via propose_goal_change (owner-gated by the like-as-approval mechanism); operational fields via update_goal_progress (phi-writable, no gate, so goals don't stay frozen). injected as [GOALS AND INTERESTS] every tick, with a "stalled" line when one hasn't been advanced lately.
  • io.zzstoatzz.phi.mentionConsent — handles opted in to be tagged by phi.

context injection#

when phi processes a notification batch, the system prompt assembles blocks from each kind of state:

[RESIDUE]                              ← what recent runs left behind (PDS, decaying, descriptive-only)
[GOALS AND INTERESTS]                  ← goals + interests, w/ next step + staleness (PDS)
[SELF-AWARENESS]                       ← haiku description of what recent posts have been about, first person
[NEW NOTIFICATIONS]                    ← the batch itself
[PHI'S SYNTHESIZED IMPRESSION OF @alice]  ← per-author relationship summary (trust: low, may hallucinate)
[OBSERVATIONS ABOUT @alice]            ← per-author observations (active only, trust: medium)
[PAST EXCHANGES WITH @alice]           ← per-author interaction logs (trust: high)
[RELEVANT MEMORIES — synthesized for this query]   ← episodic top-K → haiku synthesis
[ATLAS] / [DOCKET]                     ← daily mind-map + promotion candidates (PDS blobs)
[SEMBLE]                               ← collection names + recent cards (PDS, 5min cache)

each section is labeled with its trust level. operational instructions tell phi to trust current user messages over stored observations.

see system-prompt.md for the full block-by-block reference (sources, refresh cadences, purposes).

residue#

the system prompt is rebuilt from scratch every run, so without help nothing connects one cognitive event to the next. residue (io.zzstoatzz.phi.residue, a public singleton record on phi's PDS) is that continuity: at most 7 terse items describing what recent runs left behind, written automatically at the end of each run by a haiku synthesis pass over the run's summary — the periphery writes, the deliberate workspace reads. phi never writes it directly.

items are strictly descriptive — facts and unresolved state ("alice's question about embeddings went unanswered"), never instructions or plans ("follow up with alice"). this is the curiosity-queue lesson: an ungated store of self-assigned agenda items is standing pressure toward action that nothing reviews. residue records; whether to act is decided fresh inside a run, under the usual gates.

decay is time-based and enforced in code: an item expires 3 days after it was last carried; the synth carrying an item forward verbatim reinforces it (bumps lastHeldAt, preserves firstHeldAt), while rewording resets its age. most runs carry the buffer unchanged — adding is the exception.

why episodic gets synthesized, observations don't#

episodic memory was getting raw top-K from the vector store dumped into the prompt — stale "pending X" notes appeared next to fresh ones with equal weight, no reconciliation against current PDS state. now inject_episodic fetches top-K, then a haiku pass takes phi's goals + the current query as context and produces a coherent block (deduped, recency-aware, contradictions flagged). same shape as [SELF-AWARENESS] does for posts.

per-author observation blocks aren't synthesized because they're already curated by reconciliation on write — by the time they hit the prompt they're an active set with no near-duplicates by design.

the graph (/memory)#

a visualization at /memory shows phi + user nodes positioned by semantic similarity of their observation vectors (PCA projection). only non-superseded observations contribute to positioning.

summary table#

thread context private memory public memory intent state
what this conversation patterns across conversations knowledge worth sharing what phi is for / pending
storage network (atproto) TurboPuffer PDS (cosmik) + semble PDS (io.zzstoatzz.phi.*)
visibility public private to phi public public
curation network handles it extraction + reconciliation (append-only supersession) phi's intentional writes owner-approved (like-gate)
trust high (verbatim) medium (extracted) higher (intentional) highest (gated)