diff --git a/.agents/skills/code-review.md b/.agents/skills/code-review.md index 0d690867..90b9134d 100644 --- a/.agents/skills/code-review.md +++ b/.agents/skills/code-review.md @@ -12,19 +12,23 @@ multiple source-of-truth codebases. Accuracy is critical. ## Source Code Verification (Required for SDK/CLI/App docs) -When reviewing documentation that references APIs, function signatures, class names, or code examples -from an upstream repository, you **MUST** clone the corresponding repository and verify the documentation -against the actual source code. Do not trust that code examples or API descriptions are accurate without -checking. +When reviewing documentation that references APIs, function signatures, class names, code examples, +or behavioral descriptions from an upstream repository, you **MUST** clone the corresponding repository +and verify the documentation against the actual source code. Do not trust that code examples or API +descriptions are accurate without checking. -### Repositories to clone for verification +**Every review comment and every approval MUST include evidence from the source code.** For each +documentation claim you verify (or flag as incorrect), provide a direct GitHub permalink to the +relevant source file and line(s). A review that simply says "looks good" without citing source +code is incomplete. -| Documentation path | Source repository | -|--------------------|-------------------| -| `sdk/` | `OpenHands/software-agent-sdk` | -| `openhands/` | `OpenHands/OpenHands` | -| CLI-related docs | `OpenHands/OpenHands-CLI` | +### Repositories to clone for verification +| Documentation path | Source repository | GitHub base URL | +|--------------------|-------------------|-----------------| +| `sdk/` | `OpenHands/software-agent-sdk` | `https://github.com/OpenHands/software-agent-sdk` | +| `openhands/` | `OpenHands/OpenHands` | `https://github.com/OpenHands/OpenHands` | +| CLI-related docs | `OpenHands/OpenHands-CLI` | `https://github.com/OpenHands/OpenHands-CLI` | ### Prefer upstream PR branches when linked @@ -42,6 +46,7 @@ It's OK to approve a docs/ PR on the basis of a linked upstream PR, they will be - **Field/attribute names** on data classes and models are correct - **Supported values** (e.g., format strings like `"github:owner/repo"`) are actually handled in code - **Behavioral descriptions** match the implementation logic +- **Prompt/context descriptions** distinguish between initial injection/construction, conversation-history inclusion, LLM context, and actual request transport. Flag ambiguous wording such as “sent with each request” unless the docs are intentionally describing transport-level behavior. - **Example code** would actually run without errors ### How to verify @@ -58,6 +63,46 @@ git clone --depth=1 https://github.com/OpenHands/software-agent-sdk.git /tmp/age grep -rn "function_name" /tmp/agent-sdk/ ``` +### Providing evidence in review comments (Required) + +For **every** documentation change that describes code behavior, APIs, or implementation details, +your review MUST include a link to the corresponding source code as evidence. Use GitHub permalinks +(with commit SHA or branch) so links remain stable. + +**Format for inline review comments:** + +When commenting on a specific line or section of the documentation, include evidence like: + +``` +✅ Verified: `is_agentskills_format` field exists on the Skill class. +→ Source: https://github.com/OpenHands/software-agent-sdk/blob/main/openhands-sdk/openhands/sdk/context.py#L42 + +🔴 Incorrect: The docs say `trigger=None` causes injection into ``, but the code +shows it injects into ``. +→ Source: https://github.com/OpenHands/software-agent-sdk/blob/main/openhands-sdk/openhands/sdk/agent.py#L150-L165 +``` + +**Format for the overall review body:** + +Include a "Source Verification" section that lists the key claims verified and their evidence: + +``` +## Source Verification + +| Documentation Claim | Verified? | Source Evidence | +|---------------------|-----------|-----------------| +| Legacy skills with `trigger=None` are included in the initial system prompt and remain in LLM context for subsequent turns | ✅ | [agent.py#L150](permalink) | +| `load_skills_from_dir()` returns tuple of (skills, repo_skills) | ✅ | [context.py#L85](permalink) | +| AgentSkills format uses progressive disclosure | ❌ Incorrect | [agent.py#L200](permalink) shows... | +``` + +If you cannot find source code to verify a documentation claim, explicitly flag it: + +``` +⚠️ Unverified: Could not find source code for the claimed behavior of "X". +This should be verified before merging. +``` + ## Review Decisions You **must** use the correct GitHub review `event` value when submitting your review. diff --git a/AGENTS.md b/AGENTS.md index a8e99f35..de1edc63 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -151,6 +151,7 @@ Workflow: `.github/workflows/sync-agent-sdk-openapi.yml` - Follow the style rules in `openhands/DOC_STYLE_GUIDE.md`. - Use Mintlify components (``, ``, ``, etc.) where appropriate. - When linking internally, prefer **absolute** doc paths (e.g. `/overview/quickstart`). +- When documenting prompt/context behavior, avoid ambiguous transport phrasing like “sent with each request” unless discussing the actual API transport. Prefer precise wording such as “included in the initial system prompt” and “remains part of the conversation/LLM context for subsequent turns.” - Cloud integration docs live under `openhands/usage/cloud/`, and pages surfaced in **Documentation → Integrations → Cloud API** must also be added to the `Cloud API` group in `docs.json`. ### Mintlify tab ownership diff --git a/sdk/guides/skill.mdx b/sdk/guides/skill.mdx index 42ed749a..5bf4d441 100644 --- a/sdk/guides/skill.mdx +++ b/sdk/guides/skill.mdx @@ -9,6 +9,57 @@ This guide shows how to implement skills in the SDK. For conceptual overview, se OpenHands supports an **extended version** of the [AgentSkills standard](https://agentskills.io/specification) with optional keyword triggers. +## Skill Injection Behavior + +Understanding where skill content appears in the prompt is critical. The behavior differs based on skill format and trigger configuration: + +| Skill Format | Trigger | Where Content Appears | Model Mediated? | +|--------------|---------|----------------------|-----------------| +| **AgentSkills** (`SKILL.md`) | Any | `` (description only) | ✅ Yes — agent calls `invoke_skill()` | +| **AgentSkills** (`SKILL.md`) | Has triggers | `` + auto-inject on match | ✅ Yes | +| **Legacy** (inline/`*.md`) | `None` | **`` (full content in the initial system prompt; included in LLM context for each turn)** | ❌ No | +| **Legacy** (inline/`*.md`) | Has triggers | `` + auto-inject on match | ✅ Yes | + + +**Token Usage Warning**: Legacy skills with `trigger=None` add their **full content** to `` in the initial `SystemPromptEvent`. That system message remains part of the conversation context for subsequent LLM calls, so the content still affects token usage on each turn. Consider using AgentSkills format (`SKILL.md`) for progressive disclosure instead. + + +### Prompt Structure + +Skills appear in different parts of the system prompt: + +```xml icon="file" + + + + + [BEGIN context from [agents]] + ... AGENTS.md content ... + [END Context] + + + + + + + github + Interact with GitHub... + + + +``` + +When a trigger matches, content is injected into the **user message**: + +```xml icon="file" + +The following information has been included based on a keyword match for "github". +Skill location: /path/to/skill +... skill content ... + +``` + ## Context Loading Methods | Method | When Content Loads | Use Case | @@ -50,6 +101,10 @@ agent_context = AgentContext( ) ``` + +**Important**: Inline skills with `trigger=None` use **legacy format** behavior — full content is added to `` in the initial system prompt and remains part of the conversation context for subsequent LLM calls. For large skills, consider using the AgentSkills `SKILL.md` format for progressive disclosure. + + ## Trigger-Loaded Context Content injected when keywords appear in user messages. See [Keyword-Triggered Skills](/overview/skills/keyword). @@ -836,9 +891,15 @@ from openhands.sdk.context.skills import load_skills_from_dir repo_skills, knowledge_skills, agent_skills = load_skills_from_dir(skills_dir) ``` -- **repo_skills**: Skills from `repo.md` files (always active) -- **knowledge_skills**: Skills from `knowledge/` subdirectories -- **agent_skills**: Skills from `SKILL.md` files (AgentSkills standard) +| Return Value | Source Files | Injection Behavior | +|--------------|--------------|-------------------| +| **repo_skills** | `repo.md`, `AGENTS.md`, `.cursorrules` | Full content in `` in the initial system prompt; included in LLM context for each turn | +| **knowledge_skills** | `knowledge/` subdirectories, `*.md` with triggers | Listed in ``, auto-inject on trigger | +| **agent_skills** | `SKILL.md` files (AgentSkills standard) | Listed in ``, agent calls `invoke_skill()` | + + +When passing to `AgentContext(skills=...)`, all three types are accepted. The injection behavior depends on the skill's `is_agentskills_format` flag and `trigger` field — see [Skill Injection Behavior](#skill-injection-behavior). + #### `discover_skill_resources()` @@ -1165,6 +1226,57 @@ print(rendered) # Commands replaced with output The `working_dir` parameter sets the current directory for command execution, enabling workspace-relative commands like `git status`. +## Migrating from Legacy to AgentSkills Format + +If you have legacy inline skills consuming many tokens, convert them to AgentSkills format for progressive disclosure: + +### Before (Legacy Format) + +```python icon="python" +# Legacy: Full content in in the initial system prompt +Skill( + name="api-guidelines", + content=""" + # API Guidelines + ... 2000 lines of detailed documentation ... + """, + trigger=None, # Always-on context - affects token usage on each turn! +) +``` + +### After (AgentSkills Format) + +Create a directory `api-guidelines/SKILL.md`: + +```markdown icon="markdown" +--- +name: api-guidelines +description: Comprehensive API design guidelines for the project. Invoke when designing or reviewing API endpoints. +--- + +# API Guidelines + +... 2000 lines of detailed documentation ... +``` + +Then load it: + +```python icon="python" +from openhands.sdk.skills import load_skills_from_dir + +# AgentSkills: Only description in prompt, agent reads full content on demand +_, _, skills = load_skills_from_dir("/path/to/skills") +agent_context = AgentContext(skills=list(skills.values())) +``` + +### Benefits + +| Aspect | Legacy `trigger=None` | AgentSkills `SKILL.md` | +|--------|----------------------|------------------------| +| Token usage | Full content in system prompt; included in LLM context for each turn | Description only (~100 chars) | +| Model control | None — always present | Agent decides when to read | +| Scalability | Limited by context window | Many skills without token bloat | + ## Next Steps - **[Custom Tools](/sdk/guides/custom-tools)** - Create specialized tools