ソース情報
- リポジトリ
- QianJinGuo/wiki
- ソースの最終更新活動
- 2026年8月26日 17:19
- 検出された SKILL.md の言語
- 英語
- スター
- 1
- フォーク
- 1
インストール方法
デフォルトでは、最初にソースを確認する Prompt が選択されています。直接コマンドに切り替えるか、ローカルコピーをダウンロードすることもできます。
ソースファイルを確認
インストールを決める前に、SKILL.md と SkillsMP に表示されている付属ファイルをお読みください。
メニュー
デフォルトでは、最初にソースを確認する Prompt が選択されています。直接コマンドに切り替えるか、ローカルコピーをダウンロードすることもできます。
インストールを決める前に、SKILL.md と SkillsMP に表示されている付属ファイルをお読みください。
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
直接コマンドでは確認用 Prompt が省略されます。実行前にソースを確認してください。
npx skills add https://github.com/QianJinGuo/wiki --skill llm-provider-resilienceコマンドは1行のまま表示されます。コピー前に横へスクロールして全体を確認してください。
ローカルで確認しますか?SkillsMP が現在取得できるファイルをダウンロードできます。
精选高价值 RSS feeds 扫描,输出到 raw/rss-inbox/ 暂存区。只保留有独立知识深度的 feed(非 digest 类),不再自动入库。包含 rss-inbox-curl-recovery.py 绕过 blogwatcher read-state 漏抓的兜底。
Meta-orchestrator that wires web-content-reviewer, llm-wiki, and wiki-evolver into a single four-phase knowledge pipeline (Triage → Gate → Store → Evolve). Use as the single entry point for all knowledge base operations. Includes a 6-URL-validated user-pasted WeChat URL fast path, three-axis dedup decision matrix (NEW/MERGE/DEDUP), orphan-raw detection protocol, and sibling-subagent race V7 evidence, and a two-variant V6 mid-write fix for matching vs different-slug duplicates.
从 Gmail 中提取 TLDR AI 等 newsletter 的链接,写入 raw/email-inbox/candidates.md,供后续 inbox-screener 评分。只做链接不做评分,与 inbox-screener 配合使用。
SKILL.md を表示中
| name | llm-provider-resilience |
| description | Use when LLM provider flakiness breaks cron jobs or probes. |
| version | 1.0.0 |
| author | Hermes Agent |
| license | MIT |
| platforms | ["macos","linux"] |
| metadata | {"hermes":{"tags":["llm","provider","cron","fallback","reliability","opencode-go"],"related_skills":["cron-job-provider-migration","we-mp-rss-troubleshooting"]}} |
Use when agent cron jobs fail with provider-related errors, when a model provider is intermittently flaky, or when deciding between provider migration vs adding a fallback. Covers the failure taxonomy, the fallback_model config mechanism, and the verified re-run/probe patterns.
| Symptom in cron output | Class | Meaning |
|---|---|---|
TimeoutError: Cron job '<name>' idle for Ns (limit 600s) — last activity: waiting for non-streaming API response | HANG | Request sent, response never arrived. Client has no (or too-long) request timeout. The 600s cron watchdog kills the job. |
RuntimeError: HTTP 429 / 401 / 5xx or Connection error | ERROR / RATE-LIMIT | Provider responded with a failure. |
| Job runs instantly, exit 0, but did nothing useful | FALSE-HEALTH | Script logic doesn't check its own output quantity (e.g. a collection script reporting "30/30 ok" while fetching 0 items). Not a provider issue — a script bug. |
Superseded-path trap (2026-08-21, wechat-article-discover): a cron job can be broken not because its code is wrong but because its collection path was replaced. Retrying it confirms it's still broken (e.g. Done: 30/30 ok, 0 err, new_articles=0 → exit 1, all feeds return 0 in Playwright mode) — and re-enabling it produces a false daily error. Before re-enabling a previously-paused errored job, confirm its path still exists: (a) cookie-renew success (token write, container HTTP 200) does NOT imply discovery success (article-list fetch auth) — the two are separate; (b) check whether the pipeline now ingests through a mirror/other job (e.g. wechat2rss mirror via rss-feed-scan + wechat-inbox-pipeline). If superseded, keep it paused and say why.
Verify the underlying WeChat ban directly (200013 probe, 2026-08-26): to confirm WHETHER the account is still banned before deciding to re-enable wechat-article-discover, don't trust the unblock-probe's silence alone — it exits silently on BOTH ret==200013 (still banned) and probe failure. Run the probe yourself. The container's driver.token module supplies token+cookie; heredoc via docker exec ... <<'PY' is unreliable (empty output), so write the probe to a local file, docker cp it in, then run it:
# /tmp/probe_ret.py — docker cp into we-mp-rss, run with container python
import sys, requests, urllib3; urllib3.disable_warnings()
sys.path.insert(0, '/app')
from driver.token import get
token, cookie = get('token',''), get('cookie','')
url = "https://mp.weixin.qq.com/cgi-bin/appmsgpublish"
params = {"sub":"list","sub_action":"list_ex","begin":0,"count":1,
"fakeid":"MzA3MjgyODI4MzMw","type":"101_1","free_publish_type":1,
"token":token,"lang":"zh_CN","f":"json","ajax":1}
headers = {"User-Agent":"Mozilla/5.0","Referer":"https://mp.weixin.qq.com/"}
cd = {}
for item in cookie.split(";"):
item = item.strip()
if "=" in item:
k,v = item.split("=",1); cd[k.strip()] = v.strip()
try:
r = requests.get(url, params=params, headers=headers, cookies=cd, timeout=15, verify=False)
print("RET=" + (r.json().get(,{}).get()))
Exception e:
( + (e))
docker cp /tmp/probe_ret.py we-mp-rss:/tmp/probe_ret.py
docker exec we-mp-rss /app/env_x86_64/bin/python3 /tmp/probe_ret.py 2>&1 | grep -E "RET=|ERROR="
# RET=200013 → still banned (keep job paused); RET=0 → unblocked (unblock-probe will auto-restore); RET=200003 → session expired
Hang vs error matters for the fix: fallback chains trigger on errors/timeouts/rate-limits, NOT on pure hangs (see below). If the class is HANG, a fallback alone may not help — you also need a client-side request timeout so the hang becomes a timeout the fallback can catch, or accept the 600s watchdog kill + next-tick retry.
fallback_model — automatic backup provider (no migration needed)Config key in ~/.hermes/config.yaml (verified in agent/agent_init.py + agent/agent_runtime_helpers.py, 2026-08-12):
fallback_model: # single dict OR ordered chain
- provider: minimax-cn
model: <model>
- provider: deepseek
model: deepseek-chat
provider + model (config validation rejects entries missing either field).fallback_model covers all jobs. Per-job model/provider overrides in cronjob records take precedence.cronjob(action='run', job_id=...) executes the job immediately and reliably (verified 2026-08-12: 8/8 errored agent jobs re-ran to last_status: ok in one pass, plus a 9th that had re-errored on its schedule).last_status: error on the job list is a HISTORICAL ARTIFACT of the last execution — after a provider outage day, it does not mean the job is broken now. Re-run, then verify the OUTPUT FILE content (~/.hermes/cron/output/<job_id>/<latest>.md) shows real work, not just exit 0.cronjob run 4-6 jobs per tool-call block; jobs re-fire sequentially, so rate-limit collisions are unlikely, but stagger anyway if the provider has frequency limits.cronjob update has NO model overrideTo point all agent cron jobs at a different provider/model, the cronjob tool's update action does NOT expose a model/provider parameter — calling it with just job_id/name is a no-op that leaves provider unchanged (verified 2026-08-19). The dependable path is a direct batch edit of ~/.hermes/cron/jobs.json, then revalidate JSON, then restart the gateway (the scheduler caches job config in memory):
import json
p = '/Users/jinguo/.hermes/cron/jobs.json'
data = json.load(open(p))
for j in data['jobs']:
if j.get('model'): # agent jobs only; no_agent/script jobs have model=None
j['provider'] = 'ark'
j['model'] = 'deepseek-v4-flash'
j['base_url'] = 'https://ark.cn-beijing.volces.com/api/coding/v3'
json.dump(data, open(p, 'w'), ensure_ascii=False, indent=2)
Then python3 -c "import json; json.load(open(p))" to revalidate, back up jobs.json first, and verify the result via cronjob(action='list'). Full workflow detail lives in the cron-job-provider-migration skill (user-owned — recommend hermes curator adopt cron-job-provider-migration to make it curatable).
Real case (2026-08-10): a background verification docker exec we-mp-rss ... do_job(mp=feed) hung 10 HOURS past its signal.alarm(50) — SIGALRM does not reliably interrupt requests stuck in C-level sockets, and the process stayed alive holding the pipe. The scheduled result was lost.
gtimeout 90 docker exec ... (macOS: brew install coreutils for gtimeout), or run it with terminal(background=true) + process(action='kill') fallback.sleep N && probe in a background process and assume the probe terminates on its own.sleep.When a batch of agent-driven crons fails with RuntimeError: Request timed out but no_agent script jobs stay green, suspect provider-wide large-context degradation, not per-job bugs. Verified against ark (deepseek-v4-flash): a small probe (max_tokens=10) returned HTTP 200 in ~2s WHILE the same provider was timing out on the cron's real workload — because agent-driven cron prompts embed the full skills catalog + memory (~130K tokens), and large-context requests are the FIRST thing to degrade during a provider outage window. A green small-probe is NOT evidence of health.
stream:true. If that returns 200 fast, the outage window has passed and jobs will recover on re-run.hermes cron run <job_id> per failed job. Heavy agent jobs exceed 180s foreground — trigger them with terminal(background=true). Output Job is already being fired by the scheduler; not run again means it's mid-run (my earlier trigger queued it), NOT a failed trigger.last_status doesn't refresh until the run completes): grep "Job '<name>' completed successfully" ~/.hermes/logs/agent.log. Heavy ingest jobs (wechat-inbox-pipeline) take 40–60 min across 70+ tool turns with ~99% prompt-cache hit — steady API-call progression in agent.log means healthy, not stuck.Primary (2026-08-19, after migration): ark (base_url: https://ark.cn-beijing.volces.com/api/coding/v3, model deepseek-v4-flash, ~1M context). This is a custom_providers entry, not a built-in. Migrated here 2026-08-19 (main session, all 17 agent cron jobs, and delegation) from opencode-go.
Earlier primary (2026-08): opencode-go / deepseek-v4-flash (base_url: https://opencode.ai/zen/go/v1). Intermittent hangs observed 08-10 (mass), 08-12, 08-13 — transient, self-healing on retry, but noisy. opencode-go is a REAL built-in provider (key OPENCODE_GO_API_KEY), NOT a display alias — don't assume a cron provider label you don't recognize is a normalization artifact; check hermes-agent skill's provider table first.
Fallback candidates with keys already present: minimax-cn (already in config.providers — the zero-config choice), deepseek, anthropic, xiaomi. Check key NAMES only: grep -oE "^[A-Z_]+_(API_KEY|KEY|TOKEN)" ~/.hermes/.env | sort -u.
Observed 08-13 → 08-17: LLM-provider failures recur in WAVES clustered in evening (20:30–23:00) and morning (09:00–10:30) windows, not uniformly. A single wave takes out 3–8 unrelated agent crons simultaneously with the same signature (TimeoutError: Cron job 'X' idle for NNNs or RuntimeError: Connection error). Diagnosis shortcut: count failures by hour in executions.db — if 3+ jobs failed within a 30-min window, it is a provider wave, NOT N independent job bugs:
SELECT substr(started_at,12,5) hm, count(*) FROM executions
WHERE started_at > datetime('now','-24 hours') AND status='failed'
GROUP BY hm ORDER BY hm;
Response: wait for the wave to pass (provider self-heals in 1–2h), then batch re-run all errored jobs (cronjob run, 4–6 per tool-call block). Do NOT chase each job individually during the wave — they will fail again until the provider recovers.
running but the agent is deadDistinct from the HANG class: the execution row stays at running forever (never transitions to completed/failed) because the agent process died mid-run without the executor writing a terminal state. Recurred 3× on wiki/wechat inbox crons (08-13, 08-14).
Three-signal zombie check (all must hold):
ps aux | grep -E '<job_id>' | grep -v grep → empty (no agent subprocess)cat ~/wiki/heartbeat/<job>.last-run vs date (hours old)find <inbox-dir> -name '*.md' -newermt '<round start>' | wc -l → 0Fix: verify dead, then cronjob action=run — do NOT wait for the next scheduled round (a zombie never completes, so the next tick just starts another round on the same unprocessed files). The unprocessed files were never consumed — the re-run picks them up.
fallback_model configured with entries that each have provider+modelcronjob run and verified real work in the output files