Skip to content

fix(footer): show runtime provider, not configured primary, in OpenClaw footer - #67968

Open
madaxia wants to merge 1 commit into
NousResearch:mainfrom
madaxia:feat/footer-provider-fix
Open

madaxia wants to merge 1 commit into
NousResearch:mainfrom
madaxia:feat/footer-provider-fix

Conversation

@madaxia

@madaxia madaxia commented Jul 20, 2026

Copy link
Copy Markdown

Problem

The footer displayed model.provider from config instead of the provider that actually answered the turn. After a fallback switch this was wrong — e.g. showing Provider: kimi while the agent ran volces-agent.

Root cause

agent/turn_finalizer.py invoked the transform_llm_output hook without passing provider, so the runtime-footer plugin fell back to config.model.provider. gateway/run.py likewise did not propagate the runtime provider into the agent_result dicts consumed by the built-in footer path.

Changes (scoped to provider propagation only)

Per triage feedback, this PR is now scoped strictly to the provider-propagation bug. The broader OpenClaw footer formatting / field-behavior work stays in #66372.

  • agent/turn_finalizer.py — pass provider=getattr(agent, "provider", None) and the agent id into the transform_llm_output hook call. (root fix)
  • gateway/run.py — include "provider": getattr(_agent, "provider", None) in both agent_result dicts; pass provider to build_footer_line.
  • gateway/runtime_footer.py — add a provider param to format_runtime_footer and build_footer_line; falls back to config.model.provider only when the runtime value is missing (legacy call sites stay populated).
  • tests/gateway/test_runtime_footer.py — +4 cases: runtime provider wins over config, config fallback, omitted-when-both-missing.

Verification

  • venv/bin/python -m pytest tests/gateway/test_runtime_footer.py -q29 passed
  • End-to-end: with provider="volces-agent" propagated, the footer now shows volces-agent instead of kimi (the configured primary).

Relationship to #66372 / #62277

This PR is now orthogonal to both: it only fixes the provider-display root cause (the transform_llm_output hook not receiving the runtime provider). OpenClaw footer formatting and field-behavior enhancements remain in #66372. #62277 (CLI status-bar provider display) is a separate surface.

@alt-glitch alt-glitch added type/bug Something isn't working comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint comp/gateway Gateway runner, session dispatch, delivery P3 Low — cosmetic, nice to have needs-decision Awaiting maintainer decision before any implementation sweeper:risk-message-delivery Sweeper risk: may drop, duplicate, misroute, or suppress messages labels Jul 20, 2026
@alt-glitch

Copy link
Copy Markdown

This was generated by AI during triage.

Related to #66372 and #62277. Runtime-provider propagation fixes a distinct fallback-display bug, while this branch also adds broader OpenClaw footer formatting and field behavior; please choose or split the overlapping footer work.

…mary

The footer displayed model.provider from config instead of the provider
that actually answered the turn. After a fallback switch this was wrong
— e.g. showing 'Provider: kimi' while the agent ran 'volces-agent'.

Root cause: agent/turn_finalizer.py invoked the transform_llm_output hook
without passing provider, so the runtime-footer plugin fell back to
config's model.provider. gateway/run.py likewise didn't propagate the
runtime provider into the agent_result dicts consumed by the built-in
footer path.

Changes (scoped to the provider-propagation bug only — OpenClaw footer
formatting/field work stays in NousResearch#66372):
- agent/turn_finalizer.py: pass provider + agent id into the
  transform_llm_output hook call.
- gateway/run.py: include 'provider' in both agent_result dicts and pass
  it to build_footer_line.
- gateway/runtime_footer.py: add a provider param to format_runtime_footer
  and build_footer_line; falls back to config.model.provider only when the
  runtime value is missing (legacy call sites stay populated).
- tests/gateway/test_runtime_footer.py: +4 cases — runtime provider wins
  over config, config fallback, omitted-when-both-missing.

29 passed.
@madaxia
madaxia force-pushed the feat/footer-provider-fix branch from bf83ed9 to b31091a Compare July 20, 2026 12:08
@madaxia

madaxia commented Jul 20, 2026

Copy link
Copy Markdown
Author

Thanks for the triage. Good call on the scope — I've narrowed this PR to only the runtime-provider propagation fix (the distinct fallback-display bug), and dropped the broader OpenClaw footer formatting / field-behavior changes so they stay in #66372.

What remains in this PR (b31091a, +93/-0):

  • agent/turn_finalizer.py: pass provider (+ agent id) into the transform_llm_output hook — the root cause; the runtime-footer plugin was falling back to config.model.provider because the hook never received the runtime value.
  • gateway/run.py: propagate provider into both agent_result dicts and pass it to build_footer_line.
  • gateway/runtime_footer.py: add a provider param (with config.model.provider fallback for legacy call sites) — no style/duration/field-alias changes.
  • tests/gateway/test_runtime_footer.py: +4 cases (runtime-wins-over-config, config fallback, omitted-when-both-missing).

What moved out (openclaw style, duration, ctx/cwd_label aliases, labelled Agent: | Model: | Provider: rendering) stays in #66372, which is the OpenClaw-footer PR.

This PR is now orthogonal to both #66372 and #62277. venv/bin/python -m pytest tests/gateway/test_runtime_footer.py -q → 29 passed.

@teknium1 teknium1 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for splitting the provider-propagation work out of the broader footer changes. The core premise is real: fallback activation updates agent.provider in agent/chat_completion_helpers.py:1877-1879, while current main drops that value before the footer at gateway/run.py:23175, gateway/run.py:23302, and gateway/run.py:14710-14717.

Problems

  • provider is newly accepted as a footer field, but website/docs/user-guide/configuration.md:1658-1665 still documents only model, context_pct, and cwd.
  • The added tests call build_footer_line() directly. They do not cover either changed result-dict path or the final gateway call site that propagates the value.
  • agent/turn_finalizer.py also adds an undocumented agent argument to the public transform_llm_output hook. The documented callback contract at website/docs/user-guide/features/hooks.md:1257-1275 does not include it, and it is outside the stated provider-only scope.

Suggested changes

  • Document the new field and add a gateway-level fallback regression test.
  • Remove the agent hook kwarg unless its contract is documented and independently covered.

Automated hermes-sweeper review.

Comment thread agent/turn_finalizer.py
model=agent.model,
platform=getattr(agent, "platform", None) or "",
provider=getattr(agent, "provider", None),
agent=getattr(agent, "agent_id", None) or getattr(agent, "id", None),

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

transform_llm_output is a public plugin hook, but its documented callback contract currently has no agent kwarg (website/docs/user-guide/features/hooks.md:1257-1275). Please remove this scope expansion or document and test the new hook payload separately.

Comment thread gateway/runtime_footer.py
m = _model_short(model)
if m:
parts.append(m)
elif field == "provider":

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please update the runtime-footer configuration reference: it currently declares only model, context_pct, and cwd as supported fields (website/docs/user-guide/configuration.md:1658-1665).

@teknium1 teknium1 added sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform labels Jul 30, 2026
@jimmywu0816

Copy link
Copy Markdown

Independent provider-only implementation and verification

I reproduced and implemented the provider-propagation slice independently against the current upstream main (as of today).

Current main still drops the live runtime provider before the built-in footer render path: agent.provider is updated on fallback activation, but agent_result only carried model/tokens, so a footer configured with the provider never renders it. The minimal, byte-stable change is:

  • gateway/runtime_footer.py — add an opt-in provider field (legacy default fields model, context_pct, cwd untouched; field skipped when the runtime value is missing).
  • gateway/run.py — capture provider from the same live agent instance as model on both result paths and pass it to build_footer_line().
  • tests/gateway/test_runtime_footer.py — field order, missing-provider omission, and the public build_footer_line() path.
  • English + Simplified Chinese configuration docs — document the new field.

Validation on current upstream main + this minimal patch:

uv run --extra dev pytest -q tests/gateway/test_runtime_footer.py
40 passed in 2.02s
git diff --check
clean

Real-world Telegram output with the field enabled (default profile, fallback chain active in the second example):

default · deepseek · deepseek-v4-flash · 12%
default · openrouter · gpt-5.6-luna · 29%

This is intentionally narrower than the token/cost/quota expansion in #35427 / #18188. Since this PR already targets the same runtime-provider propagation problem (including the agent_result provider propagation), I did not open a duplicate PR — please consider folding the minimal documentation and field-order coverage into this branch or the canonical footer-expansion work.

@alt-glitch alt-glitch removed needs-decision Awaiting maintainer decision before any implementation sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform labels Aug 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint comp/gateway Gateway runner, session dispatch, delivery P3 Low — cosmetic, nice to have sweeper:risk-message-delivery Sweeper risk: may drop, duplicate, misroute, or suppress messages type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants