mirror of
https://github.com/bytedance/deer-flow.git
synced 2026-05-22 16:06:50 +00:00
fix(agents): propagate agent_name into ToolRuntime.context for setup_agent (#2679)
* fix(agents): propagate agent_name into ToolRuntime.context for setup_agent (#2677) When creating a custom agent via the web UI, SOUL.md was always written to the global base_dir/SOUL.md instead of agents/<name>/SOUL.md. Root cause: the bootstrap flow sends agent_name via body.context, but two layers were broken: 1. services.py only forwarded body.context keys into config["configurable"]; config["context"] was never populated. 2. worker.py constructed the parent Runtime with a hard-coded {thread_id, run_id} context, ignoring config["context"] entirely. After the langgraph >= 1.1.9 bump (#98a5b34f), ToolRuntime.context no longer falls back to configurable, so setup_agent's runtime.context.get("agent_name") returned None and the tool's silent agent_name=None -> base_dir fallback kicked in, overwriting the global SOUL.md. Fix: - services.py: extract merge_run_context_overrides() and write the whitelisted context keys into both configurable (legacy readers) and context (langgraph 1.1+ ToolRuntime consumers). - worker.py: extract _build_runtime_context() and merge config["context"] into the Runtime's context (without letting callers override thread_id/run_id). The base_dir fallback in setup_agent_tool.py is left in place because the IM /bootstrap channel command depends on it. That code path can be tightened in a follow-up. Adds regression tests covering both helpers. * Apply suggestions from code review Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --------- Co-authored-by: Willem Jiang <willem.jiang@gmail.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -256,6 +256,37 @@ def test_context_merges_into_configurable():
|
||||
assert "thread_id" not in {k for k in context if k in _CONTEXT_CONFIGURABLE_KEYS}
|
||||
|
||||
|
||||
def test_merge_run_context_overrides_propagates_to_runtime_context():
|
||||
"""Regression for issue #2677: ``agent_name`` (and other whitelisted keys) from
|
||||
``body.context`` must be propagated into BOTH ``config['configurable']`` and
|
||||
``config['context']``. Previously only ``configurable`` was populated, so after
|
||||
the LangGraph 1.1.x upgrade removed the fallback from ``configurable``, the
|
||||
``setup_agent`` tool read ``runtime.context`` with ``agent_name=None`` and
|
||||
silently wrote SOUL.md to the global base_dir.
|
||||
"""
|
||||
from app.gateway.services import build_run_config, merge_run_context_overrides
|
||||
|
||||
config = build_run_config("thread-1", None, None)
|
||||
merge_run_context_overrides(config, {"agent_name": "my-agent", "is_bootstrap": True, "thread_id": "ignored"})
|
||||
|
||||
assert config["configurable"]["agent_name"] == "my-agent"
|
||||
assert config["configurable"]["is_bootstrap"] is True
|
||||
assert config["context"]["agent_name"] == "my-agent"
|
||||
assert config["context"]["is_bootstrap"] is True
|
||||
# Non-whitelisted keys are not forwarded.
|
||||
assert "thread_id" not in config["context"]
|
||||
|
||||
|
||||
def test_merge_run_context_overrides_noop_for_empty_context():
|
||||
from app.gateway.services import build_run_config, merge_run_context_overrides
|
||||
|
||||
config = build_run_config("thread-1", None, None)
|
||||
before = {k: dict(v) if isinstance(v, dict) else v for k, v in config.items()}
|
||||
merge_run_context_overrides(config, None)
|
||||
merge_run_context_overrides(config, {})
|
||||
assert config == before
|
||||
|
||||
|
||||
def test_context_does_not_override_existing_configurable():
|
||||
"""Values already in config.configurable must NOT be overridden by context."""
|
||||
from app.gateway.services import build_run_config
|
||||
|
||||
Reference in New Issue
Block a user