Skip to content

Skill list injected twice per request wastes ~5K–7K tokens of context budget #22236

Description

@zubingtan

Description

Every LLM request includes the full skill list twice — once in the system prompt body via SystemPrompt.skills(), and once in the skill tool's description field. With 30+ skills, this costs roughly 5,000–7,000 tokens per request that carry no new information.

How it happens

Injection point 1 — System prompt body (session/system.ts):

Skill.fmt(list, { verbose: true })
// → XML format with <name>, <description>, <location> for each skill

Injection point 2 — skill tool description (tool/skill.ts):

Skill.fmt(list, { verbose: false })
// → Compact markdown: "## Available Skills\n- **name**: description"

Both are sent in every request. The model sees the same 30+ skills listed in two different formats.

History

Impact

For a user with 30+ skills (custom + built-in), the baseline system prompt already exceeds 60,000 tokens before any conversation starts. The duplicated skill list accounts for 8–12% of that overhead. This is especially painful for models with smaller context windows (128K) where it eats 5% of the total budget on day-zero.

Suggested alternatives

  1. Keep only one injection point. The system prompt version (verbose XML) is likely sufficient — the model doesn't need a second copy in the tool description to know skills exist. The tool description could simply say "Load a skill. Run without arguments to see available skills."
  2. Lazy-load the skill list. Instead of embedding the full list in every request, inject a short summary (e.g., skill count + top 5 most relevant) and let the model call the skill tool to get the full list on demand.
  3. Make it configurable. Add a config option like "skills": { "prompt_injection": "single" | "dual" | "none" } so users can opt out of the duplication.

Measured token counts (approximate)

Component Tokens
Verbose XML (system prompt, 30 skills) ~3,500
Compact markdown (tool desc, 30 skills) ~2,000
Duplication overhead ~5,500
cc @rekram1-node — you authored the original dual-injection design in #17053. Curious if you've seen measurable improvements in skill invocation rates that justify the token cost, or if a single injection point would work just as well now that models are better at tool use.

Plugins

No response

OpenCode version

1.4.3

Steps to reproduce

No response

Screenshot and/or share link

No response

Operating System

No response

Terminal

No response

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

bugSomething isn't workingcoreAnything pertaining to core functionality of the application (opencode server stuff)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