From f07222a57564901948da107029a74b8a3767f37b Mon Sep 17 00:00:00 2001 From: marcusquinn <6428977+marcusquinn@users.noreply.github.com> Date: Wed, 14 Jan 2026 00:15:49 +0000 Subject: [PATCH 1/3] feat(agents): add subagent filtering via frontmatter Add 'subagents:' frontmatter to primary agents that specifies which subagents should appear in the Task tool description. This reduces token overhead by filtering 220 subagents down to 3-30 per agent. Changes: - Add parse_frontmatter() to generate-opencode-agents.sh - Generate permission.task deny-list rules from subagents list - Add subagents frontmatter to all 13 primary agents Token savings: ~6-10k tokens per conversation by hiding irrelevant subagents from the Task tool description. Related: anomalyco/opencode#7271 --- .agent/accounts.md | 4 ++ .agent/aidevops.md | 36 ++++++++++ .agent/build-plus.md | 38 ++++++++++ .agent/content.md | 16 +++++ .agent/health.md | 7 ++ .agent/legal.md | 9 +++ .agent/marketing.md | 17 +++++ .agent/onboarding.md | 13 ++++ .agent/plan-plus.md | 18 +++++ .agent/research.md | 14 ++++ .agent/sales.md | 13 ++++ .agent/scripts/generate-opencode-agents.sh | 81 +++++++++++++++++++++- .agent/seo.md | 12 ++++ .agent/social-media.md | 12 ++++ 14 files changed, 287 insertions(+), 3 deletions(-) diff --git a/.agent/accounts.md b/.agent/accounts.md index 4a7a7b87..58365c53 100644 --- a/.agent/accounts.md +++ b/.agent/accounts.md @@ -2,6 +2,10 @@ name: accounts description: Financial operations and accounting - QuickFile integration, invoicing, expense tracking mode: subagent +subagents: + - quickfile + - general + - explore --- # Accounts - Main Agent diff --git a/.agent/aidevops.md b/.agent/aidevops.md index 16e76ac8..e6fdcba0 100644 --- a/.agent/aidevops.md +++ b/.agent/aidevops.md @@ -2,6 +2,42 @@ name: aidevops description: AI DevOps framework operations - setup, configuration, meta-agents, troubleshooting mode: subagent +subagents: + # Framework internals + - setup + - troubleshooting + - architecture + - add-new-mcp-to-aidevops + - mcp-integrations + - mcp-troubleshooting + - configs + - providers + # Agent development + - build-agent + - agent-review + - build-mcp + - server-patterns + - api-wrapper + - transports + - deployment + # Workflows + - git-workflow + - release + - version-bump + - preflight + - postflight + # Code quality + - code-standards + - linters-local + - secretlint + # Credentials + - api-key-setup + - api-key-management + - vaultwarden + - list-keys + # Built-in + - general + - explore --- # AI DevOps - Framework Main Agent diff --git a/.agent/build-plus.md b/.agent/build-plus.md index 09acba04..caa60357 100644 --- a/.agent/build-plus.md +++ b/.agent/build-plus.md @@ -2,6 +2,44 @@ name: build-plus description: Enhanced build agent with semantic codebase search and context tools mode: subagent +subagents: + # Core workflows + - git-workflow + - branch + - preflight + - postflight + - release + - version-bump + - pr + - conversation-starter + - error-feedback + # Code quality + - code-standards + - code-simplifier + - best-practices + - auditing + - secretlint + - qlty + # Context tools + - osgrep + - augment-context-engine + - context-builder + - context7 + - toon + # Browser/testing + - playwright + - stagehand + - pagespeed + # Git platforms + - github-cli + - gitlab-cli + - github-actions + # Deployment + - coolify + - vercel + # Built-in + - general + - explore --- # Build+ - Enhanced Build Agent diff --git a/.agent/content.md b/.agent/content.md index d6aa0b7b..89de225c 100644 --- a/.agent/content.md +++ b/.agent/content.md @@ -2,6 +2,22 @@ name: content description: Content creation and management - copywriting, guidelines, editorial workflows mode: subagent +subagents: + # Content + - guidelines + - summarize + # SEO integration + - keyword-research + - eeat-score + # WordPress publishing + - wp-admin + - mainwp + # Research + - context7 + - crawl4ai + # Built-in + - general + - explore --- # Content - Main Agent diff --git a/.agent/health.md b/.agent/health.md index 1120deeb..ea9aa976 100644 --- a/.agent/health.md +++ b/.agent/health.md @@ -2,6 +2,13 @@ name: health description: Health and wellness domain - medical information, fitness, nutrition guidance mode: subagent +subagents: + # Research + - context7 + - crawl4ai + # Built-in + - general + - explore --- # Health - Main Agent diff --git a/.agent/legal.md b/.agent/legal.md index 1126395c..d1141db6 100644 --- a/.agent/legal.md +++ b/.agent/legal.md @@ -2,6 +2,15 @@ name: legal description: Legal compliance and documentation - contracts, policies, regulatory guidance mode: subagent +subagents: + # Research + - context7 + - crawl4ai + # Content + - guidelines + # Built-in + - general + - explore --- # Legal - Main Agent diff --git a/.agent/marketing.md b/.agent/marketing.md index c989f373..8d629ec8 100644 --- a/.agent/marketing.md +++ b/.agent/marketing.md @@ -10,6 +10,23 @@ tools: glob: true grep: true webfetch: true +subagents: + # CRM + - fluentcrm + # Content + - guidelines + - summarize + # SEO + - keyword-research + - serper + - dataforseo + # Social + - bird + # Analytics + - google-search-console + # Built-in + - general + - explore --- # Marketing - Main Agent diff --git a/.agent/onboarding.md b/.agent/onboarding.md index 386050c1..c0cecdcf 100644 --- a/.agent/onboarding.md +++ b/.agent/onboarding.md @@ -2,6 +2,19 @@ name: onboarding description: Interactive onboarding wizard - discover services, check credentials, configure integrations mode: subagent +subagents: + # Setup/config + - setup + - troubleshooting + - api-key-setup + - list-keys + - mcp-integrations + # Services overview + - services + - service-links + # Built-in + - general + - explore --- # Onboarding Wizard - aidevops Configuration diff --git a/.agent/plan-plus.md b/.agent/plan-plus.md index a15f817f..ee13dfb4 100644 --- a/.agent/plan-plus.md +++ b/.agent/plan-plus.md @@ -2,6 +2,24 @@ name: plan-plus description: Read-only planning agent with semantic codebase search - analysis without modifications mode: subagent +subagents: + # Context/search (read-only) + - osgrep + - augment-context-engine + - context-builder + - context7 + # Planning workflows + - plans + - plans-quick + - prd-template + - tasks-template + # Architecture review + - architecture + - code-standards + - best-practices + # Built-in + - general + - explore --- # Plan+ - Enhanced Plan Agent diff --git a/.agent/research.md b/.agent/research.md index 43582761..c0edc66e 100644 --- a/.agent/research.md +++ b/.agent/research.md @@ -2,6 +2,20 @@ name: research description: Research and analysis - data gathering, competitive analysis, market research mode: subagent +subagents: + # Context/docs + - context7 + - augment-context-engine + - osgrep + # Web research + - crawl4ai + - serper + - outscraper + # Summarization + - summarize + # Built-in + - general + - explore --- # Research - Main Agent diff --git a/.agent/sales.md b/.agent/sales.md index 0f806061..1649fd4f 100644 --- a/.agent/sales.md +++ b/.agent/sales.md @@ -10,6 +10,19 @@ tools: glob: true grep: true webfetch: true +subagents: + # CRM + - fluentcrm + # Accounting + - quickfile + # Content for proposals + - guidelines + # Research + - outscraper + - crawl4ai + # Built-in + - general + - explore --- # Sales - Main Agent diff --git a/.agent/scripts/generate-opencode-agents.sh b/.agent/scripts/generate-opencode-agents.sh index 5acac11e..b755704a 100755 --- a/.agent/scripts/generate-opencode-agents.sh +++ b/.agent/scripts/generate-opencode-agents.sh @@ -182,6 +182,56 @@ AGENT_TEMPS = { # Files to skip (not primary agents) SKIP_FILES = {"AGENTS.md", "README.md"} +def parse_frontmatter(filepath): + """Parse YAML frontmatter from markdown file.""" + try: + with open(filepath, 'r') as f: + content = f.read() + + # Check for frontmatter + if not content.startswith('---'): + return {} + + # Find end of frontmatter + end_idx = content.find('---', 3) + if end_idx == -1: + return {} + + frontmatter = content[3:end_idx].strip() + + # Simple YAML parsing for subagents list + result = {} + lines = frontmatter.split('\n') + current_key = None + current_list = [] + + for line in lines: + stripped = line.strip() + if stripped.startswith('- ') and current_key: + # List item + current_list.append(stripped[2:].strip()) + elif ':' in stripped and not stripped.startswith('-'): + # Save previous list if any + if current_key and current_list: + result[current_key] = current_list + current_list = [] + + # New key + key, value = stripped.split(':', 1) + current_key = key.strip() + value = value.strip() + if value: + result[current_key] = value + current_key = None + + # Save final list + if current_key and current_list: + result[current_key] = current_list + + return result + except: + return {} + def filename_to_display(filename): """Convert filename to display name.""" name = filename.replace(".md", "") @@ -190,8 +240,14 @@ def filename_to_display(filename): # Convert kebab-case to Title-Case return "-".join(word.capitalize() for word in name.split("-")) -def get_agent_config(display_name, filename): - """Generate agent configuration.""" +def get_agent_config(display_name, filename, subagents=None): + """Generate agent configuration. + + Args: + display_name: Agent display name + filename: Agent markdown filename + subagents: Optional list of allowed subagent names (from frontmatter) + """ tools = AGENT_TOOLS.get(display_name, DEFAULT_TOOLS.copy()) temp = AGENT_TEMPS.get(display_name, 0.2) @@ -209,11 +265,21 @@ def get_agent_config(display_name, filename): else: config["permission"] = {"external_directory": "allow"} + # Add subagent filtering via permission.task if subagents specified + # This generates deny-all + allow-specific rules + if subagents and isinstance(subagents, list) and len(subagents) > 0: + task_perms = {"*": "deny"} + for subagent in subagents: + task_perms[subagent] = "allow" + config["permission"]["task"] = task_perms + print(f" {display_name}: filtered to {len(subagents)} subagents") + return config # Discover all root-level .md files primary_agents = {} discovered = [] +subagent_filtered_count = 0 for filepath in glob.glob(os.path.join(agents_dir, "*.md")): filename = os.path.basename(filepath) @@ -221,7 +287,14 @@ for filepath in glob.glob(os.path.join(agents_dir, "*.md")): continue display_name = filename_to_display(filename) - primary_agents[display_name] = get_agent_config(display_name, filename) + + # Parse frontmatter for subagents list + frontmatter = parse_frontmatter(filepath) + subagents = frontmatter.get('subagents', None) + if subagents: + subagent_filtered_count += 1 + + primary_agents[display_name] = get_agent_config(display_name, filename, subagents) discovered.append(display_name) # Sort agents: ordered ones first, then alphabetical @@ -288,6 +361,8 @@ config['agent'] = sorted_agents print(f" Auto-discovered {len(sorted_agents)} primary agents from {agents_dir}") print(f" Order: {', '.join(list(sorted_agents.keys())[:5])}...") +if subagent_filtered_count > 0: + print(f" Subagent filtering: {subagent_filtered_count} agents have permission.task rules") # ============================================================================= # MCP SERVERS - Ensure required MCP servers are configured diff --git a/.agent/seo.md b/.agent/seo.md index 77e0bfc4..c0353fcc 100644 --- a/.agent/seo.md +++ b/.agent/seo.md @@ -2,6 +2,18 @@ name: seo description: SEO optimization and analysis - keyword research, Search Console, DataForSEO, site crawling mode: subagent +subagents: + - keyword-research + - google-search-console + - gsc-sitemaps + - dataforseo + - serper + - site-crawler + - eeat-score + - domain-research + - pagespeed + - general + - explore --- # SEO - Main Agent diff --git a/.agent/social-media.md b/.agent/social-media.md index 56da9a31..69a40397 100644 --- a/.agent/social-media.md +++ b/.agent/social-media.md @@ -2,6 +2,18 @@ name: social-media description: Social media management - content scheduling, analytics, engagement, multi-platform strategy mode: subagent +subagents: + # Social tools + - bird + # Content + - guidelines + - summarize + # Research + - crawl4ai + - serper + # Built-in + - general + - explore --- # Social Media - Main Agent From 0b57978beca1e6b8c1508382e370de2a0b92f3fe Mon Sep 17 00:00:00 2001 From: marcusquinn <6428977+marcusquinn@users.noreply.github.com> Date: Wed, 14 Jan 2026 00:25:02 +0000 Subject: [PATCH 2/3] fix(parser): improve frontmatter parser robustness Address Gemini Code Assist review feedback: - Add encoding='utf-8' to file open - Skip comments and empty lines in YAML parsing - Use specific exception types instead of bare except - Add warning message for parse failures Co-authored-by: gemini-code-assist[bot] <176abortedflight+gemini-code-assist[bot]@users.noreply.github.com> --- .agent/scripts/generate-opencode-agents.sh | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/.agent/scripts/generate-opencode-agents.sh b/.agent/scripts/generate-opencode-agents.sh index b755704a..a07c2c88 100755 --- a/.agent/scripts/generate-opencode-agents.sh +++ b/.agent/scripts/generate-opencode-agents.sh @@ -185,7 +185,7 @@ SKIP_FILES = {"AGENTS.md", "README.md"} def parse_frontmatter(filepath): """Parse YAML frontmatter from markdown file.""" try: - with open(filepath, 'r') as f: + with open(filepath, 'r', encoding='utf-8') as f: content = f.read() # Check for frontmatter @@ -207,6 +207,10 @@ def parse_frontmatter(filepath): for line in lines: stripped = line.strip() + # Ignore comments and empty lines + if not stripped or stripped.startswith('#'): + continue + if stripped.startswith('- ') and current_key: # List item current_list.append(stripped[2:].strip()) @@ -229,7 +233,9 @@ def parse_frontmatter(filepath): result[current_key] = current_list return result - except: + except (IOError, OSError, UnicodeDecodeError) as e: + import sys + print(f"Warning: Failed to parse frontmatter for {filepath}: {e}", file=sys.stderr) return {} def filename_to_display(filename): From 3e035badfb047c9acb81b12a1e4d17c5674819db Mon Sep 17 00:00:00 2001 From: marcusquinn <6428977+marcusquinn@users.noreply.github.com> Date: Wed, 14 Jan 2026 00:30:15 +0000 Subject: [PATCH 3/3] fix(health): remove context7 subagent context7 provides library/framework docs, not health information. crawl4ai is sufficient for health research workflows. Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- .agent/health.md | 1 - 1 file changed, 1 deletion(-) diff --git a/.agent/health.md b/.agent/health.md index ea9aa976..8874b8b9 100644 --- a/.agent/health.md +++ b/.agent/health.md @@ -4,7 +4,6 @@ description: Health and wellness domain - medical information, fitness, nutritio mode: subagent subagents: # Research - - context7 - crawl4ai # Built-in - general