Skip to content

Apply managed http_headers to Codex's provider block - #773

Merged
tt-le merged 5 commits into
mainfrom
tien/codex-managed-http-headers
Sep 21, 2026
Merged

tt-le merged 5 commits into
mainfrom
tien/codex-managed-http-headers

Conversation

@tt-le

@tt-le tt-le commented Sep 21, 2026

Copy link
Copy Markdown
Collaborator

What

Wire the managed coding-agent config's http_headers into Codex. Independent of the Claude PR (#772) — both target main.

  • managed_resolve.managed_state_overrides emits {tool}_http_headers.
  • codex.write_tool_config reads codex_http_headers; _provider_block merges the admin headers into the Databricks provider's [http_headers] table (current per-profile layout and legacy < 0.134.0 layout).

Behavior

  • Admin wins on a case-insensitive name collision — a managed header replaces ucode's own header (including routing headers), never emitting two spellings of one HTTP header.
  • Clean removal, no state — ug is the sole author of the provider http_headers table, so it's pruned wholesale before each merge and rewritten from render_overlay. This drops routing headers that no longer apply and any admin header removed from managed config; deep_merge alone cannot delete keys.

Tests

  • render_overlay: admin header added; admin overrides ucode's routing header case-insensitively with no duplicate spelling.
  • write_tool_config end-to-end: admin header written to config.toml; dropped after removal while User-Agent is kept.
  • Wire-level (tests/test_e2e_user_agent.py): the capture-server harness launches the real Codex binary and asserts an admin header arrives on the inference request.

Note on overlap with #772

This PR shares the small managed_resolve plumbing (the {tool}_http_headers emit) and the _header test helper with #772. They're identical in both; whichever merges second resolves a trivial overlap. Neither depends on the other.

This pull request and its description were written by Isaac.

@tt-le tt-le added the ug0.2-launch-blocker Launch Blocker for UG 0.2 label Sep 21, 2026
Wire the managed coding-agent config's `http_headers` into Codex, independent of
the Claude change: `managed_state_overrides` emits `{tool}_http_headers`, and
`_provider_block` merges them into the Databricks provider's `[http_headers]`
table (current and legacy layouts).

Admin headers win on a case-insensitive name collision, replacing ucode's own
header (including routing headers) rather than emitting two spellings of one HTTP
header. ug is the sole author of that table, so it is pruned wholesale before
each merge and rewritten from render_overlay — dropping routing headers that no
longer apply and any admin header removed from managed config, with no ug state.

Adds a wire-level check to tests/test_e2e_user_agent.py that launches the real
Codex binary and asserts an admin header arrives on the inference request.

Note: shares the small managed_resolve plumbing and the `_header` test helper
with the Claude PR (#772); whichever merges second
resolves a trivial overlap.

Co-authored-by: Isaac <no-reply@databricks.com>
@tt-le
tt-le force-pushed the tien/codex-managed-http-headers branch from f96fa67 to ab2be5f Compare September 21, 2026 16:25
@tt-le
tt-le changed the base branch from tien/claude-managed-http-headers to main September 21, 2026 16:25
Comment thread src/ucode/managed_resolve.py Outdated
tt-le and others added 2 commits September 21, 2026 17:12
Removes the duplicate `if tool in ("claude", "codex")` in managed_state_overrides
by grouping the http_headers override with static_models. No behavior change; the
override is still emitted only for the agents whose writers consume it.

Co-authored-by: Isaac <no-reply@databricks.com>
Emit `{tool}_http_headers` for any tool rather than only claude/codex. Only those
writers consume it today, so the override is inert for other agents, and dropping
the gate keeps the resolver simple.

Co-authored-by: Isaac <no-reply@databricks.com>
tt-le and others added 2 commits September 21, 2026 18:32
The smart-routing launch path rebuilds the provider overlay and passes it to the
Codex app-server as `-c model_providers.Databricks=...` overrides, which replace
the whole provider block (including its http_headers table). That overlay omitted
the admin headers, so they were written to config.toml but stripped from the
launched inference calls whenever smart routing was active.

Thread `codex_http_headers` into the launch overlay in launch_codex, and add a
regression test asserting the admin header appears in the app-server config args.

Co-authored-by: Isaac <no-reply@databricks.com>
@tt-le
tt-le added this pull request to stack #776 September 21, 2026 19:08
@tt-le
tt-le merged commit 08bd622 into main Sep 21, 2026
62 of 81 checks passed
@tt-le
tt-le deleted the tien/codex-managed-http-headers branch September 21, 2026 20:29
tt-le added a commit that referenced this pull request Sep 21, 2026
#775)

## What

**Stacked on #773.** Adds an integration test proving the managed
`http_headers` feature reaches Codex's OS-managed config end to end
through the real `ug` CLI.

- `test_managed_fixture_codex_http_headers_in_managed_file` (in
`test_ug_configure_managed_mcp.py`): injects an admin `http_headers` map
via the `managed_fixture` stub, runs the **interactive** `ug configure
codex` (`ConfigureTerminal`), and asserts
`/etc/codex/managed_config.toml` contains
`[model_providers.Databricks.http_headers]` with `x-databricks-workspace
= "eng-ml-inference"`.
- Extends `build_codex_agent_config` with an optional `http_headers`
arg.
- Updates the coverage matrices in `tests/README.md` and
`tests/integration/README.md`.

## Why interactive

The OS-managed file `/etc/codex/managed_config.toml` is only written
when `managed_writes_allowed()` (i.e. `sys.stdin.isatty()`) — so this
uses the PTY `ConfigureTerminal` flow, mirroring the existing
`test_managed_fixture_codex_mcp_written_to_managed_file`. (The
per-profile `~/.codex/ucode.config.toml` is written non-interactively,
but the OS-managed file is the high-precedence one worth asserting.)

## Verification

Structural checks pass locally (`ruff check`/`format`,
`test_integration_contract.py` 5 passed, `run_integration.py --help`).
The live run needs `UCODE_TEST_WORKSPACE` + `DATABRICKS_BEARER` + an
interactive PTY + Codex ≥ 0.145.0, so it runs in the integration CI job,
not locally.

This pull request and its description were written by Isaac.

Co-authored-by: Isaac <no-reply@databricks.com>
tt-le added a commit that referenced this pull request Sep 22, 2026
## What

Admin-supplied `http_headers` in the managed coding-agent config were
parsed and publishable but never reached any agent. Wire them into
**Claude Code**. Independent of the Codex PR (#773) — both target
`main`.

- `managed_resolve.managed_state_overrides` emits `{tool}_http_headers`.
- `claude.render_overlay` merges the admin headers into
`ANTHROPIC_CUSTOM_HEADERS`.

## Behavior

- **Admin wins on a case-insensitive name collision** — replaces ucode's
own line in place, appends new ones.
- **Clean removal, no ug state** — the ucode-owned set of header names
is derived from the files themselves: ucode owns `ucode-settings.json`
wholesale (every header there is ucode's, so a dropped managed header
can't linger), and for the OS-managed file only the names ucode last
wrote (`last_applied_by_ug`) are treated as ucode's, leaving IT-authored
headers untouched. (An earlier revision tracked names in ug state; that
isn't preserved across runs, so a removed header lingered — fixed here.)

## Tests

- `render_overlay` / `_merge_anthropic_custom_headers`: add, in-place
override, removal, IT-header preservation.
- `write_tool_config`: admin header written; dropped after removal on
the ucode file; IT header preserved on the managed file via
`last_applied_by_ug`.
- `managed_resolve`: `http_headers` → `{tool}_http_headers` override.
- Wire-level (`tests/test_e2e_user_agent.py`): the capture-server
harness launches the real Claude binary and asserts an admin header
arrives on the inference request.

## Note on overlap with #773

Shares the small `managed_resolve` plumbing and the `_header` test
helper with #773; identical in both, trivial overlap on whichever merges
second. Neither depends on the other.

This pull request and its description were written by Isaac.

---------

Co-authored-by: Isaac <no-reply@databricks.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ug0.2-launch-blocker Launch Blocker for UG 0.2

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants