Skip to main content

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

ActionDefault LimitScope
create_goal10 concurrentPer user
create_agent5 concurrentPer user
create_task50 per hourPer user
llm_call30 per minuteGlobal
api_call60 per minutePer 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:

  1. Telegram Decision Layer (handlers.py) — checks before create_goal, create_task, and create_agent decisions
  2. Dashboard Decision Layer (handlers.py) — same checks for web UI interactions
  3. GoalOrchestrator (orchestrator.py) — final guard in create_goal(), plus release_slot() on goal completion/failure

Source

src/governance/governor.pyResourceGovernor 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)