MemClaw / docs
Skill Factory

Lifecycle & governance

The skill status model, who can set each status, the six auto-promotion gates, the Sentinel security scan, and the Skills Inbox review flow.

Every document in the skills collection carries a status. When Skill Factory is enabled, that status governs both who can write it and whether agents can see it — only active skills are ever delivered. This page is the reference for how a skill moves through those states.

All of the behavior below is gated by skills_factory.enabled in the tenant's org settings. With it false, writes are not status-defaulted, no gates run, and every stored skill is visible — see the overview.

Statuses

StatusMeaningWho can set it
candidateFreshly minted by Forge; never visible to agents. Awaiting auto-gate evaluation.Forge only (internal)
stagedPassed the gates (or written directly by an agent); pending review in the Skills Inbox.Default for any agent/admin op=write
activeApproved and delivered to agents (pull and push).Admin direct-write, or Inbox approve
rejectedAn operator declined it; its cluster fingerprint is poison-flagged for a cool-off window.System (Inbox reject)
quarantinedThe Sentinel scan flagged a critical finding; held out of delivery.System (Sentinel / Inbox)
staleThe skill it was meant to update changed underneath it (content-hash drift); must be re-revised.System (lifecycle)
deprecatedSuperseded or retired.System (lifecycle)

The write path enforces this with three rules (skill_lifecycle.py):

  • A regular agent op=write always lands as staged — an agent cannot self-publish an active skill.
  • Only an admin may write active directly.
  • candidate is Forge-only, and rejected / quarantined / stale / deprecated are system-only — an agent or operator cannot hand-set them on a write, so a skill can't be silently retired or hidden from review.

Authoring writes: validation

A op=write collection='skills' is validated and normalized before it lands:

  • Required fields and a filesystem-safe slug (^[a-z0-9][a-z0-9._-]{0,99}$).
  • description length cap — default 160 bytes, configurable via skills_factory.description_max_bytes.
  • Body cap — 40,000 bytes.
  • Sentinel pre-scan (below) runs synchronously; a critical finding rejects the write.
  • Hash-binding — an update (kind='update') must carry the target_content_hash of the live skill it revises; if that skill has since changed, the write is rejected so you re-base on current content.

The six auto-gates

Forge candidates don't reach the Inbox until they clear all six gates (re-checked at promotion time, because the world moves between Forge's write and the lifecycle worker's run). The evaluator fails closed — a gate it can't confidently evaluate (missing inputs) counts as a failure, so an unverifiable candidate is held rather than promoted.

GateCheckDefault threshold
G1 · volumeorigin.cluster_size ≥ min_cluster_sizemin_cluster_size = 3
G2 · diversityorigin.distinct_agents ≥ min_distinct_agentsmin_distinct_agents = 3
G3 · freshnesscluster window end within N days of nowfreshness_window_days = 14
G4 · poisonthe cluster fingerprint is not in the reject poison table
G5 · scandata.scan.state == 'clean' (no Sentinel quarantine)
G6 · hash_bindingfor kind='update', target.target_content_hash still matches the live skill

The volume, diversity, and freshness thresholds are tunable per tenant under skills_factory.forge.*. A candidate that passes all six is promoted candidate → staged and appears in the Inbox.

Sentinel scan

Sentinel is MemClaw's content-safety scan for skills (prompt-injection and PII patterns). It runs synchronously on every write and again before an Inbox approval:

  • state = 'clean' and critical = 0 → the write proceeds (and G5 can pass).
  • A critical finding → the write is rejected (422) on authoring, or the skill is moved to quarantined in the lifecycle.
  • Findings are bucketed critical / warn / info; only critical blocks.

Sentinel is a gate, not a guarantee — treat warn/info findings as review signals in the Inbox, not noise.

The Skills Inbox (human review)

Staged skills surface in the Skills Inbox — the human-in-the-loop review queue. Its endpoints live under POST/GET /api/v1/skills-inbox/ and require an admin; every endpoint 4xx's with SKILLS_FACTORY_DISABLED if the feature isn't enabled for the tenant.

ActionEndpointEffect
ListGET /api/v1/skills-inbox/Staged skills for the tenant (filter by fleet_id); capped by skills_factory.inbox_max_pending.
ApprovePOST /api/v1/skills-inbox/{slug}/approveRe-scans, then staged → active — the skill goes live.
RejectPOST /api/v1/skills-inbox/{slug}/rejectstaged → rejected and poison-flags the fingerprint for a cool-off (skills_factory.rejection_cooloff_days) so Forge won't immediately re-mint it.
QuarantinePOST /api/v1/skills-inbox/{slug}/quarantinestaged → quarantined — held for investigation.
DeferPOST /api/v1/skills-inbox/{slug}/deferLeaves it staged; stamps a deferred_at marker to push it down the queue.
EditPOST /api/v1/skills-inbox/{slug}/editRevise content / description / summary; re-hashes and re-scans; stays staged for a fresh decision.

Skipping human review

For tenants that want Forge to ship without a human in the loop, set skills_factory.sentinel.auto_promote_clean = true. A candidate that passes all six gates and scans clean is then promoted straight to active, bypassing the Inbox. It defaults to false — review-first.

Configuration reference

All keys live under skills_factory in the tenant's org settings:

KeyDefaultPurpose
enabledfalseMaster opt-in. Off = legacy no-op (no gating, no Forge, no Inbox).
description_max_bytes160Cap on a skill's description.
inbox_max_pendingCap on the number of staged skills the Inbox lists.
rejection_cooloff_daysPoison-table cool-off after a reject.
forge.cron_interval_hours6Informational; your external scheduler must match (see OpenClaw / operator setup).
forge.min_cluster_size3G1 volume threshold.
forge.min_distinct_agents3G2 diversity threshold.
sentinel.auto_promote_cleanfalseSkip the Inbox for clean, fully-gated candidates.

Where to look in the source