本页目录
Subagents / 子 AgentNote 35

03 runtime context 传播

它是什么

它是什么

父 Agent 调用时传入的 runtime context 会自动传给同步 subagent。子 Agent 的工具可以通过 ToolRuntime[Context] 读取同一份 runtime.context。它解决的问题是:用户 ID、session ID、权限位这类运行时配置不需要塞进 prompt。

常用程度

高。只要是多用户、多租户、带权限的 Agent,runtime context 基本绕不开。

适合放 context:

  • user_id
  • tenant_id
  • session_id
  • 当前角色或权限位
  • 工具需要的连接信息引用

不适合放 context:

  • 子 Agent 需要长期记住的信息,这应该走 memory/store。
  • 需要被模型自然语言推理的大段业务资料,这通常放文件、skills 或工具结果。

传播链路

parent.invoke(..., context=UserContext(...))
-> 主 Agent runtime.context 可见
-> task 启动 subagent
-> subagent runtime.context 仍然是同一份结构
-> subagent 工具通过 ToolRuntime[UserContext] 读取

注意:context 不会自动变成 prompt 文本。只有工具读取并返回,模型才会看到它。

最小代码

文件:deepagent_src/subagents_teach/03_context_propagation.py

@dataclass
class UserContext:
    user_id: str
    session_id: str


@tool
def read_context_marker(runtime: ToolRuntime[UserContext]) -> str:
    return f"{runtime.context.user_id}@{runtime.context.session_id}"

运行

uv run python deepagent_src/subagents_teach/03_context_propagation.py

预期输出末尾:

subagent context propagation real agent ok

验证方式

脚本真实调用主 Agent 并传入 UserContext(user_id="user-123", session_id="session-abc"),断言 subagent 的 task 结果能读到 user-123@session-abc

这证明用户和会话信息没有塞进用户消息,也能被子 Agent 工具读到。

常见误区

context 传播不等于把这些值展示给模型。只有工具或 middleware 主动读取并输出时,模型才会看到相关内容。

如果不同 subagent 需要不同配置,别建一堆全局变量。用字段区分,例如 researcher_max_depthfact_checker_strict_mode,或者用扁平 namespaced key。

相关资源

  • 查看示例代码:deepagent_src/subagents_teach/03_context_propagation.py
    from __future__ import annotations
    
    from dataclasses import dataclass
    
    from deepagents import create_deep_agent
    from langchain.tools import ToolRuntime, tool
    
    from _model import get_real_model
    from deepagent_src.agent_output import invoke_and_pretty_print
    
    
    @dataclass
    class UserContext:
        user_id: str
        session_id: str
    
    
    @tool
    def read_context_marker(runtime: ToolRuntime[UserContext]) -> str:
        """Return the runtime context marker visible inside a subagent."""
        return f"{runtime.context.user_id}@{runtime.context.session_id}"
    
    
    context_subagent = {
        "name": "context-reader",
        "description": "Use this subagent to read runtime context through a tool.",
        "system_prompt": (
            "You are the context-reader subagent. Always call read_context_marker "
            "and return only the tool result."
        ),
        "tools": [read_context_marker],
    }
    
    
    def main() -> None:
        agent = create_deep_agent(
            model=get_real_model(),
            system_prompt=(
                "You are a coordinator. Delegate context checks to context-reader."
            ),
            subagents=[context_subagent],
            context_schema=UserContext,
        )
        result = invoke_and_pretty_print(
            agent,
            {
                "messages": [
                    {
                        "role": "user",
                        "content": "请委派 context-reader subagent 读取 runtime context。",
                    }
                ]
            },
            context=UserContext(user_id="user-123", session_id="session-abc"),
        )
    
        task_outputs = [
            getattr(message, "content", "")
            for message in result["messages"]
            if getattr(message, "name", "") == "task"
        ]
    
        assert any("user-123@session-abc" in output for output in task_outputs)
        print("subagent context propagation real agent ok")
    
    
    if __name__ == "__main__":
        main()