Skip to content

fix(adapters) namespace workspace skill per agent so uploads carry the right identity - #571

Merged
zomux merged 1 commit into
developfrom
bugfix/per-agent-workspace-skill-identity
Jul 28, 2026
Merged

fix(adapters) namespace workspace skill per agent so uploads carry the right identity#571
zomux merged 1 commit into
developfrom
bugfix/per-agent-workspace-skill-identity

Conversation

@QuanCheng-QC

Copy link
Copy Markdown
Collaborator

Problem

Agents configured with the same working directory all wrote the SAME workspace skill file (.claude/skills/openagents-workspace.md), whose curl commands embed the writing agent's upload identity (source=openagents:<agent>). Whichever agent wrote last stamped its name into every other agent's file uploads — files generated by one agent showed up in the workspace Files list attributed to another (e.g. a doc produced by qiyue-bot listed as uploaded by cherie-bot). A resumed Claude session that had once read a wrongly-stamped skill kept the wrong curl identity in its context indefinitely, so the misattribution persisted even when the other agent was idle.

Chat replies were never affected — the adapter posts those itself under its own name — which is why the mismatch only ever showed up on files.

Fix

  • Skill files and their frontmatter names are now per-agent (openagents-workspace-<agent>), mirroring what the OpenClaw adapter already did. System-prompt references follow the per-agent name, and the legacy shared-name file is deleted on write so a stale copy with another agent's identity can never be read again. (claude, cursor, opencode; openclaw switched to the shared helper)
  • Skill names satisfy the Agent Skills naming rules — lowercase kebab-case, no consecutive/leading/trailing hyphens, max 64 chars. Lossy normalization or truncation appends a stable short hash of the raw name so distinct agents (My_Agent vs my-agent) can never converge on one skill. Already-valid names stay readable with no hash suffix.
  • Cursor has no system-prompt flag, so every spawn now prepends an identity header pinning the agent name and the exact skill to follow — otherwise the CLI learns who it is only from whichever coexisting skill it happens to open.
  • OpenClaw migration removes the pre-normalization raw-name skill dir, guarded by a safe-charset check, a skills-root containment check, and an ownership proof read from the stored SKILL.md (quote-delimited exact identity match) — covering path traversal and Windows/macOS case-insensitive aliasing (agent Foo's legacy path being agent foo's live dir).

Known accepted limitation

The naming encoding is not closed — a verbatim legal name can in principle equal another name's <stem>-<hash8> output. Triggering it takes a ~2^-32 accident or editing daemon.yaml, which already grants direct access to every skill file and token. Hashing every name would close the gap but was rejected in favor of readable skill names; documented in workspaceSkillName.

Tests

19 new tests in test/workspace-prompt.test.js: per-agent naming and identity embedding across all four builders, spec compliance for hostile names, collision resistance, determinism, coexisting cursor skills keeping separate identities, the pinned cursor identity header, claude legacy-file cleanup, and openclaw migration (rename, case-alias regression, unprovable ownership, path traversal). OpenClaw tests sandbox the state dir at prototype level so construction never touches a real ~/.openclaw.

Full suite 715/715 passing.

…e right identity

Agents sharing a working directory all wrote the SAME skill file
(.claude/skills/openagents-workspace.md), whose curl commands embed the
writing agent's upload identity — whichever agent wrote last stamped its
name into every other agent's file uploads, so files one agent created were
attributed to another in the workspace Files list. A resumed Claude session
that had once read a wrongly-stamped skill kept the wrong identity in
context indefinitely. Chat replies were never affected — the adapter posts
those itself under its own name — which is why the mismatch only showed up
on files.

Skill files and frontmatter names are now per-agent
(openagents-workspace-<agent>), mirroring what OpenClaw already did, with
system-prompt references following suit and the legacy shared-name file
deleted on write. Names satisfy the Agent Skills rules (lowercase
kebab-case, max 64 chars); lossy normalization or truncation appends a
stable short hash of the raw name so distinct agents (My_Agent vs my-agent)
can never converge on one skill, while already-valid names stay readable.
The remaining theoretical collision (a verbatim name equal to another's
stem-plus-hash output, ~2^-32 or requires editing daemon.yaml which already
grants full access) is documented as an accepted tradeoff.

Cursor has no system-prompt flag and previously learned its identity ONLY
from whichever coexisting skill it happened to open — every spawn now
prepends a header pinning the agent name and the exact skill to follow.

OpenClaw migration removes the pre-normalization raw-name skill dir,
guarded by a safe-charset check, a skills-root containment check (agent
names are unvalidated, so the raw name must not let the join escape before
a recursive delete), and an ownership proof read from the stored SKILL.md
(quote-delimited exact identity match) — covering path traversal and the
Windows/macOS case-alias where agent Foo's legacy path IS agent foo's live
dir. When ownership cannot be proven the dir is left in place.

Adds 19 tests — per-agent naming and identity across all four builders,
spec compliance for hostile names, collision resistance, determinism,
coexisting cursor skills, the pinned cursor header, claude legacy-file
cleanup, and openclaw migration (rename, case-alias regression, unprovable
ownership, traversal). OpenClaw tests sandbox the state dir at prototype
level so construction never touches a real ~/.openclaw.
@vercel

vercel Bot commented Jul 28, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
openagents-workspace Ready Ready Preview, Comment Jul 28, 2026 11:51am

Request Review

@zomux zomux left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed in depth. Fixes a real identity-misattribution bug (agents sharing a working dir clobbered one shared skill file → uploads stamped with the last writer's identity). Per-agent skill naming with a sha256 suffix on lossy/truncated normalization prevents distinct names converging (documented 2^-32 limitation is acceptable). Security-sensitive file deletions are well-guarded: Claude legacy cleanup uses a constant filename (no traversal); the OpenClaw recursive rmSync is gated by legacy!=current + safe charset + direct-child containment + an ownership proof read from the stored SKILL.md (defends case-insensitive FS aliasing). Traced the agentName='..' edge — resolves to a harmless single-segment dir, not a traversal escape. 19 tests cover naming/identity across all four builders, hostile names, collision resistance, cursor coexistence, and the OpenClaw migration incl. path traversal + case-alias + unprovable-ownership. Full suite 715/715. LGTM.

@zomux
zomux merged commit c452947 into develop Jul 28, 2026
14 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants