Skip to content

feat(codex): add agent.text_verbosity config for GPT-5+ response length control - #59844

Open
qxxaa wants to merge 3 commits into
NousResearch:mainfrom
qxxaa:feat/codex-text-verbosity-v3
Open

feat(codex): add agent.text_verbosity config for GPT-5+ response length control#59844
qxxaa wants to merge 3 commits into
NousResearch:mainfrom
qxxaa:feat/codex-text-verbosity-v3

Conversation

@qxxaa

@qxxaa qxxaa commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Problem

OpenAI's Responses API exposes text.verbosity as a first-class request
parameter for controlling output length on GPT-5+ models. Hermes already
surfaces the companion controls - reasoning_effort for thinking depth,
service_tier for priority routing - but text.verbosity has no config
path. Users who want concise agent output from GPT-5+ have no way to
request it without patching source.

This is not a cosmetic gap. In agent workflows, verbose output compounds:
every excess token in an assistant response becomes input on the next turn,
inflating both cost and time-to-first-token across the entire session.
Measured on GPT-5.5: text.verbosity: "low" reduced output from 585 to
369 words (37%) on identical prompts. Over a 20-turn session, that
reduction applies to every subsequent API call's input context.

The preflight validator in codex_responses_adapter.py also actively
blocks text as an unsupported field, so even users who discover the
extra_body workaround described in #20203 cannot use the native
top-level parameter that the SDK expects.

Fix

New config key agent.text_verbosity:

agent:
  text_verbosity: "low"  # "low" | "medium" | "high" | "" (default, no injection)

Default is empty string - zero behaviour change unless explicitly
opted in. When set, injects text: {"verbosity": "<value>"} into
Responses API payloads for GPT-5+ models only.

Prior art

@JiehoonKwak's #29574 identified the cleanest loading approach: reading
text_verbosity inside init_agent() directly from _agent_section,
avoiding the need to thread the parameter through every CLI/gateway/TUI
startup path. This PR adopts that approach and adds two safety layers:

  1. GPT-5+ model guard with vendor prefix handling. Parses the major
    version from the model name and injects only for GPT-5+. Strips vendor
    prefixes (openai/gpt-5.5 -> gpt-5.5) before matching, so custom
    provider setups and vendor-prefixed model names work without a
    provider-name blocklist. Non-GPT models are silently skipped.

  2. Safe dict merge with request_overrides. Merges verbosity into
    any existing text dict rather than replacing it. Without this, setting
    text.verbosity would clobber text.format from request_overrides -
    silently breaking structured output for anyone combining both features.

Design decisions

Config loading (from #29574): Loaded inside init_agent() directly
from _agent_section, consistent with reasoning_effort, service_tier,
and tool_use_enforcement. Every agent creation path converges through
init_agent(), so no caller plumbing is needed.

Gateway hot-reload: Cache-bust tuple ("agent", "text_verbosity")
added to _CACHE_BUSTING_CONFIG_KEYS. Config changes evict the cached
agent and rebuild with the new value. Correct because text_verbosity
has no runtime command (unlike service_tier which has /fast).

Model guard (new): Parses gpt-X.Y, extracts major version, injects
only when >= 5. Strips vendor prefixes before matching. Non-GPT models
silently skipped.

Dict merge (new): Merges verbosity into any existing text dict,
preserving text.format from request_overrides.

Preflight pass-through: "text" added to both the allowed_keys
whitelist and the normalization copy path. The preflight validator
requires both - without the copy block, the field passes validation but
is silently dropped before reaching the API.

Transport scope: codex_responses only. Chat completions and
Anthropic transports are untouched.

No validation: Consistent with reasoning_effort. Invalid values
pass through to the API, which returns a clear error.

Files changed (9)

File Change
hermes_cli/config.py Default "" in agent defaults
agent/agent_init.py Early attribute default + config read from _agent_section
agent/chat_completion_helpers.py Pass to codex transport
agent/codex_responses_adapter.py Preflight whitelist + pass-through
agent/transports/codex.py GPT-5+ guard + safe dict merge
gateway/run.py Cache-bust tuple
tests/agent/test_codex_responses_adapter.py 3 preflight text pass-through tests
tests/agent/transports/test_codex_transport.py 19 transport tests
website/docs/user-guide/configuration.md Documentation

Regression risk

Low. Default is empty string. The if text_verbosity and isinstance(text_verbosity, str) guard ensures no injection unless
explicitly configured. Zero behaviour change for existing users.

Tests

22 new tests across two files:

19 transport tests:

  • Model guard: inject on 6 GPT-5+ variants, skip on 5 non-GPT-5 models
  • Bare gpt- prefix (no version): skip
  • Empty verbosity: no injection (2 tests)
  • Merge preservation: text.format + text.verbosity coexist
  • Vendor-prefixed models: inject on 3 prefixed GPT-5+, skip on prefixed GPT-4

3 preflight adapter tests:

  • text dict survives normalization
  • text.format + text.verbosity coexist through preflight
  • Empty text dict correctly dropped
scripts/run_tests.sh tests/agent/transports/test_codex_transport.py tests/agent/test_codex_responses_adapter.py -q

82/82 passed (60 existing + 22 new). Zero regressions.

Closes #20203.

@alt-glitch alt-glitch added type/feature New feature or request comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint provider/openai OpenAI / Codex Responses API area/config Config system, migrations, profiles P3 Low — cosmetic, nice to have labels Jul 6, 2026
@alt-glitch

Copy link
Copy Markdown
Collaborator

This was generated by AI during triage.

Resubmission of your closed #59711 (same feature). This also competes with the open #20258 (feat(openai): support Responses text verbosity), which likewise implements #20203. Cross-linking so a maintainer can pick a canonical PR: #20258 is earlier and narrower; this PR adds the GPT-5+ model guard, lifts the text preflight block, and plumbs the full config surface + docs. Not marking either duplicate — both are open competing approaches.

@teknium1

Copy link
Copy Markdown
Contributor

Thanks for the focused opt-in implementation. The current main still rejects top-level text in the Codex Responses preflight (agent/codex_responses_adapter.py:912-917, :1016-1020), so the feature addresses a live gap.

Problems

  • Required CI is currently red. GitHub run 29406951092 fails the stale merge-ref version of test_normalize_codex_response_salvage_is_xai_scoped. Current main now passes issuer_kind="codex_backend" at tests/agent/test_codex_responses_adapter.py:508-510; retain that current regression coverage when salvaging.

Suggested changes

  • Salvage the feature commit e5f04b59a3da263c8ad868aa74362554683732e9, not the branch merge commit, so the current test correction remains intact.
  • Add a config-to-wire regression test: agent.text_verbosity config → agent/chat_completion_helpers.py:908-924 → normalized Codex request.

Automated hermes-sweeper review.

@teknium1 teknium1 added sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:risk-caching Sweeper risk: may break/degrade prompt caching or cache-key stability (invariant) sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform labels Jul 15, 2026
@qxxaa
qxxaa force-pushed the feat/codex-text-verbosity-v3 branch from 1090baa to dc14a6c Compare July 16, 2026 10:02
@qxxaa

qxxaa commented Jul 16, 2026

Copy link
Copy Markdown
Contributor Author

Hi @teknium1 , thanks for the review. I've rebased onto current main to absorb the issuer_kind="codex_backend" pinning from 8fa8aabb (#64844), so test_normalize_codex_response_salvage_is_xai_scoped passes again.

Added a config-to-wire regression test in test_run_agent_codex_responses.py that exercises the full path: agent.text_verbosity config -> chat_completion_helpers -> normalized Codex request payload. Covers both the injection case (GPT-5+ with "low") and the empty-default no-injection case.

@alt-glitch alt-glitch added comp/cli CLI entry point, hermes_cli/, setup wizard comp/gateway Gateway runner, session dispatch, delivery needs-decision Awaiting maintainer decision before any implementation and removed sweeper:risk-caching Sweeper risk: may break/degrade prompt caching or cache-key stability (invariant) labels Jul 16, 2026
@qxxaa
qxxaa force-pushed the feat/codex-text-verbosity-v3 branch from dc14a6c to 09a3aa1 Compare July 23, 2026 13:10
@qxxaa
qxxaa force-pushed the feat/codex-text-verbosity-v3 branch from 09a3aa1 to 3160fb9 Compare July 24, 2026 11:42
@qxxaa
qxxaa force-pushed the feat/codex-text-verbosity-v3 branch from 03d4bab to 36db2ed Compare July 29, 2026 11:24
@qxxaa
qxxaa force-pushed the feat/codex-text-verbosity-v3 branch 2 times, most recently from bb7d721 to a619783 Compare July 31, 2026 21:42
@alt-glitch alt-glitch added the sweeper:risk-message-delivery Sweeper risk: may drop, duplicate, misroute, or suppress messages label Jul 31, 2026
@qxxaa
qxxaa force-pushed the feat/codex-text-verbosity-v3 branch from 7715964 to c39a56d Compare August 4, 2026 07:42
@qxxaa
qxxaa force-pushed the feat/codex-text-verbosity-v3 branch from c39a56d to adf4023 Compare August 8, 2026 14:12
@qxxaa
qxxaa force-pushed the feat/codex-text-verbosity-v3 branch from adf4023 to 8c39198 Compare August 10, 2026 09:46
@alt-glitch alt-glitch removed the needs-decision Awaiting maintainer decision before any implementation label Aug 10, 2026
@qxxaa
qxxaa force-pushed the feat/codex-text-verbosity-v3 branch from 8c39198 to fdb7d56 Compare August 10, 2026 10:03
@alt-glitch alt-glitch added the needs-decision Awaiting maintainer decision before any implementation label Aug 10, 2026
@qxxaa
qxxaa force-pushed the feat/codex-text-verbosity-v3 branch from fdb7d56 to 9793011 Compare August 14, 2026 09:57
@alt-glitch

Copy link
Copy Markdown
Collaborator

This was generated by AI during triage.

Related: #20258, #29574, #63543, and #72638 are open implementations of #20203. #59844 has a concrete GPT-5+ guard and config-to-wire regression coverage; maintainer consolidation/selection is needed.

qxxaa added 3 commits August 14, 2026 17:17
…th control

Closes NousResearch#20203. Based on NousResearch#29574's init_agent() loading approach, with
added GPT-5+ model guard (vendor prefix handling) and safe dict merge
(preserves text.format from request_overrides).

Add agent.text_verbosity config key that injects text.verbosity into
OpenAI Responses API payloads for GPT-5+ models. Valid values: low,
medium, high, or empty string (default, no injection).

- Config loaded inside init_agent() from _agent_section
- Gateway hot-reload via cache-bust tuple
- GPT-5+ model guard with vendor prefix stripping
- Safe merge into existing text dict (preserves text.format)
- Preflight whitelist + pass-through in codex_responses_adapter
- 22 tests (19 transport + 3 preflight adapter)
… regression

Rebase onto current main absorbs the issuer_kind="codex_backend"
pinning in test_normalize_codex_response_salvage_is_xai_scoped
(8fa8aab, NousResearch#64844), fixing CI.

Add config-to-wire regression test per sweeper review: exercises
agent.text_verbosity -> chat_completion_helpers -> normalized Codex
request payload, covering both the injection and empty-default paths.

Addresses feedback from NousResearch#59844 (comment).
@qxxaa
qxxaa force-pushed the feat/codex-text-verbosity-v3 branch from 9793011 to 088c329 Compare August 14, 2026 17:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/config Config system, migrations, profiles comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint comp/cli CLI entry point, hermes_cli/, setup wizard comp/gateway Gateway runner, session dispatch, delivery needs-decision Awaiting maintainer decision before any implementation P3 Low — cosmetic, nice to have provider/openai OpenAI / Codex Responses API sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:risk-message-delivery Sweeper risk: may drop, duplicate, misroute, or suppress messages type/feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature]: Add configuration support for OpenAI Responses API text verbosity

3 participants