Files
timmy-home/uniwizard/job_profiles_design.md

9.4 KiB

Job Profiles Design Document

[ROUTING] Streamline local Timmy automation context per job

Issue: timmy-config #90
Author: Timmy (AI Agent)
Date: 2026-03-30
Status: Design Complete - Ready for Implementation


Executive Summary

Local Hermes sessions experience context thrashing when all 40 tools (~9,261 tokens of schema) are loaded for every job. This design introduces job-specific toolset profiles that narrow the tool surface based on task type, achieving 73-91% token reduction and preventing the "loop or thrash" behavior observed in long-running automation.


Problem Statement

When toolsets: [all] is enabled (current default in ~/.hermes/config.yaml), every AIAgent instantiation loads:

  • 40 tools across 12+ toolsets
  • ~9,261 tokens of JSON schema
  • Full browser automation (12 tools)
  • Vision, image generation, TTS, MoA reasoning
  • All MCP servers (Morrowind, etc.)

For a simple cron job checking Gitea issues, this is massive overkill. The LLM:

  1. Sees too many options
  2. Hallucinates tool calls that aren't needed
  3. Gets confused about which tool to use
  4. Loops trying different approaches

Solution Overview

Leverage the existing enabled_toolsets parameter in AIAgent.__init__() to create job profiles—pre-defined toolset combinations optimized for specific automation types.

Key Design Decisions

Decision Rationale
Use YAML profiles, not code Easy to extend without deployment
Map to existing toolsets No changes needed to Hermes core
5 base profiles Covers 95% of automation needs
Token estimates in comments Helps users understand trade-offs

Profile Specifications

1. CODE-WORK Profile

Purpose: Software development, git operations, code review

toolsets: [terminal, file]
tools_enabled: 6
token_estimate: "~2,194 tokens"
token_savings: "~76%"

Included Tools:

  • terminal, process - git, builds, shell commands
  • read_file, search_files, write_file, patch

Use Cases:

  • Automated code review
  • Refactoring tasks
  • Build and test automation
  • Git branch management

Not Included:

  • Web search (assumes local docs/code)
  • Browser automation
  • Vision/image generation

2. RESEARCH Profile

Purpose: Information gathering, documentation lookup, analysis

toolsets: [web, browser, file]
tools_enabled: 15
token_estimate: "~2,518 tokens"
token_savings: "~73%"

Included Tools:

  • web_search, web_extract - quick lookups
  • Full browser suite (12 tools) - deep research
  • File tools - save findings, read local docs

Use Cases:

  • API documentation research
  • Competitive analysis
  • Fact-checking reports
  • Technical due diligence

Not Included:

  • Terminal (prevents accidental local changes)
  • Vision/image generation

3. TRIAGE Profile

Purpose: Read-only status checking, issue monitoring, health checks

toolsets: [terminal, file]
tools_enabled: 6
token_estimate: "~2,194 tokens"
token_savings: "~76%"
read_only: true  # enforced via prompt

Included Tools:

  • terminal - curl for Gitea API, status commands
  • read_file, search_files - log analysis, config inspection

Critical Note on Write Safety: The file toolset includes write_file and patch. For truly read-only triage, the job prompt MUST include:

[SYSTEM: This is a READ-ONLY triage job. Only use read_file and search_files.
Do NOT use write_file, patch, or terminal commands that modify state.]

Future Enhancement: Consider adding a disabled_tools parameter to AIAgent for granular control without creating new toolsets.

Use Cases:

  • Gitea issue triage
  • CI/CD status monitoring
  • Log file analysis
  • System health checks

4. CREATIVE Profile

Purpose: Content creation, writing, editing

toolsets: [file, web]
tools_enabled: 4
token_estimate: "~1,185 tokens"
token_savings: "~87%"

Included Tools:

  • read_file, search_files, write_file, patch
  • web_search, web_extract - references, fact-checking

Use Cases:

  • Documentation writing
  • Content generation
  • Editing and proofreading
  • Newsletter/article composition

Not Included:

  • Terminal (no system access needed)
  • Browser (web_extract sufficient for text)
  • Vision/image generation

5. OPS Profile

Purpose: System operations, maintenance, deployment

toolsets: [terminal, process, file]
tools_enabled: 6
token_estimate: "~2,194 tokens"
token_savings: "~76%"

Included Tools:

  • terminal, process - service management, background tasks
  • File tools - config editing, log inspection

Use Cases:

  • Server maintenance
  • Log rotation
  • Service restart
  • Deployment automation
  • Docker container management

How Toolset Filtering Works

The Hermes harness already supports this via AIAgent.__init__:

def __init__(
    self,
    ...
    enabled_toolsets: List[str] = None,   # Only these toolsets
    disabled_toolsets: List[str] = None,  # Exclude these toolsets
    ...
):

The filtering happens in model_tools.get_tool_definitions():

def get_tool_definitions(
    enabled_toolsets: List[str] = None,
    disabled_toolsets: List[str] = None,
    ...
) -> List[Dict[str, Any]]:
    # 1. Resolve toolsets to tool names via toolsets.resolve_toolset()
    # 2. Filter by availability (check_fn for each tool)
    # 3. Return OpenAI-format tool definitions

Current Cron Usage (Line 423-443 in cron/scheduler.py):

agent = AIAgent(
    model=turn_route["model"],
    ...
    disabled_toolsets=["cronjob", "messaging", "clarify"],  # Hardcoded
    quiet_mode=True,
    platform="cron",
    ...
)

Wiring into Cron Dispatch

Step 1: Load Profile

import yaml
from pathlib import Path

def load_job_profile(profile_name: str) -> dict:
    """Load a job profile from ~/.timmy/uniwizard/job_profiles.yaml"""
    profile_path = Path.home() / ".timmy/uniwizard/job_profiles.yaml"
    with open(profile_path) as f:
        config = yaml.safe_load(f)
    profiles = config.get("profiles", {})
    return profiles.get(profile_name, profiles.get("minimal", {"toolsets": ["file"]}))

Step 2: Modify run_job() in cron/scheduler.py

def run_job(job: dict) -> tuple[bool, str, str, Optional[str]]:
    ...
    # Load job profile (default to minimal if not specified)
    profile_name = job.get("tool_profile", "minimal")
    profile = load_job_profile(profile_name)
    
    # Build toolset filter
    enabled_toolsets = profile.get("toolsets", ["file"])
    disabled_toolsets = profile.get("disabled_toolsets", ["cronjob", "messaging", "clarify"])
    
    agent = AIAgent(
        model=turn_route["model"],
        ...
        enabled_toolsets=enabled_toolsets,      # NEW
        disabled_toolsets=disabled_toolsets,    # MODIFIED
        quiet_mode=True,
        platform="cron",
        ...
    )

Step 3: Update Job Definition Format

Add tool_profile field to ~/.hermes/cron/jobs.yaml:

jobs:
  - id: daily-issue-triage
    name: "Triage Gitea Issues"
    schedule: "0 9 * * *"
    tool_profile: triage    # <-- NEW
    prompt: "Check timmy-config repo for new issues..."
    deliver: telegram

  - id: weekly-docs-review
    name: "Review Documentation"
    schedule: "0 10 * * 1"
    tool_profile: creative  # <-- NEW
    prompt: "Review and improve README files..."

Token Savings Summary

Profile Tools Tokens Savings
Full (all) 40 ~9,261 0%
code-work 6 ~2,194 -76%
research 15 ~2,518 -73%
triage 6 ~2,194 -76%
creative 4 ~1,185 -87%
ops 6 ~2,194 -76%
minimal 4 ~800 -91%

Benefits:

  1. Faster prompt processing (less context to scan)
  2. Reduced API costs (fewer input tokens)
  3. More focused tool selection (less confusion)
  4. Faster tool calls (smaller schema to parse)

Migration Path

Phase 1: Deploy Profiles (This PR)

  • Create ~/.timmy/uniwizard/job_profiles.yaml
  • Create design document
  • Post Gitea issue comment

Phase 2: Cron Integration (Next PR)

  • Modify cron/scheduler.py to load profiles
  • Add tool_profile field to job schema
  • Update existing jobs to use appropriate profiles

Phase 3: CLI Integration (Future)

  • Add /profile slash command to switch profiles
  • Show active profile in CLI banner
  • Profile-specific skills loading

Files Changed

File Purpose
~/.timmy/uniwizard/job_profiles.yaml Profile definitions
~/.timmy/uniwizard/job_profiles_design.md This design document

Open Questions

  1. Should we add disabled_tools parameter to AIAgent?

    • Would enable true read-only triage without prompt hacks
    • Requires changes to model_tools.py and run_agent.py
  2. Should profiles include model recommendations?

    • e.g., recommended_model: claude-opus-4 for code-work
    • Could help route simple jobs to cheaper models
  3. Should we support profile composition?

    • e.g., profiles: [ops, web] for ops jobs that need web lookup

References

  • Hermes toolset system: ~/.hermes/hermes-agent/toolsets.py
  • Tool filtering logic: ~/.hermes/hermes-agent/model_tools.py:get_tool_definitions()
  • Cron scheduler: ~/.hermes/hermes-agent/cron/scheduler.py:run_job()
  • AIAgent initialization: ~/.hermes/hermes-agent/run_agent.py:AIAgent.__init__()