A little suggestion: - set a `fallback_llm` e.g. ...
# proj-automation
c
A little suggestion: • set a
fallback_llm
e.g. “glm” profile on the pr-review automation running on open source repositories • we merged a tiny improvement in speed, to fall back to it without waiting retries • but it needs set in the automation. • (it’s an attribute on the LLM) (currently it fails everywhere because GPT-Sol is exhausted, for 4 days) I won’t be here today until late. Fwiw @quick-window-91705 @limited-student-10747 the agent is telling me we could just add it in the Plugin script, but I’m not so sure; it’s saved in automations.db and I’m not familiar enough with editing automations path and its safety in the 5 minutes I got 😅🙏 but I could look into it tomorrow or something
h
l
litellm supports this so I think it should be possible already.
🎉 1
@fresh-machine-37269 check OpenHands/OpenHands, can we set a fallback LM in language model profiles through the frontend? or backend only? or is this not supported yet.
👀 1
f
🤖 On it! View progress here: oss-agent-canvas.ngrok.dev/conversations/…
c
We have an implementation in the SDK.
It just needs configured with the automation.
f
✅ Done! Short answer: the fallback mechanism exists in the backend/SDK, but you can't set it via the frontend's LLM profile UI — and it isn't even persisted through the profile save path yet. Details from the repos: • Backend/SDK (supported):
openhands-sdk
has a
FallbackStrategy
class with a
fallback_llms
list (ordered profile names), and
LLM.fallback_strategy
field. It kicks in on transient errors (rate limit, timeout, 503, etc.) after retries, and falls back to those named profiles. See
openhands/sdk/llm/fallback_strategy.py
and the
39_llm_fallback.py
example. OpenRouter-style routing/`allow_fallbacks` metadata is also handled in the SDK. • Frontend (not supported): the Agent Canvas frontend (
src/components/features/settings/llm-profiles/
) has zero references to `fallback_strategy`/`fallback_llms`. The profile form only exposes
model
,
api_key
,
base_url
, auth type, subscription vendor, and provider connection — no fallback field. • The catch:
fallback_strategy
is marked
exclude=True
on the
LLM
model ("Excluded from serialization; must be reconfigured after load"). So even if you hand-crafted a profile JSON with a fallback,
save_profile
→
to_persisted()
drops it. It doesn't survive profile persistence at all. Net: today it's code-level only — you construct
FallbackStrategy(fallback_llms=[...])
on the
LLM
object in code (e.g. in an automation/plugin script, exactly the "attribute on the LLM" the thread mentioned), not via the profile editor. If you want it as a first-class profile field, it needs backend changes (remove the
exclude
, persist the field, expose it in the profile/settings schema) plus frontend work (a fallback picker in the profile form).
c
Hah, not "just" 😄
l
@fresh-machine-37269 We have a schema-based settings renderer in the frontend to prevent settings that exist from not being rendered in the frontend. Why does this not work for fallback_strategy?
👀 1
f
✅ Done! The schema renderer doesn't show it because of three separate things in the backend, not the frontend: 1.
exclude=True
on the field.
fallback_strategy
is declared with
exclude=True
("Excluded from serialization; must be reconfigured after load"). The schema exporter explicitly drops any excluded nested field —
if nested_field.exclude: continue
(
openhands/sdk/settings/model.py
, the LLM section loop). So the field never appears in the
/api/settings/agent-schema
payload the frontend renders from. 2. No settings metadata. The renderer only emits a field when it carries
SettingsFieldMetadata
(via
field_meta()
in
json_schema_extra
).
fallback_strategy
has none, so even without the
exclude
flag,
settings_metadata()
returns
None
→
continue
, and it's skipped. 3. It's a nested
FallbackStrategy
model with a list of profile names, not a scalar.
Even if (1) and (2) were fixed, the schema renderer's type inference would just treat it as an "object", and there's no built-in control for "pick an ordered list of other LLM profiles" — the
fallback_llms
list refers to profile-store names resolved at runtime, which is a relationship the generic schema form can't express today. And separately from rendering:
to_persisted()
uses
exclude
semantics, so the value is also dropped on save/load —
fallback_strategy
doesn't survive profile persistence regardless of the UI. So the schema renderer is working as designed — it's guarding against unannotated/unknown settings, not against a field the backend has deliberately excluded from both serialization and schema. To make it renderable you'd need to: remove
exclude=True
, add
field_meta(...)
metadata, teach the value-type inference / form to handle an ordered list of profile names, and persist the field through `to_persisted`/`from_persisted`.