Skip to content

feat: support workspace skills in requests#8884

Merged
Soulter merged 4 commits into
masterfrom
codex/workspace-skills
Jun 19, 2026
Merged

feat: support workspace skills in requests#8884
Soulter merged 4 commits into
masterfrom
codex/workspace-skills

Conversation

@Soulter

@Soulter Soulter commented Jun 18, 2026

Copy link
Copy Markdown
Member

Summary

  • detect request-scoped workspace Skills under the current local workspace and inject them into the Skills prompt
  • keep workspace Skills out of the WebUI management list and document source priority
  • sanitize workspace Skill descriptions and avoid reading oversized Skill files during request construction

Tests

  • uv run pytest tests/test_skill_metadata_enrichment.py tests/unit/test_astr_main_agent.py -q
  • uv run ruff check astrbot/core/skills/skill_manager.py astrbot/core/astr_main_agent.py tests/test_skill_metadata_enrichment.py tests/unit/test_astr_main_agent.py

Summary by Sourcery

Add support for request-scoped workspace Skills that are discovered per-session and injected into requests with defined source precedence and sanitization.

New Features:

  • Discover and load Skills from the current session workspace and inject them into the request Skills prompt in local runtime.
  • Treat workspace-scoped Skills as a distinct, highest-priority Skill source when merging with local, plugin, and sandbox Skills.

Enhancements:

  • Sanitize workspace Skill descriptions in the Skills prompt similarly to sandbox-only Skills and avoid using dangerous or malformed content.
  • Limit how much of a workspace Skill's SKILL.md frontmatter is read when extracting metadata to prevent oversized file reads.
  • Ensure personas configured to disable Skills also suppress workspace Skills, and skip workspace Skills entirely in sandbox runtime.

Documentation:

  • Document Skill sources, precedence rules, and workspace Skill behavior in both English and Chinese user guides.

Tests:

  • Add unit tests covering workspace Skill discovery, description parsing and size limits, precedence and filtering with personas, and behavior differences between local and sandbox runtimes.

@dosubot dosubot Bot added size:L This PR changes 100-499 lines, ignoring generated files. area:core The bug / feature is about astrbot's core, backend feature:plugin The bug / feature is about AstrBot plugin system. labels Jun 18, 2026

@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 request-scoped 'Workspace Skills' that are discovered under the session workspace directory and injected during local runtime execution. It includes priority rules for merging workspace skills with other skill sources, updates to documentation and localization, and comprehensive unit tests. The review feedback suggests resolving the workspace root and verifying that the resolved skills root is relative to it to prevent directory traversal vulnerabilities, as well as wrapping directory iteration in a try-except block to handle potential OS errors.

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.

Comment thread astrbot/core/skills/skill_manager.py Outdated

@sourcery-ai sourcery-ai 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.

Hey - I've found 2 issues, and left some high level feedback:

  • In list_workspace_skills, there are several broad except Exception/except OSError blocks that silently drop entries; consider narrowing the exception types and/or adding minimal logging so unexpected filesystem issues are detectable rather than quietly skipping skills.
  • The logic that merges workspace_skills into skills in _ensure_persona_and_skills builds a dict and then re-sorts by name; if priority ordering across different sources ever becomes more complex, it might be clearer to extract this merge/priority policy into a dedicated helper to keep the agent setup function easier to follow.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In `list_workspace_skills`, there are several broad `except Exception`/`except OSError` blocks that silently drop entries; consider narrowing the exception types and/or adding minimal logging so unexpected filesystem issues are detectable rather than quietly skipping skills.
- The logic that merges `workspace_skills` into `skills` in `_ensure_persona_and_skills` builds a dict and then re-sorts by name; if priority ordering across different sources ever becomes more complex, it might be clearer to extract this merge/priority policy into a dedicated helper to keep the agent setup function easier to follow.

## Individual Comments

### Comment 1
<location path="astrbot/core/skills/skill_manager.py" line_range="401" />
<code_context>
+                SkillInfo(
+                    name=skill_name,
+                    description=description,
+                    path=str(resolved_skill_md).replace("\\", "/"),
+                    active=True,
+                    source_type="workspace",
</code_context>
<issue_to_address>
**suggestion:** Consider using `Path.as_posix()` instead of manual string replacement for normalization.

Because `resolved_skill_md` is already a `Path`, `resolved_skill_md.as_posix()` is a clearer and more robust way to normalize separators than `str(...).replace("\\", "/")`, and avoids issues if backslashes appear elsewhere in the string representation.

```suggestion
                    path=resolved_skill_md.as_posix(),
```
</issue_to_address>

### Comment 2
<location path="tests/unit/test_astr_main_agent.py" line_range="850-853" />
<code_context>
+        req = ProviderRequest()
+        req.conversation = MagicMock(persona_id=None)
+
+        await module._ensure_persona_and_skills(req, {}, mock_context, mock_event)
+
+        assert "**workspace-skill**" in req.system_prompt
</code_context>
<issue_to_address>
**suggestion (testing):** Make the runtime explicit in the test to decouple it from default behavior

Right now the test passes `{}` for `runtime`, which depends on `_ensure_persona_and_skills`’ default runtime behavior. Because workspace skills are only enabled for certain runtime modes (e.g. `"local"`), the test could change meaning if that default changes. Please pass an explicit runtime config (e.g. `{"computer_use_runtime": "local"}`) and assert behavior for that specific mode.

```suggestion
        req = ProviderRequest()
        req.conversation = MagicMock(persona_id=None)

        runtime_config = {"computer_use_runtime": "local"}

        await module._ensure_persona_and_skills(req, runtime_config, mock_context, mock_event)
```
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment thread astrbot/core/skills/skill_manager.py Outdated
Comment thread tests/unit/test_astr_main_agent.py Outdated
@Soulter Soulter merged commit 29d66b8 into master Jun 19, 2026
21 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:core The bug / feature is about astrbot's core, backend feature:plugin The bug / feature is about AstrBot plugin system. size:L This PR changes 100-499 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant