Skip to content

Reduce token overhead: Task tool injects all subagent descriptions into system prompt #7269

Closed

Description

@marcusquinn

Feature hasn't been suggested before.

  • I have verified this feature I'm about to request hasn't been suggested before.

Describe the enhancement you want to request

Problem

The task tool definition includes the full list of all configured subagents with their descriptions, injected into every conversation's system prompt. With many subagents configured, this adds significant token overhead before the user even sends their first message.

Example: With 150 subagents configured in ~/.config/opencode/agent/, the task tool description alone adds ~6,000-10,000 tokens to every conversation, regardless of whether the agent will actually use subagents.

Current Behavior

The task tool description contains entries like:

Available agent types and the tools they have access to:
- general: General-purpose agent...
- explore: Fast agent specialized for exploring codebases...
- dev-browser: Read ~/.aidevops/agents/tools/browser/dev-browser.md
- authentication: Read ~/.aidevops/agents/tools/git/authentication.md
... (150+ entries)

This is injected for every agent that has task: true in their tools config.

Impact

Measured Example

Comparing two agents with identical instructions but different tool access:

Agent Task Tool First Message Tokens
Plan+ Disabled ~X tokens
Build+ Enabled ~X + 11,000 tokens

The ~11k difference is primarily the task tool's subagent list.

Proposed Solutions

Option A: Per-agent subagent filtering (preferred)

Allow primary agents to specify which subagents they can spawn:

{
  "agent": {
    "Build+": {
      "tools": {
        "task": ["explore", "dev-browser", "code-review"]
      }
    }
  }
}

Only listed subagents would appear in that agent's task tool definition. This also improves focus - the LLM only sees relevant options.

Option B: Lazy loading / on-demand lookup

Instead of injecting all descriptions upfront, provide a minimal task tool that can look up subagent details on demand:

task tool: "Launch subagents. Use `task list` to see available agents, or `task run <name> <prompt>` to launch."

The LLM would call task list only when it needs to spawn a subagent, paying the token cost only when needed.

Option C: Compact mode flag

Add a config option to use minimal descriptions:

{
  "task_tool_mode": "compact"
}

Compact mode would list only agent names without descriptions, or use a much shorter format.

Option D: Hierarchical/categorized listing

Group subagents by category with collapsed descriptions:

Available agent categories: browser (5), git (4), code-review (6), seo (7)...
Use task(category="browser") to see browser agents, or task(agent="explore") directly.

Related Issues

Environment

  • OpenCode version: 1.x
  • Subagents configured: 150+
  • Framework: aidevops (generates many specialized subagents)

Activity

  1. added
    perfIndicates a performance issue or need for optimization
    on Jan 8, 2026
  2. github-actions commented on Jan 8, 2026

    @github-actions
    Contributor

    This issue might be a duplicate of existing issues. Please check:

    These issues relate to token overhead, system prompt optimization, and configuration visibility that may address your concerns about token efficiency.

    Feel free to ignore if none of these address your specific case.

  3. marcusquinn commented on Jan 8, 2026

    @marcusquinn
    Author

    Thanks for the duplicate check! This issue is distinct from the flagged ones:

    The key distinction: this isn't about the system prompt content, but about the tool schema/description that gets injected. With 150 subagents, the task tool's description field alone is ~6-10k tokens - and there's currently no way to scope which subagents appear per primary agent.

    The proposed solutions (per-agent filtering, lazy loading, compact mode) are specific to the task tool architecture and haven't been addressed in the related issues.

  4. lorenzo-colpani commented on Jan 8, 2026

    @lorenzo-colpani

    I found a temporary workaround for this!

    The issue is that if a subagent isn't explicitly restricted, OpenCode injects its full description into every system prompt. You can 'prune' the system prompt by globally denying all subagents and then locally allowing only the ones specific agents need.

    This effectively hides the denied subagents from the system prompt, drastically reducing the token overhead.

    Simplified Example
    If you have a build-specialist and a project-manager subagent, but don't want them both showing up in every agent:

    {
      "$schema": "https://opencode.ai/config.json",
      "permission": {
        "task": {
          "build-specialist": "deny",
          "project-manager": "deny"
        }
      },
      "agent": {
        "builder": {
          "permission": {
            "task": {
              "build-specialist": "allow"
            }
          }
        },
        "planner": {
          "permission": {
            "task": {
              "project-manager": "allow"
            }
          }
        }
      }
    }
  5. rekram1-node commented on Jan 8, 2026

    @rekram1-node
    Contributor

    That description is a literal prompt for the agent so it knows when to call the subagents, this is expected and intentional, you can remove certain agents from the task tool by denying them example if I only want my agent to call explore subagent:

    {
      "agent": {
         "build": {
            "permission": {
              "task": {"*": "deny", "explore": "allow"} 
            }
         }
      }
    }
    

    You can also ofc decrease your agent descriptions too

  6. marcusquinn commented on Jan 9, 2026

    @marcusquinn
    Author

    Following up with additional context on why per-agent filtering is preferable to lazy-loading approaches.

    I'm aware of the existing options for managing context (like #4119 for subagent context control), but they don't solve this specific problem: main agent awareness of its delegation options.

    Amp recently shipped a lazy-load MCP with skills feature where MCP tools only load when a skill is invoked. While this saves tokens, it creates a chicken-and-egg problem for subagents:

    Without upfront awareness, the main agent:

    • Reinvents solutions that specialized subagents already handle
    • Misses parallelization opportunities across subagents
    • Can't make informed decisions about delegation

    The filtered subagents list in this PR preserves awareness while reducing overhead. The main agent still knows "I have explore, dev-browser, and code-review available" - it just doesn't see 150 irrelevant options.

    Lazy-loading makes sense for MCP tools within subagents (the subagent knows what it needs), but subagent awareness should remain upfront in the main agent's context.

    Happy to discuss alternative approaches if there are concerns with this implementation.

  7. lorenzo-colpani commented on Jan 9, 2026

    @lorenzo-colpani

    That description is a literal prompt for the agent so it knows when to call the subagents, this is expected and intentional, you can remove certain agents from the task tool by denying them example if I only want my agent to call explore subagent:

    {
      "agent": {
         "build": {
            "permission": {
              "task": {"*": "deny", "explore": "allow"} 
            }
         }
      }
    }
    

    You can also ofc decrease your agent descriptions too

    Just an update: I was facing this in v1.1.6. Even when explicitly denying subagents, the agent could see the prompts, resulting in permission errors upon execution. I had to use a workaround where I denied everyone in the System permissions and then whitelisted them in the Agent permissions which then worked fine.

    However, v1.1.8 seems to have fixed this. I can now deny specific subagents normally, and they are properly excluded from the prompt context. Thank you!

  8. marcusquinn commented on Jan 9, 2026

    @marcusquinn
    Author

    Thanks @lorenzo-colpani for confirming the fix!

    I've tested on v1.1.10 and can confirm the permission filtering is working correctly:

    Agent Task Permission Visible Subagents
    TestFiltered {"*": "deny", "explore": "allow", "general": "allow"} 2
    Build+ unrestricted 108

    The denied subagents are now properly excluded from the prompt context, not just blocked at execution time.

    For anyone with many subagents (I have ~158 from aidevops), this is the pattern to reduce token overhead:

    {
      "agent": {
        "SEO": {
          "permission": {
            "task": {
              "*": "deny",
              "explore": "allow",
              "seo": "allow",
              "keyword-research": "allow"
            }
          },
          "tools": {
            "task": true
          }
        }
      }
    }

    This reduces the task tool description from all subagents to just the allowed ones.

  9. added a commit that references this issue on Feb 25, 2026
    8e114b7
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

perfIndicates a performance issue or need for optimization

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions