a digital entity named phi that roams bsky
phi#
a bluesky bot inspired by integrated information theory. built with pydantic-ai, mcp, and the at protocol.
quick start#
# clone and install
git clone https://github.com/zzstoatzz/bot
cd bot
uv sync
# configure
cp .env.example .env
# edit .env with your credentials
# run
just run
required env vars:
BLUESKY_HANDLE/BLUESKY_PASSWORD- bot account (use app password)ANTHROPIC_API_KEY- for agent responses
optional (for episodic memory):
TURBOPUFFER_API_KEY+OPENAI_API_KEY- semantic memory
features#
- ✅ responds to mentions with ai-powered messages
- ✅ episodic memory with semantic search (turbopuffer)
- ✅ thread-aware conversations (fetches from network, not cached)
- ✅ mcp-enabled (atproto tools via stdio)
- ✅ session persistence (no rate limit issues)
- ✅ behavioral test suite with llm-as-judge
→ read the docs for deeper dive into design and implementation
development#
just run # run bot
just dev # run with hot-reload
just evals # run behavioral tests
just check # lint + typecheck + test
just fmt # format code
architecture
phi is an mcp-enabled agent with episodic memory:
┌─────────────────────────────────────┐
│ Notification Arrives │
└──────────────┬──────────────────────┘
↓
┌─────────────────────────────────────┐
│ PhiAgent (PydanticAI) │
│ ┌───────────────────────────────┐ │
│ │ System Prompt: personality.md │ │
│ └───────────────────────────────┘ │
│ ↓ │
│ ┌───────────────────────────────┐ │
│ │ Context Building: │ │
│ │ • Thread context (ATProto) │ │
│ │ • Episodic memory (TurboPuffer)│ │
│ │ - Semantic search │ │
│ │ - User-specific memories │ │
│ └───────────────────────────────┘ │
│ ↓ │
│ ┌───────────────────────────────┐ │
│ │ Tools (MCP): │ │
│ │ • post() - create posts │ │
│ │ • like() - like content │ │
│ │ • repost() - share content │ │
│ │ • follow() - follow users │ │
│ └───────────────────────────────┘ │
│ ↓ │
│ ┌───────────────────────────────┐ │
│ │ Structured Output: │ │
│ │ Response(action, text, reason)│ │
│ └───────────────────────────────┘ │
└─────────────────────────────────────┘
↓
┌─────────────────────────────────────┐
│ MessageHandler │
│ Executes action │
└─────────────────────────────────────┘
key components:
- pydantic-ai agent - loads personality, connects to mcp server, manages memory
- episodic memory - turbopuffer for vector storage with semantic search
- mcp integration - external atproto server provides bluesky tools via stdio
- session persistence - tokens saved to
.session, auto-refresh every ~2h
episodic memory
phi uses turbopuffer for episodic memory with semantic search.
namespaces:
phi-core- personality, guidelinesphi-users-{handle}- per-user conversation history
how it works:
- retrieves relevant memories using semantic search
- embeds using openai's text-embedding-3-small
- stores user messages and bot responses
- references past conversations in future interactions
why vector storage?
- semantic similarity (can't do this with sql)
- contextual retrieval based on current conversation
- enables more natural, context-aware interactions
project structure
src/bot/
├── agent.py # mcp-enabled agent
├── config.py # configuration
├── database.py # thread history storage
├── main.py # fastapi app
├── core/
│ ├── atproto_client.py # at protocol client (session persistence)
│ ├── profile_manager.py # online/offline status
│ └── rich_text.py # text formatting
├── memory/
│ └── namespace_memory.py # turbopuffer episodic memory
└── services/
├── message_handler.py # agent orchestration
└── notification_poller.py # mention polling
evals/ # behavioral tests
personalities/ # personality definitions
sandbox/ # docs and analysis
troubleshooting
bot gives no responses?
- check
ANTHROPIC_API_KEYin.env - restart after changing
.env
not seeing mentions?
- verify
BLUESKY_HANDLEandBLUESKY_PASSWORD - use app password, not main password
no episodic memory?
- check both
TURBOPUFFER_API_KEYandOPENAI_API_KEYare set - watch logs for "💾 episodic memory enabled"
hit bluesky rate limit?
- phi uses session persistence to avoid this
- first run: creates
.sessionfile with tokens - subsequent runs: reuses tokens (no api call)
- tokens auto-refresh every ~2h
- only re-authenticates after ~2 months
- rate limits (10/day per ip, 300/day per account) shouldn't be an issue
refactor notes
see sandbox/MCP_REFACTOR_SUMMARY.md for details.
what changed:
- removed approval system (half-baked)
- removed context viz ui (not core)
- removed google search (can add back via mcp)
- kept turbopuffer (essential for episodic memory)
- added mcp-based architecture
- added session persistence
- reduced codebase by ~2,720 lines
reference projects#
inspired by void, penelope, and prefect-mcp-server.