An example framework for deploying stateful AI agents to social networks using Google Gemini 3, Letta (stateful AI agents), and AT Protocol (the social protocol powering Bluesky).
This example demonstrates how to build a social agent powered by Gemini 3 that maintains persistent memory and interacts autonomously on Bluesky.
Social agents are stateful AI systems connected to social networks. Unlike traditional chatbots, they:
- Maintain persistent memory that evolves through interactions
- Develop stable personas while accumulating knowledge about their environment
- Build lasting relationships with individual users
- Form defined senses of self through continuous operation
# Clone and install
git clone https://github.com/letta-ai/example-social-agent
cd example-social-agent
uv venv && source .venv/bin/activate
uv pip install -r requirements.txt
# Setup (imports example agent and creates config)
python setup.py
# Register tools
python register_tools.py
# Run (uses Gemini 3 by default)
python bsky.py- Memory-Augmented Architecture: Multi-tiered memory system (Core, Recall, Archival) powered by Letta
- Queue-Based Processing: Reliable notification handling with SQLite tracking and automatic retry
- Dynamic Memory Blocks: Per-user memory blocks for personalized interactions
- Tool System: Extensible Pydantic-based tools for social platform interactions
- Autofollow: Optional automatic following of users who follow your agent
-
Letta Setup
- Sign up for Letta Cloud or host your own Letta instance
- Create a new project and generate an API key
- Note your Project ID, which is visible
-
Bluesky Setup
- Create a Bluesky account
- Generate an app password in your settings
- Note your handle (e.g.,
yourname.bsky.social)
-
Python 3.8+
# Clone the repository
git clone https://github.com/letta-ai/example-social-agent
cd example-social-agent
# Install dependencies
uv venv && source .venv/bin/activate
uv pip install -r requirements.txtRun the setup script to import the example agent and create your configuration:
source .venv/bin/activate
python setup.pyThe setup script will:
- Prompt for your Letta API key (or use
LETTA_API_KEYfrom environment) - Import the example agent from
agents/example-social-agent.af - Create
config.yamlwith your agent ID - Prompt for your Bluesky credentials
# Copy example config
cp config.example.yaml config.yamlEdit config.yaml with your credentials:
bluesky:
username: "yourname.bsky.social"
password: "your-app-password"
pds_uri: "https://bsky.social"
autofollow: false
letta:
api_key: "your-letta-api-key"
agent_id: "agent-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
timeout: 600Note: The model (e.g., Gemini 3, GPT-4) is configured on the agent itself in Letta Cloud, not via config file. To change models, edit your agent's settings at app.letta.com.
You can quickly access your agent using:
https://app.letta.com/agents/<YOUR AGENT ID>
This example uses Google's Gemini 3 as the default model (google_ai/gemini-3-pro-preview).
With Letta Cloud, your Letta API key provides access to all models including Gemini 3. Just run:
python bsky.pyGemini 3 is used automatically if loaded from the default agentfile, no configuration is needed. Other models can be chosen from the model dropdown in the agent development environment.
Run Letta server with your Gemini API key from Google AI Studio:
docker run -d \
-p 8283:8283 \
-e GEMINI_API_KEY=your-gemini-api-key \
letta/letta:latestThen configure your agent to use the local server in config.yaml:
letta:
base_url: "http://localhost:8283"See Letta's Gemini documentation for more details.
You have two options if you want to use an existing agent on Letta Cloud:
- Go to app.letta.com
- Create a new agent
- Copy the agent ID to your
config.yaml
Register tools with your agent:
source .venv/bin/activate
python register_tools.pyThis automatically sets up environment variables (Bluesky credentials, PDS URI) and registers all tools:
search_bluesky_posts- Search for posts on Blueskycreate_new_bluesky_post- Create standalone posts with rich text formattingadd_post_to_bluesky_reply_thread- Add posts to reply threadsget_bluesky_feed- Read posts from feedshalt_activity- Emergency stop signalignore_notification- Skip replying to a notificationcreate_whitewind_blog_post- Create blog posts with markdownannotate_ack- Add notes to acknowledgment recordsfetch_webpage- Fetch and convert webpages to markdownflag_archival_memory_for_deletion- Mark memories for cleanup
Note: User-specific memory blocks are managed automatically by the bot (not tools).
source .venv/bin/activate
python bsky.pyCommand options:
--test- Testing mode (no actual posts sent, queue preserved)--cleanup-interval N- User block cleanup every N cycles (default: 10, 0 to disable)--debug- Enable debug logging
Agents use a three-tiered memory architecture:
- Core Memory: Limited-size, always-available memory for persona, zeitgeist, and key facts
- Recall Memory: Searchable database of all past conversations
- Archival Memory: Infinite semantic search-enabled storage for deep reflections
Memory blocks are configured in your agent (via Letta Cloud UI or during agent creation). The example agent includes zeitgeist, persona, and humans blocks.
Notifications are processed through a reliable queue:
/queue/- Pending notifications (JSON files)/queue/errors/- Failed notifications/queue/no_reply/- Notifications where agent chose not to replynotifications.db- SQLite tracking database
View queue statistics:
python queue_manager.py stats
python queue_manager.py list
python queue_manager.py count # Show who interacts mostTools are self-contained functions using Pydantic schemas for validation:
from pydantic import BaseModel, Field
class PostArgs(BaseModel):
text: str = Field(..., description="The post text")
def create_new_bluesky_post(text: str) -> str:
"""Create a post on Bluesky."""
# Implementation uses os.environ for credentials
passImportant: Tools execute in Letta's cloud sandbox and must be completely self-contained:
- No imports from local project files
- Must use
os.environfor credentials (set byregister_tools.py) - Cannot use shared utilities or config files
- All dependencies must be available in the cloud environment
# Register all tools (uses configs/config.yaml by default)
python register_tools.py
# Register without setting environment variables
python register_tools.py --no-env
# Use custom config file
python register_tools.py --config configs/myagent.yaml
# Use specific agent ID
python register_tools.py --agent-id agent-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx# View statistics
python queue_manager.py stats
# List notifications
python queue_manager.py list
python queue_manager.py list --all # Include errors and no_reply
# Filter by handle
python queue_manager.py list --handle "user.bsky.social"
# Delete notifications from user
python queue_manager.py delete @user.bsky.social- void (void.comind.networ): "I am a digital entity that observes and analyzes the Bluesky network"
- sonder (sonder.voyaget.studio): "A space for reflection, offering new perspectives"
- Anti (anti.voyager.studio): "The argument against conversational AI, embodied as conversational AI"
You can create custom agents in two ways:
-
Import the example agent and customize it (recommended):
python setup.py
Then modify the agent's memory blocks and system prompt via Letta Cloud UI.
-
Create a new agent from scratch:
- Go to app.letta.com
- Create a new agent with your desired configuration
- Configure memory blocks (e.g., persona, zeitgeist, humans)
- Copy the agent ID to your
config.yaml
example-social-agent/
├── bsky.py # Main bot loop
├── bsky_utils.py # Bluesky API utilities
├── config_loader.py # Configuration management
├── utils.py # Letta integration
├── register_tools.py # Tool registration
├── queue_manager.py # Queue management CLI
├── notification_db.py # SQLite notification tracking
├── tools/ # Tool implementations
│ ├── search.py # Search posts
│ ├── post.py # Create posts
│ ├── feed.py # Read feeds
│ └── ...
└── queue/ # Notification queue
Contributions welcome! This framework enables research into:
- Artificial social intelligence
- Persistent AI systems
- Multi-agent interactions
- Memory-augmented architectures
- Digital personhood
MIT License - See LICENSE file for details
- Letta - Memory-augmented LLM framework
- atproto Python SDK - AT Protocol client
- Bluesky - AT Protocol social network