opencode icon indicating copy to clipboard operation
opencode copied to clipboard

[FEATURE]: Client-Side Model Selection Control for SDK

Open enving opened this issue 2 weeks ago • 2 comments

Feature hasn't been suggested before.

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

Describe the enhancement you want to request

Feature Request: Client-Side Model Selection Control for SDK

Summary

The OpenCode SDK currently ignores client-side model configuration, making it impossible to enforce cost controls for autonomous long-running agents. This creates unexpected costs and prevents use of free-tier models.

Problem Description

When using the OpenCode Python SDK for autonomous coding agents, the server-side model selection logic overrides all client-side configuration, including:

  1. .opencode.json configuration file
  2. SDK method parameters (model_id, provider_id)
  3. Docker environment variables (DEFAULT_MODEL)

Expected Behavior

When configured with:

{
  "model": "openrouter/meta-llama/llama-3.1-8b-instruct:free",
  "max_tokens": 200
}

And calling the SDK with required parameters as defined in the official API:

# Official SDK signature from opencode-ai v0.1.0a36:
# async chat(id, *, model_id: str, provider_id: str, parts, extra_body, ...)

result = await client.session.chat(
    session_id,
    model_id="mistralai/mistral-7b-instruct:free",  # REQUIRED parameter
    provider_id="openrouter",                        # REQUIRED parameter
    parts=[{"type": "text", "text": message}],
    extra_body={"max_tokens": 200}
)

Note: According to the SDK's Python signature, model_id and provider_id are required parameters, not optional. We used the API correctly.

Expected: Server uses mistralai/mistral-7b-instruct:free (free tier, $0.00 cost)

Actual Behavior

The OpenCode server ignores configuration and selects different models:

  • google/gemini-3-pro-preview (paid, $0.15/request)
  • claude-haiku-4.5 via Amazon Bedrock (paid, $0.01-0.02/request)

Evidence from Docker container inspection:

# Environment variable explicitly set:
$ docker exec opencode-server env | grep MODEL
DEFAULT_MODEL=openrouter/meta-llama/llama-3.1-8b-instruct:free

# But session data shows different model was used:
$ docker exec opencode-server cat /root/.local/share/opencode/storage/message/.../msg_*.json
{
  "modelID": "google/gemini-3-pro-preview",
  "providerID": "openrouter",
  "cost": 0.014294
}

Result: Unexpected costs accumulate rapidly in long-running autonomous sessions.

Evidence

OpenRouter usage logs from a 10-minute test session:

Dec 10, 08:56 PM - Gemini 3 Pro Preview - 19,849 tokens - $0.152
Dec 10, 08:56 PM - Claude Haiku 4.5 - 12,290 tokens - $0.0125
Dec 10, 08:54 PM - Gemini 3 Pro Preview - 12,617 tokens - $0.0136
Dec 10, 08:54 PM - Claude Haiku 4.5 - 1,862 tokens - $0.00192
(21+ similar requests)

Total cost: ~$0.30-0.50 for 10 minutes instead of $0.00 (free tier)

Use Case

Building autonomous coding agents that:

  • Run for hours/days implementing features
  • Need predictable, controllable costs
  • Should use free-tier models for development/testing
  • Follow the Anthropic Long-Running Agents Guide

Proposed Solution

Add client-side control over model selection with one of these approaches:

Option 1: Honor SDK Parameters (Preferred)

When model_id and provider_id are explicitly passed to client.session.chat(), use them without modification:

# This should guarantee the exact model is used
result = await client.session.chat(
    session_id,
    model_id="mistralai/mistral-7b-instruct:free",
    provider_id="openrouter",
    enforce_model=True,  # New parameter to enforce exact model
    ...
)

Option 2: Strict Mode Configuration

Add a configuration option to disable server-side model selection:

{
  "model": "openrouter/meta-llama/llama-3.1-8b-instruct:free",
  "enforce_model": true,  // Disable server-side model switching
  "fallback_behavior": "error"  // Fail if model unavailable instead of switching
}

Option 3: Model Allowlist

Allow users to specify which models are allowed:

{
  "allowed_models": [
    "openrouter/mistralai/mistral-7b-instruct:free",
    "openrouter/meta-llama/llama-3.1-8b-instruct:free"
  ],
  "block_paid_models": true
}

Impact

Without this feature:

❌ OpenCode SDK is unsuitable for cost-sensitive autonomous agents
❌ Developers cannot control costs in long-running sessions
❌ Free-tier development/testing is impossible
❌ SDK behavior is unpredictable and undocumented

With this feature:

✅ Developers have full cost control
✅ Free-tier models can be guaranteed
✅ Autonomous agents can run safely for hours/days
✅ SDK behavior is predictable and documented

Workarounds Attempted

All failed to prevent server-side model switching:

  1. ✅ Configured .opencode.json with explicit model
  2. ✅ Passed model parameters via SDK methods
  3. ✅ Set Docker environment variables
  4. ✅ Used extra_body to limit max_tokens
  5. None prevented the server from selecting paid models

Environment

  • OpenCode Server: Docker ghcr.io/sst/opencode (latest)
  • OpenCode Python SDK: opencode-ai v0.1.0a36
  • Provider: OpenRouter
  • Models Configured: Free tier (mistralai/mistral-7b-instruct:free, meta-llama/llama-3.1-8b-instruct:free)
  • Models Actually Used: Paid tier (Gemini 3 Pro, Claude Haiku)

SDK Method Signature (verified):

async def chat(
    self, id: str, *,
    model_id: str,              # REQUIRED - but ignored by server
    provider_id: str,           # REQUIRED - but ignored by server  
    parts: Iterable[...],
    extra_body: Body | None,    # Used for max_tokens - but ignored by server
    ...
) -> AssistantMessage

The parameters model_id and provider_id are required by the SDK API, yet the server overrides them.

Additional Context

This issue affects autonomous coding workflows described in:

The lack of client-side model control makes OpenCode SDK incompatible with cost-controlled autonomous development, forcing developers to either:

  1. Accept unpredictable costs
  2. Implement custom harnesses with direct API calls (bypassing OpenCode entirely)

References

  • Project Repository: https://github.com/[user]/opencode_harness_autonomous_coding
  • Anthropic Guide: https://www.anthropic.com/engineering/effective-harnesses-for-long-running-agents
  • OpenCode Docs: https://opencode.ai/docs

Is this a bug or a feature request?

Both. It's a bug that configuration is ignored, and a feature request to add explicit client-side model control.

Priority: High - Affects SDK usability for autonomous agents and cost control.

enving avatar Dec 10 '25 21:12 enving

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

  • #4901: Bug: SDK Messages cause switch back to default model (SDK calls reset session model selection)
  • #4981: Model/Agent selection on the intro screen not applied (Configuration and SDK parameters being ignored)
  • #4475: Plugins using noReply seem to cause model to switch to agent default (SDK messages resetting user model selection)
  • #4559: [FEATURE]: Add configurable spending limit / "Kill Switch" per session (Cost control for sessions)
  • #4133: [FEATURE]: Use a cheap model to name sessions (Cost optimization for model selection)

These issues all relate to cost control, model selection persistence, and SDK parameter handling. Your issue specifically addresses the need for client-side model selection control to prevent unexpected costs with autonomous agents.

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

github-actions[bot] avatar Dec 10 '25 21:12 github-actions[bot]

are u using our python sdk? or ur own I would have to look at the python but it definitely respects client side model selection, if it isnt then its a bug in sdk or ur code

rekram1-node avatar Dec 11 '25 00:12 rekram1-node