Resource Governor
The Resource Governor is a Redis-backed rate limiter that enforces per-user and system-wide resource budgets. It prevents runaway goal creation, excessive LLM calls, and API abuse — while degrading gracefully if Redis is unavailable.
Protected Actions
| Action | Default Limit | Scope |
|---|---|---|
create_goal | 10 concurrent | Per user |
create_agent | 5 concurrent | Per user |
create_task | 50 per hour | Per user |
llm_call | 30 per minute | Global |
api_call | 60 per minute | Per user |
Architecture
Decision Layer (handlers.py)
│
▼
governor.check_allow(action, user_id)
├── compute Redis key (time-bucketed)
├── INCR + check limit
└── return (allowed: bool, reason: str)
│
├── allowed=True → proceed
│ └── governor.record_action(action, user_id)
│
└── allowed=False → return error to user
"Resource limit reached: too many active goals"
Goal completion/failure
│
▼
governor.release_slot(action, user_id) ← decrements concurrent counter
Redis Key Scheme
Keys are time-bucketed to implement sliding windows:
gov:active_goals:{user_id} → concurrent goal count (slot-based)
gov:active_agents:{user_id} → concurrent agent count (slot-based)
gov:tasks_hour:{user_id}:{YYYY-MM-DD-HH} → hourly task count (TTL 7200s)
gov:llm_min:{YYYY-MM-DD-HH-MM} → global LLM call count (TTL 120s)
gov:api_min:{user_id}:{YYYY-MM-DD-HH-MM} → per-user API calls (TTL 120s)
Safe Degradation
If Redis is unavailable, the governor always allows the action:
try:
count = await redis.incr(key)
return count <= limit, ""
except Exception:
return True, "" # Fail open — never block on infrastructure failure
This ensures Redis outages never cause user-visible failures.
Usage Report
report = await governor.get_usage_report(user_id)
# Returns:
{
"active_goals": 3,
"active_agents": 1,
"tasks_this_hour": 12,
"llm_calls_this_minute": 8,
"api_calls_this_minute": 5
}
Configuration
All limits are configurable via src/config.py:
governor_enabled: bool = True
governor_max_goals_per_user: int = 10
governor_max_agents_per_user: int = 5
governor_max_tasks_per_hour: int = 50
governor_max_llm_calls_per_minute: int = 30
governor_max_api_calls_per_minute: int = 60
Or via environment variables:
GOVERNOR_ENABLED=true
GOVERNOR_MAX_GOALS_PER_USER=10
GOVERNOR_MAX_LLM_CALLS_PER_MINUTE=30
Integration Points
The governor is wired into three places:
- Telegram Decision Layer (
handlers.py) — checks beforecreate_goal,create_task, andcreate_agentdecisions - Dashboard Decision Layer (
handlers.py) — same checks for web UI interactions - GoalOrchestrator (
orchestrator.py) — final guard increate_goal(), plusrelease_slot()on goal completion/failure
Source
src/governance/governor.py — ResourceGovernor class
src/governance/__init__.py — exports ResourceGovernor
Initialized in src/main.py and late-wired to handlers:
governor = ResourceGovernor(
redis_url=settings.redis_url,
max_goals=settings.governor_max_goals_per_user,
max_agents=settings.governor_max_agents_per_user,
max_tasks_per_hour=settings.governor_max_tasks_per_hour,
max_llm_per_minute=settings.governor_max_llm_calls_per_minute,
max_api_per_minute=settings.governor_max_api_calls_per_minute,
)
goal_orchestrator.governor = governor
handler = EventHandler(..., governor=governor)