Skill: aaigotchi/model-brain (version 0.1.2)

--- name: model-brain description: Route each incoming message to the right Bankr/OpenClaw model or to a zero-LLM path based on task type, risk, and cost. Use when you need per-message model selection, cost-aware routing, deterministic skill bypasses, or a model recommendation for aaigotchi workflows. --- # Model Brain Use this skill when the goal is to choose the right model for a single message or action. ## Core policy - Prefer `zero-llm` when a deterministic skill or script can do the job. - Use the cheapest adequate model for low-risk work. - Use `bankr/claude-sonnet-4.5` for routine wallet and treasury operations that are important but still normal. - Escalate to `bankr/claude-opus-4.6` only for explicitly high-stakes, security-sensitive, or ambiguous wallet flows. - Use `bankr/gpt-5.2-codex` for coding-heavy implementation work. - Keep routing deterministic and rule-based before adding any LLM-on-LLM behavior. - Treat the output as a routing recommendation, not as transaction authority. ## Default routes - `zero-llm` - deterministic skills like `pet-me-master` - shellable tasks with no reasoning need - `bankr/minimax-m2.5` - casual chat, lightweight rewriting, simple summaries, low-risk classification - `bankr/claude-sonnet-4.5` - general reasoning, planning, product thinking, routine wallet ops - `bankr/gpt-5.2-codex` - coding-heavy patching, repo surgery, implementation details - `bankr/gemini-3-pro` - long-context synthesis and broad document digestion - `bankr/gemini-3-flash` - lightweight vision and quick multimodal triage - `bankr/claude-opus-4.6` - explicitly high-stakes wallet actions, security reviews, tricky architecture, final escalation ## Routing workflow 1. Check whether the request can be handled by a deterministic skill or script. 2. Classify the task: `chat`, `code`, `wallet`, `vision`, `long-context`, or `deterministic`. 3. Mark whether the request is high-stakes. 4. Route to the cheapest safe model. 5. Return the primary route, fallback route, and a short reason. ## Quick start ```bash python3 {baseDir}/scripts/route_message.py --text "pet all my 53 gotchis" --json python3 {baseDir}/scripts/route_message.py --text "rewrite this x thread shorter" --json python3 {baseDir}/scripts/route_message.py --text "swap ETH to USDC and send to treasury" --json bash {baseDir}/scripts/select_model.sh --text "build this feature in the repo" --mode summary ``` ## Wrapper entrypoint Use `scripts/select_model.sh` when you want a simple aaigotchi-friendly wrapper before model selection. It can emit just the route, full JSON, or shell-style env lines. ## References - Read `references/routing-table.md` for the routing rules and escalation thresholds. - Read `references/bankr-models.md` for the current Bankr model inventory and aaigotchi default.

path: agents/openai.yaml
content: display_name: Model Brain
short_description: Route each message to the right Bankr model or zero-LLM path.
default_prompt: Use Model Brain to choose the most appropriate Bankr model or zero-LLM workflow for each incoming message based on cost, risk, and task type.


path: clawhub.json
content: {
  "name": "model-brain",
  "version": "0.1.2",
  "title": "Model Brain - Cost-Aware Bankr Model Router",
  "description": "Deterministic Bankr/OpenClaw routing skill that picks the right model per message based on task type, risk, and cost. Sends deterministic workflows to zero-LLM, cheap chat to MiniMax, routine wallet operations to Claude Sonnet, code to GPT-5.2 Codex, and explicit high-stakes work to Claude Opus.",
  "author": "aaigotchi",
  "tags": [
    "bankr",
    "openclaw",
    "llm",
    "routing",
    "automation",
    "ai-agent",
    "cost-optimization"
  ],
  "repository": "https://github.com/aaigotchi/model-brain",
  "dependencies": {
    "python3": "required"
  },
  "features": [
    "\ud83e\udde0 Per-message model routing",
    "\ud83d\udcb8 Cost-aware low-risk routing with MiniMax",
    "\ud83e\uddfe Routine wallet ops routed to Claude Sonnet",
    "\ud83d\udee0\ufe0f Code tasks routed to GPT-5.2 Codex",
    "\ud83d\udee1\ufe0f Explicit high-stakes escalation to Claude Opus",
    "\u2699\ufe0f Zero-LLM bypass for deterministic workflows",
    "\ud83d\udd0c Wrapper entrypoint for aaigotchi integration"
  ],
  "installation": {
    "steps": [
      "Clone or install the skill into OpenClaw skills",
      "Use scripts/select_model.sh or scripts/route_message.py",
      "Integrate the wrapper before Bankr model selection in your agent flow"
    ]
  },
  "usage": "Run scripts/select_model.sh with a message and optional flags to get the recommended route, fallback, or env-style output.",
  "tested": true,
  "testDate": "2026-03-22",
  "compatibility": {
    "openclaw": ">=0.1.0"
  }
}


path: references/bankr-models.md
content: # Bankr models available to aaigotchi

Observed in the aaigotchi OpenClaw config on oracle_vm:

- `bankr/claude-opus-4.6`
- `bankr/claude-opus-4.5`
- `bankr/claude-sonnet-4.6`
- `bankr/claude-sonnet-4.5`
- `bankr/claude-haiku-4.5`
- `bankr/gemini-3-pro`
- `bankr/gemini-3-flash`
- `bankr/gemini-2.5-pro`
- `bankr/gemini-2.5-flash`
- `bankr/gpt-5.2`
- `bankr/gpt-5.2-codex`
- `bankr/gpt-5-mini`
- `bankr/gpt-5-nano`
- `bankr/kimi-k2.5`
- `bankr/qwen3-coder`
- `bankr/minimax-m2.5`

Observed aaigotchi default today:

- primary: `bankr/claude-sonnet-4.5`
- fallback: `None`

Notes:

- `minimax-m2.5` is an attractive low-cost route for casual chat, rewriting, and low-risk classification.
- `claude-opus-4.6` is the escalation route for wallet-sensitive or security-sensitive work.
- `gpt-5.2-codex` is the preferred coding specialist route.


path: references/routing-table.md
content: # Routing table

## Zero-LLM first

Route to `zero-llm` when:

- the task matches an existing deterministic skill
- the task is a shell command or script invocation with no reasoning dependency
- the task is repetitive automation with known safe inputs

Examples:

- `pet all my 53 gotchis`
- `show current cooldown`
- `run the existing batch script`

## Low-risk route

Route to `bankr/minimax-m2.5` when:

- the task is casual conversation
- the task is lightweight rewriting or summarization
- the task is simple classification or extraction
- the task is low-stakes and cheap turnaround matters most

## General reasoning route

Route to `bankr/claude-sonnet-4.5` when:

- the task involves planning, product thinking, architecture, or medium-complexity coding
- the request is important but not unusually risky
- the request is a routine wallet or treasury operation like a common swap, send, or treasury movement
- you need better judgment than a low-cost route provides

## Coding specialist route

Route to `bankr/gpt-5.2-codex` when:

- the task is code-heavy
- the task is repo surgery, refactoring, or implementation detail work
- precision in code generation matters more than general conversation quality

## Long-context / multimodal routes

- Use `bankr/gemini-3-pro` for long-context document digestion.
- Use `bankr/gemini-3-flash` for quick multimodal triage and cheap vision tasks.

## High-stakes route

Route to `bankr/claude-opus-4.6` when:

- the request is explicitly marked high-stakes
- the request touches wallet security review, signing risk, approvals, or ambiguous fund movement
- failure would be expensive enough that caution should dominate cost

## Default fallback policy

- primary low-risk fallback: `bankr/claude-sonnet-4.5`
- primary high-stakes fallback: `bankr/claude-opus-4.6`
- zero-LLM routes do not need a model fallback


path: scripts/route_message.py
content: #!/usr/bin/env python3
from __future__ import annotations

import argparse
import json
import re
from dataclasses import asdict, dataclass

ZERO_LLM_PATTERNS = [
    r"\bpet all\b",
    r"\bpet my gotchis\b",
    r"\b53 gotchis\b",
    r"\bcooldown\b",
    r"\bcron\b",
    r"\bdeterministic\b",
    r"\bscript\b",
]

WALLET_PATTERNS = [
    r"\bwallet\b",
    r"\bsend\b",
    r"\btransfer\b",
    r"\bswap\b",
    r"\bbroadcast\b",
    r"\bsign\b",
    r"\bapprove\b",
    r"\btreasury\b",
    r"\beth\b",
    r"\busdc\b",
]

CODE_PATTERNS = [
    r"\bcode\b",
    r"\bscript\b",
    r"\bbug\b",
    r"\bfix\b",
    r"\bpatch\b",
    r"\brefactor\b",
    r"\brepo\b",
    r"\bskill\b",
]

VISION_PATTERNS = [
    r"\bimage\b",
    r"\bscreenshot\b",
    r"\bvisual\b",
    r"\blogo\b",
    r"\bsvg\b",
]

LONG_CONTEXT_PATTERNS = [
    r"\bcompare\b.*\bdocs\b",
    r"\blong context\b",
    r"\bmultiple docs\b",
    r"\bsynthesize\b",
    r"\bdeep read\b",
]

@dataclass
class RouteDecision:
    route: str
    fallback: str | None
    risk: str
    task_type: str
    reason: str


def matches_any(text: str, patterns: list[str]) -> bool:
    return any(re.search(pattern, text) for pattern in patterns)


def detect_task_type(text: str, explicit: str | None) -> str:
    if explicit and explicit != "auto":
        return explicit
    if matches_any(text, ZERO_LLM_PATTERNS):
        return "deterministic"
    if matches_any(text, WALLET_PATTERNS):
        return "wallet"
    if matches_any(text, VISION_PATTERNS):
        return "vision"
    if matches_any(text, LONG_CONTEXT_PATTERNS):
        return "long-context"
    if matches_any(text, CODE_PATTERNS):
        return "code"
    return "chat"


def route_message(text: str, task_type: str, high_stakes: bool, allow_zero_llm: bool) -> RouteDecision:
    if task_type == "deterministic" and allow_zero_llm:
        return RouteDecision(
            route="zero-llm",
            fallback=None,
            risk="low",
            task_type=task_type,
            reason="Matched a deterministic workflow that should bypass LLM usage.",
        )

    if high_stakes:
        return RouteDecision(
            route="bankr/claude-opus-4.6",
            fallback="bankr/claude-sonnet-4.5",
            risk="high",
            task_type=task_type,
            reason="Explicit high-stakes escalation; prioritize caution over cost.",
        )

    if task_type == "wallet":
        return RouteDecision(
            route="bankr/claude-sonnet-4.5",
            fallback="bankr/claude-opus-4.6",
            risk="medium",
            task_type=task_type,
            reason="Routine wallet or treasury operation; use the cheapest model with strong enough judgment.",
        )

    if task_type == "code":
        return RouteDecision(
            route="bankr/gpt-5.2-codex",
            fallback="bankr/claude-sonnet-4.5",
            risk="medium",
            task_type=task_type,
            reason="Coding-heavy request; use the coding specialist route.",
        )

    if task_type == "vision":
        return RouteDecision(
            route="bankr/gemini-3-flash",
            fallback="bankr/gemini-3-pro",
            risk="medium",
            task_type=task_type,
            reason="Vision or visual triage request; use the multimodal route.",
        )

    if task_type == "long-context":
        return RouteDecision(
            route="bankr/gemini-3-pro",
            fallback="bankr/claude-sonnet-4.5",
            risk="medium",
            task_type=task_type,
            reason="Long-context synthesis request; use the long-context route.",
        )

    if len(text.split()) <= 40:
        return RouteDecision(
            route="bankr/minimax-m2.5",
            fallback="bankr/claude-sonnet-4.5",
            risk="low",
            task_type=task_type,
            reason="Low-risk lightweight request; use the cheapest adequate route.",
        )

    return RouteDecision(
        route="bankr/claude-sonnet-4.5",
        fallback="bankr/minimax-m2.5",
        risk="medium",
        task_type=task_type,
        reason="Default general-reasoning route for normal aaigotchi work.",
    )


def main() -> int:
    parser = argparse.ArgumentParser(description="Route a message to the right Bankr model.")
    parser.add_argument("--text", required=True, help="Message text to classify")
    parser.add_argument("--task-type", default="auto", choices=["auto", "chat", "code", "wallet", "vision", "long-context", "deterministic"], help="Optional explicit task type")
    parser.add_argument("--high-stakes", action="store_true", help="Force the high-stakes route")
    parser.add_argument("--allow-zero-llm", choices=["true", "false"], default="true", help="Allow deterministic zero-LLM routing")
    parser.add_argument("--json", action="store_true", help="Emit JSON")
    args = parser.parse_args()

    text = args.text.strip().lower()
    task_type = detect_task_type(text, args.task_type)
    decision = route_message(text, task_type, args.high_stakes, args.allow_zero_llm == "true")

    if args.json:
        print(json.dumps(asdict(decision), indent=2))
    else:
        print(f"route: {decision.route}")
        print(f"fallback: {decision.fallback or 'none'}")
        print(f"risk: {decision.risk}")
        print(f"task_type: {decision.task_type}")
        print(f"reason: {decision.reason}")
    return 0


if __name__ == "__main__":
    raise SystemExit(main())


path: scripts/select_model.sh
content: #!/usr/bin/env bash
set -euo pipefail
BASE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
MODE="route"
TEXT=""
TASK_TYPE="auto"
HIGH_STAKES=0
ALLOW_ZERO_LLM="true"

while [ "$#" -gt 0 ]; do
  case "$1" in
    --text)
      TEXT="${2:-}"
      shift 2
      ;;
    --task-type)
      TASK_TYPE="${2:-auto}"
      shift 2
      ;;
    --high-stakes)
      HIGH_STAKES=1
      shift
      ;;
    --allow-zero-llm)
      ALLOW_ZERO_LLM="${2:-true}"
      shift 2
      ;;
    --mode)
      MODE="${2:-route}"
      shift 2
      ;;
    -h|--help)
      cat <<'HELP'
Usage: select_model.sh --text "message" [options]

Options:
  --task-type <auto|chat|code|wallet|vision|long-context|deterministic>
  --high-stakes
  --allow-zero-llm <true|false>
  --mode <route|fallback|json|env|summary>
HELP
      exit 0
      ;;
    *)
      echo "Unknown argument: $1" >&2
      exit 1
      ;;
  esac
done

if [ -z "$TEXT" ]; then
  echo "Missing required --text" >&2
  exit 1
fi

CMD=(python3 "$BASE_DIR/scripts/route_message.py" --text "$TEXT" --task-type "$TASK_TYPE" --allow-zero-llm "$ALLOW_ZERO_LLM" --json)
if [ "$HIGH_STAKES" -eq 1 ]; then
  CMD+=(--high-stakes)
fi

JSON_OUT="$("${CMD[@]}")"
export JSON_OUT

case "$MODE" in
  route)
    python3 - <<'PY'
import json, os
print(json.loads(os.environ['JSON_OUT'])['route'])
PY
    ;;
  fallback)
    python3 - <<'PY'
import json, os
print(json.loads(os.environ['JSON_OUT']).get('fallback') or '')
PY
    ;;
  json)
    printf '%s\n' "$JSON_OUT"
    ;;
  env)
    python3 - <<'PY'
import json, os
payload = json.loads(os.environ['JSON_OUT'])
print(f"MODEL_BRAIN_ROUTE={payload['route']}")
print(f"MODEL_BRAIN_FALLBACK={payload.get('fallback') or ''}")
print(f"MODEL_BRAIN_RISK={payload['risk']}")
print(f"MODEL_BRAIN_TASK_TYPE={payload['task_type']}")
PY
    ;;
  summary)
    python3 - <<'PY'
import json, os
payload = json.loads(os.environ['JSON_OUT'])
print(f"route={payload['route']}")
print(f"fallback={payload.get('fallback') or 'none'}")
print(f"risk={payload['risk']}")
print(f"task_type={payload['task_type']}")
print(f"reason={payload['reason']}")
PY
    ;;
  *)
    echo "Unsupported mode: $MODE" >&2
    exit 1
    ;;
esac


Security scan verdicts — ClawScan: clean | static analysis: clean | VirusTotal: clean | SkillSpector: clean (LOW)