Repository navigation
Description
Description
Subagents defined via markdown files (.opencode/agents/*.md) have their frontmatter.description ignored by the Task tool's agent list. The describeTask function in packages/opencode/src/tool/registry.ts falls through to "This subagent should only be called manually by the user." for agents without a description property, even when the field is present in the YAML frontmatter.
Agents defined via JSON config (opencode.json) work correctly — their description appears in the Task tool. Only markdown-defined agents are affected.
Plugins
@opencode-ai/plugin
OpenCode version
1.15.1
Steps to reproduce
Create .opencode/agents/test.md:
description: "Test agent — does X and Y"
mode: subagent
permission:
read: allow
You are a test agent.
2.
Start a session and inspect the Task tool parameter description. The agent will appear as:
- test: This subagent should only be called manually by the user.
Expected:
- test: Test agent — does X and Y
Root Cause Analysis
The propagation chain is:
config/agent.ts:load() — calls ConfigMarkdown.parse() (gray-matter) which correctly extracts frontmatter.description into md.data.description. This is packed into { name, ...md.data, prompt } and validated through AgentSchema (which has description: optional(String)).
2.
config/config.ts — merges markdown agents into cfg.agent via mergeDeep.
3.
agent/agent.ts — iterates cfg.agent and sets:
item.description = value.description ?? item.description
For non-built-in agents (no prior entry in the agents record), item.description is undefined, so this should resolve to value.description.
4.
tool/registry.ts:describeTask() — calls agents.list() and renders:
- ${item.name}: ${item.description ?? "This subagent should only be called manually by the user."}
The bug is likely in step 2 or 3 — either mergeDeep drops the field, or the normalize() function in config/agent.ts strips it, or the description is null/undefined in the parsed config despite being present in the frontmatter.
Candidate Fix Locations
packages/opencode/src/agent/agent.ts — line where item.description = value.description ?? item.description is set (ensure it's not using ?? where value.description is an empty string or gets overwritten elsewhere)
packages/opencode/src/config/agent.ts — normalize() function (ensure description isn't being lost during KNOWN_KEYS filtering)
packages/opencode/src/config/markdown.ts — parse() function (verify gray-matter is outputting the description field correctly with multi-line frontmatter containing non-standard YAML keys)
Environment
OpenCode version: 1.15.0 / 1.15.1 (@opencode-ai/plugin also 1.15.1, same behavior)
OS: Linux (WSL2)
Agent location: .opencode/agents/*.md
Additional Context
Built-in subagents (explore, general, scout) and JSON-configured agents work correctly — only markdown-defined agents are affected. The @ autocomplete menu displays the description correctly, suggesting the issue is specific to how agents.list() populates description for non-native agents, not the parsing itself.
Confirmed via compiled binary at ~/.opencode/bin/opencode — the fallback string "This subagent should only be called manually by the user." appears in source at tool/registry.ts as item.description ?? "manual fallback".
Operating System
Linux (WSL2 — kernel 6.6.87.2-microsoft-standard-WSL2)
Terminal
Powershell
Activity
PeterPonyu commentedon May 16, 2026
This appears to be already resolved on current
upstream/dev(verified atf80651fa9/ v1.15.3).The propagation chain you traced is intact end-to-end in the current source:
ConfigMarkdown.parse()correctly extractsdescriptionfrom frontmatter via gray-matter (no recent changes to this path).packages/opencode/src/config/agent.ts:58—descriptionis in the known-keys allowlist, sonormalize()does NOT strip it duringKNOWN_KEYSfiltering. The schema at line 35 declaresdescription: Schema.optional(Schema.String)with annotation"Description of when to use the agent".packages/opencode/src/config/agent.ts:30— schema decode preservesdescription: Schema.optional(Schema.String).packages/opencode/src/tool/registry.ts:307—describeTaskrenders:`- ${item.name}: ${item.description ?? "This subagent should only be called manually by the user."}`item.descriptioncorrectly populated from the markdown frontmatter, this resolves to the real description, not the fallback.I followed your suspected "step 2 or 3" —
mergeDeepdoes not drop the field, andnormalize()does not strip it, becausedescriptionis explicitly inKNOWN_KEYS.Could you check whether you're still seeing this on v1.15.x? If you're on v1.15.1 as the report says, please try
bunx opencode@latest upgrade(or run withOPENCODE_DEBUG=1againstdist/dev) to confirm. If the bug still reproduces on a current build, a minimal repro markdown file + the exactagents.list()output for that file would help — given the source looks correct now, there may be an environment-specific issue (e.g. file encoding, BOM in the frontmatter, plugin override) that's distinct from the original report.Most likely safe to close if you can't reproduce on the latest version.
fix(config): preserve description field from markdown agent frontmatter
github-actions commentedon Jul 16, 2026
To stay organized issues are automatically closed after 60 days of no activity. If the issue is still relevant please open a new one.