grisuno/lazyown/loop-llm
Claude Code and agent skill by grisuno/lazyown
- community
- ext:[{"type":"plugin","description":"Custom plugin integration"}]
Checking that the SKILL.md file is still in the repository.
Add a new LLM leg to LazyOwn loop mode (auto_loop/lazy_loop) in one shot. Knows the pool-member contract, the factory spec-prefix rule, priority/backfill semantics and the validation tests.
Install
npx vskill@latest install grisuno/lazyown/loop-llmSemi-extensibleMentions customization, but needs skill-specific knowledge. Read the extensible skills standard
SKILL.md
/loop-llm
Add one LLM leg to loop mode so auto_loop / lazy_loop fail over through it. No iteration: follow the contract, wire the leg, update the defaults, run the self-check.
Usage
Step 1 — The contract (read before touching code)
Loop mode asks the pool, never a backend directly:
modules/lazy_loop.pyLlmPool.DEFAULT_MEMBERS— the 5 legs, each
{"name": <unique-id>, "model": "<prefix>:<model-id>", "priority": <int>}. Higher priority tries first; equal priority round-robins via the rr cursor in sessions/lazy/llm_pool.json.
LlmPool.complete()resolves each member'smodelspec through
modules.llm_factory.complete(spec, prompt, max_tokens).
complete()accepts abackend:prefix. Registered factory backends
(SUPPORTED_BACKENDS) plus leg-only prefixes (toposwarm:, pi:) are valid. Leg-only prefixes are the correct choice for agent CLIs and routers: they need NO entry in SUPPORTED_BACKENDS, NO payload-schema key, and NO change to test_llm_contract.py (which pins the canonical backend tuple).
- Dead legs MUST raise
RuntimeError(never return""on outage):
the pool catches it, trips the shared health breaker (modules/llm_pool.py, persisted at sessions/lazy/llm_health.json), and fails over to the next member. Empty prompt returns "" without calling anything.
_seed_defaults()backfills newDEFAULT_MEMBERSby name into
existing sessions/lazy/llm_pool.json files, so operators gain the leg without losing their edits. Never rename an existing member.
- Subprocess legs use list-form
argvwithshell=False(see
core/safe_subprocess.py). Secrets never travel as placeholders or argv; keyless local legs need no credentials at all.
Current legs (name, model, priority):
| name | model | priority | notes | |
|---|---|---|---|---|
llamacpp-local | llamacpp:local-model | 10 | raw HTTP to llama.cpp, fastest local | |
groq-cloud | groq:llama-3.3-70b-versatile | 7 | needs api_key | |
pi-qwen | pi:local-model | 6 | pi CLI agent on local Qwen 27B, keyless, slow | |
ollama-local | ollama:deepseek-r1:1.5b | 5 | keyless, small | |
toposwarm-agent | toposwarm:router | 1 | agentic router, keyless, last resort |
Step 2 — Wire the leg (worked example: pi:)
- In
modules/llm_factory.pyadd a private completer following
_pi_complete(model, prompt, max_tokens): resolve the binary with shutil.which, run list-form subprocess.run(..., shell=False) with a bounded timeout (LAZYOWN_PI_TIMEOUT, default 300s for CPU-served 27B models), raise RuntimeError on missing binary, timeout, non-zero exit, or empty stdout.
- Register the prefix in BOTH
complete()andstream_complete()
spec allowlists. Streaming legs may simply delegate to complete() (the pool falls back automatically when no streamer exists).
- Update the
complete()docstring leg list. - Constants live next to the other backend defaults:
PI_PROVIDER_ID = "local-qwen" (must match the provider id that scripts/pi_qwen_setup.sh registers in ~/.pi/agent/models.json), PI_DEFAULT_MODEL = "local-model".
- The leg needs NO new
payload.json/params/*.yamlkey: it reuses
llamacpp_host + llm_model_llamacpp. After assign llamacpp_host <url>, re-run the pi_qwen addon once so the setup script re-registers the endpoint URL.
Step 3 — Register the pool member
Append to LlmPool.DEFAULT_MEMBERS in modules/lazy_loop.py:
Keep priority sorted descending. Placement guidance: raw local endpoints first (fast), cloud second (needs key), agent CLIs third (smart but slow: minutes per turn on CPU), tiny/embedded next, routers last. Operators reorder live with set_priority() or by editing sessions/lazy/llm_pool.json.
Step 4 — Tests (all must pass before shipping)
Rules:
- New legs ship
tests/test_<leg>_leg.pywith mocked subprocess:
missing binary, non-zero exit, empty reply, timeout, model passthrough, case-insensitive prefix, empty-prompt short-circuit, stream fallback, and one pool-level test driving LlmPool.complete(..., members=[...]).
tests/test_intel_fusion.py::test_llm_defaults_seededpins the full
member table: extend it, never weaken it.
- Never add the leg id to
SUPPORTED_BACKENDS: the canonical-backend
contract test pins that tuple and leg-only prefixes intentionally bypass it (same as toposwarm:).
Step 5 — Verify live
Expect the exact reply. First call warms the model: allow minutes on CPU. Then run one loop-mode turn bound to the leg and confirm the pi-qwen row in the usage ledger (sessions/lazy/llm_usage.json).
Security
- Security scanPassed, 90 of 100Pattern checks on the skill's files.
- Model reviewPassed
Quality evaluation
- Task evaluationNot runNo evaluation yet. Run one in Skill Studio.
Source
- SKILL.md in the repositoryCheckingskills/loop-llm/SKILL.md
Popularity
- 7-day trend score
- 0
Not refreshed yet.
Extension points
pluginCustom plugin integration
Works with
Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.
- Claude Code
- Cursor
- GitHub Copilot
- Windsurf
- Codex
- Gemini CLI
- Cline
- Amp
- Roo Code
- Goose
- Continue
- Kilo Code
- Junie
- Trae
- OpenHands
- Qwen Code
- AI Agent
- Tabnine Chat
- Sourcegraph Cody
- Amazon Q
- Firebase Genkit
- Sweep
- Devin
- Phind
- Mentat
- Claude Desktop
- Aider
- GPT Pilot
- Plandex
- bolt.new
- v0
- Replit Agent
- Anse
- TypingMind
- BetterChatGPT
- LibreChat
- Warp AI
- Pieces
- Fig AI
Embed badge
[](https://verified-skill.com/skills/grisuno/lazyown/loop-llm)