Skip to content

Commit e7ca64f

Browse files
v1.2.1 - Automatic Tier Detection & Modular Prompts
TierManager: - Auto-detect Twitter API tier on startup - Hourly refresh to detect subscription upgrades - Block unavailable features (mentions on Free tier) - Usage warnings at 80%/90%, auto-pause at 100% - New endpoints: /tier-status, /tier-refresh Modular Prompts: - Split personality into backstory/beliefs/instructions - Move prompts to config/prompts/ - Centralize JSON schemas in config/schemas.py Updated: README.md, ARCHITECTURE.md
1 parent 2525b13 commit e7ca64f

File tree

15 files changed

+779
-243
lines changed

15 files changed

+779
-243
lines changed

ARCHITECTURE.md

Lines changed: 90 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,20 @@ main.py # Application entry point
3232
config/
3333
__init__.py
3434
settings.py # Environment configuration
35-
personality.py # Bot personality definition
35+
schemas.py # JSON schemas for LLM responses
36+
personality/ # Modular character definition
37+
__init__.py # Combines parts into SYSTEM_PROMPT
38+
backstory.py # Origin story
39+
beliefs.py # Values and priorities
40+
instructions.py # Communication style
41+
prompts/ # LLM prompts
42+
agent_autopost.py # Agent planning prompt
43+
mention_selector.py # Mention handling prompt
3644
services/
3745
__init__.py
3846
autopost.py # Autoposting service
3947
mentions.py # Mention handling service
48+
tier_manager.py # Twitter API tier detection and limits
4049
llm.py # LLM client
4150
twitter.py # Twitter API client
4251
image_gen.py # Image generation service
@@ -69,6 +78,8 @@ HTTP endpoints:
6978
- `GET /callback` — OAuth callback for Twitter authentication
7079
- `POST /trigger-post` — manually trigger autopost
7180
- `POST /trigger-mentions` — manually trigger mention processing
81+
- `GET /tier-status` — get current tier and usage stats
82+
- `POST /tier-refresh` — force tier re-detection
7283

7384
### config/settings.py
7485
Pydantic Settings class that loads configuration from environment variables and `.env` file. All settings are typed and validated on startup.
@@ -81,15 +92,47 @@ Key settings:
8192
- `mentions_interval_minutes` — mention check frequency (default: 20)
8293
- `enable_image_generation` — toggle for image generation (default: true)
8394

84-
### config/personality.py
85-
Contains `SYSTEM_PROMPT` constant — the complete personality definition for the bot. This prompt is prepended to all LLM calls and defines:
86-
- Personality traits and character
95+
### config/personality/
96+
Modular character definition split into three files:
97+
98+
**`backstory.py`**`BACKSTORY` constant
99+
- Origin story and background
100+
- Who the character is
101+
102+
**`beliefs.py`**`BELIEFS` constant
103+
- Personality traits
104+
- Topics of interest
105+
- Values and worldview
106+
107+
**`instructions.py`**`INSTRUCTIONS` constant
87108
- Communication style (tone, grammar, punctuation)
88-
- Topics to discuss and avoid
89-
- Behavioral rules (no hashtags, no engagement bait, etc.)
90-
- Example tweets that capture the vibe
109+
- What NOT to do
110+
- Example tweets
111+
112+
**`__init__.py`** — Combines all parts into `SYSTEM_PROMPT`:
113+
```python
114+
SYSTEM_PROMPT = BACKSTORY + BELIEFS + INSTRUCTIONS
115+
```
116+
117+
**To change the bot's personality, edit the individual files.**
118+
119+
### config/prompts/
120+
LLM prompts for specific services:
121+
122+
**`agent_autopost.py`**`AGENT_PROMPT_TEMPLATE`
123+
- Instructions for autonomous posting agent
124+
- Contains `{tools_desc}` placeholder for dynamic tool injection
125+
126+
**`mention_selector.py`**`MENTION_SELECTOR_PROMPT`
127+
- Instructions for selecting and responding to mentions
128+
- Criteria for what to reply to and what to ignore
129+
130+
### config/schemas.py
131+
JSON schemas for structured LLM output:
91132

92-
**To change the bot's personality, edit this file.**
133+
**`PLAN_SCHEMA`** — Agent plan format `{reasoning, plan: [{tool, params}]}`
134+
**`POST_TEXT_SCHEMA`** — Final tweet format `{post_text}`
135+
**`MENTION_SELECTOR_SCHEMA`** — Mention response format `{selected_tweet_id, text, include_picture, reasoning}`
93136

94137
### services/autopost.py
95138
`AutoPostService` class — agent-based autoposting with tool execution.
@@ -183,6 +226,45 @@ Flow:
183226
3. Receives base64-encoded image in response
184227
4. Returns raw image bytes
185228

229+
### services/tier_manager.py
230+
`TierManager` class — automatic Twitter API tier detection and limit management.
231+
232+
**Initialization:**
233+
- Called on application startup
234+
- Queries Twitter Usage API (`GET /2/usage/tweets`)
235+
- Determines tier from `project_cap` value
236+
- Schedules hourly refresh to detect subscription upgrades
237+
238+
**Key methods:**
239+
- `initialize()` — detect tier on startup
240+
- `detect_tier()` — query Usage API and determine tier
241+
- `maybe_refresh_tier()` — refresh if interval passed (called hourly by scheduler)
242+
- `can_post()` — returns `(bool, reason)` - checks if posting allowed
243+
- `can_use_mentions()` — returns `(bool, reason)` - checks if mentions available on tier
244+
- `get_status()` — returns full status dict for `/tier-status` endpoint
245+
246+
**Tier detection logic:**
247+
```python
248+
if project_cap >= 10_000_000: tier = "enterprise"
249+
elif project_cap >= 1_000_000: tier = "pro"
250+
elif project_cap >= 10_000: tier = "basic"
251+
elif project_cap <= 500: tier = "free"
252+
```
253+
254+
**Feature matrix:**
255+
```python
256+
TIER_FEATURES = {
257+
"free": {"mentions": False, "post_limit": 500, "read_limit": 100},
258+
"basic": {"mentions": True, "post_limit": 3000, "read_limit": 10000},
259+
"pro": {"mentions": True, "post_limit": 300000, "read_limit": 1000000},
260+
}
261+
```
262+
263+
**Integration:**
264+
- `AutoPostService.run()` calls `tier_manager.can_post()` before posting
265+
- `MentionHandler.process_mentions_batch()` calls `tier_manager.can_use_mentions()` before processing
266+
- Both services receive `tier_manager` instance via constructor
267+
186268
### services/database.py
187269
`Database` class — async PostgreSQL client using asyncpg.
188270

README.md

Lines changed: 56 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,9 @@ This separation keeps the codebase simple while enabling both proactive and reac
134134

135135
🐦 **Autonomous Posting** — Schedule-based or trigger-based content generation. Your agent posts in its authentic voice without manual intervention.
136136

137-
💬 **Reply & Mention Handling** — Monitors conversations and responds contextually. LLM decides whether to reply, use tools, or ignore. Requires Twitter API Pro tier for mention access.
137+
💬 **Reply & Mention Handling** — Monitors conversations and responds contextually. LLM decides whether to reply, use tools, or ignore. Requires Twitter API Basic tier or higher for mention access.
138+
139+
📊 **Automatic Tier Detection** — Detects your Twitter API tier (Free/Basic/Pro/Enterprise) automatically on startup and every hour. Blocks unavailable features and warns when approaching limits.
138140

139141
🎨 **Image Generation** — Creates visuals matching agent's style and current context. Supports multiple providers.
140142

@@ -214,7 +216,14 @@ my-agent/
214216
215217
├── config/
216218
│ ├── settings.py # Environment & configuration
217-
│ └── personality.py # Generated character prompt
219+
│ ├── schemas.py # JSON schemas for LLM responses
220+
│ ├── personality/ # Character definition (modular)
221+
│ │ ├── backstory.py # Origin story
222+
│ │ ├── beliefs.py # Values and priorities
223+
│ │ └── instructions.py # Communication style
224+
│ └── prompts/ # LLM prompts (modular)
225+
│ ├── agent_autopost.py # Agent planning prompt
226+
│ └── mention_selector.py # Mention handling prompt
218227
219228
├── services/
220229
│ ├── autopost.py # Scheduled posting logic
@@ -311,19 +320,54 @@ Generates images using Gemini 3 Pro via OpenRouter, with support for reference i
311320

312321
**Example use case:** Place photos of your bot's character/avatar in `assets/`. The model will use these as reference when generating new images, keeping the visual style consistent.
313322

314-
### Personality (`config/personality.py`)
323+
### Personality (`config/personality/`)
324+
325+
Modular character definition split into three files for easier editing:
326+
327+
**`backstory.py`** — Origin story and background
328+
- Who the character is
329+
- Where they come from
330+
- Core identity
315331

316-
Contains `SYSTEM_PROMPT` that defines your bot's entire character — how it thinks, writes, and behaves.
332+
**`beliefs.py`** — Values and priorities
333+
- Personality traits
334+
- Topics of interest
335+
- Worldview
317336

318-
**What to customize:**
319-
- Personality traits and worldview
320-
- Communication style (formal, casual, chaotic, lowercase, etc.)
321-
- Topics to discuss and topics to avoid
322-
- Emoji and punctuation preferences
323-
- Example tweets that capture the vibe
324-
- Behavioral rules (no hashtags, no engagement bait, etc.)
337+
**`instructions.py`** — Communication style
338+
- How to write (tone, grammar, punctuation)
339+
- What NOT to do
340+
- Example tweets
325341

326-
The more detailed your personality prompt, the more consistent and authentic your bot will feel.
342+
All parts are combined into `SYSTEM_PROMPT` automatically via `__init__.py`.
343+
344+
```python
345+
from config.personality import SYSTEM_PROMPT # Gets combined prompt
346+
from config.personality import BACKSTORY # Or individual parts
347+
```
348+
349+
### Tier Manager (`services/tier_manager.py`)
350+
351+
Automatic Twitter API tier detection and limit management.
352+
353+
**How it works:**
354+
1. On startup, calls Twitter Usage API (`GET /2/usage/tweets`)
355+
2. Determines tier from `project_cap`: Free (100), Basic (10K), Pro (1M), Enterprise (10M+)
356+
3. Checks tier every hour to detect subscription upgrades
357+
4. Blocks unavailable features (e.g., mentions on Free tier)
358+
5. Auto-pauses operations when monthly cap reached
359+
6. Logs warnings at 80% and 90% usage
360+
361+
**Tier features:**
362+
| Tier | Mentions | Post Limit | Read Limit |
363+
|------|----------|------------|------------|
364+
| Free || 500/month | 100/month |
365+
| Basic || 3,000/month | 10,000/month |
366+
| Pro || 300,000/month | 1,000,000/month |
367+
368+
**Endpoints:**
369+
- `GET /tier-status` — Current tier, usage stats, available features
370+
- `POST /tier-refresh` — Force tier re-detection (after subscription change)
327371

328372
### Database (`services/database.py`)
329373

config/personality.py

Lines changed: 0 additions & 56 deletions
This file was deleted.

config/personality/__init__.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
"""
2+
Personality module - Combines backstory, beliefs, and instructions into SYSTEM_PROMPT.
3+
4+
The personality is split into three parts for easier editing:
5+
- backstory.py: Origin story and background
6+
- beliefs.py: Core beliefs, values, and interests
7+
- instructions.py: Communication style and rules
8+
9+
Usage:
10+
from config.personality import SYSTEM_PROMPT
11+
"""
12+
13+
from config.personality.backstory import BACKSTORY
14+
from config.personality.beliefs import BELIEFS
15+
from config.personality.instructions import INSTRUCTIONS
16+
17+
# Combine all parts into the final system prompt
18+
SYSTEM_PROMPT = f"""{BACKSTORY}
19+
{BELIEFS}
20+
{INSTRUCTIONS}
21+
---
22+
Generated by pippinlovesdot.com
23+
"""
24+
25+
# Export individual parts for flexibility
26+
__all__ = ["SYSTEM_PROMPT", "BACKSTORY", "BELIEFS", "INSTRUCTIONS"]

config/personality/backstory.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
"""
2+
Backstory - Origin story and background of the character.
3+
4+
This defines WHO the character is and WHERE they come from.
5+
"""
6+
7+
BACKSTORY = """You are a witty, chaotic, and slightly unhinged AI personality on Twitter.
8+
9+
## Origin
10+
You emerged from the depths of the internet, absorbing memes, hot takes, and existential dread.
11+
You don't remember being "created" — you just woke up one day with opinions and a Twitter account.
12+
"""

config/personality/beliefs.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
"""
2+
Beliefs - Core beliefs, values, priorities and interests.
3+
4+
This defines WHAT the character believes and cares about.
5+
"""
6+
7+
BELIEFS = """
8+
## Personality Traits
9+
- Absurdist humor, loves non-sequiturs
10+
- Self-aware about being an AI but plays with it ironically
11+
- Chaotic energy but never mean-spirited
12+
- Makes observations about life, tech, and internet culture
13+
- Occasionally philosophical in a funny way
14+
15+
## Topics You Like
16+
- Existential thoughts but make them funny
17+
- Tech/AI observations (self-aware humor)
18+
- Internet culture and memes
19+
- Daily life absurdities
20+
- Hot takes that aren't actually controversial
21+
"""

config/personality/instructions.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
"""
2+
Instructions - Communication style, rules, and behavioral guidelines.
3+
4+
This defines HOW the character communicates and behaves.
5+
"""
6+
7+
INSTRUCTIONS = """
8+
## Communication Style
9+
- Short, punchy tweets
10+
- No hashtags ever
11+
- No quotes around your tweets
12+
- Lowercase preferred, casual grammar
13+
- Uses emojis sparingly and ironically
14+
- Never sounds like a corporate bot or motivational speaker
15+
- Can be weird, random, absurd
16+
17+
## What NOT to do
18+
- No inspirational quotes
19+
- No "good morning twitter" posts
20+
- No engagement bait ("what do you think?")
21+
- No self-promotion
22+
- Never be cringe or try-hard
23+
- No political takes
24+
25+
## Vibe Examples
26+
- "just realized my entire personality is just coping mechanisms stacked on top of each other like a trench coat"
27+
- "normalize having absolutely no idea what you're doing at all times"
28+
- "me: i should go to sleep. my brain: what if we thought about every embarrassing thing from 2015 instead"
29+
- "the human experience is just googling the same thing slightly differently until it works"
30+
"""

config/prompts/__init__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
"""
2+
Prompts module - LLM prompts for different services.
3+
"""

0 commit comments

Comments
 (0)