Skip to content

Fix-with-agent misdiagnoses a backend/infra run failure as a graph bug, destroys a correct workflow, then dead-loops #5191

Description

@graycyrus

Summary

When a workflow run fails for a backend/infra reason (not a wiring problem), the "Fix with agent" repair turn (mode=Repair) treats it as a graph-wiring bug: it restructures a correct graph into a broken one, produces inconsistent intermediate graphs that the author-gate correctly rejects, and then dead-loops on repeated edit_workflow failures and gives up with no proposal.

Problem

Observed run (live)

A file-attachment workflow was built correctly as a 6-node native chain:

trigger -> research(agent) -> build_html(code_executor) -> upload_file(oh:storage_upload_file) -> get_link(oh:storage_get_link) -> send(GMAIL_SEND_EMAIL)

The run reached upload_file and failed with a pure backend error (unrelated to the graph):

tool_call `oh:storage_upload_file` failed: File upload failed: Backend returned 500 Internal Server Error
for POST_MULTIPART .../agent-integrations/file-storage/files: The specified bucket does not exist

(steps: research success, build_html success, upload_file error.)

What "Fix with agent" did

mode=Repair then:

  1. Tore out the upload_file and get_link nodes, collapsing the correct 6-node chain back to a broken 4-node shape (trigger -> research -> build_html -> send).
  2. Left send.attachment bound to =nodes.get_link.item.json.url while get_link no longer existed, so the author-gate correctly rejected the dangling reference:
    required-arg resolvability check: arg resolved null in sandbox - rejecting node=send field=attachment expression==nodes.get_link.item.json.url
    
  3. Looped on edit_workflow (4x Error), hit the middleware halt (repeated tool failure - halting run ... tool=edit_workflow step=8), and ended trail_off=true has_proposal=false - i.e. it gave up with no fix.

Root cause

The repair turn does not distinguish a backend/infra failure ("the specified bucket does not exist", a 500 from the file-storage service) from a graph-wiring failure (a null-resolved binding, a wrong slug). A backend 500 means "the graph is fine, the environment is broken" - the correct repair is to surface that and NOT touch the graph. Instead the agent assumes the wiring is wrong, restructures a correct graph, and destroys it.

Impact

  • A correct, working workflow is degraded into a broken one by the repair flow whenever the backend has a transient/infra failure.
  • The repair then dead-loops and delivers no proposal, so the user is left worse off than before clicking "Fix with agent".
  • The graph the repair produced (4 nodes, no upload/link) cannot ever attach a file even after the backend recovers.

Steps to reproduce

  1. Build a workflow whose run fails for a backend reason (e.g. oh:storage_upload_file when the file-storage bucket is misconfigured - see #5174).
  2. Run it; it fails at the upload step with the backend 500.
  3. Click "Fix with agent".
  4. Observe: it restructures the (correct) graph, the gate rejects inconsistent intermediates, edit_workflow loops, and the turn ends with no proposal (trail_off).

Environment: desktop dev build, current file-attachment branch (#5148). The gate carve-out and native-tool handling in #5148 are working correctly here - the initial build was correct and the run failed loudly at the right node; this issue is strictly about the repair turn's misdiagnosis.

Solution (suspected)

The repair flow needs to classify the run's failure before acting:

  • A tool_call failure whose error is a provider/backend transport error (5xx, "bucket does not exist", connection/timeouts) is not a graph bug. Surface it to the user as a backend/infra failure and do not restructure the graph. (The core already classifies budget-exhausted errors as kind="budget" and skips them - a similar kind="backend"/"infra" classification for run failures could gate the repair.)
  • Only a genuine wiring/validation failure (null-resolved required arg, unreal slug, dangling reference) should trigger a graph edit.
  • Independently, the repair should not collapse a correct native file chain back to an in-agent shape - but the primary fix is the diagnosis gate above.

Acceptance criteria

  • No graph destruction on backend failure - a run that fails with a backend/infra error (e.g. storage 500) does not cause "Fix with agent" to restructure or degrade a correct graph.
  • Actionable message - the repair surfaces the backend failure ("the file-storage backend returned an error; your workflow is fine") instead of silently mangling the graph.
  • No dead-loop - the repair turn either proposes a real fix or clearly explains the backend failure; it does not exhaust edit_workflow retries and trail_off with no proposal.
  • Regression coverage - a test that a backend-class run error does not trigger a graph edit.

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    Status
    Todo

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions