第1章 第 1 章 Action Runtime 架构解析
第 1 章 Action Runtime
语言:English · 中文
Agently 的 action 堆栈在 orchestration 层下方包含三个可替换的插件层:
text TriggerFlow ◄── 位于 action 上方的 orchestration(循环、分支、暂停/恢复) │ ▼ ActionRuntime ◄── 规划 + 调度 │ (使用 ActionFlow 作为通向 orchestration 层的桥接) ▼ ActionExecutor ◄── 原子执行(本地函数、MCP、沙箱)
分层详解
| 层 | 职责范围 | 默认内置实现 | | :--- | :--- | :--- | | TriggerFlow | 位于 action 上方的高层 orchestration(循环、分支、暂停/恢复、子流程)——参见 TriggerFlow | TriggerFlow 核心 | | ActionRuntime | 规划协议、action 调用规范化、默认执行编排 | AgentlyActionRuntime | | ActionFlow | ActionRuntime 与 flow 表示之间的桥接 | TriggerFlowActionFlow | | ActionExecutor | action 的具体运行方式 | 本地函数、MCP、Python/Bash 沙箱、Search/Browse、Node.js、Docker、SQLite 执行器 | | ExecutionEnvironment | 调用执行器前所需的管理执行依赖 | MCP、Bash、Python、Node、Docker、Browser、SQLite 提供者 |
`agently.core` 中的 `Action` 是一个外观类,它负责连接: * `ActionRegistry` 和 `ActionDispatcher`(稳定的核心原语) * 一个活跃的 `ActionRuntime` 插件 * 一个活跃的 `ActionFlow` 插件
默认连接关系
text Agent → ActionExtension → Action 外观 → ActionRuntime → ActionFlow → ActionExecutor
插件类型
你可以替换的插件类型如下: * ActionRuntime:用于修改规划协议或调用规范化逻辑 * ActionFlow:用于修改 orchestration 形态(例如自定义 flow 表示法) * ActionExecutor:用于添加新的后端(HTTP、gRPC、自定义沙箱、远程 worker)
从 `agently.types.plugins` 导入协议和处理器别名:
python from agently.types.plugins import ( ActionExecutor, ActionRuntime, ActionFlow, ActionPlanningHandler, ActionExecutionHandler, )
旧的 `ToolManager` 插件类型和 `AgentlyToolManager` 类仅保留用于明确的遗留用途,并会在每个 Python 进程中针对每个弃用的 API 发出一次弃用警告,除非禁用了 `runtime.show_deprecation_warnings`。请勿针对 ToolManager 编写新的插件。
推荐接口 — actions
对于新代码:
python from agently import Agently
agent = Agently.create_agent()
@agent.action_func async def add(a: int, b: int) -> int: """Add two integers.""" return a + b
@agent.action_func async def python_code_executor(python_code: str): """Execute Python code and return the result.""" ...
agent.use_actions([add, python_code_executor])
# 或者一次性注册并运行 @agent.auto_func def calculate(formula: str) -> int: """Compute {formula}. Use available actions.""" ...
print(calculate("3333+6666=?"))
| 接口 | 用途 | | :--- | :--- | | `@agent.action_func` | 将函数标记为 action,从签名 + 文档字符串推导其 schema | | `agent.use_actions(actions)` | 向 agent 注册 action 列表、单个 action 或字符串命名的 action | | `agent.use_actions(["name1", "name2"])` | 通过名称注册预注册的 actions | | `agent.use_actions(Search(...))` | 挂载来自 `agently.builtins.actions` 的内置 Search 包 | | `agent.use_actions(Browse(...))` | 挂载来自 `agently.builtins.actions` 的内置 Browse 包 | | `agent.enable_python(...)` | 挂载受管理的 `run_python` action,用于确定性代码执行 | | `agent.enable_shell(...)` | 挂载带工作区和命令白名单的受管理 `run_bash` action | | `agent.enable_nodejs(...)` | 挂载受管理的 `run_nodejs` action | | `agent.enable_sqlite(...)` | 挂载受管理的 `query_sqlite` action | | `agent.enable_workspace_file_actions(...)` | 将当前 Workspace 文件区域暴露为 list/search/read/write actions | | `@agent.auto_func` | 将 Python 函数签名 + 文档字符串转化为基于模型实现的函数,该实现使用 agent 的 actions | | `agent.get_action_result(prompt=turn.prompt)` | 检索请求作用域 turn 的 action 调用记录 | | `extra.action_logs` | 在 action 循环期间产生的结构化日志 |
`agent.action.get_action_info()` 和 `agent.action.get_tool_info()` 默认返回注册在该 agent 上的可见 action/tool schema,包括 agent 作用域 actions、通过 `agent.use_mcp(...)` 挂载的 MCP 工具,以及 `enable_*` 组件辅助函数。只有当您需要窄化子集时,才显式传入 `tags=[...]`。
对于应用程序代码,如果目标是向模型提供 Python、shell 或 workspace 访问等通用能力,请优先使用 `enable_*` 辅助函数。当您在构建自定义 Action 后端时,请使用 `register_action(..., executor=..., execution_environments=[...])`。
内置能力包位于 `agently.builtins.actions` 下。例如:
python from agently.builtins.actions import Browse, Search
agent.use_actions(Search(timeout=15, backend="auto")) agent.use_actions(Browse())
`Search` 是 Action 原生包,不使用 Execution Environment;proxy、timeout、backend 和 region 是包/执行器配置。`Browse` 也是 Action 原生的;其默认路径是 Playwright + BS4,而 pyautogui 保留为遗留/高级配置。如果 Browse action 需要受管理的 browser/page/session,请在启用 Browser Execution Environment 的情况下注册它。
`enable_*` 辅助函数上的 `desc=` 参数是可选的。默认情况下,它会作为额外指导附加,以便模型仍能看到基线用法和安全约束。如果您有意替换默认描述,请使用 `desc_mode="override"`;如果希望忽略提供的描述并仅保留内置描述,请使用 `desc_mode="default"`。
执行召回
诸如 `run_bash`、`run_python`、`run_nodejs`、`query_sqlite`、`browse` 和 `search` 等指令密集型 action 通过记录执行摘要加工件引用来保持后续模型上下文的紧凑性。
摘要通常是下一轮 action 规划所看到的内容。它包含 action id、调用 id、目的、状态、紧凑的指令预览、结果预览、脱敏注释和工件引用。完整原始内容(如完整代码、shell 输出、SQL 行、页面 HTML、截图或日志)作为脱敏工件保留,而不是插入到每个提示中。
当模型或应用程序需要省略的细节时,显式读取:
python turn = agent.input("Use the action and summarize the result.") records = agent.get_action_result(prompt=turn.prompt) artifact_ref = records[0]["artifact_refs"][0]
raw = agent.action.read_action_artifact( artifact_id=artifact_ref["artifact_id"], action_call_id=artifact_ref["action_call_id"], )
对于指令密集型 action,`Action.to_action_results(records)` 使用摘要,因此后续回复可以推理发生了什么,而默认情况下不会接收完整负载。
兼容接口 — tools
旧接口仍然有效:
python @agent.tool_func def add(a: int, b: int) -> int: return a + b
agent.use_tool(add) agent.use_tools([add]) agent.use_mcp("https://...") agent.use_sandbox(...) extra.tool_logs # 在旧接口中等价于 extra.action_logs
这些仍是有效的公共挂载接口。它们在内部映射到新的 action runtime——并不意味着 ToolManager 实现。在方便时迁移到 action 接口;不会立即破坏现有代码。
规划模型 key
Action 规划是一个由模型拥有的步骤。当 Agent 使用 `model_pool` 时,将 `action.planning_model_key` 设置为应该规划 action 轮次的业务模型 key:
python agent.set_settings("model_pool", {"task-main": "deepseek-chat-prod"}) agent.set_settings("model_profiles", { "deepseek-chat-prod": { "provider": "OpenAICompatible", "base_url": "https://api.deepseek.com/v1", "model": "deepseek-chat", "api_key_pool": "deepseek-prod", } }) agent.set_settings("action.planning_model_key", "task-main")
这适用于默认的 structured-plan 和原生 tool-call 规划路径。当更高层的运行时(如 `SkillsExecutor` 或 `AgentTaskLoop`)将受限的 action 轮次委托给 `ActionRuntime` 时,这一点尤为重要。
处理器接口
如果您正在编写自定义 `ActionRuntime` 或 `ActionFlow` 插件,规划和执行处理器使用一个稳定的双参数契约:
python async def planning_handler( context: ActionRunContext, request: ActionPlanningRequest, ) -> ActionDecision: ...
async def execution_handler( context: ActionRunContext, request: ActionExecutionRequest, ) -> list[ActionResult]: ...
上下文字段包括 prompt、settings、agent_name、round_index、max_rounds、done_plans、last_round_records、action、runtime。请求字段包括 action_list、planning_protocol、action_calls、async_call_action、concurrency、timeout。
自定义 `ActionFlow` 插件可以接受一个可选的 `runtime_observation_handler` 关键字参数。如果存在,flow 应向该处理器发送纯观察字典,而不是直接发射官方的 `action.*` 或 `tool.*` RuntimeEvents;核心会将这些观察映射到官方事件流。
没有遗留的位置参数处理器签名——公共契约仅为 `(context, request)`。
扩展指南
| 您想要改变 | 替换对象 | | :--- | :--- | | 仅后端(HTTP、gRPC、远程 worker、沙箱) | ActionExecutor | | 规划协议或调用规范化方式 | ActionRuntime | | runtime 与 flow 之间的 orchestration 形态 | ActionFlow | | 跨越多个 action 调用的更高层流程控制 | 在 runtime 上方使用 TriggerFlow——不要将其嵌入执行器中 | | MCP/沙箱/进程类依赖的生命周期 | 声明 ExecutionEnvironment 要求——不要在执行器内隐藏生命周期 |
参见
* Actions Overview — Action Runtime 终止和 orchestration 开始的地方 * Execution Environment — 受管理的 MCP/沙箱依赖 * Tools — 更详细的兼容接口 * MCP — `agent.use_mcp(...)` * TriggerFlow Overview — 位于 action 上方的 orchestration