Skip to content

Forward variant to opencode agent registration (fixes variant use in opencode task() tool)#41

Merged
tctinh merged 1 commit intotctinh:mainfrom
imarshallwidjaja:fix/properly-pass-variants-for-task-tool
Feb 6, 2026
Merged

Forward variant to opencode agent registration (fixes variant use in opencode task() tool)#41
tctinh merged 1 commit intotctinh:mainfrom
imarshallwidjaja:fix/properly-pass-variants-for-task-tool

Conversation

@imarshallwidjaja
Copy link
Collaborator

PR: Forward variant to opencode agent registration

Problem

After this implementaion anomalyco/opencode#11410

The config hook in opencode-hive reads variant from ConfigService.getAgentConfig() but does not include it in the agent config objects registered with opencode. The agent configs set model and temperature but omit variant.

This matters because opencode's built-in variant resolution in createUserMessage (session/prompt.ts:831-838) checks agent.variant:

const variant =
  input.variant ??
  (agent.variant &&
   agent.model &&
   model.providerID === agent.model.providerID &&
   model.modelID === agent.model.modelID
    ? agent.variant
    : undefined)

Since agent.variant was always undefined, this path never produced a value. The chat.message hook (introduced in the per-agent variant PR) was the only working path for variant injection.

What changed

Added variant: <agentUserConfig>.variant to all six agent config objects in the config hook:

  • hiveConfig
  • architectConfig
  • swarmConfig
  • scoutConfig
  • foragerConfig
  • hygienicConfig

One line per agent. No other changes.

How the two paths now interact

There are two paths for variant to reach the LLM request:

  1. Built-in resolution (prompt.ts:831): opencode reads agent.variant and agent.model, checks they match the model in use, and sets variant on the message info. This now works because agent.variant is populated.

  2. chat.message hook (index.ts:417): fires after built-in resolution. Checks output.message.variant and only sets it if currently undefined. Acts as a fallback for cases where the model guard in path 1 fails (e.g., model mismatch).

Both paths agree. Path 1 sets the value when model matches; the hook's if (output.message.variant !== undefined) return guard skips it. When model doesn't match, path 1 produces undefined and the hook fills it in.

Scope

  • packages/opencode-hive/src/index.ts only.
  • No changes to hive-core, vscode-hive, tests, or schema.
  • No upstream opencode changes.

Verification

bun run build          # passes
bun -w opencode-hive test  # 306 pass, 0 fail
bun -w hive-core test      # 85 pass, 0 fail

Manual verification

Requires both agent_hive.json and opencode.json configured with a variant-capable model.

agent_hive.json:

{
  "agents": {
    "forager-worker": {
      "model": "anthropic/claude-sonnet-4-20250514",
      "variant": "high"
    }
  }
}

opencode.json (model must define the variant key):

{
  "provider": {
    "anthropic": {
      "models": {
        "claude-sonnet-4-20250514": {
          "variants": {
            "high": {
              "thinking": { "type": "enabled", "budgetTokens": 16000 }
            }
          }
        }
      }
    }
  }
}

Prompt the hive-master agent:

Use the task tool to spawn a forager-worker subagent. Have it read the file opencode.json in the project root and report back the first 5 lines.

Check opencode logs (~/.local/share/opencode/log/) for the forager-worker session's LLM request. The thinking options should be present in the provider options. As a negative control, remove variant from agent_hive.json and repeat -- the thinking block should disappear.

The config hook was reading variant from ConfigService but not including it
in the agent config objects registered with opencode. This meant opencode's
built-in variant resolution in createUserMessage (prompt.ts:831-838) always
saw agent.variant as undefined, making the chat.message hook the only path
for variant injection. Now both paths work correctly.
@tctinh tctinh merged commit 5fe2ef4 into tctinh:main Feb 6, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants