Skip to content

feat: support global Agent skills#9272

Draft
Soulter wants to merge 1 commit into
masterfrom
agent/support-global-agent-skills
Draft

feat: support global Agent skills#9272
Soulter wants to merge 1 commit into
masterfrom
agent/support-global-agent-skills

Conversation

@Soulter

@Soulter Soulter commented Jul 14, 2026

Copy link
Copy Markdown
Member

What changed

  • Discover read-only skills from ~/.agent/skills and workspace .agent/skills directories.
  • Preserve existing local, plugin, sandbox, and legacy workspace skill behavior.
  • Expose global skill source metadata and read-only state in the dashboard.
  • Add tests for discovery, precedence, sandbox metadata, and read-only file access.

Why

Users can have Agent-managed skills outside AstrBot's editable skills directory. AstrBot should display and allow reading those skills without treating them as editable or downloadable local skills.

Impact

Global Agent skills become visible in skill management and can be inspected safely. Delete, edit, and download mutations remain blocked for externally managed sources.

Validation

  • ruff format .
  • ruff check .
  • pytest tests/test_skill_metadata_enrichment.py (40 passed)
  • pnpm typecheck
  • pnpm build

Summary by Sourcery

Add support for discovering and displaying read-only global Agent skills alongside existing local, plugin, sandbox, and workspace skills.

New Features:

  • Discover global Agent-managed skills from user and workspace .agent/skills directories and include them in the unified skills list and workspace skills view.
  • Expose global skill source type, labels, and read-only metadata to the dashboard for accurate display and interaction handling.

Bug Fixes:

  • Ensure sandbox-only, plugin, and global skills are correctly classified so they cannot be mistakenly edited, deleted, or downloaded via local skill management.

Enhancements:

  • Centralize skill description reading with bounded frontmatter loading for local, workspace, global, and plugin skills.
  • Adjust skill resolution and precedence so Agent workspace skills override legacy workspace skills and skill name collisions prefer non-legacy sources.
  • Refine dashboard skill UI labeling, coloring, and deletion/download flows to account for global and other read-only skill sources.

Tests:

  • Add unit tests covering global Agent skill discovery, sandbox cache interaction, read-only file access, and workspace precedence between Agent and legacy skills.

@gemini-code-assist gemini-code-assist Bot 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.

Code Review

This pull request introduces support for global and workspace-scoped Agent skills, allowing the application to load, list, and manage skills from .agent/skills directories. It marks these global skills as read-only in both the backend services and the frontend dashboard, and includes comprehensive unit tests to verify the new resolution logic. The review feedback suggests two robustness improvements: defaulting the maximum character limit when reading skill descriptions to avoid loading excessively large files into memory, and wrapping directory iteration in a try-except block to safely handle potential OS errors when accessing external skill directories.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

return description.strip()


def _read_skill_description(skill_md: Path, *, max_chars: int | None = None) -> str:

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.

medium

To prevent reading unnecessarily large SKILL.md files entirely into memory when only parsing the frontmatter description, consider defaulting max_chars to WORKSPACE_SKILL_FRONTMATTER_MAX_CHARS (64 KB) instead of None.

def _read_skill_description(
    skill_md: Path,
    *,
    max_chars: int | None = WORKSPACE_SKILL_FRONTMATTER_MAX_CHARS,
) -> str:

local_exists=True,
sandbox_exists=sandbox_exists,
)
for entry in sorted(skills_root.iterdir()):

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.

medium

Since global_skills_root (e.g., ~/.agent/skills) is an externally managed directory, calling skills_root.iterdir() directly can raise OSError (such as PermissionError or FileNotFoundError in case of broken symlinks/permissions). It is safer to wrap the directory listing in a try-except OSError block to prevent list_skills from crashing.

            try:
                entries = sorted(skills_root.iterdir())
            except OSError:
                continue
            for entry in entries:

@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Preview URL Updated (UTC)
✅ Deployment successful!
View logs
astrbot-docs b0ab050 Commit Preview URL

Branch Preview URL
Jul 14 2026, 01:06 AM

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.

1 participant