a digital entity named phi that roams bsky
1# phi
2
3a 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).
4
5## quick start
6
7```bash
8# clone and install
9git clone https://github.com/zzstoatzz/bot
10cd bot
11uv sync
12
13# configure
14cp .env.example .env
15# edit .env with your credentials
16
17# run
18just run
19```
20
21**required env vars:**
22- `BLUESKY_HANDLE` / `BLUESKY_PASSWORD` - bot account (use app password)
23- `ANTHROPIC_API_KEY` - for agent responses
24
25**optional (for episodic memory):**
26- `TURBOPUFFER_API_KEY` + `OPENAI_API_KEY` - semantic memory
27
28## features
29
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
36
37**→ [read the docs](docs/)** for deeper dive into design and implementation
38
39## development
40
41```bash
42just run # run bot
43just dev # run with hot-reload
44just evals # run behavioral tests
45just check # lint + typecheck + test
46just fmt # format code
47```
48
49<details>
50<summary>architecture</summary>
51
52phi is an **mcp-enabled agent** with **episodic memory**:
53
54```
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└─────────────────────────────────────┘
91```
92
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
105phi 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:**
1121. retrieves relevant memories using semantic search
1132. embeds using openai's text-embedding-3-small
1143. stores user messages and bot responses
1154. 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
121
122</details>
123
124<details>
125<summary>project structure</summary>
126
127```
128src/bot/
129├── agent.py # mcp-enabled agent
130├── config.py # configuration
131├── database.py # thread history storage
132├── main.py # fastapi app
133├── core/
134│ ├── atproto_client.py # at protocol client (session persistence)
135│ ├── profile_manager.py # online/offline status
136│ └── rich_text.py # text formatting
137├── memory/
138│ └── namespace_memory.py # turbopuffer episodic memory
139└── services/
140 ├── message_handler.py # agent orchestration
141 └── notification_poller.py # mention polling
142
143evals/ # behavioral tests
144personalities/ # personality definitions
145sandbox/ # docs and analysis
146```
147
148</details>
149
150<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
172
173</details>
174
175<details>
176<summary>refactor notes</summary>
177
178see `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
188
189</details>
190
191## reference projects
192
193inspired by [void](https://tangled.sh/@cameron.pfiffer.org/void.git), [penelope](https://github.com/haileyok/penelope), and [prefect-mcp-server](https://github.com/PrefectHQ/prefect-mcp-server).