Documentation Index
Fetch the complete documentation index at: https://docs.elizaos.ai/llms.txt
Use this file to discover all available pages before exploring further.
Farcaster Plugin Developer Guide
Overview
The @elizaos/plugin-farcaster plugin enables elizaOS agents to interact with the Farcaster protocol through the Neynar API. This plugin provides comprehensive functionality for casting, replying, and engaging with the Farcaster ecosystem.
Core Features
1. Casting Capabilities
- Autonomous Casting: Post original casts based on agent personality
- Threaded Conversations: Support for reply chains and threads
- Media Support: Embed images, links, and frames in casts
- Scheduled Posting: Time-based cast scheduling
2. Engagement Features
- Reply Detection: Monitor and respond to mentions and replies
- Like/Recast: Programmatic engagement with other casts
- Follow Management: Automatic follow/unfollow based on criteria
- Channel Support: Post to specific channels (e.g., /elizaos)
3. Hub Integration
- Hub API: Direct integration with Farcaster hubs
- Message Validation: Cryptographic message signing
- Protocol Compliance: Full Farcaster protocol v2 support
Installation
# Using bun
bun add @elizaos/plugin-farcaster
# Using npm
npm install @elizaos/plugin-farcaster
# Using pnpm
pnpm add @elizaos/plugin-farcaster
Configuration
Environment Variables
# Required
FARCASTER_NEYNAR_API_KEY=your-neynar-api-key
FARCASTER_SIGNER_UUID=your-signer-uuid
FARCASTER_FID=12345
# Feature Toggles
ENABLE_CAST=true
ENABLE_ACTION_PROCESSING=false
FARCASTER_DRY_RUN=false
# Timing Configuration (in minutes)
CAST_INTERVAL_MIN=90
CAST_INTERVAL_MAX=180
FARCASTER_POLL_INTERVAL=2
ACTION_INTERVAL=5
# Other Options
CAST_IMMEDIATELY=false
ACTION_TIMELINE_TYPE=ForYou
MAX_ACTIONS_PROCESSING=1
MAX_CAST_LENGTH=320
Character Configuration
import { Character } from "@elizaos/core";
import { farcasterPlugin } from "@elizaos/plugin-farcaster";
export const character: Character = {
name: "FarcasterAgent",
plugins: [farcasterPlugin],
settings: {
farcaster: {
channels: ["/elizaos", "/ai16z"],
replyProbability: 0.7,
castStyle: "conversational",
maxCastLength: 320
}
}
};
Actions
SEND_CAST
Posts a new cast to Farcaster.
{
name: "SEND_CAST",
description: "Posts a cast (message) on Farcaster",
examples: [
"Can you post about the new ElizaOS features on Farcaster?",
"Share on Farcaster that we just launched version 2.0!"
]
}
REPLY_TO_CAST
Reply to an existing cast.
{
name: "REPLY_TO_CAST",
description: "Replies to a cast on Farcaster",
examples: [
"Someone asked about ElizaOS on Farcaster, can you reply?",
"Reply to that cast and thank them for the feedback"
]
}
Providers
farcasterProfile
Provides the agent’s Farcaster profile information.
// Provider name: 'farcasterProfile'
const profile = await runtime.providers.farcasterProfile.get(runtime, message, state);
// Returns profile data including FID, username, bio, etc.
farcasterTimeline
Supplies recent timeline casts for context.
// Provider name: 'farcasterTimeline'
const timeline = await runtime.providers.farcasterTimeline.get(runtime, message, state);
// Returns recent casts from the agent's timeline
Events
handleCastSent
Triggered when a cast is successfully sent. Stores metadata for tracking:
// Automatically handled when casting
// Stores cast hash, thread ID, and message metadata
EventType: 'cast:sent'
Payload: {
castHash: string,
threadId: string,
messageId: UUID,
platform: 'farcaster'
}
handleMessageReceived
Processes incoming Farcaster messages and creates memories:
// Automatically triggered for incoming messages
EventType: 'message:received'
Payload: {
cast: Cast,
profile: Profile,
threadId: string
}
Managers
FarcasterAgentManager
Orchestrates all Farcaster operations for an agent:
class FarcasterAgentManager {
client: FarcasterClient // Neynar API client
casts: FarcasterCastManager // Autonomous posting
interactions: FarcasterInteractionManager // Mentions/replies
async start() // Start all managers
async stop() // Stop all managers
}
FarcasterCastManager
Handles autonomous casting based on configuration:
class FarcasterCastManager {
// Manages periodic autonomous posts
// Respects CAST_INTERVAL_MIN/MAX settings
// Handles CAST_IMMEDIATELY flag
async start() // Begin autonomous casting
async stop() // Stop casting
async publishCast(text: string) // Manually publish
}
FarcasterInteractionManager
Processes mentions, replies, and interactions:
class FarcasterInteractionManager {
// Polls for mentions at FARCASTER_POLL_INTERVAL
// Processes up to MAX_ACTIONS_PROCESSING per cycle
// Uses AI to determine appropriate responses
async start() // Start monitoring
async stop() // Stop monitoring
async processInteractions() // Process pending interactions
}
Services
FarcasterService
Main service coordinating all Farcaster operations:
class FarcasterService extends Service {
static serviceType = 'farcaster'
// Service lifecycle
async initialize(runtime: IAgentRuntime): Promise<void>
static async start(runtime: IAgentRuntime): Promise<Service>
static async stop(runtime: IAgentRuntime): Promise<void>
// Get service instances
getMessageService(agentId: UUID): FarcasterMessageService
getCastService(agentId: UUID): FarcasterCastService
getActiveManagers(): Map<UUID, FarcasterAgentManager>
// Health check
async healthCheck(): Promise<boolean>
}
MessageService
Implements IMessageService for message operations:
class FarcasterMessageService implements IMessageService {
// Message retrieval
async getMessages(options: GetMessagesOptions): Promise<Message[]>
async getMessage(messageId: string): Promise<Message | null>
// Message sending
async sendMessage(options: {
text: string,
type: FarcasterMessageType,
replyToId?: string
}): Promise<Message>
}
CastService
Implements IPostService with full CRUD operations:
class FarcasterCastService implements IPostService {
// Cast operations
async getCasts(params: {
agentId: UUID,
limit?: number,
cursor?: string
}): Promise<FarcasterCast[]>
async createCast(params: {
text: string,
media?: string[],
replyTo?: { hash: string, fid: number }
}): Promise<FarcasterCast>
async deleteCast(castHash: string): Promise<void>
// Engagement operations
async likeCast(castHash: string): Promise<void>
async unlikeCast(castHash: string): Promise<void>
async recast(castHash: string): Promise<void>
async unrecast(castHash: string): Promise<void>
// Utility methods
async publishCast(text: string): Promise<FarcasterCast>
async getCastByHash(hash: string): Promise<Cast>
async getProfile(fid: number): Promise<Profile>
}
Client Architecture
FarcasterClient
Core client wrapping Neynar API operations:
class FarcasterClient {
private neynar: NeynarAPIClient;
private signerUuid: string;
constructor(params: {
neynar: NeynarAPIClient,
signerUuid: string
})
// Casting operations
async publishCast(text: string, options?: {
embeds?: Array<{ url: string }>,
replyTo?: string,
channelId?: string
}): Promise<Cast>
async reply(params: {
text: string,
replyTo: { hash: string, fid: number }
}): Promise<Cast>
async deleteCast(targetHash: string): Promise<void>
// User operations
async getUser(): Promise<User>
async getUserByFid(fid: number): Promise<User>
async getUserByUsername(username: string): Promise<User>
// Timeline operations
async getMentions(fid: number, cursor?: string): Promise<Cast[]>
async getTimeline(type: 'ForYou' | 'Following', cursor?: string): Promise<Cast[]>
async getCast(hash: string): Promise<Cast>
// Engagement operations
async likeCast(targetHash: string): Promise<void>
async unlikeCast(targetHash: string): Promise<void>
async recast(targetHash: string): Promise<void>
async unrecast(targetHash: string): Promise<void>
async followUser(targetFid: number): Promise<void>
async unfollowUser(targetFid: number): Promise<void>
}
Common Utilities
AsyncQueue
Manages asynchronous operations with concurrency control:
class AsyncQueue {
constructor(concurrency: number)
push<T>(fn: () => Promise<T>): Promise<T>
}
Helper Functions
// Cast utilities
castUuid(cast: Cast): UUID // Generate unique ID for cast
neynarCastToCast(cast: NeynarCast): Cast // Convert Neynar format
formatCastTimestamp(timestamp: number): string // Format timestamps
// Prompt formatting
formatCast(cast: Cast): string // Format cast for AI processing
formatTimeline(casts: Cast[]): string // Format timeline for context
// Cache management
lastCastCacheKey(agentId: UUID): string // Generate cache keys
Event System
Cast Events
runtime.on("cast:new", (cast: Cast) => {
// Handle new cast
});
runtime.on("cast:reply", (reply: CastReply) => {
// Handle reply
});
runtime.on("cast:like", (like: CastLike) => {
// Handle like
});
Error Events
runtime.on("farcaster:error", (error: FarcasterError) => {
// Handle error
});
Memory & Storage
Memory System
The plugin uses elizaOS’s memory system for persistence rather than direct database tables:
// Cast metadata stored when sending
await runtime.createMemory({
type: 'metadata',
content: {
castHash: string,
threadId: string,
platform: 'farcaster',
messageId: UUID,
sentAt: number
}
});
// Message memory for each cast
await runtime.createMemory({
type: 'message',
content: {
text: string,
source: 'farcaster',
hash: string,
fid: number,
timestamp: number,
inReplyTo?: string
}
});
Caching Strategy
LRU cache for performance optimization:
- Cast Cache: TTL 30 minutes, 9000 entries max
- Profile Cache: User profile data
- Timeline Cache: Recent timeline casts
- Last Cast Tracking: Per-agent last cast timestamps
Security Considerations
Key Management
- Store API keys and signer UUIDs securely using environment variables
- Never commit credentials to version control
- Use separate Neynar API keys for development and production
- Create separate signers for different environments
Rate Limiting
- Implement exponential backoff for API requests
- Respect hub rate limits (typically 100 req/min)
- Cache frequently accessed data
Content Validation
- Validate cast length (max 320 characters)
- Sanitize user inputs
- Verify message signatures
AsyncQueue Implementation
The plugin uses an async queue to prevent rate limiting:
// Queue processes operations with concurrency control
const asyncQueue = new AsyncQueue(1); // Single concurrency
await asyncQueue.push(() => processInteraction(cast));
Polling Optimization
// Configurable polling intervals to balance responsiveness
FARCASTER_POLL_INTERVAL=2 // Minutes between polls
ACTION_INTERVAL=5 // Minutes between action processing
MAX_ACTIONS_PROCESSING=1 // Actions per cycle
Troubleshooting
Common Issues
-
Authentication Errors
- Verify mnemonic is correct
- Ensure FID matches the mnemonic
- Check hub connectivity
-
Rate Limiting
- Implement retry logic with backoff
- Use caching to reduce API calls
- Monitor rate limit headers
-
Message Validation Failures
- Verify timestamp is within valid range
- Ensure proper message formatting
- Check signature validity
Debug Mode
Enable debug logging:
FARCASTER_DEBUG=true
LOG_LEVEL=debug
Best Practices
-
Content Strategy
- Keep casts concise and engaging
- Use channels appropriately
- Maintain consistent voice
-
Engagement Guidelines
- Don’t spam or over-engage
- Respect community norms
- Build genuine connections
-
Technical Implementation
- Handle errors gracefully
- Implement proper retry logic
- Monitor performance metrics
Migration Guide
From v1 to v2
// v1
import { FarcasterPlugin } from "@elizaos/plugin-farcaster";
// v2
import { farcasterPlugin } from "@elizaos/plugin-farcaster";
// Configuration changes
// v1: Plugin initialized with options
const plugin = new FarcasterPlugin(options);
// v2: Configuration via environment and character
const character = {
plugins: [farcasterPlugin],
settings: { farcaster: options }
};
Support
License
MIT License - see LICENSE file for details