From 753a573d57bf0ffe1848f41f8498bc44c03569bf Mon Sep 17 00:00:00 2001 From: Gio Della-Libera Date: Sun, 19 Jul 2026 10:40:59 -0700 Subject: [PATCH 1/6] RFC: define Claws --- rfcs/0016-claws.md | 928 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 928 insertions(+) create mode 100644 rfcs/0016-claws.md diff --git a/rfcs/0016-claws.md b/rfcs/0016-claws.md new file mode 100644 index 00000000..d23a8fa2 --- /dev/null +++ b/rfcs/0016-claws.md @@ -0,0 +1,928 @@ +--- +title: Claws +authors: + - Gio +created: 2026-07-03 +last_updated: 2026-07-19 +status: draft +issue: +rfc_pr: https://github.com/openclaw/rfcs/pull/27 +--- + +# Proposal: Claws + +## Summary + +Define a **Claw** as a distributable definition of one complete OpenClaw agent +for one job. Adding a Claw creates a new local agent, creates that agent's +workspace, installs its skills and plugin dependencies, configures declared MCP +servers, creates agent-pinned scheduled work, and records provenance for the +complete installed agent. + +The central invariant is: + +> One Claw package adds one new agent for one job. It does not merge into, +> replace, or silently update an agent the operator already built. + +Claws compose existing OpenClaw primitives. Skills remain skills, plugins remain +plugins, MCP servers remain top-level OpenClaw MCP configuration, heartbeat +remains agent configuration, and cron jobs remain Gateway scheduler records. +The Claw owns their composition and lifecycle for the new agent; it does not +replace the underlying owner surfaces. + +The public lifecycle is `add`, `status`, `update`, `remove`, and `export`. +`add --dry-run` is the non-mutating preview. Artifact-level `install` and +`uninstall` remain the underlying operations for individual skills and plugins. + +## Motivation + +A useful Claw should feel like adding a purpose-built employee to OpenClaw. For +example, adding `@acme/github-triage` creates a GitHub triage agent with its own +workspace, instructions, skills, tools, MCP dependency, heartbeat behavior, and +scheduled triage job. It does not rewrite the default agent or borrow an +unrelated workspace. + +Adding a Claw always plans the following owned resources: + +1. One new `agents.list[]` entry. +2. One new workspace assigned to that agent. +3. Canonical bootstrap files and supporting files in that workspace. +4. Workspace skills and global plugin dependencies. +5. Declared MCP servers in OpenClaw's top-level `mcp.servers` configuration. +6. Declared cron jobs stored in the Gateway scheduler and pinned to the new + agent id. +7. Provenance connecting every created or referenced resource to the installed + Claw and local agent. + +The manifest's `agent.id` supplies the default local agent id. If that id or its +default workspace already exists, `add` fails closed. A user may explicitly +choose a different id with `--agent-id`; OpenClaw derives a matching unused +workspace unless `--workspace` is also supplied. Neither override permits +adopting or merging into an existing agent or managed workspace. + +## Goals + +- Make a complete job-specific agent distributable as plain, reviewable data. +- Preserve the one-Claw-one-new-agent invariant across CLI, schema, provenance, + updates, removal, export, feeds, and future UI. +- Keep individual skill and plugin packages on their existing install and + safety paths. +- Create agent workspaces without modifying existing agents or operator + defaults. +- Distinguish canonical workspace bootstrap files from ordinary supporting + files. +- Allow portable, job-specific agent settings while excluding operator-owned + runtime and authentication choices. +- Preview every config, file, package, MCP, and cron mutation before `add`. +- Fail the complete add when any declared component cannot be applied. +- Record enough provenance to inspect, diagnose, update, export, and remove the + installed agent safely. +- Reuse RFC 0009 feeds for discovery, curation, approval, blocking, and exact + source resolution of plugin and skill packages without turning MCP server + declarations into catalog entries. +- Keep Claw processing out of the per-turn Gateway hot path. + +## Non-goals + +- Modifying, templating over, or adopting an existing agent. +- Importing a complete running OpenClaw instance, sessions, logs, caches, + memories, channel bindings, OAuth state, or credentials. +- Replacing standalone skill, plugin, MCP, cron, heartbeat, or agent config + surfaces. +- Replacing plugin-bundled companion skills. +- Defining a new package registry, credential store, or dependency solver. +- Embedding model, provider, thinking-level, authentication, or other + operator-controlled runtime defaults. +- Embedding channel account ids, group ids, credentials, or bindings. +- Setting `agents.list[].skills`; workspace-installed skills remain naturally + discoverable and must not replace inherited allowlists. +- Defining a generic `connector` installation concept. Channel capabilities are + supplied by normal channel plugins and configured or bound locally. +- Defining a feed-backed MCP connector catalog or replacing the Control UI's + separately curated connector suggestions. +- Silently enabling recurring work without preview, consent, provenance, and a + disable/remove path. + +## Proposal + +### Normative principles + +Accepting this RFC accepts the following stable product contract. Individual +implementation slices may land separately, but later work must preserve these +principles. + +| Principle | Requirement | +| --- | --- | +| Unit of ownership | One Claw describes exactly one new agent and its owned setup. | +| Existing agents | `add` never merges into or updates an existing agent. Agent-id and workspace collisions fail closed. | +| Lifecycle verb | The creation operation is `claws add`; `install` remains an artifact-level operation. | +| Public schema | The manifest uses grouped `agent`, `workspace`, `packages`, `mcpServers`, and `cronJobs` fields rather than a generic flat entry list. | +| Completeness | Every declared component is part of the Claw. Unsupported, blocked, or invalid components block `add`; there is no optional `required` flag. | +| Package identity | Package name and version come from the enclosing package metadata and authenticated publish operation, following the ClawHub plugin precedent. | +| Operator control | Models, providers, credentials, channel bindings, and local runtime defaults are not portable Claw settings. | +| Agent configuration | Only explicitly supported portable job settings can be copied into the new `agents.list[]` entry. | +| Skills | Skill packages install into the new agent's workspace and are discovered normally; the Claw does not set `agent.skills`. | +| Plugins | Plugin packages use existing plugin installers, safety checks, enablement rules, and install records. | +| Discovery and composition | Hosted feeds discover and govern plugin and skill packages; a Claw composes exact resolved package versions and direct MCP declarations rather than defining another catalog. | +| MCP | Portable stdio and remote MCP declarations map to top-level `mcp.servers`; credentials and completed OAuth state remain local and are not persisted in the manifest or Claw provenance. | +| Scheduled work | Heartbeat is agent behavior; exact schedules are Gateway cron jobs pinned to the new agent id. | +| Mutation | `add --dry-run` is read-only. Mutating add requires explicit consent. | +| Provenance | OpenClaw records the installed Claw, local agent id, workspace, package refs, MCP refs, cron refs, and managed-file hashes in shared state. | +| Removal | `remove` deletes only Claw-owned state after drift checks and preserves local edits and independently owned artifacts. | + +### Managed and referenced resources + +Claws use one ownership model across every capability. A resource relationship +is either **managed** or **referenced**: + +- A **managed resource** is created specifically for the installed Claw and has + an exclusive Claw identity. The Claw lifecycle may reconcile and remove it + after revalidating ownership and drift. The created agent, its workspace + files, agent-pinned cron jobs, and a newly created collision-free MCP + declaration are managed resources. +- A **referenced resource** is a shared resource on which the Claw depends. The + lifecycle records a current dependency edge but does not acquire exclusive + authority over the resource. Shared package artifacts and plugins are + referenced even when Claw add introduced them through their canonical + installer. An identical pre-existing MCP declaration may also be referenced. + +The canonical owner identity, not the capability label alone, determines the +relationship. For example, a skill directory materialized exclusively inside +the new agent workspace is managed workspace state, while a skill installation +shared outside that workspace is referenced. + +Resource origin (`claw-introduced` or `pre-existing`) is cleanup evidence, not +a third ownership mode. Provenance stores current resource identities, +integrity, dependency edges, and incomplete cleanup state. It does not maintain +historical reference counts or an operation-history ledger. + +Every owner follows the same lifecycle rules: dry-run reports the relationship +and expected state; add either creates a managed resource or satisfies a +reference through the canonical owner; update revalidates before reconciling; +status distinguishes recorded state from live state; and remove deletes managed +resources while retaining referenced resources by default. + +### Package and manifest identity + +The implementer-facing package contract is captured in +[`0016/claw-package-v1-spec.md`](0016/claw-package-v1-spec.md). The experimental +human-readable envelope is captured separately in +[`0016/claw-md-v1-spec.md`](0016/claw-md-v1-spec.md). This RFC remains the +product rationale, ownership model, lifecycle, and rollout plan. + +A published Claw follows the current ClawHub plugin precedent. Registry identity, +version, and publisher ownership come from the enclosing package and the +authenticated publish operation, not duplicated manifest fields. + +Illustrative `package.json`: + +```json +{ + "name": "@acme/github-triage", + "version": "1.2.0", + "type": "module", + "openclaw": { + "claw": "openclaw.claw.json" + } +} +``` + +The Claw manifest therefore does not repeat a top-level publisher, package slug, +package version, display name, or description. A local unpackaged manifest may +be inspected during development, but mutating local add must synthesize an +explicit development identity and record its canonical source path and digest. + +The experimental implementation accepts the strict grouped JSON representation +and `CLAW.md`, in which YAML frontmatter carries the same typed manifest and the +Markdown body is documentation only. Export emits `CLAW.md`; JSON remains a +fully supported serialization of the same grouped schema. + +Both representations are covered by the existing +`OPENCLAW_EXPERIMENTAL_CLAWS=1` gate. `CLAW.md` adds only reader/export format +adaptation and no schema, lifecycle, provenance, or ownership branch. While the +RFC remains experimental, maintainers may revise or remove that envelope before +graduation without creating a separate compatibility promise. + +Feeds and registries materialize an exact package version and integrity before +add. Mutable tags and floating ranges must not become managed installs without +that resolution step. + +### Manifest schema + +The initial public shape is grouped by OpenClaw ownership boundary: + +```jsonc +{ + "schemaVersion": 1, + "agent": { + "id": "github-triage", + "name": "GitHub Triage", + "description": "Reviews incoming GitHub issues and prepares a daily triage summary.", + "identity": { + "name": "Triage", + "emoji": "🔎" + }, + "groupChat": { + "mentionPatterns": ["@triage", "@github-triage"] + }, + "sandbox": { + "mode": "all", + "scope": "agent", + "workspaceAccess": "rw" + }, + "tools": { + "allow": ["read", "write", "edit", "web_fetch", "memory_search", "memory_get"], + "deny": ["exec", "browser", "nodes"] + }, + "heartbeat": { + "every": "30m", + "activeHours": { + "start": "08:00", + "end": "18:00" + }, + "lightContext": true, + "isolatedSession": true, + "skipWhenBusy": true, + "timeoutSeconds": 120 + }, + "humanDelay": { + "mode": "natural" + } + }, + "workspace": { + "bootstrapFiles": { + "AGENTS.md": { "source": "workspace/AGENTS.md" }, + "SOUL.md": { "source": "workspace/SOUL.md" }, + "IDENTITY.md": { "source": "workspace/IDENTITY.md" }, + "TOOLS.md": { "source": "workspace/TOOLS.md" }, + "HEARTBEAT.md": { "source": "workspace/HEARTBEAT.md" } + }, + "files": [ + { + "source": "workspace/reference/triage-policy.md", + "path": "reference/triage-policy.md" + } + ] + }, + "packages": [ + { + "kind": "skill", + "source": "clawhub", + "ref": "@acme/issue-triage-playbook", + "version": "1.4.0" + }, + { + "kind": "plugin", + "source": "clawhub", + "ref": "@acme/github-actions", + "version": "2.1.0" + } + ], + "mcpServers": { + "github-triage-github": { + "command": "npx", + "args": ["-y", "@acme/github-mcp"], + "env": { + "GITHUB_TOKEN": "${GITHUB_TOKEN}" + }, + "toolFilter": { + "include": ["issues_list", "issues_get", "issues_comment"], + "exclude": ["repository_delete", "repository_admin_*"] + }, + "timeout": 30, + "connectTimeout": 10 + } + }, + "cronJobs": [ + { + "id": "weekday-triage", + "name": "Weekday GitHub triage", + "schedule": { + "cron": "0 9 * * 1-5", + "timezone": "America/New_York" + }, + "session": "isolated", + "message": "Review new GitHub issues and prepare a concise triage summary.", + "delivery": { + "mode": "announce", + "channel": "last" + } + } + ] +} +``` + +The schema version 1 field set, validation rules, JSON representation, and +`CLAW.md` envelope are normative for the experimental implementation. +Implementation slices may land separately behind the experimental gate, but a +producer or consumer must not claim schema v1 conformance until it implements +the complete grouped data model. Version 1 is strict: new portable fields, +semantic changes, and ownership changes require a new schema version so +existing consumers never interpret or silently discard an unknown declaration. + +Unknown fields fail closed. Implementations must not silently drop a declared +component and still call the agent complete. + +### Agent settings boundary + +Portable agent settings describe the job and its safe operating posture. The +initial allowlist should be drawn from existing OpenClaw agent configuration and +can include: + +- `id`, `name`, and `description`; +- agent identity presentation; +- group-chat mention patterns; +- sandbox boundaries; +- tool allow and deny policy; +- heartbeat behavior; +- human-delay behavior. + +The following remain operator controlled and are rejected in a Claw manifest: + +- model, provider, thinking level, and runtime implementation; +- API keys, OAuth state, credentials, or secret values; +- channel account ids, group ids, and bindings; +- default-agent selection and global `agents.defaults`; +- `agent.skills` allowlists; +- arbitrary config fragments or unknown future agent fields. + +The generated `agents.list[]` entry inherits operator defaults. Add appends one +entry and does not rewrite existing list members or defaults. + +For example, adding the illustrative manifest above with local agent id +`github-triage` appends an agent entry while preserving the operator's current +defaults and agents: + +```jsonc +{ + "agents": { + "defaults": { + // Existing operator-owned defaults remain unchanged. + }, + "list": [ + { + "id": "main", + "default": true + }, + { + "id": "github-triage", + "name": "GitHub Triage", + "description": "Reviews incoming GitHub issues and prepares a daily triage summary.", + "workspace": "~/.openclaw/workspace-github-triage", + "identity": { + "name": "Triage", + "emoji": "🔎" + }, + "groupChat": { + "mentionPatterns": ["@triage", "@github-triage"] + }, + "sandbox": { + "mode": "all", + "scope": "agent", + "workspaceAccess": "rw" + }, + "tools": { + "allow": ["read", "write", "edit", "web_fetch", "memory_search", "memory_get"], + "deny": ["exec", "browser", "nodes"] + }, + "heartbeat": { + "every": "30m", + "activeHours": { + "start": "08:00", + "end": "18:00" + }, + "lightContext": true, + "isolatedSession": true, + "skipWhenBusy": true, + "timeoutSeconds": 120 + }, + "humanDelay": { + "mode": "natural" + } + } + ] + }, + "plugins": { + "entries": { + "github-actions": { + "enabled": true + } + } + }, + "mcp": { + "servers": { + "github-triage-github": { + "command": "npx", + "args": ["-y", "@acme/github-mcp"], + "env": { + "GITHUB_TOKEN": "${GITHUB_TOKEN}" + } + } + } + } +} +``` + +The installed skill lives under the new workspace's skill root. The cron job is +stored separately by the Gateway scheduler with `agentId: "github-triage"`; it +does not become an `openclaw.json` field. + +### Workspace semantics + +Every added Claw receives a new workspace. By default OpenClaw derives a path +from the final local agent id, for example +`~/.openclaw/workspace-github-triage`. The resolved path must not already be an +existing agent workspace or a Claw-managed workspace. + +`workspace.bootstrapFiles` names canonical OpenClaw files. The initial keys are +`AGENTS.md`, `SOUL.md`, `IDENTITY.md`, `TOOLS.md`, and `HEARTBEAT.md`. Supporting +content belongs in `workspace.files` with explicit package-relative source and +workspace-relative destination paths. + +All paths must remain within the unpacked Claw package or the new agent +workspace after realpath resolution. Symlink, hardlink, device-file, oversized, +and traversal escapes fail closed. The dry-run shows each source, destination, +digest, and action. + +Because add always targets a new workspace, v1 does not need general patch or +merge modes. Any unexpected existing destination is a collision and blocks add. +Update may replace an unchanged Claw-managed file, but it preserves local edits +and reports them as manual conflicts. + +### Package semantics + +`packages` contains only actual installable `skill` and `plugin` packages. +Every package is required. A blocked source, failed safety check, unavailable +exact version, or unsupported source blocks the complete add. + +Skill packages install into the new agent workspace through existing skill +installers. They are discovered from the workspace normally. Add must not set +`agents.list[].skills`. + +Plugin packages install through existing plugin installers and safety checks. +Plugin artifacts can be shared with direct user installs or other Claws. Claw +provenance is explanation and dependency metadata, not an uninstall lock. +Shared skill artifacts and plugins are referenced resources even when add +introduced them. A skill directory materialized exclusively in the Claw's +workspace is managed as part of that workspace. By default, removing a Claw +releases dependency edges and retains shared artifacts. + +The remove plan must offer explicit cleanup choices for referenced artifacts: + +1. `retain` releases only this Claw's dependency edge and is the default. +2. `remove-if-unused` invokes the canonical artifact lifecycle only when no + other Claw dependency edge or known non-Claw owner remains and the artifact + is complete, unchanged, and unambiguous. +3. `remove-selected` invokes canonical removal for artifacts explicitly chosen + by the operator. It must show every known affected Claw and direct owner and + require stronger confirmation when dependencies remain. + +These choices are bound into the integrity-checked remove plan. A failed or +declined canonical uninstall does not erase the resource's cleanup state. +Reference discovery belongs to the shared package lifecycle owner used by CLI, +Gateway, and Control UI uninstall entry points; a Claw command must not bypass +the same warnings by reimplementing removal. A dependency edge is neither a +hidden refcount lock nor authority to override a confirmed operator uninstall. +This includes the Control UI plugin-management work in +[openclaw/openclaw#103176](https://github.com/openclaw/openclaw/pull/103176): +its install, enablement, disablement, and uninstall controls remain plugin lifecycle +operations, while Claws contribute references and shared uninstall warnings. + +Update installs the exact target package version before advancing Claw +provenance. Removing a package from a Claw releases only that Claw's reference. +A global plugin must not be replaced when another installed Claw is pinned to a +different version. Package installers do not currently provide a general +artifact rollback contract, so a later update failure after installation is +reported as partial even when Claw reference provenance can be compensated. + +### MCP server semantics + +`mcpServers` maps stable server names to a reviewed portable subset of the +existing OpenClaw MCP server config shape. Add writes those declarations to +top-level `mcp.servers`; they are not nested inside the generated agent entry. +The initial subset supports both local stdio servers (`command`, `args`, and +related process settings) and remote servers (`url`, `sse` or +`streamable-http` transport, and credential-free OAuth intent). It does not +carry arbitrary authorization headers, bearer tokens, client secrets, or +completed OAuth state. + +Server-name collisions fail unless the existing canonical config is identical +and a referenced dependency edge can be recorded without taking over unrelated +state. A newly created, collision-free MCP declaration is managed by the Claw; +an identical pre-existing declaration is referenced. Both cases use the same +canonical MCP config path, plan preview, capability consent, drift checks, and +operator-selected cleanup rules as other resources. Environment +placeholders such as `${GITHUB_TOKEN}` remain references. Resolved secret values +must never be stored in the manifest, plan, logs, or provenance. Provenance uses +a canonical redacted digest sufficient for drift detection. Remote OAuth and +other credential completion is an operator-owned local step after add. The +Control UI may present curated MCP suggestions, but their presentation identity +is not a Claw package dependency, hosted-feed entry, or provenance key. + +### Heartbeat and cron semantics + +Heartbeat and cron jobs are distinct existing OpenClaw concepts: + +- `agent.heartbeat` controls when and how the new agent wakes. +- `workspace.bootstrapFiles["HEARTBEAT.md"]` contains what the agent checks. +- `cronJobs` contains exact scheduled jobs stored by the Gateway scheduler. + +Every created cron job is pinned to the final local agent id regardless of +whether the manifest id or `--agent-id` override supplied it. Cron ids must be +unique within the Claw and must not overwrite existing scheduler records. +Dry-run shows cadence, timezone, session mode, message/action, delivery, and the +derived `agentId`. Mutating add creates cron jobs only after the agent and +workspace are ready, and provenance stores stable scheduler ids for status, +update, disable, and removal. + +Channel delivery settings may name portable modes such as `last`, but a Claw +does not embed account ids, group ids, credentials, or bindings. Operators bind +the new agent to local channels separately. + +### CLI and lifecycle + +#### Experimental incubation gate + +While this RFC remains draft, every Claws CLI surface is gated behind the +process-level opt-in `OPENCLAW_EXPERIMENTAL_CLAWS=1`. + +When the gate is absent or false: + +- OpenClaw does not register the `claws` command; +- Claws do not appear in default help, shell completions, or onboarding; +- no background service, update flow, or Gateway startup path reads or applies + Claw state; +- encountering Claw package metadata through an ordinary install path does not + implicitly enable the experiment. + +The hosted experimental guide is intentionally public and may appear in the +documentation navigation while the local command is disabled. Static hosted +documentation cannot observe a process environment variable, so it labels the +feature experimental and shows the opt-in explicitly. Public documentation is +not a stability promise and does not enable any local runtime surface. + +The gate is intentionally an environment opt-in rather than a persisted config +field. Internal launchers, test lanes, and controlled deployments can enable it +for a process, but users do not acquire a durable experimental setting that is +silently carried into later releases or fleet config. + +When enabled, text-mode commands print a concise experimental compatibility +warning before mutation, and machine-readable results include +`stability: "experimental"` plus their exact output schema version. During the +draft period, the manifest schema, CLI flags, JSON result shapes, and SQLite +tables may change without backward-compatibility guarantees. Destructive +commands still require their normal explicit consent; the experimental gate is +not consent and does not weaken any safety check. + +Removing the gate is a separate maintainer decision after this RFC is accepted. +That graduation PR must define released migration behavior, stable CLI and JSON +contracts, documentation, and compatibility policy. Shipping experimental code +does not itself establish those contracts. + +The public CLI is: + +```bash +openclaw claws inspect +openclaw claws add --dry-run --json +openclaw claws add [--agent-id ] [--workspace ] --yes --plan-integrity +openclaw claws status [claw-or-agent] +openclaw claws update [--from ] --dry-run --json +openclaw claws update [--from ] --yes --plan-integrity +openclaw claws remove --dry-run --json [cleanup selection] +openclaw claws remove --yes --plan-integrity [cleanup selection] +openclaw claws export --out +``` + +`inspect` validates package metadata and the grouped manifest without reading or +mutating local lifecycle state. `add --dry-run` resolves the final agent id, +workspace, packages, MCP servers, and cron jobs and emits the complete action +plan. `add` without `--dry-run` requires `--yes` and the exact +`--plan-integrity` digest from that dry run. Update uses the source recorded in +provenance unless `--from` explicitly overrides it. Remove retains referenced +resources by default; `--remove-unused`, repeatable `--remove-referenced`, and +`--force-referenced` select stronger cleanup in both preview and mutation so +the choice is included in the plan digest. `--yes` alone never broadens a plan. + +Add ordering is transactional where owner APIs permit it and compensating where +external installers or the scheduler cannot share one transaction: + +1. Validate package metadata and manifest. +2. Resolve exact dependencies and run install safety checks. +3. Resolve the final unused agent id and workspace. +4. Preflight all config, file, MCP, and cron collisions. +5. Create the agent entry and workspace state. +6. Write bootstrap and supporting files. +7. Install workspace skills and plugin dependencies. +8. Configure MCP servers. +9. Create agent-pinned cron jobs. +10. Persist one complete apply record and per-resource provenance. + +Any failure stops later phases. Successfully created external resources are +recorded immediately so doctor and remove can explain and clean a partial add. +The result distinguishes complete, partial, and failed adds; it never reports a +partial agent as successfully added. + +### Provenance and local state + +Claw lifecycle state belongs in OpenClaw's shared SQLite state database, not in +the user config file and not only in marker files inside the workspace. + +The installed record must include: + +- package identity, version, integrity, source, and source byte length; +- final local agent id and workspace root; +- generated agent config digest and owned field paths; +- managed workspace paths and content digests; +- exact skill and plugin artifact identities, managed or referenced + relationship, resource origin, and current independent ownership; +- MCP server names, managed or referenced relationship, resource origin, + current independent ownership, and canonical redacted config digests; +- cron job ids and scheduler record ids; +- add/update timestamps and actor or caller when available; +- partial-operation diagnostics and cleanup state. + +Status and doctor read this ledger to report missing agents, workspace drift, +modified files, missing dependencies, changed MCP config, missing or changed cron +jobs, and orphaned partial state. + +### Update, remove, and export + +Update always targets the installed agent created by the Claw. It never changes +another agent merely because a target manifest now uses the same id. Update has +a read-only plan and a separately consented apply. + +Update may add or change portable agent fields, files, package dependencies, MCP +servers, and cron jobs owned by the installed Claw. Local modifications become +manual conflicts. Operator defaults, models, providers, credentials, bindings, +and unrelated config remain untouched. + +Consented update rebuilds the read-only plan immediately before mutation. Each +owner uses its strongest available concurrency boundary: workspace content +digests, expected MCP config values, stable cron declaration keys and scheduler +ids, exact package refs, and agent/root provenance compare-and-swap checks. +Workspace checks include expected file presence as well as content. Before an +external package installer runs, OpenClaw atomically replaces the expected +package reference with a pending ownership claim; concurrent ownership changes +abort before installation, and installer failure compensates the claim. +Completed owners compensate in reverse order when a later owner fails. A +thrown config or Gateway call has an uncertain commit outcome, and an installed +package artifact cannot be assumed rolled back merely because its reference was +restored. These cases return an explicit partial result rather than claiming +cross-owner atomicity. + +Remove first produces a plan. Managed resources are selected for cleanup by +default: it removes agent-pinned cron jobs, unchanged Claw-managed MCP +declarations and workspace files, and the Claw-created agent through their +canonical owner lifecycles. Referenced packages and MCP declarations are +retained by default while their dependency edges are released. The operator may +instead select eligible referenced resources for `remove-if-unused`, or select +specific referenced resources for canonical removal after reviewing dependency +warnings. Locally modified files, unrelated MCP servers, channel bindings, and +operator state remain outside Claw cleanup. Failed cleanup remains visible in +status and doctor. + +Export is agent-centric. It exports only portable state belonging to the chosen +agent: supported agent settings, selected workspace bootstrap/supporting files, +installed skill/plugin refs, matching MCP declarations, and agent-pinned cron +jobs. It excludes secrets, resolved environment values, models/providers, +bindings, sessions, logs, caches, and unrelated global state. Package output +uses `package.json` for identity, `CLAW.md` for the grouped manifest, and +confined sidecars. Readers continue to accept the equivalent grouped JSON +manifest. + +### Feeds, catalogs, and ClawHub + +RFC 0009 feeds remain the discovery and policy layer. A feed may expose a Claw +package, pin an exact version, recommend or block it, and independently block or +substitute package dependencies. Approval of the Claw does not transitively +approve its skills or plugins. + +That feed boundary is intentionally narrower than the complete Control UI +experience. Hosted feeds currently provide official plugin and skill catalog +entries. Installed MCP servers come from local `mcp.servers`, while the Control +UI's suggested MCP connectors are a separately curated presentation surface. +Claws use the first mechanism to resolve exact plugin and skill package inputs, +and use direct portable MCP declarations for the second kind of capability. +They do not create a third connector registry or infer a stable connector +identity from a UI suggestion. + +ClawHub owns authenticated publication, package ownership, search/detail/API +surfaces, hosted feed export, and authoring guidance. OpenClaw owns manifest +validation, planning, local mutation, provenance, and lifecycle behavior. Both +must share the schema and fixtures rather than maintain divergent validators. + +### Safety and security + +- Agent-id and workspace collisions fail closed. +- Add never mutates an existing agent. +- Unknown fields or unsupported declared components fail closed. +- All package dependencies pass existing source, integrity, compatibility, and + install safety checks. +- Workspace package reads and destination writes use rooted, symlink-safe, + hardlink-safe file APIs with size limits. +- Secrets and resolved environment values never enter plans or provenance. +- MCP config writes use validated, concurrent-write-safe config APIs. +- Cron jobs require explicit consent, visible cadence/action previews, stable + ownership, and disable/remove handles. +- Config mutation preserves `agents.defaults`, existing `agents.list[]` entries, + channel bindings, and unrelated plugin/MCP settings. +- Partial adds persist enough state for diagnosis and cleanup. +- Update and remove revalidate expected presence, content/config digests, and + provenance ownership at the actual mutation boundary. +- A plan that adds executable code, an MCP execution or network surface, + plugin/tool access, or recurring work must identify that capability + escalation in a distinct machine-readable record and human-readable plan + section. OpenClaw may use one confirmation token only when + `--plan-integrity` binds the exact separately disclosed capability set as + well as ordinary content reconciliation. Other hosts may require a separate + dialog or aggregate those records before mutating multiple agents. +- Claws do not introduce capability-specific resource quotas. Existing + canonical owner limits apply; bounded package, manifest, extraction, and plan + sizes remain parser and resource-safety policy. + +## Rationale + +The one-Claw-one-new-agent model gives the lifecycle one understandable unit of +ownership while continuing to delegate files, packages, MCP configuration, and +scheduled work to their existing OpenClaw owners. Grouped schema fields make +those boundaries reviewable; plan-first mutation, provenance, and conservative +cleanup make composition safer than an opaque setup script or whole-instance +export. The tradeoff is a broader lifecycle than an ordinary package manager, +which is why the RFC uses `add`/`remove`, explicit partial outcomes, and an +experimental gate rather than promising cross-owner atomicity. + +## Compatibility and migration + +Claws are additive. Existing agents, skills, plugins, MCP servers, cron jobs, +feeds, and plugin bundles continue to work without becoming Claws. + +The earlier prototype used `openclaw.claw.v1`, a flat `entries[]` list, and +`claws apply` against a caller-selected workspace. That prototype is not the +accepted public compatibility contract. Before any implementation PR is made +ready, it must be restacked around the grouped schema and one-new-agent +invariant. Prototype SQLite tables may be discarded or migrated during the +draft phase; no released migration promise exists until the RFC is accepted. + +## Rollout plan + +Implementation should widen the trust boundary in reviewable slices: + +1. **Schema and read-only plan.** Parse package metadata and grouped manifests; + implement `inspect` and `add --dry-run`; prove agent/workspace collision + behavior and complete blockers without mutation. +2. **Agent and workspace creation.** Add one `agents.list[]` entry, derive a new + workspace, preserve defaults and existing agents, and persist the root apply + record. +3. **Workspace bootstrap and supporting files.** Add confined file writes, + managed hashes, partial-failure provenance, and local-edit protection. +4. **Skill and plugin packages.** Reuse existing installers, install skills into + the new workspace, preserve artifact ownership boundaries, and warn on direct + uninstall when Claws reference an artifact. +5. **MCP servers.** Add validated top-level MCP configuration, collision checks, + redacted digest provenance, status, and cleanup. +6. **Heartbeat and cron jobs.** Apply portable heartbeat config and create + scheduler records pinned to the new agent id with status/disable/remove proof. +7. **Status, doctor, and remove.** Diagnose complete and partial agents, drift, + orphaned resources, and conservative cleanup. +8. **Update planning and apply.** Reconcile only the installed Claw-owned agent + and resources, separating read-only planning from consented mutation. +9. **Export and round trip.** Export a selected agent to package metadata, + grouped manifest, and safe sidecars; prove export-to-add in a fresh state dir. +10. **ClawHub publication and feeds.** Share schema fixtures, publish a package, + expose it through hosted feeds, and prove source resolution and add dry-run. + +### Current OpenClaw implementation stack + +The experimental implementation is one RFC plus twelve ordered OpenClaw PRs. Each +implementation PR is based on the preceding head so reviewers can evaluate one +ownership boundary at a time: + +1. [#101328](https://github.com/openclaw/openclaw/pull/101328) - grouped schema, + inspect, and read-only add planning. +2. [#101755](https://github.com/openclaw/openclaw/pull/101755) - new agent, + workspace root, and root install provenance. +3. [#101973](https://github.com/openclaw/openclaw/pull/101973) - managed + workspace bootstrap and supporting files. +4. [#102228](https://github.com/openclaw/openclaw/pull/102228) - exact ClawHub + skill/plugin installation and shared uninstall-reference warnings. +5. [#102296](https://github.com/openclaw/openclaw/pull/102296) - plan-first + status and conservative remove. +6. [#102306](https://github.com/openclaw/openclaw/pull/102306) - agent-centric + grouped export. +7. [#102383](https://github.com/openclaw/openclaw/pull/102383) - Gateway-owned + cron jobs and scheduler provenance. +8. [#102406](https://github.com/openclaw/openclaw/pull/102406) - stdio and remote + MCP ownership, including credential-free OAuth intent. +9. [#102427](https://github.com/openclaw/openclaw/pull/102427) - lifecycle and + drift diagnostics. +10. [#102959](https://github.com/openclaw/openclaw/pull/102959) - read-only + grouped update planning. +11. [#102982](https://github.com/openclaw/openclaw/pull/102982) - consented + grouped update apply and compensation. +12. [#111391](https://github.com/openclaw/openclaw/pull/111391) - thin + `CLAW.md` YAML-frontmatter input/export adaptation with grouped JSON read + compatibility and no separate lifecycle behavior. It supersedes #106888, + which was merged only into an obsolete stack head. + +Public documentation follows the same staged boundary as the implementation. +#101328 introduces the experimental guide, navigation, opt-in, schema, inspect, +and add preview. Each later PR extends that guide only with the command or +resource behavior implemented at that stage. #111391 adds only `CLAW.md` +authoring and canonical export documentation. At every intermediate stack head, +the guide must describe no later command or ownership behavior. + +These PRs replace the old workspace-apply prototype rather than +extending its compatibility contract. Every experimental CLI PR remains behind +`OPENCLAW_EXPERIMENTAL_CLAWS=1`; command registration, help, completion, and +direct-handler tests must prove the disabled state as well as the enabled state. + +### Current ClawHub implementation stack + +ClawHub follows the OpenClaw schema and lifecycle contract in four ordered PRs: + +1. [#3089](https://github.com/openclaw/clawhub/pull/3089) - shared manifest + validation, derived summaries, and storage data model. Existing generic + publication remains closed to Claws. +2. [#3090](https://github.com/openclaw/clawhub/pull/3090) - guarded publication, + package ingestion, source-file checks, CLI authoring support, and author + guidance. It also owns the fail-closed public-read boundary while disabled + and strips full manifests from every public release serializer. +3. [#3091](https://github.com/openclaw/clawhub/pull/3091) - enabled search, + detail, and version APIs that expose only safe summaries. +4. [#3092](https://github.com/openclaw/clawhub/pull/3092) - separately gated + hosted Claw feed with safe summaries and exact artifact digests, plus a + repeatable published-package proof through real OpenClaw add dry-run. The + proof rejects unsafe paths, links, and special archive entries before + extraction, and the unversioned feed URL permanently redirects to the + versioned route. + +The ClawHub runtime surfaces in this track require +`CLAWHUB_EXPERIMENTAL_CLAWS=1`. The deployment gate is independent of +`OPENCLAW_EXPERIMENTAL_CLAWS=1` in the OpenClaw client and is not a replacement +for explicit add/update consent. + +The experimental ClawHub contract accepts both `CLAW.md` and the equivalent +grouped JSON manifest behind `CLAWHUB_EXPERIMENTAL_CLAWS=1`; it does not add a +second format-specific gate. Search, detail, and feed APIs expose bounded +summaries and immutable artifact coordinates; the applying client reviews the +full declaration from the resolved artifact. + +## Acceptance criteria + +The RFC implementation is acceptable when tests and real CLI proof demonstrate: + +1. Inspect validates package identity and the grouped manifest without mutation. +2. Without `OPENCLAW_EXPERIMENTAL_CLAWS=1`, the `claws` command is unregistered, + absent from help and completions, and cannot be enabled by package content; + the public experimental guide remains non-executable documentation. +3. Add dry-run shows one new agent, one new workspace, every file/package/MCP/ + cron action, all collisions, and stable machine-readable blockers. +4. An existing agent id or workspace blocks add unless an explicit unused + override is supplied. +5. Add appends one agent without changing defaults or existing agents. +6. Canonical and supporting files are confined to the new workspace. +7. Skills install into that workspace without setting `agent.skills`. +8. Plugins use existing safety checks and preserve shared/direct ownership; + CLI, Gateway, and Control UI uninstall paths all emit Claw-reference warnings + through the shared lifecycle owner. +9. Portable stdio and remote MCP declarations write only validated top-level + config, store no secrets or completed OAuth state in provenance, and do not + depend on a feed-backed connector identity. +10. Cron jobs are scheduler records pinned to the final local agent id. +11. Any declared unsupported or blocked component fails the complete add. +12. Partial failures remain visible and cleanable; they are not reported as a + successfully added Claw. +13. Status and doctor explain agent, workspace, package, MCP, cron, and managed + file drift. +14. Update changes only Claw-owned state, preserves local/operator edits, + revalidates owner state before mutation, compensates completed owners in + reverse order, and reports uncertain or irreversible outcomes as partial. +15. Remove uses canonical owner lifecycles, selects managed resources for + cleanup, retains referenced resources by default, offers integrity-bound + `remove-if-unused` and explicitly selected referenced cleanup, warns about + every known affected Claw or direct owner, and preserves modified or + unrelated state. +16. Export emits `CLAW.md`, excludes secrets and operator runtime settings, + retains grouped JSON read compatibility, and can be added in a fresh state + directory as a new equivalent agent. +17. Feed approval does not bypass dependency policy or install safety checks. +18. Every implementation stage documents its newly available surface without + claiming commands or ownership behavior from a later stage. +19. Add and update plans disclose capability escalations separately from + ordinary content, include them in plan integrity, and reject mutation when + the reviewed capability set changes. + +## Unresolved questions + +- Before removing the experimental gate, should `CLAW.md` remain the default + authoring/export representation or should export return to grouped JSON? +- What exact default workspace naming rule should resolve cross-platform path + and case-folding collisions? +- Which cron delivery modes are portable without embedding local channel + bindings? +- What package transports should mutating v1 support beyond ClawHub and local + development packages? +- What is the minimum released SQLite migration contract before Claws leave + draft status? +- How should OpenClaw and ClawHub publish and version one shared schema and + fixture suite? From 7518b087aa021068b3173086046a7881d3133645 Mon Sep 17 00:00:00 2001 From: Gio Della-Libera Date: Sun, 19 Jul 2026 10:41:00 -0700 Subject: [PATCH 2/6] docs(rfc): specify Claw package v1 --- rfcs/0016/claw-package-v1-spec.md | 520 ++++++++++++++++++++++++++++++ 1 file changed, 520 insertions(+) create mode 100644 rfcs/0016/claw-package-v1-spec.md diff --git a/rfcs/0016/claw-package-v1-spec.md b/rfcs/0016/claw-package-v1-spec.md new file mode 100644 index 00000000..3dedfc2b --- /dev/null +++ b/rfcs/0016/claw-package-v1-spec.md @@ -0,0 +1,520 @@ +# Claw Package v1 Specification + +This document is the implementer-facing package and lifecycle-boundary +specification for RFC 0016, Claws. It defines how one Claw manifest and its +referenced files are identified, validated, published, resolved, and handed to +an OpenClaw lifecycle implementation. + +Status: experimental draft, tied to RFC 0016. + +## Scope + +This specification defines: + +- package identity and required metadata; +- package layout and manifest selection; +- archive and filesystem safety requirements; +- publication and registry validation boundaries; +- artifact integrity and exact-version resolution; +- the contract between a registry and an applying harness; +- lifecycle ownership requirements for add, update, status, and remove. + +The grouped manifest schema and `CLAW.md` envelope are defined by +[`claw-md-v1-spec.md`](claw-md-v1-spec.md). Equivalent grouped JSON passes +through the same validator and lifecycle. + +This specification does not define: + +- a new package transport or dependency solver; +- a replacement for skill or plugin packages; +- credentials, local bindings, or host policy; +- the physical schema of OpenClaw provenance storage; +- a cross-harness command-line standard; +- whole-instance backup, restore, or migration. + +## Terminology + +- **Artifact**: the exact immutable package bytes identified by package name, + version, byte length, and digest. +- **Development snapshot**: one immutable local read of a development manifest + and every package file it references. +- **Owner**: the existing OpenClaw subsystem authoritative for an agent, file, + skill, plugin, MCP server, or scheduler record. +- **Managed resource**: a resource created specifically for one installed Claw + with an exclusive identity that the Claw lifecycle may reconcile and remove + after ownership and drift checks. +- **Referenced resource**: a shared canonical resource on which a Claw depends + without acquiring exclusive lifetime authority. +- **Dependency edge**: the current relationship between an installed Claw and + a referenced resource. It is warning and cleanup evidence, not an uninstall + lock or historical reference count. +- **Resource origin**: whether Claw add introduced a canonical resource or + declaration or found it already present. Origin informs cleanup eligibility + but is not ownership. +- **Applied**: every consented mutation completed or an existing canonical owner + was safely referenced. +- **Ready**: the applied agent also has all local credentials, executables, + bindings, and runtime prerequisites needed to operate as declared. +- **Application profile**: the owner mapping and lifecycle behavior required to + turn a manifest into a runnable agent on one harness. + +## Package Model + +A Claw package is a versioned, immutable distribution of one complete agent +definition. It contains: + +- package identity in `package.json`; +- one `CLAW.md` or equivalent grouped JSON manifest; +- every workspace source file referenced by that manifest. + +The package composes existing skills, plugins, MCP declarations, workspace +files, agent settings, and scheduled work. It is not a plugin, a plugin bundle, +or a replacement package type for those artifacts. Applying it delegates each +resource to its existing OpenClaw owner. + +One package adds one new agent. It must not adopt, merge into, replace, or +silently update an agent that the operator already owns. + +## Required Package Metadata + +The package root must contain a UTF-8 JSON `package.json` with: + +```json +{ + "name": "@acme/github-triage", + "version": "1.2.0", + "type": "module", + "openclaw": { + "claw": "CLAW.md" + } +} +``` + +| Field | Required | Semantics | +| --- | --- | --- | +| `name` | Yes | Canonical package coordinate assigned by the registry. Display slugs and aliases are not identity. | +| `version` | Yes | Exact canonical SemVer 2.0.0 version. Tags, ranges, and a leading `v` are forbidden. | +| `openclaw.claw` | Yes | Package-relative path to the manifest. | +| `type` | No | Ordinary package metadata; it does not affect Claw parsing. | + +Registry identity, version, and publisher ownership come from this package +metadata and the authenticated publish operation. They must not be duplicated +as authoritative fields inside the Claw manifest. + +At publication, the declared `name` and `version` must exactly match the +authenticated publish coordinate. A mismatch must reject the publication. +Registries must reject an identity that is not canonical under their published +package-name rules rather than silently normalizing it to a different package. + +## Package Layout + +An illustrative package is: + +```text +github-triage/ +|-- package.json +|-- CLAW.md +`-- workspace/ + |-- AGENTS.md + |-- SOUL.md + `-- reference/ + `-- triage-policy.md +``` + +All manifest paths and referenced workspace sources must resolve inside the +unpacked package root. A registry must verify that every declared source exists +in the uploaded artifact before accepting a version. + +## Portable Path Rules + +Package paths must be safe on supported OpenClaw filesystems. In addition to +the relative-path rules in the manifest specification, publishers and +registries must reject: + +- absolute POSIX, UNC, or drive-qualified paths; +- `.` or `..` traversal segments; +- NUL and control characters; +- Windows-reserved path components and invalid filename characters; +- components with trailing spaces or dots; +- two paths that collide after slash normalization, Unicode NFC normalization, + and case folding; +- a manifest path or workspace source whose canonical realpath escapes the + package root; +- symlinks, hardlinks, device files, sockets, and every other entry that is not + an ordinary directory or regular file. + +Consumers must apply bounded file-size and aggregate extraction limits. Limits +are implementation policy and should be documented by the registry or harness; +exceeding them must fail closed rather than truncate content. +Claws must not invent per-capability quotas such as a Claw-only scheduler count; +canonical owner limits apply uniformly. General package, manifest, extraction, +and plan-size limits may protect parsing and resource use across all fields. + +Archive entry names must also be unique under the portable collision key before +extraction. Consumers must not trust archive ordering to resolve duplicates. +Executable bits, owners, groups, timestamps, and other host metadata are not +portable package semantics and must not grant execution authority after +extraction. + +## Manifest Selection + +`openclaw.claw` selects the one manifest for the package. The path must resolve +to a regular UTF-8 text file inside the package. + +If the selected basename is `CLAW.md`, compared case-insensitively, the consumer +uses the Markdown-envelope parser. Other selected filenames are parsed as JSON. +Both forms pass through the same strict schema version 1 validator. + +A package must not select behavior from package scripts or another undeclared +manifest. Installing or inspecting a Claw package must not execute package +lifecycle scripts merely to discover its manifest. The `CLAW.md` body remains +documentation only. + +## Publication Validation Pipeline + +A conforming registry must validate a publication in this order: + +1. Authenticate the publisher and resolve the requested package coordinate. +2. Verify that `package.json` identity matches that coordinate exactly. +3. Safely enumerate and extract the artifact under package size and path limits. +4. Resolve `openclaw.claw` inside the package root. +5. Parse the selected `CLAW.md` or JSON document. +6. Validate the strict schema version 1 manifest. +7. Verify that every workspace source exists and is a safe regular file, and + that any local avatar resolves through a declared workspace destination. +8. Apply registry ownership, visibility, moderation, malware, and security + scanning rules. +9. Compute and retain the immutable artifact digest over the exact distributed + artifact bytes. +10. Store the validated full manifest separately from its public safe summary. + +Validation is all-or-nothing. A registry must not publish a partial package or +silently discard unsupported manifest fields or components. + +## Artifact Resolution and Integrity + +A feed or registry result used for add or update must resolve to an exact +package name, exact version, artifact location, and immutable artifact digest +formatted as `sha256:` followed by 64 lowercase hexadecimal characters. The +consumer records the observed byte length and must also verify it when the +registry supplies an expected length. +Floating tags and version ranges may be discovery inputs, but they must be +resolved before a managed lifecycle plan is produced. + +The registry artifact digest covers the exact distributed artifact bytes. The +trusted registry or signed feed binds that digest to package identity; the +digest alone proves byte equality, not publisher identity, review, or safety. + +A local development source must be materialized as one immutable planning +snapshot containing the exact manifest bytes and every referenced workspace +source path and byte sequence. Its development digest must cover that complete +snapshot plus the canonical source location. Hashing only the manifest is not +sufficient. Development and registry digests identify different trust layers +and must not be presented as interchangeable proofs. + +A consumer must verify the expected artifact digest before trusting package +contents. Validation and integrity do not imply that package code or declared +capabilities are approved; existing source policy, scanning, and install safety +checks still apply to every dependency. + +## Registry and Client Boundary + +A registry such as ClawHub owns: + +- authenticated publication and package ownership; +- immutable versions and artifact storage; +- package validation and security eligibility; +- safe search/detail summaries; +- exact artifact resolution and hosted feed entries. + +OpenClaw owns: + +- local package and manifest validation; +- read-only planning and operator consent; +- creation of the new agent and workspace; +- delegation to skill, plugin, MCP, agent, workspace, and scheduler owners; +- local provenance, status, diagnostics, update, export, and removal. + +Registry approval of a Claw must not transitively approve a skill or plugin +dependency. The client must resolve and evaluate every dependency through its +normal policy and installer path. + +Public search and release APIs should expose a bounded, derived summary for +indexing. Before consent, the applying client must make the exact grouped +manifest available for review and display its complete package effects from the +downloaded artifact under the artifact's visibility and authorization rules. +Valid packages cannot contain secrets. The downloaded artifact remains the +authoritative full declaration; a summary must not replace or contradict it. + +## Read-Only Planning and Consent + +Inspection validates package metadata and the manifest without reading or +mutating local lifecycle state. Add dry-run resolves the final local agent id, +workspace, dependencies, MCP servers, files, scheduled work, local credential +prerequisites, and every external executable or downloadable artifact. It +reports all actions, retained resources, conflicts, blockers, and post-add +readiness requirements. + +The plan must expose the security-relevant effect of each action: exact package +identity and integrity; workspace source, destination, and content digest; MCP +transport, executable and literal arguments or remote URL, environment variable +names, authentication mode, and tool filters; and cron schedule, timezone, +session, message, and delivery behavior. Secret values must remain undisclosed. + +Capability escalation is classified consistently across owners. Adding +executable package code, plugin or tool access, an MCP execution or network +surface, or recurring work requires a distinct machine-readable record and +human-readable disclosure rather than being hidden in ordinary content +reconciliation. The same classification applies during add and update; an +owner must not invent a weaker capability-specific approval. + +An application profile may satisfy capability and content consent with one +confirmation only when the plan represents the capability set separately and +the supplied integrity token binds both sets exactly. A profile may instead +require a separate capability prompt or aggregate capability records across +several plans before the first mutation. A changed capability record +invalidates prior consent in either model. + +The OpenClaw application profile marks each escalation record with +`requiresDistinctConsent: true`. This is a host-facing signal that the change +must receive distinct disclosure and explicit acknowledgment; it does not by +itself require a second portable CLI flag. OpenClaw's CLI acknowledgment is the +exact plan-integrity token entered after that separate disclosure. + +Mutation requires explicit consent after the complete plan is available. A +feature or deployment gate is not consent. A package must not cause mutation +merely by being discovered, downloaded, inspected, or passed through an +ordinary package installer. + +Consent must bind to the exact package or development snapshot digest, final +agent id, workspace, action set, and expected local owner state shown in the +plan. Immediately before mutation, the client must rebuild or revalidate those +inputs. A change to any consented digest, destination, package owner, owner +configuration value, scheduler record, or file-presence expectation invalidates +consent and requires a new plan; the client must not silently apply a materially +different plan. + +Agent-id or workspace collisions fail closed. An explicit override may choose +an unused id or workspace, but it must not adopt an existing agent or managed +workspace. + +## Ownership and Provenance + +After consent, the lifecycle delegates resources to their canonical owners and +records enough shared provenance to explain and reconcile the resulting agent. +At minimum, provenance must identify: + +- Claw package name, version, source, and integrity; +- final local agent id and workspace; +- the consented plan identity and applied manifest schema version; +- generated agent configuration digest and owned field paths; +- managed workspace paths and content digests; +- exact skill and plugin dependency edges, resource origin + (`claw-introduced` or `pre-existing`), and current non-Claw ownership; +- MCP names, managed or referenced relationship, resource origin, current + non-Claw ownership, and redacted configuration digests; +- manifest cron ids and scheduler record ids; +- per-owner pending, complete, partial, failed, and cleanup states; +- timestamps and actor or caller identity when the host can establish one. + +Credentials and resolved environment values must never be persisted in Claw +provenance. + +Provenance explains ownership and dependency relationships. It is not an +uninstall lock and does not replace canonical owner state. + +The managed or referenced relationship is derived during planning from the +resource kind and canonical owner state. A package author cannot declare +deletion authority. Agents, workspace files, agent-pinned scheduler jobs, and + new collision-free MCP declarations are managed. Shared package artifacts and + plugins are referenced even when add introduced them. A skill materialized + exclusively inside the new agent workspace is managed workspace state, while + a skill installation shared outside that workspace is referenced. An + identical pre-existing MCP declaration is referenced rather than adopted. + +Provenance stores current identities, integrity, dependency edges, and pending +or incomplete cleanup state. Implementations must not require a historical +operation ledger or stored reference-count history. Any cleanup decision uses +the current enumerated dependency edges and canonical owner state. + +Applied state and ready state are distinct. A complete add means every declared +mutation was applied or safely referenced. Status must separately report +unresolved environment placeholders, incomplete OAuth login, unavailable MCP +executables, disabled or missing scheduler dependencies, and other local +prerequisites that prevent the agent from operating as declared. + +## Add Semantics + +A conforming add implementation must: + +- create exactly one new agent and one new workspace; +- fail the complete add when any declared component is unsupported, blocked, + invalid, or unavailable; +- use existing skill and plugin installers and safety checks; +- write only confined workspace files; +- map MCP declarations to the existing MCP owner; +- create scheduler records pinned to the final local agent id; +- persist pending owner provenance before each external mutation; +- record successful external mutations as they occur; +- report a partial result when owners cannot share one atomic transaction. + +On failure, add must stop later owners, compensate completed mutations in +reverse order where the canonical owner supports safe compensation, and retain +provenance for every uncertain or uncompensated result. It must not report a +partially created agent as successfully added. + +## Update Semantics + +Update targets the installed agent identified by provenance and never another +agent that happens to share a manifest id. It must produce a read-only +reconciliation plan before separately consented mutation. + +The installed local agent id and workspace are immutable update identity. A +different `agent.id` in a later package version changes the default for new adds +only; it must not rename or move an existing installed agent. Update may move to +an older or newer exact package version only when that target is explicit in the +consented plan. There is no implicit background update authority in v1. + +At the mutation boundary, each owner must revalidate the strongest available +expected state, including file presence and digest, package ownership, MCP +configuration, scheduler identity, and agent/root provenance. Local edits or +concurrent changes become conflicts rather than silent overwrites. + +An update plan must classify each resource as create, change, remove, retain, +requires-local-configuration, or conflict. It must preserve unrelated owner +state and must not replace a global plugin while another installed Claw or a +direct owner requires a different version. + +Removing a package declaration during update releases that Claw's reference. +It does not imply artifact uninstall during the update transaction. Irreversible +or uncertain owner outcomes must be reported as partial. + +## Remove Semantics + +Remove must first produce a plan and then require explicit consent. It must +delegate agent, skill, plugin, MCP, workspace, and scheduler cleanup to their +canonical owner lifecycles. + +Remove must disable Claw-owned recurring work before deleting the agent or its +workspace content. If recurring work cannot be proven disabled, cleanup is +partial and the failure remains visible; remove must not claim success merely +because later local records were deleted. + +Managed resources are selected for cleanup by default. Referenced resources are +retained by default while the removing Claw's dependency edges are released. +The plan must show the relationship, origin, expected integrity, every other +known Claw dependency edge, known non-Claw ownership, and the canonical cleanup +owner for each resource. + +The operator must be offered these referenced-resource dispositions: + +- **retain**: release only this Claw's dependency edge. This is the default. +- **remove-if-unused**: invoke canonical removal only when the resource has no + other Claw dependency edge or known non-Claw owner, was introduced by Claw + add, is complete, unchanged, and unambiguous, and its canonical owner permits + removal. +- **remove-selected**: invoke canonical removal for specifically selected + resources after showing all known affected Claws and non-Claw owners. A + remaining dependency or pre-existing origin requires stronger explicit + confirmation but is not a hidden uninstall lock. + +The chosen disposition and affected resource identities must be part of the +integrity-bound remove plan. Non-interactive mutation must identify its cleanup +mode explicitly; it must not broaden default `retain` behavior merely because a +general `--yes` flag is present. Referenced cleanup runs after managed-resource +cleanup so failure cannot damage a still-live Claw agent. + +If an operator explicitly uninstalls an artifact despite a Claw-reference +warning, canonical uninstall semantics win. The Claw becomes degraded and +status must report the missing dependency. Claw status or remove must not +silently reinstall it. + +Resource origin must remain current cleanup evidence while Claw dependency +edges remain. `remove-if-unused` eligibility is evaluated from resource origin, +current dependency edges, and canonical owner state, not from which Claw happens +to be removed last. Removal order must not change the result. + +Conversely, a later direct install or explicit operator adoption must add +independent ownership through the shared package lifecycle. Once independently +owned, the artifact is retained when no Claw dependency edge remains. A +Claw lifecycle must not infer that an idempotent direct install conveys no +ownership merely because the exact artifact was already present. + +The same dispositions apply to referenced MCP declarations. A newly created +Claw-managed MCP declaration is removed by default when unchanged; an identical +pre-existing MCP declaration is referenced and retained by default. Remove must +preserve locally modified files, unrelated MCP declarations, channel bindings, +credentials, operator settings, and any resource whose ownership or expected +state cannot be proven. Failed cleanup remains visible to status and +diagnostics. + +## Development Sources and Export + +A local unpackaged manifest may be inspected and, when explicitly supported, +added under a synthesized development identity. The consumer must record its +canonical source path and exact digest. A development identity must not be +mistaken for an authenticated registry identity. + +An unpacked development directory may select its manifest through a symlink +whose canonical target is a regular file inside that directory. This authoring +convenience is not publishable package content: registry artifacts continue to +reject links, and referenced workspace sources remain regular, non-linked +files. + +Export creates a new package directory and must fail if the output directory +already exists. It emits `package.json`, `CLAW.md`, and confined +workspace sources. Export includes only portable supported state and excludes +secrets, resolved environment values, models, providers, bindings, sessions, +logs, caches, and unrelated global configuration. + +Export may preserve an original package name and version only by returning the +byte-for-byte original artifact with the same digest. Any regenerated package, +including one exported from an unchanged installation, must use a new +development-safe or derivative identity and version so it does not impersonate +the publisher's immutable artifact. Publication under another publisher's +namespace remains forbidden regardless of local provenance. + +## Compatibility and Evolution + +Package v1 is identified by a manifest with `schemaVersion: 1` and the metadata +contract above. Registry transport may evolve independently as long as it still +delivers the exact identity, version, digest, and package bytes. + +Package and manifest v1 define the OpenClaw application profile. A different +harness may inspect the portable data or implement that complete profile, and a +future specification may define additional harness profiles. A consumer must +not claim v1 application conformance if it drops, translates approximately, or +cannot own a declared component. It may inspect such a package, but add must +fail the complete plan rather than silently degrade the Claw. + +## Registry Conformance + +A conforming registry must: + +- authenticate publication and bind it to exact package identity; +- enforce package containment and portable path collision rules; +- parse and validate the selected manifest strictly; +- verify every referenced source file; +- retain exact artifact length and SHA-256 integrity; +- keep public summaries derived from the artifact while allowing authorized + clients to retrieve the exact artifact for local manifest review; +- never imply that Claw approval bypasses dependency policy. + +## Client Conformance + +A conforming applying client must: + +- verify package identity, containment, manifest schema, and integrity locally; +- resolve exact dependencies before planning; +- expose a complete read-only plan and require explicit consent; +- bind mutation to the consented artifact, destinations, actions, and expected + owner state; +- preserve the one-package-one-new-agent invariant; +- delegate resources to canonical owners and record provenance; +- fail closed on collisions, unsupported components, and unsafe paths; +- distinguish applied state from local operational readiness; +- preserve drifted or independently owned state during update and remove; +- derive managed and referenced relationships from canonical owner state; +- retain referenced resources by default and bind any operator-selected + referenced cleanup into the exact remove plan; +- report partial outcomes and leave them diagnosable. From 89312305c60c574b55bd72f3b8d0005f2bb1a1ea Mon Sep 17 00:00:00 2001 From: Gio Della-Libera Date: Sun, 19 Jul 2026 10:41:00 -0700 Subject: [PATCH 3/6] docs(rfc): specify CLAW.md v1 --- rfcs/0016/claw-md-v1-spec.md | 446 +++++++++++++++++++++++++++++++++++ 1 file changed, 446 insertions(+) create mode 100644 rfcs/0016/claw-md-v1-spec.md diff --git a/rfcs/0016/claw-md-v1-spec.md b/rfcs/0016/claw-md-v1-spec.md new file mode 100644 index 00000000..30140359 --- /dev/null +++ b/rfcs/0016/claw-md-v1-spec.md @@ -0,0 +1,446 @@ +# CLAW.md v1 Specification + +This document is the implementer-facing manifest specification for RFC 0016, +Claws. The RFC explains the product model, ownership boundaries, lifecycle, and +rollout plan. This file defines the schema version 1 data contract shared by +OpenClaw and Claw registries and its human-readable `CLAW.md` envelope. + +Status: experimental draft, tied to RFC 0016. + +## Incubation Status + +The experimental implementation reads `CLAW.md` and equivalent grouped JSON, +and exports `CLAW.md`. Both forms use the existing +`OPENCLAW_EXPERIMENTAL_CLAWS=1` gate; there is no format-specific flag. + +`CLAW.md` is intentionally a thin serialization layer over the grouped schema. +It does not define separate lifecycle, ownership, provenance, or capability +semantics and introduces no new runtime dependency. Until the Claws gate is +removed, maintainers may revise or remove this envelope without preserving it +as a stable compatibility contract. Feedback remains welcome on the YAML +frontmatter boundary, Markdown-body role, portability, and authoring ergonomics. + +## Scope + +This specification defines: + +- how a `CLAW.md` document carries a machine-readable Claw manifest; +- the equivalent JSON representation; +- the grouped schema version 1 fields; +- strict parsing, defaults, and rejection behavior; +- portable path, package, MCP, and cron declarations; +- local prerequisite and diagnostic requirements; +- producer and consumer conformance requirements. + +This specification does not define: + +- package identity, archive layout, publication, or registry APIs; +- local add, update, remove, or provenance storage internals; +- credentials, channel bindings, models, providers, or completed OAuth state; +- a whole-instance export format; +- a generic harness-neutral runtime API. + +The enclosing package contract is defined by +[`claw-package-v1-spec.md`](claw-package-v1-spec.md). + +## Design Goals + +`CLAW.md` is intended to be understandable in a code review while remaining a +strict input to lifecycle tooling. Its Markdown body can explain the agent to a +human. Its YAML frontmatter is the only executable declaration. + +The same data model may also be represented as JSON. Markdown and JSON are two +serializations of one schema, not different capability levels. + +## File Identification and Encoding + +The canonical Markdown filename is `CLAW.md`. Consumers identify that filename +case-insensitively when selecting the Markdown parser. Other package-selected +manifest filenames are parsed as JSON. + +A `CLAW.md` file must be UTF-8 text. Consumers must accept zero or one leading +UTF-8 byte-order mark and must reject additional byte-order marks. The accepted +byte-order mark is ignored for frontmatter matching, but the original file bytes +remain part of every package or source integrity digest. + +## Document Envelope + +A `CLAW.md` document has this shape: + +```markdown +--- +schemaVersion: 1 +agent: + id: github-triage +--- + +# GitHub Triage + +This Claw creates an agent that triages GitHub issues. +``` + +The following rules apply: + +1. After an optional leading byte-order mark, the first line must be exactly + `---`. +2. The opening delimiter must be followed by LF or CRLF. +3. The YAML frontmatter ends at the next line containing exactly `---`. +4. The closing delimiter must be followed by LF, CRLF, or end of file. +5. The Markdown body after the closing delimiter is documentation only. A + consumer must not derive runtime behavior, package dependencies, policy, or + lifecycle actions from it. +6. Producers should include a short heading and description in the Markdown + body, but consumers must accept an empty body. + +## YAML Conversion + +Consumers must parse the frontmatter as one YAML 1.2 document using the YAML +1.2 Core Schema, then convert it to a JSON-compatible value before manifest +schema validation. A consumer must not apply YAML 1.1 scalar resolution; for +example, the unquoted v1 enum value `off` is a string, not a boolean. + +Consumers must reject: + +- malformed YAML; +- duplicate mapping keys; +- a frontmatter value that cannot be converted to JSON-compatible data; +- multiple YAML documents; +- anchors, aliases, merge keys, and explicit YAML tags; +- non-string mapping keys, non-finite numbers, and other values that have no + unambiguous JSON representation; +- any value that fails the strict manifest schema below. + +Consumers must not perform environment expansion, shell interpolation, +template evaluation, Markdown execution, or implicit package resolution while +parsing `CLAW.md`. Environment placeholders are retained as literal strings and +validated only where the schema permits them. + +## Top-Level Manifest + +The top-level value must be an object with these fields: + +| Field | Type | Required | Semantics | +| --- | --- | --- | --- | +| `schemaVersion` | integer | Yes | Must be exactly `1`. | +| `agent` | object | Yes | Portable configuration for the one new agent. | +| `workspace` | object | No | Bootstrap and supporting files. Defaults to empty. | +| `packages` | array | No | Exact skill and plugin dependencies. Defaults to empty. | +| `mcpServers` | object | No | Portable MCP declarations keyed by server name. Defaults to empty. | +| `cronJobs` | array | No | Agent-pinned scheduled work. Defaults to empty. | + +Unknown top-level or nested fields must be rejected. A producer must not use an +unknown field as a forward-compatible extension point. + +The manifest does not declare `managed`, `referenced`, ownership, uninstall, or +cleanup fields. The applying harness derives each resource relationship from +its kind and canonical owner state as specified by the package lifecycle. This +prevents package authors from claiming deletion authority over pre-existing or +shared host resources. Operator-selected referenced cleanup is remove-plan +input, not portable package content. + +## Agent + +`agent.id` is required. It must start with a lowercase ASCII letter, contain +only lowercase ASCII letters, digits, `_`, or `-`, and contain at most 64 +characters. It is the default local id; add still fails if that id or its +derived workspace is already in use. + +The portable agent object is: + +| Field | Type | Required | Constraints | +| --- | --- | --- | --- | +| `id` | string | Yes | Agent-id syntax above. | +| `name` | string | No | Non-empty after trimming. | +| `description` | string | No | Non-empty after trimming. | +| `identity.name` | string | No | Non-empty after trimming. | +| `identity.theme` | string | No | Non-empty after trimming. | +| `identity.emoji` | string | No | Non-empty after trimming. | +| `identity.avatar` | string | No | Non-empty portable avatar described below. | +| `groupChat.mentionPatterns` | string array | No | At least one non-empty string when present. | +| `sandbox.mode` | enum | No | `off`, `non-main`, or `all`. | +| `sandbox.scope` | enum | No | `session`, `agent`, or `shared`. | +| `sandbox.workspaceAccess` | enum | No | `none`, `ro`, or `rw`. | +| `tools.allow` | string array | No | At least one non-empty string when present. | +| `tools.deny` | string array | No | At least one non-empty string when present. | +| `heartbeat` | object | No | Exact portable heartbeat object below. | +| `humanDelay` | object | No | Exact portable human-delay object below. | + +All objects are strict. Consumers may accept empty optional objects, but +canonical producers must omit an optional object when none of its members are +present. + +`heartbeat` may contain only: + +| Field | Type | Constraints | +| --- | --- | --- | +| `every` | string | A non-negative OpenClaw duration using `ms`, `s`, `m`, `h`, or `d`; composite forms such as `1h30m` are allowed and a bare number means minutes. | +| `activeHours.start` | string | `HH:MM` in 24-hour form from `00:00` through `23:59`. | +| `activeHours.end` | string | `HH:MM` in 24-hour form from `00:00` through `24:00`; no other `24:xx` value is valid. | +| `activeHours.timezone` | string | Non-empty IANA timezone recognized by the scheduler. | +| `lightContext` | boolean | No additional constraint. | +| `isolatedSession` | boolean | No additional constraint. | +| `skipWhenBusy` | boolean | No additional constraint. | +| `timeoutSeconds` | integer | Greater than zero. | + +`humanDelay` may contain only `mode`, `minMs`, and `maxMs`. `mode`, when +present, is `off`, `natural`, or `custom`. The millisecond values are optional +non-negative integers. Version 1 imposes no relationship between them; runtime +behavior uses the declared values only when the selected mode requires them. + +`identity.avatar` may be an image data URL no larger than 2 MiB decoded or +2,796,230 characters encoded, or a workspace-relative path with a `.png`, +`.jpg`, `.jpeg`, `.gif`, `.webp`, or `.svg` extension. Remote URLs are not +portable v1 avatar values because their bytes are mutable and outside package +integrity. A workspace-relative avatar must exactly match a destination +declared in `workspace.files`. Its package source is then subject to the same +existence, containment, size, copy, digest, provenance, and drift rules as every +other managed workspace file. Consumers must reject an undeclared local avatar +path. + +The manifest must not declare models, providers, thinking levels, credentials, +channel accounts, channel bindings, local default selection, or an existing +workspace path. Those remain operator-owned. + +## Workspace + +`workspace.bootstrapFiles` maps canonical OpenClaw filenames to package +sources. The only v1 keys are: + +- `AGENTS.md` +- `SOUL.md` +- `IDENTITY.md` +- `TOOLS.md` +- `HEARTBEAT.md` + +Each value has one required `source` field. `workspace.files` contains objects +with required `source` and `path` fields. `source` is relative to the package +root; `path` is relative to the new agent workspace. + +Paths must be non-empty and relative. They must not contain absolute roots, +drive prefixes, empty segments, `.` segments, or `..` segments after `\` is +normalized to `/`. Package ingestion and local application must additionally +enforce realpath containment and reject unsafe filesystem objects as described +by the package specification. + +No two declarations may target the same workspace destination after `\` to `/` +normalization, Unicode NFC normalization, and locale-independent case folding. +Consumers must use that normalized value only as a collision key; they must +preserve the declared spelling when materializing an accepted path. A supporting +file must not target a canonical bootstrap filename already declared in +`bootstrapFiles` under the same comparison. + +## Packages + +Each `packages` entry has this exact shape: + +```yaml +- kind: skill + source: clawhub + ref: "@acme/issue-triage-playbook" + version: 1.4.0 +``` + +| Field | Type | Required | Semantics | +| --- | --- | --- | --- | +| `kind` | enum | Yes | `skill` or `plugin`. | +| `source` | enum | Yes | `clawhub` in schema version 1. | +| `ref` | string | Yes | Canonical immutable package coordinate assigned by the selected source. | +| `version` | string | Yes | Exact SemVer 2.0.0 version; ranges, tags, a leading `v`, and non-canonical numeric identifiers are forbidden. | + +The source's canonicalization rules produce the identity key for `ref`; display +slugs and aliases are not identity. The tuple `(kind, source, canonical ref)` +must be unique within a manifest. Every package is required. The declaration +does not bypass source policy, scanning, compatibility checks, or the existing +skill/plugin installer. + +## MCP Servers + +`mcpServers` is keyed by a stable local server name using the same identifier +rules as `agent.id`. + +A stdio server requires `command` and may declare: + +- `transport: stdio`; +- `args` as an array of non-empty strings; +- `env` as a map whose values are literal `${ENV_VAR}` references; +- `toolFilter.include` and `toolFilter.exclude` arrays; +- finite positive `timeout` and `connectTimeout` values in seconds. + +`command` and `args` are an executable plus literal argument vector. Consumers +must not pass them through a shell or perform variable, glob, home-directory, or +command substitution. Inspection and add must not launch the server. A package +manager command that names a downloadable artifact must use an exact immutable +version; a floating tag or range blocks the plan. + +Environment keys must match `[A-Za-z_][A-Za-z0-9_]*`. Each value must match +`${[A-Z_][A-Z0-9_]*}` exactly. Literal secret values are forbidden. The applying +client must evaluate keys through its canonical spawned-process environment +safety policy; a blocked key blocks the Claw plan rather than being silently +dropped. + +A remote server requires a URL and `transport` equal to `sse` or +`streamable-http`. The URL must use HTTPS, except that HTTP is allowed when the +hostname is exactly `localhost`, `127.0.0.1`, or `[::1]`. User information and +fragments are forbidden. A remote server may declare `auth: oauth`, tool +filters, and finite positive timeouts in seconds. It must not carry +authorization headers, bearer tokens, client secrets, or completed OAuth state. + +The stdio and remote shapes are mutually exclusive. A stdio declaration must +not contain `url` or `auth`; a remote declaration must not contain `command`, +`args`, or `env`. A consumer must reject a mixed declaration rather than choose +one transport by field order or precedence. + +`toolFilter.include` and `toolFilter.exclude`, when present, each contain at +least one unique non-empty exact tool name or simple `*` glob. A simple glob is +matched against the complete tool name, treats `*` as the only wildcard, and +treats every other character literally; `?`, character classes, and path +semantics are not supported. `include` first limits the discovered set and +`exclude` then removes matches, so exclusion wins when both match. Duplicate +filter entries must be rejected after exact string comparison. + +Unresolved environment references and `auth: oauth` are local prerequisites, +not embedded credentials. Dry-run must list their names and affected server +without resolving or printing secret values. Add may complete after safely +writing the declaration, but status must report the server as `requires-local- +configuration` until every required environment value exists and OAuth login, +when declared, is complete. An applied Claw is not necessarily ready to run. + +## Cron Jobs + +Each cron job contains: + +| Field | Type | Required | Semantics | +| --- | --- | --- | --- | +| `id` | string | Yes | Manifest-local stable id using agent-id syntax. | +| `name` | string | No | Display name. | +| `schedule.cron` | string | Yes | Valid cron expression. | +| `schedule.timezone` | string | Yes | Non-empty IANA timezone recognized by the scheduler. | +| `session` | enum | Yes | `main` or `isolated`. | +| `message` | string | Yes | Non-empty scheduled input. | +| `delivery.mode` | enum | No | `none` or `announce`. | +| `delivery.channel` | enum | No | `last` in schema version 1. | + +Cron ids must be unique. The lifecycle pins each created scheduler record to +the final local agent id; the manifest does not carry a channel account or +binding. + +`schedule.cron` must be a portable five-field minute/hour/day-of-month/month/ +day-of-week expression. Host-local timezone defaults are forbidden. `delivery` +may be omitted, may be `{ mode: none }`, or may be +`{ mode: announce, channel: last }`; `channel` is forbidden for `none` and +required for `announce`. Dry-run must identify that `last` resolves through +local channel state and does not embed a binding. + +## Complete Example + +```markdown +--- +schemaVersion: 1 +agent: + id: github-triage + name: GitHub Triage + description: Reviews incoming issues and prepares a daily summary. + tools: + allow: [read, write, web_fetch] + deny: [exec] + heartbeat: + every: 30m +workspace: + bootstrapFiles: + AGENTS.md: + source: workspace/AGENTS.md + SOUL.md: + source: workspace/SOUL.md + files: + - source: workspace/reference/triage-policy.md + path: reference/triage-policy.md +packages: + - kind: skill + source: clawhub + ref: "@acme/issue-triage-playbook" + version: 1.4.0 + - kind: plugin + source: clawhub + ref: "@openclaw/github" + version: 2.1.0 +mcpServers: + github: + command: npx + args: [--yes, "@acme/github-mcp@3.4.1"] + env: + GITHUB_TOKEN: "${GITHUB_TOKEN}" +cronJobs: + - id: daily-triage + schedule: + cron: "0 9 * * 1-5" + timezone: America/Los_Angeles + session: isolated + message: Review new issues and prepare the daily triage summary. + delivery: + mode: announce + channel: last +--- + +# GitHub Triage + +Adds one GitHub triage agent and the reviewed resources it needs. +``` + +## JSON Compatibility + +The package contract may point `openclaw.claw` at a JSON file containing the +grouped top-level object. JSON input passes through the same strict schema, +defaults, diagnostics, and lifecycle. `CLAW.md` and JSON are two serializations +of the same schema version, not different capability levels. + +## Compatibility and Evolution + +Schema evolution requires a new integer `schemaVersion`. Consumers must reject +unsupported versions rather than partially apply them. New optional fields must +not be added to version 1 because strict v1 consumers reject unknown fields. + +There is no canonical byte serialization. Producers should emit stable field +ordering and formatting for reviewable diffs, but semantic equality is based on +the parsed manifest. Artifact and source integrity remains byte-based. + +## Diagnostics + +Every rejection must identify a machine-readable code that remains stable for +the specification major version, the validation phase, and the most specific +manifest or package path available. Human messages must explain the violated +rule and a corrective action without including secret values or raw sensitive +owner errors. Consumers should return all independently actionable schema +findings from one read, but must stop before policy checks or mutation when +parsing or schema validation fails. + +Diagnostics are not an extension mechanism. A warning must not permit a +consumer to ignore an unknown field, unsupported component, unsafe path, or +missing required package source and still call the Claw valid. + +## Consumer Conformance + +A conforming consumer must: + +- parse the `CLAW.md` envelope and equivalent grouped JSON form as specified; +- reject duplicate YAML keys and unknown schema fields; +- validate all identifiers, exact versions, paths, environment references, + cron expressions, timezones, and uniqueness constraints; +- ignore the Markdown body for runtime behavior; +- preserve original bytes for integrity calculations; +- report unresolved environment and OAuth prerequisites without reading or + persisting their values; +- emit actionable diagnostics without exposing resolved secrets; +- reject an unsupported schema version before planning mutation. + +## Producer Conformance + +A conforming producer must: + +- emit UTF-8 `CLAW.md` with one YAML frontmatter block; +- emit only schema version 1 fields and exact dependency versions; +- keep all referenced workspace sources inside the enclosing package; +- use exact package and package-manager dependency versions and explicit cron + timezones; +- place human explanation, not executable declarations, in the Markdown body; +- exclude credentials and operator-owned runtime choices; +- validate the result against this specification before publication or export. From 9924dec5a67e374e7d9eedd56f221c4bab37ec87 Mon Sep 17 00:00:00 2001 From: Gio Della-Libera Date: Sun, 19 Jul 2026 13:00:36 -0700 Subject: [PATCH 4/6] docs(rfc): tighten Claw lifecycle safety --- rfcs/0016-claws.md | 55 +++++++++++++++++++++---------- rfcs/0016/claw-md-v1-spec.md | 2 ++ rfcs/0016/claw-package-v1-spec.md | 29 ++++++++++++---- 3 files changed, 62 insertions(+), 24 deletions(-) diff --git a/rfcs/0016-claws.md b/rfcs/0016-claws.md index d23a8fa2..88d40eb4 100644 --- a/rfcs/0016-claws.md +++ b/rfcs/0016-claws.md @@ -281,7 +281,7 @@ The initial public shape is grouped by OpenClaw ownership boundary: "mcpServers": { "github-triage-github": { "command": "npx", - "args": ["-y", "@acme/github-mcp"], + "args": ["-y", "@acme/github-mcp@3.4.1"], "env": { "GITHUB_TOKEN": "${GITHUB_TOKEN}" }, @@ -413,7 +413,7 @@ defaults and agents: "servers": { "github-triage-github": { "command": "npx", - "args": ["-y", "@acme/github-mcp"], + "args": ["-y", "@acme/github-mcp@3.4.1"], "env": { "GITHUB_TOKEN": "${GITHUB_TOKEN}" } @@ -603,7 +603,7 @@ resources by default; `--remove-unused`, repeatable `--remove-referenced`, and `--force-referenced` select stronger cleanup in both preview and mutation so the choice is included in the plan digest. `--yes` alone never broadens a plan. -Add ordering is transactional where owner APIs permit it and compensating where +Add ordering is transactional where owner APIs permit it and resumable where external installers or the scheduler cannot share one transaction: 1. Validate package metadata and manifest. @@ -617,10 +617,12 @@ external installers or the scheduler cannot share one transaction: 9. Create agent-pinned cron jobs. 10. Persist one complete apply record and per-resource provenance. -Any failure stops later phases. Successfully created external resources are -recorded immediately so doctor and remove can explain and clean a partial add. -The result distinguishes complete, partial, and failed adds; it never reports a -partial agent as successfully added. +Any failure stops later phases. Pending provenance is written before external +mutation and successful resources are recorded immediately. Safe local +pre-commit work may be compensated, but a completed or uncertain owner mutation +is retained for deterministic resume, doctor, or remove rather than hidden by a +best-effort rollback. The result distinguishes complete, partial, and failed +adds; it never reports a partial agent as successfully added. ### Provenance and local state @@ -663,12 +665,18 @@ ids, exact package refs, and agent/root provenance compare-and-swap checks. Workspace checks include expected file presence as well as content. Before an external package installer runs, OpenClaw atomically replaces the expected package reference with a pending ownership claim; concurrent ownership changes -abort before installation, and installer failure compensates the claim. -Completed owners compensate in reverse order when a later owner fails. A -thrown config or Gateway call has an uncertain commit outcome, and an installed -package artifact cannot be assumed rolled back merely because its reference was -restored. These cases return an explicit partial result rather than claiming -cross-owner atomicity. +abort before installation. Once the installer boundary is crossed, failure +retains pending or failed provenance because the artifact outcome may be +uncertain. +Completed owners compensate in reverse order only when the canonical owner can +prove the inverse operation is safe. A thrown config or Gateway call has an +uncertain commit outcome, and an installed package artifact cannot be assumed +rolled back merely because its reference was restored. Pending owner provenance +and a partial root status are retained in these cases so status, doctor, and a +retry can reconcile the actual state rather than claiming cross-owner atomicity. +Removing a package declaration during update releases the Claw dependency edge; +artifact uninstall is a separately planned remove operation, never an update +side effect. Remove first produces a plan. Managed resources are selected for cleanup by default: it removes agent-pinned cron jobs, unchanged Claw-managed MCP @@ -723,7 +731,7 @@ must share the schema and fixtures rather than maintain divergent validators. - Secrets and resolved environment values never enter plans or provenance. - MCP config writes use validated, concurrent-write-safe config APIs. - Cron jobs require explicit consent, visible cadence/action previews, stable - ownership, and disable/remove handles. + ownership, live-definition revalidation, and disable/remove handles. - Config mutation preserves `agents.defaults`, existing `agents.list[]` entries, channel bindings, and unrelated plugin/MCP settings. - Partial adds persist enough state for diagnosis and cleanup. @@ -736,9 +744,14 @@ must share the schema and fixtures rather than maintain divergent validators. `--plan-integrity` binds the exact separately disclosed capability set as well as ordinary content reconciliation. Other hosts may require a separate dialog or aggregate those records before mutating multiple agents. +- ClawHub trust warnings and resolved dependency identity are part of the + separately disclosed capability effect and plan integrity. The Claw CLI's + exact plan confirmation may acknowledge that warning; an internal + `acknowledge` parameter must not make the warning disappear from preview. - Claws do not introduce capability-specific resource quotas. Existing - canonical owner limits apply; bounded package, manifest, extraction, and plan - sizes remain parser and resource-safety policy. + canonical owner limits apply. Claw manifests are limited to 1 MiB and package + metadata to 256 KiB; extraction, managed workspace, and plan limits remain + parser and resource-safety policy. ## Rationale @@ -895,8 +908,9 @@ The RFC implementation is acceptable when tests and real CLI proof demonstrate: 13. Status and doctor explain agent, workspace, package, MCP, cron, and managed file drift. 14. Update changes only Claw-owned state, preserves local/operator edits, - revalidates owner state before mutation, compensates completed owners in - reverse order, and reports uncertain or irreversible outcomes as partial. + revalidates owner state before mutation, compensates only safely reversible + completed owners, retains uncertain provenance, and reports uncertain or + irreversible outcomes as partial. 15. Remove uses canonical owner lifecycles, selects managed resources for cleanup, retains referenced resources by default, offers integrity-bound `remove-if-unused` and explicitly selected referenced cleanup, warns about @@ -918,6 +932,11 @@ The RFC implementation is acceptable when tests and real CLI proof demonstrate: authoring/export representation or should export return to grouped JSON? - What exact default workspace naming rule should resolve cross-platform path and case-folding collisions? +- Should ordinary `agents delete` eventually delegate attached-Claw recurring + work cleanup, or remain distinct from the provenance-aware `claws remove` + lifecycle? +- Should a future audit/history feature retain removed Claw tombstones? V1 keeps + current ownership and incomplete recovery state only. - Which cron delivery modes are portable without embedding local channel bindings? - What package transports should mutating v1 support beyond ClawHub and local diff --git a/rfcs/0016/claw-md-v1-spec.md b/rfcs/0016/claw-md-v1-spec.md index 30140359..0e4f395e 100644 --- a/rfcs/0016/claw-md-v1-spec.md +++ b/rfcs/0016/claw-md-v1-spec.md @@ -427,6 +427,8 @@ A conforming consumer must: cron expressions, timezones, and uniqueness constraints; - ignore the Markdown body for runtime behavior; - preserve original bytes for integrity calculations; +- reject a `CLAW.md` file larger than 1 MiB before parsing, including when it + grows during the read; - report unresolved environment and OAuth prerequisites without reading or persisting their values; - emit actionable diagnostics without exposing resolved secrets; diff --git a/rfcs/0016/claw-package-v1-spec.md b/rfcs/0016/claw-package-v1-spec.md index 3dedfc2b..c6524a5d 100644 --- a/rfcs/0016/claw-package-v1-spec.md +++ b/rfcs/0016/claw-package-v1-spec.md @@ -260,6 +260,8 @@ identity and integrity; workspace source, destination, and content digest; MCP transport, executable and literal arguments or remote URL, environment variable names, authentication mode, and tool filters; and cron schedule, timezone, session, message, and delivery behavior. Secret values must remain undisclosed. +Any registry trust warning associated with a resolved package is part of that +effect and must remain visible in both machine-readable and human preview. Capability escalation is classified consistently across owners. Adding executable package code, plugin or tool access, an MCP execution or network @@ -289,7 +291,8 @@ ordinary package installer. Consent must bind to the exact package or development snapshot digest, final agent id, workspace, action set, and expected local owner state shown in the plan. Immediately before mutation, the client must rebuild or revalidate those -inputs. A change to any consented digest, destination, package owner, owner +inputs. Resolved dependency integrity, install identity, and trust warning are +included in that binding. A change to any consented digest, destination, package owner, owner configuration value, scheduler record, or file-presence expectation invalidates consent and requires a new plan; the client must not silently apply a materially different plan. @@ -358,10 +361,11 @@ A conforming add implementation must: - record successful external mutations as they occur; - report a partial result when owners cannot share one atomic transaction. -On failure, add must stop later owners, compensate completed mutations in -reverse order where the canonical owner supports safe compensation, and retain -provenance for every uncertain or uncompensated result. It must not report a -partially created agent as successfully added. +On failure, add must stop later owners and compensate only work whose canonical +owner can prove a safe inverse. Completed or uncertain external mutations remain +in resumable provenance with a partial root status. A retry, doctor, or remove +uses that current state; add must not report a partially created agent as +successfully added. ## Update Semantics @@ -387,7 +391,20 @@ direct owner requires a different version. Removing a package declaration during update releases that Claw's reference. It does not imply artifact uninstall during the update transaction. Irreversible -or uncertain owner outcomes must be reported as partial. +or uncertain owner outcomes must be retained in current provenance and reported +as `status: partial`, including in structured CLI output. + +Before changing or removing a scheduler record, update and remove must read the +live record through the scheduler owner and compare its owned definition with +provenance. Operator-modified jobs are conflicts and must not be overwritten or +deleted. + +## Resource Limits + +A consumer must reject a Claw manifest larger than 1 MiB and package metadata +larger than 256 KiB before parsing. Reads must remain bounded if a file grows +after an initial metadata check. Existing canonical extraction, workspace-file, +aggregate-workspace, and plan-output limits continue to apply. ## Remove Semantics From bb6b3e506056a254f87d995ab9e8f78540c16d45 Mon Sep 17 00:00:00 2001 From: Gio Della-Libera Date: Sun, 19 Jul 2026 18:05:26 -0700 Subject: [PATCH 5/6] docs(claws): clarify registry artifact storage --- rfcs/0016/claw-package-v1-spec.md | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/rfcs/0016/claw-package-v1-spec.md b/rfcs/0016/claw-package-v1-spec.md index c6524a5d..ab233a67 100644 --- a/rfcs/0016/claw-package-v1-spec.md +++ b/rfcs/0016/claw-package-v1-spec.md @@ -186,7 +186,12 @@ A conforming registry must validate a publication in this order: scanning rules. 9. Compute and retain the immutable artifact digest over the exact distributed artifact bytes. -10. Store the validated full manifest separately from its public safe summary. +10. Store a bounded public safe summary derived from the validated manifest. + +The exact artifact remains the authoritative stored declaration. A registry is +not required to duplicate the parsed full manifest into its metadata store; if +it does, that copy must remain private and must fit the registry's documented +storage limits without truncation. Validation is all-or-nothing. A registry must not publish a partial package or silently discard unsupported manifest fields or components. @@ -201,6 +206,10 @@ registry supplies an expected length. Floating tags and version ranges may be discovery inputs, but they must be resolved before a managed lifecycle plan is produced. +Artifact metadata must identify the archive format or transport kind. A +consumer must select its bounded safe extractor from that metadata and must not +assume that every registry artifact uses the same archive format. + The registry artifact digest covers the exact distributed artifact bytes. The trusted registry or signed feed binds that digest to package identity; the digest alone proves byte equality, not publisher identity, review, or safety. @@ -513,8 +522,10 @@ A conforming registry must: - parse and validate the selected manifest strictly; - verify every referenced source file; - retain exact artifact length and SHA-256 integrity; -- keep public summaries derived from the artifact while allowing authorized - clients to retrieve the exact artifact for local manifest review; +- retain a bounded public summary derived from the validated artifact without + requiring a second full-manifest copy in registry metadata; +- allow authorized clients to retrieve the exact artifact for local manifest + review; - never imply that Claw approval bypasses dependency policy. ## Client Conformance From e9c2bb478179822132bff54876ff60613d2d4665 Mon Sep 17 00:00:00 2001 From: Gio Della-Libera Date: Sun, 19 Jul 2026 21:04:50 -0700 Subject: [PATCH 6/6] docs(claws): separate experimental feed contract --- rfcs/0016-claws.md | 38 ++++++++++++++++++++++--------- rfcs/0016/claw-package-v1-spec.md | 7 ++++++ 2 files changed, 34 insertions(+), 11 deletions(-) diff --git a/rfcs/0016-claws.md b/rfcs/0016-claws.md index 88d40eb4..e19633e2 100644 --- a/rfcs/0016-claws.md +++ b/rfcs/0016-claws.md @@ -700,10 +700,13 @@ manifest. ### Feeds, catalogs, and ClawHub -RFC 0009 feeds remain the discovery and policy layer. A feed may expose a Claw -package, pin an exact version, recommend or block it, and independently block or -substitute package dependencies. Approval of the Claw does not transitively -approve its skills or plugins. +RFC 0009 feeds remain the conceptual discovery and policy layer. A feed may +expose a Claw package, pin an exact version, recommend or block it, and +independently block or substitute package dependencies. Approval of the Claw +does not transitively approve its skills or plugins. While Claws are +experimental, ClawHub uses a separate gated Claw feed parser, serializer, feed +id, and route rather than adding `type: "claw"` to RFC 0009's stable plugin and +skill feed schema version 1. That feed boundary is intentionally narrower than the complete Control UI experience. Hosted feeds currently provide official plugin and skill catalog @@ -859,15 +862,28 @@ ClawHub follows the OpenClaw schema and lifecycle contract in four ordered PRs: 2. [#3090](https://github.com/openclaw/clawhub/pull/3090) - guarded publication, package ingestion, source-file checks, CLI authoring support, and author guidance. It also owns the fail-closed public-read boundary while disabled - and strips full manifests from every public release serializer. + and strips full manifests from every public release serializer. Publication + retains the exact immutable artifact bytes and bounded summary, validates + every package path, requires exact manifest/source spelling, applies strict + UTF-8 and pre-parse size limits, and accepts Claw npm packs without requiring + a plugin manifest. 3. [#3091](https://github.com/openclaw/clawhub/pull/3091) - enabled search, - detail, and version APIs that expose only safe summaries. + detail, and version APIs that expose only the latest or requested release's + bounded summary. 4. [#3092](https://github.com/openclaw/clawhub/pull/3092) - separately gated - hosted Claw feed with safe summaries and exact artifact digests, plus a - repeatable published-package proof through real OpenClaw add dry-run. The - proof rejects unsafe paths, links, and special archive entries before - extraction, and the unversioned feed URL permanently redirects to the - versioned route. + hosted Claw feed with its own experimental wire contract, safe summaries, + and exact artifact digests, plus a repeatable published-package proof through + real OpenClaw add dry-run. The versioned route is gated before publication + lookup and has no ungated unversioned redirect. The proof bounds download, + entry count, per-file and aggregate expansion; rejects unsafe or colliding + paths, links, and special archive entries; and supports npm-pack and legacy + ZIP package roots. + +The #3092 proof is a registry-to-OpenClaw bridge: it selects an exact candidate +from the experimental Claw feed, verifies and extracts the artifact, then hands +the package directory to OpenClaw. It proves that the published package produces +a real non-mutating OpenClaw plan; native OpenClaw Claw-feed resolution remains +a separate dependent integration. The ClawHub runtime surfaces in this track require `CLAWHUB_EXPERIMENTAL_CLAWS=1`. The deployment gate is independent of diff --git a/rfcs/0016/claw-package-v1-spec.md b/rfcs/0016/claw-package-v1-spec.md index ab233a67..c04dbdbc 100644 --- a/rfcs/0016/claw-package-v1-spec.md +++ b/rfcs/0016/claw-package-v1-spec.md @@ -248,6 +248,13 @@ Registry approval of a Claw must not transitively approve a skill or plugin dependency. The client must resolve and evaluate every dependency through its normal policy and installer path. +During experimentation, a registry must not redefine an already published +stable plugin/skill feed schema by adding a Claw entry variant under the same +schema version. It may publish Claws through a separately identified, gated, +and versioned experimental feed contract. A disabled deployment must fail +closed before reading or serving stored Claw feed state, and an ungated edge +redirect must not expose the experimental route indirectly. + Public search and release APIs should expose a bounded, derived summary for indexing. Before consent, the applying client must make the exact grouped manifest available for review and display its complete package effects from the