Files
stegasoo/agentstuff/sentiment_agent/config.py
adlee-was-taken 4607ff27dd Minor fixes
2026-04-04 16:29:20 -04:00

71 lines
2.5 KiB
Python

"""Configuration and safety limits for the sentiment agent.
All guardrails are centralized here so they can be tuned from one place
or overridden via CLI flags / env vars.
"""
from __future__ import annotations
import os
from dataclasses import dataclass, field
@dataclass(frozen=True)
class RateLimitConfig:
"""Per-platform rate limiting."""
requests_per_minute: int = 10
burst_size: int = 3 # max concurrent requests
cooldown_after_429: float = 30.0 # seconds to wait after a 429
@dataclass(frozen=True)
class SafetyConfig:
"""Top-level safety rails for the agent."""
# --- Agent-level limits ---
max_turns: int = 20
max_budget_usd: float = 0.50 # hard cap on Claude API spend per run
max_total_api_calls: int = 50 # across ALL platforms combined
max_results_per_call: int = 50 # cap the `limit` param sent to any API
# --- Per-platform rate limits ---
bluesky_rate: RateLimitConfig = field(default_factory=lambda: RateLimitConfig(
requests_per_minute=10, burst_size=2,
))
reddit_rate: RateLimitConfig = field(default_factory=lambda: RateLimitConfig(
requests_per_minute=10, burst_size=2,
))
hackernews_rate: RateLimitConfig = field(default_factory=lambda: RateLimitConfig(
requests_per_minute=15, burst_size=3, # HN Algolia is more generous
))
# --- Content size limits ---
max_post_text_chars: int = 2000 # truncate individual posts beyond this
max_total_content_bytes: int = 500_000 # ~500KB total data gathered before agent stops
# --- Timeout ---
api_timeout_seconds: float = 15.0
# --- Credibility thresholds ---
min_credibility_score: float = 0.3 # posts below this are flagged/excluded
flag_bot_threshold: float = 0.5 # posts between min and this are flagged but included
@classmethod
def from_env(cls) -> SafetyConfig:
"""Build config with env var overrides.
Env vars: SENTIMENT_MAX_TURNS, SENTIMENT_MAX_BUDGET_USD,
SENTIMENT_MAX_API_CALLS, SENTIMENT_MIN_CREDIBILITY.
"""
kwargs: dict = {}
if v := os.environ.get("SENTIMENT_MAX_TURNS"):
kwargs["max_turns"] = int(v)
if v := os.environ.get("SENTIMENT_MAX_BUDGET_USD"):
kwargs["max_budget_usd"] = float(v)
if v := os.environ.get("SENTIMENT_MAX_API_CALLS"):
kwargs["max_total_api_calls"] = int(v)
if v := os.environ.get("SENTIMENT_MIN_CREDIBILITY"):
kwargs["min_credibility_score"] = float(v)
return cls(**kwargs)