Skip to content

Claude Code generated subagents collapse configured max effort to high #704

Closed

Description

@jhste102lab

Client or integration

Claude Code

Area

Proxy and routing

Summary

OpenCodex 2.7.42 generates routed Claude Code custom-agent definitions with a pinned model, but no configurable effort. As a result, a routed agent such as ocx-deepseek-v4-pro cannot reliably request max effort.

Adding effort: "max" to the generated frontmatter is necessary but not sufficient with Claude Code 2.1.220. Live capture shows that Claude Code collapses custom-agent xhigh and max into the legacy request shape:

{
  "thinking": {
    "type": "enabled",
    "budget_tokens": 31999
  }
}

OpenCodex intentionally maps any thinking.budget_tokens > 16384 to high, so the provider receives reasoning_effort=high, not max.

Expected behavior: OpenCodex should expose a validated configuration for generated Claude Code subagent effort and preserve the exact configured level through routed inbound translation. Unset configuration must retain the existing parent-inheritance behavior.

Reproduction

Environment:

  • OpenCodex: 2.7.42
  • Claude Code: 2.1.220
  • Provider/model: opencode-go/deepseek-v4-pro
  • OS: Linux 6.8
  1. Configure opencode-go/deepseek-v4-pro in the featured subagent roster.

  2. Start Claude Code through ocx claude so OpenCodex generates <user-home>/.claude/agents/ocx-deepseek-v4-pro.md.

  3. Observe the generated frontmatter in 2.7.42:

    ---
    name: "ocx-deepseek-v4-pro"
    model: "claude-ocx-opencode-go--deepseek-v4-pro"
    ---
  4. Add effort: "max" locally and start a fresh Claude Code session.

  5. Dispatch ocx-deepseek-v4-pro once with a deterministic arithmetic prompt.

  6. Observe the Claude inbound request and the final provider request.

Before the fix, sanitized observations were:

Claude inbound model: claude-ocx-opencode-go--deepseek-v4-pro
Resolved model: opencode-go/deepseek-v4-pro
thinking.type: enabled
thinking.budget_tokens: 31999
Provider requestedEffort: high
Provider effectiveEffort: high
Wire field/value: reasoning_effort=high
HTTP status: 200

A direct Codex-path control using the same provider/model successfully requested and delivered max, which narrows the defect to the Claude Code generated-agent/inbound translation path rather than the provider integration.

Root cause

src/claude/agents-inject.ts renders generated definitions with name, description, and model, but has no effort field.

Even after adding standard Claude Code effort frontmatter, Claude Code 2.1.220 does not preserve xhigh or max as output_config.effort on these custom-agent turns. It emits a legacy 31,999-token thinking budget. src/claude/inbound.ts::effortForThinkingBudget() correctly but lossy-maps that entire range to high; a token budget alone cannot distinguish high, xhigh, and max.

OpenCodex already solves an analogous Claude Code limitation for model routing by embedding a generated ocx-route directive in the owned agent body and consuming it at the inbound proxy boundary. The proposed patch uses the same bounded system-field channel for the exact generated effort.

Proposed and tested fix

Commit: jhste102lab@5635eda7

Branch diff: dev...jhste102lab:opencodex:feat/claude-subagent-effort

The patch:

  1. Adds optional claudeCode.subagentEffort with supported values low | medium | high | xhigh | max.

  2. Renders both standard frontmatter and an OpenCodex-owned directive:

    model: "claude-ocx-opencode-go--deepseek-v4-pro"
    effort: "max"
    <!-- ocx-route: claude-ocx-opencode-go--deepseek-v4-pro -->
    <!-- ocx-effort: max -->
  3. Applies the effort directive only when a valid ocx-route directive is also present, then restores output_config.effort before Anthropic-to-Responses translation.

  4. Leaves the existing behavior unchanged when the setting is unset.

  5. Rejects invalid values at CLI/import write boundaries while degrading an invalid persisted value by ignoring only that optional field. Providers, account pools, API keys, and listen configuration remain intact.

  6. Preserves the generated-file ownership marker, user-authored ocx-* protection, atomic writes, pruning behavior, and existing route override.

Live verification after the fix

A fresh ocx claude session regenerated the agent and dispatched it once. Sanitized result:

Generated frontmatter effort: max
Generated route: claude-ocx-opencode-go--deepseek-v4-pro
Subagent response: 42
Provider: opencode-go
Model: deepseek-v4-pro
Requested effort: max
Effective effort: max
Wire field/value: reasoning_effort=max
HTTP status: 200

No raw request/response payload, credentials, account identifiers, user paths, request UUIDs, or personal data are included here.

Validation

Targeted tests: 160 passed, 0 failed
Full suite: 5964 passed, 1 skipped, 0 failed (429 files)
TypeScript: bun x tsc --noEmit passed
Privacy scan: passed
GUI lint: passed
Docs build: 146 pages built
Diff check: passed
Live Claude Code -> OpenCodex -> opencode-go/deepseek-v4-pro smoke: HTTP 200, max requested/effective

Regression coverage includes:

  • unset effort produces no frontmatter/directive and preserves inheritance;
  • all five supported values render once for roster and self definitions;
  • regeneration removes a previously configured effort;
  • invalid config candidates are rejected;
  • invalid persisted effort is ignored without wiping unrelated configuration;
  • malformed/unsupported directives are ignored;
  • a Claude Code thinking.budget_tokens=31999 routed turn is restored to exact reasoning_effort=max;
  • existing ownership and pruning tests remain green.

Version

OpenCodex 2.7.42 / source base dev@693347d4; patch commit 5635eda7

Operating system

Linux 6.8

Provider and model

opencode-go / deepseek-v4-pro

Logs or error output

# Before patch (sanitized)
requestedEffort=high effectiveEffort=high reasoningWireField=reasoning_effort reasoningWireValue=high status=200

# After patch (sanitized)
requestedEffort=max effectiveEffort=max reasoningWireField=reasoning_effort reasoningWireValue=max status=200

Redacted configuration

{
  "subagentModels": ["opencode-go/deepseek-v4-pro"],
  "claudeCode": {
    "subagentEffort": "max"
  },
  "providers": {
    "opencode-go": {
      "apiKey": "[REDACTED]"
    }
  }
}

Checks

  • I searched existing issues and documentation.
  • I removed secrets, tokens, account details, request credentials, absolute user paths, request IDs, and personal data.

Activity

  1. github-actions commented on Jul 29, 2026

    @github-actions
    Contributor

    Automated translation bookkeeping — detected language: English.

  2. lidge-jun commented on Jul 29, 2026

    @lidge-jun
    Owner

    Fixed on dev in c0ad57a, via PR #705 (commits 5635eda, b67ddb9, and the follow-up 6d5bea1).

    Thank you for the live capture — the part that made this actionable was showing that adding effort: "max" to the generated frontmatter is necessary but not sufficient, because Claude Code 2.1.220 collapses xhigh and max into the legacy thinking.budget_tokens shape, which our mapping then read back as high.

    What landed: a validated claudeCode.subagentEffort setting that generated agent definitions carry, and restoration of the exact configured level across the legacy budget shape rather than re-deriving it from the token count. The follow-up commit also tightened the persistence boundaries so an invalid value is dropped without disturbing neighbouring settings, and stopped the warning from echoing the offending value back into the log.

    Verification on dev: bun run test 5972 pass / 0 fail, typecheck / lint:gui / privacy:scan green.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions