-
Notifications
You must be signed in to change notification settings - Fork 14.9k
Non-deterministic agent/skill ordering in tool descriptions breaks prompt caching #18215
Description
Description
The task and skill tool descriptions contain agent/skill lists in non-deterministic order across API calls within the same session. Since Anthropic's prompt caching (the one I tested) is prefix-based, any byte change invalidates the entire cache, resulting in 0% cache hit rate.
Reproducible when custom agents are registered (via plugins like oh-my-opencode-slim or ~/.config/opencode/agents/). The more agents/skills, the more likely the order changes between calls. Bare opencode with only the default agent may not trigger it, but I think the fix still interesting for everyone.
Root cause:
- packages/opencode/src/tool/task.ts:39: accessibleAgents is mapped without sorting
- packages/opencode/src/tool/skill.ts:10: Skill.available() result is used unsorted
- Agent.list() in agent.ts only pins the default agent first via a boolean sort, leaving all others in undefined insertion order from filesystem/plugin loading
Proposed Fix:
Sort before mapping in both files:
// task.ts line 39
[...accessibleAgents].sort((a, b) => a.name.localeCompare(b.name))// skill.ts line 10
const list = await Skill.available(ctx?.agent).then((x) => [...x].sort((a, b) => a.name.localeCompare(b.name)))Verified result (3-turn test, ~26 agents + 7 skills):
| Turn | Before (cache read) | Afer (cache read) |
|---|---|---|
| 1 | 0 | 0 (cold start) |
| 2 | 0 | 17,837 |
| 3 | 0 | 17,837 |
Plugins
oh-my-opencode-slim, opencode-beads, opencode-antigravity-auth, @tarquinen/opencode-dcp, @franlol/opencode-md-table-formatter, opencode-openai-codex-auth, opencode-websearch-cited, @simonwjackson/opencode-direnv
OpenCode version
1.2.26
Steps to reproduce
Setup: register multiple custom agents (e.g. via oh-my-opencode-slim + custom agents in ~/.config/opencode/agents/)
Turn 1
opencode run -m anthropic/claude-sonnet-4-6 "Say hello" --format jsonNote session ID, then:
opencode run -m anthropic/claude-sonnet-4-6 --session <ID> --continue "Say goodbye" --format jsonObserve cache.read: 0 on every turn. Route through a proxy (I used litellm/langfuse) to compare request payloads, the agent list in the task tool description is in a different order each turn.
Screenshot and/or share link
No response
Operating System
MacOS 26.2 (25C56)
Terminal
Kitty