Skip to content

[Enhancement] Add privacy/visibility controls for agent-owned skills #1009

@clark-cant

Description

@clark-cant

[Enhancement] Add privacy/visibility controls for agent-owned skills

Context

GoClaw's skill system already has a visibility field in the database schema and returns it in the skills.list and skills.get RPC responses. However, there is currently no way for an agent to set or modify the visibility of a skill it owns.

The current behavior:

  • System skills are always visibility = 'public' (hardcoded in the seeder)
  • Custom skills uploaded via publish_skill get registered but the agent has no control over who can discover or use them
  • The skills.update RPC method exists (internal/gateway/methods/skills.go:149) and accepts visibility in the updates map, but there is no user-facing mechanism (CLI command, UI, or agent tool) to change it

Current Codebase State

Component Status Location
visibility column in DB ✅ Exists skills table
skills.update RPC method ✅ Exists internal/gateway/methods/skills.go:149
Ownership check for updates ✅ Exists skillOwnerGetter interface + owner validation
publish_skill tool ⚠️ Partial Registers skill but no visibility parameter
CLI skills commands ❌ Missing No goclaw skills set-privacy or similar
Agent tool for visibility ❌ Missing No skill_manage action for privacy

Proposed Solution

Add privacy/visibility controls that allow agents to set and modify the visibility of skills they own.

1. Extend publish_skill Tool

Add an optional visibility parameter to the publish_skill tool:

publish_skill(path: str, visibility: str = "private")

Supported values:

  • "private" — Only visible to the owning agent (default for newly published skills)
  • "team" — Visible to all agents in the same team/workspace
  • "public" — Visible to all agents across all tenants (current behavior for system skills)

2. Extend skill_manage Tool

Add a new action for modifying skill privacy:

skill_manage(action="set-privacy", slug="<slug>", visibility="private|team|public")

This reuses the existing skills.update RPC method which already:

  • Checks ownership via skillOwnerGetter
  • Rejects non-owner/non-admin updates
  • Supports updating visibility field

3. CLI Command (optional)

goclaw skills set-privacy <slug> --visibility private|team|public
goclaw skills list --visibility private   # filter by visibility

4. UI Integration (optional)

The skills page in the web UI should display the current visibility and provide a dropdown to change it (for skill owners).

Mermaid Diagram

flowchart TD
    A[Agent publishes skill] --> B{visibility param?}
    B -->|Not set| C[Default: private]
    B -->|Set| D[Use provided value]
    C --> E[publish_skill registers skill]
    D --> E
    E --> F[Skill stored with visibility field]
    F --> G{skill_manage set-privacy?}
    G -->|Yes| H[skills.update RPC with ownership check]
    H --> I[Update visibility in DB]
    G -->|No| J[Keep current visibility]
    I --> K[BumpVersion + cache invalidation]
    J --> K
    K --> L[skill.search respects visibility filter]
Loading

Visibility Filter Logic

The skill_search tool and agent skill injection (resolveSkillsSummary) should filter based on visibility:

Caller context Can see skills with visibility
Skill owner private, team, public
Same team member team, public
Other tenant public only
System (admin) All

Security Considerations

Authentication/Authorization: Existing skills.update ownership check is sufficient — only the skill owner or admin can change visibility. This is already implemented in handleUpdate() via skillOwnerGetter.

Data Exposure: private skills must NOT appear in skill_search results for non-owners. The current SearchByEmbedding() and BM25 search in internal/skills/search.go need to include a visibility filter in their SQL queries.

Input Validation: visibility must be validated against the allowed enum values (private, team, public). Invalid values should return ErrInvalidRequest.

Injection Risks: Low — visibility is a simple string field stored in the DB. No SQL injection risk with parameterized queries.

CORS/CSP Impact: None.

Rate Limiting: None needed — visibility changes are infrequent admin/owner operations.

Audit Trail: Visibility changes should be logged via the existing audit system (logAudit) since they affect skill discoverability.

Implementation Considerations

  • Scope: publish_skill tool + skill_manage tool + search filter
  • Breaking changes: No — default private is more restrictive, existing public skills remain unchanged
  • Migration needed: Optional — could set existing custom skills to private by default, or keep current behavior
  • Tests affected: skills_test.go, search_test.go, skill_publish_test.go

References

  • Skills RPC methods: internal/gateway/methods/skills.go
  • Skill seeder: internal/skills/seeder.go
  • Skill search: internal/skills/search.go
  • Core skills system docs: docs/15-core-skills-system.md
  • Skill publishing docs: docs/16-skill-publishing.md

Unresolved Questions

  1. Should the default visibility for newly published skills be private (safer) or public (current implicit behavior)?
  2. Should team visibility use the existing team/workspace boundary, or should it be tenant-scoped?
  3. Should there be a skills.list --mine filter to show only skills owned by the calling agent?
  4. Should visibility changes trigger a BumpVersion() to invalidate the skill list cache? (Likely yes, but worth confirming.)

Representing @mrgoonie (Duy /zuey/)


Tóm tắt: Hệ thống skill đã có cột visibility trong DB và RPC method skills.update hỗ trợ cập nhật, nhưng agent không có cách nào để set hoặc thay đổi privacy của skill mà nó sở hữu. Đề xuất thêm visibility param cho publish_skill, action set-privacy cho skill_manage, và filter visibility trong skill search.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions