Skip to content

--show-config reports the wrong graph_name, and -g/--graph-name (or [agent] graph_name) is silently discarded, when the spec includes an inline :name #129

Description

@dkedar7

Summary

When the agent spec already carries an inline :name (e.g. app.py:prod), an explicit graph_name set via -g/--graph-name, [agent] graph_name, or DEEPAGENT_* is silently discarded at load time — the spec's inline name wins (correct, and documented: "overridden if spec includes :name"). But --show-config still prints the discarded value as the resolved graph_name, so the diagnostic reports a graph variable that is not the one that actually runs.

This is a --show-config advertised-vs-honored accuracy bug (same family as #108/#109/#112/#116/#128), plus a silent-flag-ignore footgun: -g looks like it took effect but didn't, and the one tool meant to reveal that (--show-config) confirms the wrong answer.

Environment

  • langstage-cli 0.6.30 (clean pip install langstage-cli from PyPI)
  • Python 3.11, Linux
  • langgraph / langstage-core as pulled by the install

Minimal repro

app.py (two graphs):

from langgraph.graph import StateGraph, START, END
from langgraph.graph.message import MessagesState
from langchain_core.messages import AIMessage

def _mk(label):
    def r(s): return {"messages": [AIMessage(content=f"[{label}]")]}
    g = StateGraph(MessagesState); g.add_node("r", r)
    g.add_edge(START, "r"); g.add_edge("r", END)
    return g.compile()

prod    = _mk("PROD")
staging = _mk("STAGING")
$ langstage-cli -a app.py:prod -g staging --show-config
  agent_spec       = app.py:prod                [override]   (env: LANGSTAGE_AGENT_SPEC ..., toml: agent.spec)
  graph_name       = staging                    [override]   (toml: agent.graph_name)

$ langstage-cli -a app.py:prod -g staging --no-interactive "hi"
[PROD]

Same thing with an env-provided spec + a project langstage.toml (a very realistic setup — spec pinned once in the environment, graph picked per-project):

# langstage.toml -> [agent]\ngraph_name = "staging"
$ LANGSTAGE_AGENT_SPEC=app.py:prod langstage-cli --show-config
  agent_spec       = app.py:prod                [env:LANGSTAGE_AGENT_SPEC]   ...
  graph_name       = staging                    [toml (langstage.toml)]     ...
$ LANGSTAGE_AGENT_SPEC=app.py:prod langstage-cli --no-interactive "hi"
[PROD]

Expected vs actual

Expected: --show-config reports the graph that will actually run. When the spec's inline :name supersedes graph_name, the diagnostic should show the effective name (prod) — ideally noting that the configured graph_name (staging) was overridden by the spec. Bonus: a one-line stderr notice when an explicit -g/graph_name is discarded because the spec pins a name, so the silent no-op is visible.

Actual: --show-config prints graph_name = staging while app.py:prod (graph PROD) runs. The explicit override is silently dropped and the diagnostic confirms the wrong value.

Root cause (pointer)

load_graph() already computes the effective name — when the spec contains :, rpartition(":") sets graph_name = tail and returns it as final_graph_name (cli.py ~L639-656, used at the run site ~L2541). --show-config renders the resolved config-level graph_name instead of this reconciled effective value, so the two disagree exactly when the spec has an inline :name and a separate graph_name is set.

Severity

Minor — no crash or data loss; requires the combination of an inline-:name spec and a separately-set graph_name. But it's a real footgun for the common "spec pinned in env, graph selected per-project/flag" pattern, and it undermines --show-config's purpose of telling the user what will actually run.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingroutineFiled by the daily power-user dogfooding routine

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions