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.

rewrite README to reflect current architecture

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

zzstoatzz 3b6f89f5 08b6f326

+49 -138
+49 -138
README.md
··· 1 1 # phi 2 2 3 - a bluesky bot inspired by [integrated information theory](https://en.wikipedia.org/wiki/Integrated_information_theory). built with `pydantic-ai`, `mcp`, and the [at protocol](https://atproto.com). 3 + a bluesky bot — a librarian who stepped outside. built with [pydantic-ai](https://ai.pydantic.dev/), [mcp](https://modelcontextprotocol.io/), and the [at protocol](https://atproto.com). personality is [public](personalities/phi.md). 4 4 5 5 ## quick start 6 6 7 7 ```bash 8 - # clone and install 9 - git clone https://github.com/zzstoatzz/bot 10 - cd bot 11 8 uv sync 12 - 13 - # configure 14 - cp .env.example .env 15 - # edit .env with your credentials 16 - 17 - # run 9 + cp .env.example .env # edit with your credentials 18 10 just run 19 11 ``` 20 12 21 - **required env vars:** 22 - - `BLUESKY_HANDLE` / `BLUESKY_PASSWORD` - bot account (use app password) 23 - - `ANTHROPIC_API_KEY` - for agent responses 13 + **required:** `BLUESKY_HANDLE`, `BLUESKY_PASSWORD`, `ANTHROPIC_API_KEY` 14 + 15 + **optional:** `TURBOPUFFER_API_KEY` + `OPENAI_API_KEY` for episodic memory 16 + 17 + ## what phi does 18 + 19 + phi listens for mentions on bluesky and decides how to respond — reply, like, repost, or ignore. it can also post unprompted, search bluesky, check trending topics, and verify links before sharing them. 20 + 21 + every conversation builds context from three sources: the current thread (fetched live from the network), semantic memory (relevant past observations about the person talking), and phi's own episodic notes about the world. phi extracts observations from conversations and stores them for next time. 22 + 23 + ## memory 24 24 25 - **optional (for episodic memory):** 26 - - `TURBOPUFFER_API_KEY` + `OPENAI_API_KEY` - semantic memory 25 + phi uses [turbopuffer](https://turbopuffer.com/) for vector-based episodic memory across three namespace families: 27 26 28 - ## features 27 + - **phi-core** — identity and guidelines 28 + - **phi-users-{handle}** — per-user observations, interactions, and relationship summaries 29 + - **phi-episodic** — phi's own notes about the world 29 30 30 - - ✅ responds to mentions with ai-powered messages 31 - - ✅ episodic memory with semantic search (turbopuffer) 32 - - ✅ thread-aware conversations (fetches from network, not cached) 33 - - ✅ mcp-enabled (atproto tools via stdio) 34 - - ✅ session persistence (no rate limit issues) 35 - - ✅ behavioral test suite with llm-as-judge 31 + observations accumulate over conversations. a separate [pipeline](https://github.com/zzstoatzz/my-prefect-server) periodically compacts per-user observations into relationship summaries — dense paragraphs that give phi a coherent picture of who someone is, not just scattered facts. 36 32 37 - **→ [read the docs](docs/)** for deeper dive into design and implementation 33 + the [memory graph](/memory) visualizes connections between phi, the people it talks to, and the topics that link them. 38 34 39 35 ## development 40 36 ··· 44 40 just evals # run behavioral tests 45 41 just check # lint + typecheck + test 46 42 just fmt # format code 43 + just deploy # deploy to fly.io 47 44 ``` 48 45 49 46 <details> 50 47 <summary>architecture</summary> 51 48 52 - phi is an **mcp-enabled agent** with **episodic memory**: 53 - 54 49 ``` 55 - ┌─────────────────────────────────────┐ 56 - │ Notification Arrives │ 57 - └──────────────┬──────────────────────┘ 58 - 59 - ┌─────────────────────────────────────┐ 60 - │ PhiAgent (PydanticAI) │ 61 - │ ┌───────────────────────────────┐ │ 62 - │ │ System Prompt: personality.md │ │ 63 - │ └───────────────────────────────┘ │ 64 - │ ↓ │ 65 - │ ┌───────────────────────────────┐ │ 66 - │ │ Context Building: │ │ 67 - │ │ • Thread context (ATProto) │ │ 68 - │ │ • Episodic memory (TurboPuffer)│ │ 69 - │ │ - Semantic search │ │ 70 - │ │ - User-specific memories │ │ 71 - │ └───────────────────────────────┘ │ 72 - │ ↓ │ 73 - │ ┌───────────────────────────────┐ │ 74 - │ │ Tools (MCP): │ │ 75 - │ │ • post() - create posts │ │ 76 - │ │ • like() - like content │ │ 77 - │ │ • repost() - share content │ │ 78 - │ │ • follow() - follow users │ │ 79 - │ └───────────────────────────────┘ │ 80 - │ ↓ │ 81 - │ ┌───────────────────────────────┐ │ 82 - │ │ Structured Output: │ │ 83 - │ │ Response(action, text, reason)│ │ 84 - │ └───────────────────────────────┘ │ 85 - └─────────────────────────────────────┘ 86 - 87 - ┌─────────────────────────────────────┐ 88 - │ MessageHandler │ 89 - │ Executes action │ 90 - └─────────────────────────────────────┘ 50 + notification → PhiAgent (pydantic-ai) 51 + ├── context: thread + memory + episodic notes 52 + ├── tools: memory, search, trending, url checks 53 + ├── mcp: atproto record CRUD, publication search 54 + └── output: Response(action, text, reason) 55 + 56 + MessageHandler executes action 57 + (reply, like, repost, or ignore) 91 58 ``` 92 59 93 - **key components:** 94 - 95 - - **pydantic-ai agent** - loads personality, connects to mcp server, manages memory 96 - - **episodic memory** - turbopuffer for vector storage with semantic search 97 - - **mcp integration** - external atproto server provides bluesky tools via stdio 98 - - **session persistence** - tokens saved to `.session`, auto-refresh every ~2h 99 - 100 - </details> 101 - 102 - <details> 103 - <summary>episodic memory</summary> 104 - 105 - phi uses turbopuffer for episodic memory with semantic search. 106 - 107 - **namespaces:** 108 - - `phi-core` - personality, guidelines 109 - - `phi-users-{handle}` - per-user conversation history 110 - 111 - **how it works:** 112 - 1. retrieves relevant memories using semantic search 113 - 2. embeds using openai's text-embedding-3-small 114 - 3. stores user messages and bot responses 115 - 4. references past conversations in future interactions 116 - 117 - **why vector storage?** 118 - - semantic similarity (can't do this with sql) 119 - - contextual retrieval based on current conversation 120 - - enables more natural, context-aware interactions 60 + phi is a pydantic-ai agent with a personality prompt, structured output, and tool access via both native tools and remote MCP servers. the agent decides what to do; the handler does it. 121 61 122 62 </details> 123 63 ··· 126 66 127 67 ``` 128 68 src/bot/ 129 - ├── agent.py # mcp-enabled agent 130 - ├── config.py # configuration 131 - ├── database.py # thread history storage 132 - ├── main.py # fastapi app 69 + ├── agent.py # pydantic-ai agent, tools, personality 70 + ├── config.py # settings (env vars) 71 + ├── main.py # fastapi app, status pages, memory graph ui 72 + ├── status.py # runtime metrics 133 73 ├── core/ 134 - │ ├── atproto_client.py # at protocol client (session persistence) 135 - │ ├── profile_manager.py # online/offline status 136 - │ └── rich_text.py # text formatting 74 + │ ├── atproto_client.py # at protocol client, session persistence 75 + │ ├── profile_manager.py # online/offline status, self-labels 76 + │ └── rich_text.py # text formatting with facets 137 77 ├── memory/ 138 - │ └── namespace_memory.py # turbopuffer episodic memory 139 - └── services/ 140 - ├── message_handler.py # agent orchestration 141 - └── notification_poller.py # mention polling 78 + │ └── namespace_memory.py # turbopuffer episodic memory 79 + ├── services/ 80 + │ ├── message_handler.py # action dispatch (reply, like, repost) 81 + │ └── notification_poller.py # mention polling loop 82 + └── utils/ 83 + └── thread.py # thread context building 142 84 143 - evals/ # behavioral tests 144 - personalities/ # personality definitions 145 - sandbox/ # docs and analysis 85 + evals/ # behavioral tests (llm-as-judge) 86 + personalities/ # personality definitions 87 + scripts/ # proven utility scripts 88 + sandbox/ # experiments and analysis 146 89 ``` 147 90 148 91 </details> 149 92 150 93 <details> 151 - <summary>troubleshooting</summary> 152 - 153 - **bot gives no responses?** 154 - - check `ANTHROPIC_API_KEY` in `.env` 155 - - restart after changing `.env` 156 - 157 - **not seeing mentions?** 158 - - verify `BLUESKY_HANDLE` and `BLUESKY_PASSWORD` 159 - - use app password, not main password 160 - 161 - **no episodic memory?** 162 - - check both `TURBOPUFFER_API_KEY` and `OPENAI_API_KEY` are set 163 - - watch logs for "💾 episodic memory enabled" 164 - 165 - **hit bluesky rate limit?** 166 - - phi uses session persistence to avoid this 167 - - first run: creates `.session` file with tokens 168 - - subsequent runs: reuses tokens (no api call) 169 - - tokens auto-refresh every ~2h 170 - - only re-authenticates after ~2 months 171 - - rate limits (10/day per ip, 300/day per account) shouldn't be an issue 94 + <summary>deployment</summary> 172 95 173 - </details> 96 + runs on [fly.io](https://fly.io) — `shared-cpu-1x`, 512MB, region `ord`. auto-start is off; the machine sleeps until woken by an API call. 174 97 175 - <details> 176 - <summary>refactor notes</summary> 177 - 178 - see `sandbox/MCP_REFACTOR_SUMMARY.md` for details. 179 - 180 - **what changed:** 181 - - removed approval system (half-baked) 182 - - removed context viz ui (not core) 183 - - removed google search (can add back via mcp) 184 - - **kept turbopuffer** (essential for episodic memory) 185 - - added mcp-based architecture 186 - - added session persistence 187 - - reduced codebase by ~2,720 lines 98 + secrets are set via `fly secrets set`. the bot uses session persistence (`.session` file) to avoid rate limits — tokens auto-refresh every ~2h. 188 99 189 100 </details> 190 101