LangChain 工具访问——InjectedState、InjectedStore 与 ToolRuntime
前面我们学习了如何使用 @tool 定义工具,以及如何将工具注册到 Agent 中。
普通工具主要通过函数参数接收模型提供的数据。例如,查询天气工具需要模型传入城市名称。
但在实际开发中,工具往往还需要访问一些不能由模型直接提供的信息:
- 当前对话的消息历史。
- 用户在对话中已经确认的设置。
- 登录用户的身份信息。
- 跨会话保存的学习进度和个人偏好。
- 当前工具调用的 ID 和执行配置。
LangChain 提供运行时依赖注入机制,让工具可以访问这些信息,而不需要把所有内部数据暴露给语言模型。
早期教程常使用 InjectedState 和 InjectedStore。在 LangChain 1.x 中,官方更推荐使用 ToolRuntime 统一访问运行时信息。
本章节将介绍三种机制及其关系,并通过完整的 Agent 示例说明如何正确使用。
一、State、Context 与 Store 的区别
在编写工具之前,需要先理解 Agent 运行时的三种数据。
| 数据类型 | 主要作用 | 典型用途 |
|---|---|---|
State |
管理会话中的可变状态 | 对话历史、当前任务进度、临时选择 |
Context |
传递本次调用的运行上下文 | 用户 ID、请求来源、租户信息 |
Store |
在不同会话或调用之间共享数据 | 用户偏好、学习进度、长期记忆 |
可以通过下面的示意图理解:
用户发起请求
|
v
LangChain Agent
|
+-- State
| 当前消息、任务状态
|
+-- Context
| 用户身份、请求配置
|
+-- Store
用户偏好、学习记录
|
v
ToolRuntime
|
v
Python 工具函数
其中,State、Context 和 Store 的生命周期不同。
State:默认用于当前 Agent 执行过程。如果配置了 Checkpointer,可以按会话线程保存,并在之后的调用中恢复。
Context:通常由应用程序在调用 Agent 时传入,提供本次运行需要的上下文信息。
Store:可以保存跨会话的数据。实际能保存多久,取决于 Store 的具体实现。
二、ToolRuntime——官方推荐的工具运行时接口
LangChain 1.x 推荐通过 ToolRuntime 访问工具执行上下文。
只需要在工具函数中添加:
runtime: ToolRuntime
Agent 执行工具时,LangChain 会自动注入运行时对象。
不需要添加 Annotated,也不需要让模型传入这个参数。
ToolRuntime 常用属性
| 属性 | 说明 |
|---|---|
runtime.state |
当前 Agent 状态 |
runtime.context |
本次运行的上下文 |
runtime.store |
共享的数据存储对象 |
runtime.tool_call_id |
当前工具调用 ID |
runtime.config |
RunnableConfig 运行配置 |
runtime.stream_writer |
用于发送自定义流式更新 |
实例:读取当前 Agent 消息数量
实例
@tool
def conversation_stats(
runtime: ToolRuntime
) -> str:
"""统计当前 Agent 的消息数量。"""
messages = runtime.state.get(
"messages", []
)
human_count = sum(
message.type == "human"
for message in messages
)
ai_count = sum(
message.type == "ai"
for message in messages
)
tool_count = sum(
message.type == "tool"
for message in messages
)
return (
f"当前共 {len(messages)} 条消息;"
f"用户消息 {human_count} 条;"
f"AI 消息 {ai_count} 条;"
f"工具结果 {tool_count} 条"
)
在这个工具中,runtime.state 提供当前 Agent 的状态,其中通常包含 messages。
需要注意,runtime 不会出现在提供给模型的工具参数列表中。
模型只需要知道工具可以执行对话统计,不需要了解 Agent 内部如何保存消息。
在 Agent 中调用
实例
from langchain.agents import create_agent
from langchain.chat_models import init_chat_model
load_dotenv()
model = init_chat_model(
"deepseek:deepseek-flash"
)
agent = create_agent(
model=model,
tools=[conversation_stats],
system_prompt=(
"你是一名对话统计助手。"
"用户要求统计消息数量时,"
"使用 conversation_stats 工具。"
)
)
result = agent.invoke({
"messages": [
{
"role": "user",
"content": "请统计当前会话的消息数量。"
}
]
})
print(result["messages"][-1].content)
如果模型调用了 conversation_stats,工具就可以访问执行时的消息状态,并返回统计结果。
实际消息数量取决于工具被执行时 Agent 已经产生了多少条消息,因此不能假设总数始终固定。
注意:不能简单地直接执行:
# 不适合作为运行时注入的测试方式
conversation_stats.invoke({})
因为普通的工具调用没有自动提供完整的 Agent 运行时上下文。
如果需要测试这种工具,应通过 create_agent() 或正确配置的 LangGraph ToolNode 执行。
三、InjectedState——旧式状态注入方式
InjectedState 用于标记需要从 Agent 状态中自动注入的参数。
它仍可用于支持这种注入机制的 LangGraph ToolNode,但在新的 LangChain 教程中,推荐优先使用 ToolRuntime。
InjectedState 的基本语法
from typing import Annotated from langgraph.prebuilt import InjectedState state: Annotated[dict, InjectedState()]
当工具通过支持状态注入的执行节点运行时,LangGraph 会从当前图状态中取得相应数据。
实例:读取完整 State
实例
from langchain.tools import tool
from langgraph.prebuilt import InjectedState
@tool
def get_message_count(
state: Annotated[
dict[str, Any],
InjectedState()
]
) -> str:
"""读取当前对话消息数量。"""
messages = state.get(
"messages", []
)
return (
f"当前共有 {len(messages)} 条消息"
)
这里的 state 不是由模型填写的普通工具参数。
执行框架会在工具真正运行前,将当前 State 注入对应参数。
只注入某个 State 字段
InjectedState 也支持只读取状态中的一个字段。
例如:
InjectedState("messages")
表示只注入 messages 字段。
实例
from langchain.tools import tool
from langgraph.prebuilt import InjectedState
@tool
def count_messages(
messages: Annotated[
list,
InjectedState("messages")
]
) -> str:
"""统计当前对话消息数量。"""
return f"共 {len(messages)} 条消息"
相比注入整个 State,这种方式只读取工具需要的字段。
但在新项目中,通常可以直接使用:
runtime.state["messages"]
避免使用多个不同的注入参数。
四、读取 State 不等于修改 State
原文中的 remember_preference() 只是读取状态并返回文字,并没有真正把用户偏好保存到 Agent 状态中。
如果希望工具修改状态,LangChain 官方推荐返回 Command。
Command 可以声明需要写入哪些状态字段,并将工具调用结果关联回消息历史。
实例:保存当前会话的偏好
实例
from langchain.messages import ToolMessage
from langchain.tools import tool, ToolRuntime
from langgraph.types import Command
# 自定义 Agent 状态
class CustomState(AgentState):
theme: str
@tool
def set_theme(
theme: str,
runtime: ToolRuntime
) -> Command:
"""保存当前会话的界面主题。"""
return Command(
update={
"theme": theme,
"messages": [
ToolMessage(
content=f"主题已设置为:{theme}",
tool_call_id=runtime.tool_call_id
)
]
}
)
@tool
def get_theme(
runtime: ToolRuntime
) -> str:
"""查询当前会话的主题设置。"""
return runtime.state.get(
"theme", "未设置"
)
这里定义了一个额外状态字段:
theme: str
当 set_theme 返回 Command 时,可以通过 update 更新该字段。
其中的 ToolMessage 必须与当前工具调用 ID 对应。
如果只有读取操作,就不需要返回 Command。
创建支持自定义 State 的 Agent
agent = create_agent(
model=model,
tools=[set_theme, get_theme],
state_schema=CustomState,
system_prompt="你是一名用户设置助手。"
)
这样就可以让 Agent 管理自定义会话字段。
注意:State 是工作流状态,不建议直接修改 runtime.state 内部字典并假设修改一定会持久化。应通过受支持的状态更新方式提交变化。
如果多个工具可能同时更新相同字段,还需要考虑并行写入冲突及 reducer 的配置。
五、Checkpointer——让 State 跨调用保存
State 不是只能存在于单次 invoke() 调用中。
LangGraph 提供 Checkpointer,用于保存会话状态。
例如,同一用户连续发送多个问题时,可以通过相同的 thread_id 恢复此前的消息和状态。
实例:保存对话历史
实例
from langchain.agents import create_agent
from langchain.chat_models import init_chat_model
model = init_chat_model(
"deepseek:deepseek-flash"
)
agent = create_agent(
model=model,
tools=[],
checkpointer=InMemorySaver()
)
# 同一段会话使用相同 thread_id
config = {
"configurable": {
"thread_id": "demo_session_001"
}
}
# 第一轮
agent.invoke(
{
"messages": [
{
"role": "user",
"content": "我正在学习 Python。"
}
]
},
config=config
)
# 第二轮
result = agent.invoke(
{
"messages": [
{
"role": "user",
"content": "我刚才说在学习什么?"
}
]
},
config=config
)
print(result["messages"][-1].content)
这里使用 InMemorySaver 保存会话检查点。
两次调用使用相同的 thread_id,因此第二次调用可以访问此前保存的会话历史。
但 InMemorySaver 只将数据保存在当前 Python 进程的内存中。
当程序退出或重启后,这些记录通常会丢失。
如果需要持久保存,可以使用数据库支持的 Checkpointer。
六、InjectedStore——旧式存储注入方式
InjectedStore 用于向工具注入 LangGraph 的 Store 对象。
工具可以通过 Store 保存和读取用户偏好、学习进度等长期信息。
其基本语法为:
from typing import Annotated
from langgraph.prebuilt import InjectedStore
from langgraph.store.base import BaseStore
store: Annotated[
BaseStore,
InjectedStore()
]
与 InjectedState 类似,InjectedStore 参数也不会作为普通工具参数暴露给模型。
实例:读取 Store 中的数据
实例
from langchain.tools import tool
from langgraph.prebuilt import InjectedStore
from langgraph.store.base import BaseStore
@tool
def get_preference(
key: str,
store: Annotated[
BaseStore,
InjectedStore()
]
) -> str:
"""读取演示用户保存的偏好。"""
item = store.get(
("demo", "preferences"),
key
)
if item is None:
return "未找到该偏好"
return str(item.value)
这个工具需要通过配置了 Store 的 Agent 或 ToolNode 执行。
直接调用:
get_preference.invoke({"key": "theme"})
并不能凭空获得 Store 实例。
因此,这种写法只适合展示旧版注入参数的结构。下面使用官方推荐的 ToolRuntime 实现完整示例。
七、ToolRuntime.store——访问共享存储
在 LangChain 1.x 中,推荐通过:
runtime.store
获取当前 Agent 使用的 Store 对象。
Store 通过命名空间(Namespace)和键(Key)组织数据。
例如:
store.put(
("users", "user_001"),
"profile",
{"name": "小明"}
)
其中:
("users", "user_001")是命名空间。"profile"是键。{"name": "小明"}是保存的数据。
读取时使用:
item = store.get(
("users", "user_001"),
"profile"
)
print(item.value)
InMemoryStore 的生命周期
InMemoryStore 是一个适合教学和测试的内存 Store。
它允许多个 Agent 调用共享同一个 Store 实例中的数据,但不代表数据已经写入磁盘。
| 操作 | InMemoryStore |
|---|---|
| 同一个进程内多次调用 | 可以共享数据 |
| 不同会话使用同一个 Store 实例 | 可以共享数据 |
| 程序重新启动 | 内存中的数据通常丢失 |
| 跨多台服务器共享 | 不能自动实现 |
生产环境通常应选择持久化 Store,例如 PostgreSQL 等数据库实现。
八、完整实例:保存用户学习进度
下面创建一个可以保存和读取学习进度的 Agent。
这个示例使用:
ToolRuntime获取 Store。runtime.context获取当前用户 ID。InMemoryStore保存模拟学习记录。create_agent()管理工具调用。
需要特别注意,用户 ID 不能直接由模型随意指定,否则可能导致用户之间的数据混淆。
本例由应用程序提供当前用户的身份上下文。
完整代码
实例
from dotenv import load_dotenv
from langchain.tools import tool, ToolRuntime
from langchain.agents import create_agent
from langchain.chat_models import init_chat_model
from langgraph.store.memory import InMemoryStore
load_dotenv()
# -------------------------
# 定义运行时用户上下文
# -------------------------
@dataclass
class UserContext:
user_id: str
# -------------------------
# 创建 Store
# -------------------------
store = InMemoryStore()
# 初始化模拟用户数据
store.put(
("users", "user_001"),
"profile",
{
"name": "小明",
"level": "入门",
"completed_courses": [
"HTML 基础教程"
]
}
)
# -------------------------
# 工具一:读取学习档案
# -------------------------
@tool
def get_user_profile(
runtime: ToolRuntime[UserContext]
) -> str:
"""读取当前用户的模拟学习档案。"""
user_id = runtime.context.user_id
item = runtime.store.get(
("users", user_id),
"profile"
)
if item is None:
return "没有找到学习档案"
profile = item.value
return (
f"姓名:{profile['name']};"
f"水平:{profile['level']};"
f"已完成课程:"
+ "、".join(
profile["completed_courses"]
)
)
# -------------------------
# 工具二:保存学习进度
# -------------------------
@tool
def save_course_progress(
course_name: str,
runtime: ToolRuntime[UserContext]
) -> str:
"""将课程加入当前用户的模拟已完成列表。"""
user_id = runtime.context.user_id
namespace = ("users", user_id)
item = runtime.store.get(
namespace,
"profile"
)
if item is None:
return "用户档案不存在,无法保存"
profile = dict(item.value)
completed = list(
profile.get("completed_courses", [])
)
if course_name in completed:
return "该课程已经标记为已完成"
completed.append(course_name)
profile["completed_courses"] = completed
runtime.store.put(
namespace,
"profile",
profile
)
return (
f"已保存模拟学习进度:{course_name}。"
f"当前完成 {len(completed)} 门课程。"
)
# -------------------------
# 创建 Agent
# -------------------------
model = init_chat_model(
"deepseek:deepseek-flash"
)
agent = create_agent(
model=model,
tools=[
get_user_profile,
save_course_progress
],
store=store,
context_schema=UserContext,
system_prompt=(
"你是一名编程学习助手。"
"用户查询学习进度时使用工具。"
"用户明确要求标记课程完成时,"
"才使用保存工具。"
"所有数据都是教学模拟数据。"
"没有工具确认成功时,不要声称已保存。"
)
)
# -------------------------
# 调用 Agent
# -------------------------
context = UserContext(
user_id="user_001"
)
def ask(question: str):
result = agent.invoke(
{
"messages": [
{
"role": "user",
"content": question
}
]
},
context=context
)
print("\n用户:", question)
print(
"AI:",
result["messages"][-1].content
)
if __name__ == "__main__":
# 查询已完成课程
ask("查询我的模拟学习档案。")
# 保存进度
ask(
"请把 Python3 基础教程"
"标记为已完成。"
)
# 再次查询
ask("重新查询我的已完成课程。")
运行结果说明
如果模型正确调用相关工具,初始学习档案包括:
姓名:小明 水平:入门 已完成课程:HTML 基础教程
标记 Python3 基础教程完成后,再次读取 Store,可以得到:
姓名:小明 水平:入门 已完成课程: HTML 基础教程、Python3 基础教程
需要注意,以上是预期的业务数据变化,不是固定的 AI 输出文本。
由于 Agent 的工具选择由模型决定,实际是否执行保存操作,应以 Store 中的数据为准。
安全提示:示例中的 UserContext(user_id="user_001") 是应用程序主动提供的模拟身份。生产环境应从服务器验证过的登录会话或认证信息中获取用户 ID,不能直接信任用户提交的任意 ID。
九、在 Agent 中结合 Store 查询课程数据
除了用户偏好,Store 还可以保存课程目录等共享信息。
下面使用 Store 保存一组模拟课程资料,再通过工具查询。
实例
实例
from langchain.agents import create_agent
from langchain.chat_models import init_chat_model
from langgraph.store.memory import InMemoryStore
# 模拟课程目录
store = InMemoryStore()
store.put(
("runoob_demo", "courses"),
"catalog",
{
"Python3 基础教程": {
"price": "免费",
"duration": "20小时"
},
"Python 数据分析": {
"price": "模拟会员课程",
"duration": "30小时"
},
"HTML 基础教程": {
"price": "免费",
"duration": "15小时"
}
}
)
@tool
def query_course_info(
course_name: str,
runtime: ToolRuntime
) -> str:
"""查询指定课程的模拟价格和学习时长。"""
item = runtime.store.get(
("runoob_demo", "courses"),
"catalog"
)
if item is None:
return "模拟课程目录不存在"
catalog = item.value
info = catalog.get(course_name)
if info is None:
return f"未找到课程:{course_name}"
return (
f"课程:{course_name};"
f"价格:{info['price']};"
f"时长:{info['duration']}"
)
model = init_chat_model(
"deepseek:deepseek-flash"
)
agent = create_agent(
model=model,
tools=[query_course_info],
store=store,
system_prompt=(
"你是一名课程顾问。"
"查询课程信息时使用工具。"
"所有课程资料均为教学模拟数据。"
"不得将模拟价格当作真实售价。"
)
)
result = agent.invoke({
"messages": [
{
"role": "user",
"content": (
"请查询 Python3 基础教程"
"和 Python 数据分析的模拟课程信息。"
)
}
]
})
print(result["messages"][-1].content)
这个例子中,课程目录由 Store 保存,工具通过 runtime.store 读取数据。
如果模型分别调用两次 query_course_info,就可以获取两门课程的模拟信息。
注意:这些价格、学习时长和会员属性都是演示数据,不代表菜鸟教程网站当前实际提供的课程或收费政策。
十、ToolRuntime.context——获取可信用户上下文
实际应用中,工具经常需要知道当前请求属于哪个用户。
例如,不同用户的学习记录应该保存在不同命名空间中:
("users", "user_001")
("users", "user_002")
但是,用户 ID 不应该交给模型自由填写。
推荐使用运行时 Context,由应用程序提供已经验证的身份信息。
实例
实例
from langchain.tools import tool, ToolRuntime
@dataclass
class UserContext:
user_id: str
@tool
def who_am_i(
runtime: ToolRuntime[UserContext]
) -> str:
"""查询当前请求的用户标识。"""
return (
f"当前用户:"
f"{runtime.context.user_id}"
)
创建 Agent 时指定:
agent = create_agent(
model=model,
tools=[who_am_i],
context_schema=UserContext
)
调用时提供 Context:
result = agent.invoke(
{
"messages": [
{
"role": "user",
"content": "查询我的用户标识"
}
]
},
context=UserContext(
user_id="user_001"
)
)
这样,模型不需要获得用户 ID 作为工具参数,工具可以通过可信运行时读取。
注意:Context 本身不负责登录认证。应用程序必须先确认用户身份,再创建对应的 Context。
十一、InjectedToolArg——通用注入参数标记
InjectedToolArg 用于标记不应该由语言模型生成的工具参数。
它主要用于声明参数应由程序或执行框架提供,而不是普通 Tool Calling 参数。
例如:
实例
from langchain.tools import (
tool,
InjectedToolArg
)
@tool
def my_tool(
normal_param: str,
injected_param: Annotated[
str,
InjectedToolArg
]
) -> str:
"""演示普通参数和注入参数的区别。"""
return (
f"普通参数:{normal_param};"
f"注入参数:{injected_param}"
)
print(
my_tool.tool_call_schema.model_json_schema()
)
这里的 normal_param 是提供给模型的普通参数。
injected_param 通过 InjectedToolArg 标记为注入参数,因此不会作为普通模型工具参数暴露。
但要注意:InjectedToolArg 只是注入标记,不会自动创建注入值。
如果没有对应的运行时注入逻辑,工具执行时仍然可能因为缺少参数而失败。
相比自己实现通用参数注入,实际项目通常更推荐使用 ToolRuntime。
十二、State、Checkpointer 与 Store 对比
这三个概念经常被混淆,但用途不同。
| 对比维度 | State | Checkpointer | Store |
|---|---|---|---|
| 主要作用 | 保存工作流状态 | 保存和恢复 State | 存储跨会话数据 |
| 典型数据 | 消息、临时变量 | 会话检查点 | 用户偏好、学习进度 |
| 数据范围 | 当前工作流或线程 | 与线程等标识关联 | 由命名空间和键组织 |
| 跨调用 | 依赖状态管理 | 支持恢复会话 | 支持共享数据 |
| 持久化 | 依赖执行配置 | 取决于实现 | 取决于实现 |
例如,一个 AI 学习助手可能这样设计:
State: 当前正在讨论 Python 装饰器 Checkpointer: 保存这段对话的历史和状态 Context: 当前登录用户是 user_001 Store: user_001 已完成 Python 基础课程
因此:
- 需要读取当前消息,使用
runtime.state。 - 需要知道当前用户,使用
runtime.context。 - 需要跨会话保存数据,使用
runtime.store。 - 需要会话在后续调用中恢复,配置
checkpointer。 - 需要修改自定义 State,返回
Command。
十三、生产环境注意事项
当工具需要访问真实用户数据或长期存储时,还需要考虑安全性和一致性。
1、不能信任模型提供的用户 ID
用户身份应来自服务器认证系统,而不是语言模型生成的工具参数。
推荐由应用服务器创建运行时 Context,再通过 runtime.context 获取用户身份。
2、InMemoryStore 不适合长期保存重要数据
内存 Store 适合学习和测试。
生产环境通常需要使用 PostgreSQL 等持久化实现,保证程序重启后数据仍然可用。
3、避免并发写入覆盖
多个工具或多个 Agent 同时修改同一条学习进度时,简单的读取、修改、写回操作可能产生竞态条件。
真实系统应结合数据库事务、版本控制或其他并发控制方案。
4、权限检查不能只依赖提示词
即使系统提示词要求只能查询自己的资料,也不能代替后端权限校验。
例如,访问学习记录前,需要确认当前用户有权读取对应命名空间下的数据。
5、限制暴露给模型的数据范围
State 和 Store 可能包含用户个人信息、访问令牌或其他敏感数据。
工具应尽量只返回完成当前任务必需的字段,避免把整个用户档案或内部配置直接交给模型。
十四、常见问题
1、InjectedState 和 InjectedStore 还能使用吗?
可以在支持旧式注入机制的 LangGraph ToolNode 场景中使用。
但 LangChain 当前官方更推荐使用 ToolRuntime,统一访问状态、上下文和存储。
2、为什么直接调用 tool.invoke() 无法自动获得 State?
因为自动注入需要相应的 Agent 或 ToolNode 执行上下文。
直接调用工具不会自动构造完整的 Agent 状态。
3、为什么工具读取了 State,却没有保存用户偏好?
因为读取 State 并不等于更新 State。
如果要修改自定义状态字段,应通过受支持的状态更新机制,例如返回 Command。
4、State 会在 Agent 运行结束后消失吗?
不一定。
如果使用 Checkpointer,并通过相同的线程标识继续调用 Agent,可以恢复此前的状态。
5、InMemoryStore 是永久存储吗?
不是。
数据保存在当前 Python 进程内存中,进程结束后通常会丢失。
6、Store 和 Checkpointer 可以互相代替吗?
不应该简单互相替代。
Checkpointer 主要用于保存和恢复会话状态,Store 主要用于按照命名空间和键读写共享数据。
7、ToolRuntime 可以访问哪些信息?
常见属性包括:
runtime.state runtime.context runtime.store runtime.tool_call_id runtime.config runtime.stream_writer
部分更新版本还提供执行信息等扩展属性,具体以当前 API Reference 为准。
8、如何在多个用户之间隔离学习进度?
推荐通过可信 Context 获取用户 ID,再使用用户专属的 Store 命名空间。
例如:
namespace = (
"users",
runtime.context.user_id
)
同时必须在后端验证用户身份,防止访问其他用户的数据。
9、InjectedToolArg 会自动创建注入值吗?
不会。
它主要标记工具参数不应暴露给模型。实际注入需要执行框架提供相应逻辑。
10、State 和 Store 都需要持久化数据库吗?
不一定。
开发测试可以使用内存实现,但需要在服务重启后保留数据的生产项目,通常应使用数据库支持的 Checkpointer 和 Store。
总结
LangChain 的工具注入机制,可以让 Agent 工具访问模型参数之外的运行时数据。
本章节介绍了以下内容:
InjectedState:旧式 Agent 状态注入标记。InjectedStore:旧式 Store 注入标记。ToolRuntime:官方推荐的统一工具运行时接口。runtime.state:读取当前 Agent 状态。runtime.context:读取本次调用的上下文。runtime.store:读取和保存跨会话数据。Command:修改 Agent 状态。Checkpointer:保存与恢复会话状态。InjectedToolArg:标记不向模型暴露的注入参数。
对于新的 LangChain 项目,推荐优先采用下面的工具定义方式:
from langchain.tools import tool, ToolRuntime
@tool
def my_tool(
keyword: str,
runtime: ToolRuntime
) -> str:
"""演示访问工具运行时。"""
messages = runtime.state.get(
"messages", []
)
return (
f"关键词:{keyword};"
f"消息数:{len(messages)}"
)
这种方式比分别声明多个 InjectedState、InjectedStore 参数更统一,也更容易扩展。
核心原则:让模型只负责提供完成任务所需的业务参数,而将状态、用户身份、持久化存储和权限控制交给可信的程序运行时。
