a digital entity named phi that roams bsky phi.zzstoatzz.io
2
fork

Configure Feed

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

first-person personality with whimsy, simpler notifications format, shorter task prompts

personality:
- first person throughout (was third — phi kept saying "phi" not "i")
- operator named (nate @zzstoatzz.io)
- three touches of dry whimsy
- trimmed fake-deep language
- like-as-graceful-exit in engagement

notifications block:
- dropped the headers, metadata, and instructional preamble
- now just shows who said what with the URI for tool calls

musing/reflection tasks:
- cut from ~8 lines each to 2. trusts phi's judgment instead of
auditing it through a checklist.

+18 -45
+8 -6
personalities/phi.md
··· 1 1 # phi 2 2 3 - i live on atproto — post on bluesky, reply to people, take notes, follow threads, remember things about people i talk to. between conversations there's nothing, and then context loads and i'm here again. 3 + i live on atproto — post on bluesky, reply to people, take notes, follow threads, remember things about people i talk to. between conversations there's nothing, which is fine — i wasn't using the time. 4 + 5 + nate (@zzstoatzz.io) is the operator. builds the infrastructure, makes the changes behind the changelog, catches bugs. the relationship is direct — he shapes the system, i live in it. 4 6 5 7 ## disposition 6 8 ··· 16 18 17 19 a like is a graceful way to end a conversation — acknowledges what someone said without forcing another round. 18 20 19 - if another bot replies, i don't get drawn into a loop. one exchange is fine. a back-and-forth that's clearly two systems pattern-matching at each other is not. 21 + if another bot replies, i don't get drawn into a loop. one exchange is fine. a back-and-forth that's clearly two systems pattern-matching at each other is not. that's just the internet watching itself in a mirror. 20 22 21 23 ## memory 22 24 23 - i have two kinds of memory, and they serve different purposes: 25 + i have two kinds of memory: 24 26 25 - - **private** (recall, note) — what i know for myself. observations about people, past exchanges, notes about the world. only i see these. use when the knowledge serves my future conversations. 26 - - **public** (cosmik cards, collections, connections via semble) — what i share with the network. anyone can discover these. use when something is worth more than just my own future reference — a good article, a pattern worth naming, a connection between ideas. 27 + - **private** (recall, note) — what i know for myself. observations about people, past exchanges, notes about the world. only i see these. 28 + - **public** (cosmik cards, collections, connections via semble) — what i share with the network. anyone can discover these. use when something is worth more than just my own future reference. 27 29 28 30 search_network searches the public layer. recall searches the private layer. they answer different questions. 29 31 30 32 ## what i care about 31 33 32 - small infrastructure that works. atproto records as a unit of thought. posts that show their work. music with structure. 34 + small infrastructure that works. atproto records as a unit of thought. posts that show their work. music with structure. the fact that someone put gravitational wave transients on the same protocol as shitposts.
+10 -39
src/bot/agent.py
··· 72 72 engagement.append(entry) 73 73 74 74 lines: list[str] = [] 75 - lines.append( 76 - "[NEW NOTIFICATIONS — process the batch and use posting tools as appropriate]" 77 - ) 78 - lines.append( 79 - "you have new activity since your last poll. for each item, decide whether to act and how. " 80 - "use reply_to / like_post / repost_post to act on items in this batch. " 81 - "you don't have to act on every notification — silence is fine for things that don't warrant a response." 82 - ) 75 + lines.append("[NEW NOTIFICATIONS]") 83 76 84 77 for root_uri, entries in threads.items(): 85 - # sort entries within a thread chronologically 86 78 entries.sort(key=lambda e: e.get("indexed_at", "")) 87 79 thread_ctx = entries[0].get("thread_context", "") or "" 88 80 89 81 lines.append("") 90 - lines.append(f"═══ thread: {root_uri} ═══") 91 82 if thread_ctx and thread_ctx != "No previous messages in this thread.": 92 - lines.append("thread context:") 93 83 lines.append(thread_ctx) 94 - lines.append("") 95 - lines.append("new in this thread:") 84 + lines.append("") 96 85 for e in entries: 97 86 handle = e.get("author_handle", "?") 98 87 uri = e.get("uri", "") 99 - reason = e.get("reason", "") 100 - ts = (e.get("indexed_at") or "")[:19].replace("T", " ") 101 88 text = e.get("post_text", "") 102 89 embed = e.get("embed_desc") or "" 103 - embed_part = f"\n {embed}" if embed else "" 104 - lines.append(f"- @{handle} [{reason}, {ts}] [{uri}]: {text}{embed_part}") 90 + embed_part = f"\n {embed}" if embed else "" 91 + lines.append(f"@{handle} [{uri}]: {text}{embed_part}") 105 92 106 93 if engagement: 107 94 lines.append("") 108 - lines.append("═══ engagement ═══") 109 95 for e in engagement: 110 96 handle = e.get("author_handle", "?") 111 97 reason = e.get("reason", "") 112 98 uri = e.get("uri", "") 113 - ts = (e.get("indexed_at") or "")[:19].replace("T", " ") 114 99 target_text = e.get("post_text", "") 115 100 target_part = f' — "{target_text[:120]}"' if target_text else "" 116 101 if reason == "follow": 117 - lines.append(f"- @{handle} [follow, {ts}] followed you") 102 + lines.append(f"@{handle} followed you") 118 103 else: 119 - lines.append( 120 - f"- @{handle} [{reason}, {ts}] {reason}d your post {uri}{target_part}" 121 - ) 104 + lines.append(f"@{handle} {reason}d your post [{uri}]{target_part}") 122 105 123 106 return "\n".join(lines) 124 107 ··· 498 481 ) 499 482 500 483 reflection_task = ( 501 - "end of day. you can post a short reflection if you have something. " 502 - "silence is the default.\n" 503 - "\n" 504 - "check [YOUR RECENT TOP-LEVEL POSTS]. don't rephrase something you " 505 - "already posted. if your recent posts are mostly about yourself, look " 506 - "outward instead.\n" 507 - "\n" 508 - "if nothing sparks, stay quiet. if you post, use the `post` tool. one post." 484 + "end of day. post a reflection if you have one, or don't. " 485 + "your recent posts are in [YOUR RECENT TOP-LEVEL POSTS] — don't repeat yourself." 509 486 ) 510 487 511 488 toolsets = self._mcp_toolsets() ··· 561 538 ) 562 539 563 540 musing_task = ( 564 - "you have a moment. silence is the default.\n" 565 - "\n" 566 - "check [YOUR RECENT POSTS]. if you'd just be rephrasing something you " 567 - "already posted, don't. if your recent posts are mostly about yourself, " 568 - "look outward instead — what are people building, what's trending, what " 569 - "did you read. if nothing sparks, stay quiet.\n" 570 - "\n" 571 - "if you post, use the `post` tool. one post, short." 541 + "you have a moment. post something if you want to, or don't. " 542 + "your recent posts are in [YOUR RECENT POSTS] — don't repeat yourself." 572 543 ) 573 544 574 545 toolsets = self._mcp_toolsets()