Skip to content

Document subagent loader design & invariants introduced by file-based agents (PR #2183) #2200

@enyst

Description

@enyst

Context

PR #2183 ("feat(delegate): File-based agent definitions with markdown + YAML frontmatter") introduces a new file-based subagent definition mechanism (Markdown + YAML frontmatter) and centralizes agent discovery/registration logic under openhands.sdk.subagent.

As discussed in the PR comment:

The implementation is understandable, but today you have to read quite a bit of code to learn the intended behavior. We should document the design intent + invariants so both humans and agentic contributors can reason about it without reverse-engineering the loader.

What should be documented (design assumptions / invariants)

(Concrete items that are easy to accidentally break during refactors)

  1. Discovery locations & file rules

    • Project-level directories: {project}/.agents/agents/*.md then {project}/.openhands/agents/*.md
    • User-level directories: ~/.agents/agents/*.md then ~/.openhands/agents/*.md
    • Only top-level *.md files are scanned; subdirectories are ignored; README.md is skipped.
    • Errors parsing a single file should be non-fatal (logged, continue scanning).
  2. Resolution / precedence order ("who wins")

    • Programmatic register_agent() must never be overwritten.
    • Plugin-provided agents (Plugin.agents) have higher priority than file-based agents.
    • Project-level file agents override user-level file agents.
    • Within each level, .agents/ overrides .openhands/.
    • SDK built-in agents are the lowest priority (registered only if absent).
  3. Schema & semantics of Markdown agents

    • YAML frontmatter keys: name, description, tools, model (default inherit), color.
    • Unknown frontmatter keys are retained as metadata.
    • Body Markdown becomes the agent's system_prompt (currently applied as an AgentContext.system_message_suffix).
    • tools accepts either a string or a list; tool names are mapped to Tool(name=...).
    • <example>...</example> tags inside description are extracted for triggering.

Proposals (2–3 options) for documenting the design

Proposal A: Add a scoped AGENTS.md next to the implementation (best for agentic contributors)

Create openhands-sdk/openhands/sdk/subagent/AGENTS.md (or .../delegate/AGENTS.md) that:

  • states the precedence model and scanning rules as a small table
  • states the intended invariants ("first wins", "never overwrite register_agent")
  • links to the public user docs page (Proposal B)

Why: OpenHands-style agent runs will automatically pick this up, reducing code archaeology.

Proposal B: Add a short "Subagents / delegation design" page to the docs repo (best for humans)

In https://github.com/OpenHands/docs (sdk section), add a page focused on:

  • where agent definition files live
  • exact precedence rules
  • minimal examples for Markdown frontmatter
  • how this interacts with plugins (Plugin.agents) and programmatic registration

Why: Keeps user-facing + maintainer-facing understanding in one canonical place.

Proposal C: Add an ADR (Architecture Decision Record) + keep invariants executable

Add an ADR in-repo (e.g., docs/adr/XXXX-file-based-subagents.md) capturing:

  • motivation and non-goals
  • invariants above
  • rationale for the chosen precedence order

Additionally, ensure tests explicitly encode the precedence order so docs and behavior cannot drift.

Acceptance criteria

  • A future contributor can answer "where does this agent come from and why did it win" without reading LocalConversation + subagent/* code.
  • The precedence rules are written down in one place, with links from code to docs.

Metadata

Metadata

Assignees

No one assigned

    Labels

    architectureRelated to core architecture.delegationdocumentationImprovements or additions to documentationinvariantsthe design invariants of the codebase

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions