跳到主要内容

上下文管理、人格、子 Agent、沙箱

这章讲什么: §02 讲了 Agent 工具循环的骨架。本章讲让这个 Agent「更能干、更像人、更安全」的四套配套机制:上下文管理(对话太长怎么办)、人格与技能(让 Agent 有性格和专长)、子 Agent(把活分给专门的小 Agent)、沙箱(让 Agent 安全地跑代码)。这些是 AstrBot 区别于「裸工具循环」的增值部分。

1. 上下文管理:对话太长怎么办

1.1 问题

多轮对话会越积越长,迟早撑爆模型的上下文窗口。粗暴截断会丢失重要信息,不截断又会报错或烧钱。AstrBot 的策略是两级处理:先按轮次硬截断,再按 token 智能压缩。

1.2 两级流程

每个 step 调 LLM 前,都会过一遍 ContextManager.process(astrbot/core/agent/context/manager.py:45):

原始消息历史

① 按轮次截断 (enforce_max_turns != -1)
│ 超过 max 轮就丢掉最旧的 truncate_turns 轮

② 按 token 压缩 (max_context_tokens > 0)
│ 数 token,超阈值才触发压缩器


处理后的消息历史 ──► 喂给 LLM

真实逻辑见 manager.py:60(轮次截断)和 manager.py:67(token 压缩)。两级是递进的:轮次截断是便宜的硬上限,token 压缩是更精细的第二道关。

1.3 压缩有两种策略

按配置 context_limit_reached_strategy:

策略怎么做
truncate_by_turns(默认)直接丢最旧的若干轮
llm_compress用一个 LLM 把旧历史总结压缩成短文本,保留最近一定比例(llm_compress_keep_recent_ratio,默认 0.15)的原文

llm_compress 可以指定专门的压缩模型(llm_compress_provider_id),没配就用当前会话的聊天模型(_get_compress_provider,astr_main_agent.py:1235)。压缩器实现见 astrbot/core/agent/context/compressor.py,token 计数见 token_counter.py

巧妙处: token 计数用了 trusted_token_usage——上一次 LLM 响应回报的真实 token 数(tool_loop_agent_runner.py:711),比本地估算更准,避免反复全量数 token。

2. 人格与技能:让 Agent 有性格和专长

2.1 人格(Persona)

人格 = 一段系统提示 + 可选的开场对话 + 可选的工具/技能白名单。_ensure_persona_and_skills(astr_main_agent.py:458)在装配 Agent 时:

  1. 按会话/对话/平台解析出当前人格(resolve_selected_persona,astr_main_agent.py:472)。
  2. 把人格的 prompt 拼进系统提示(astr_main_agent.py:489),开场白插到上下文最前(:491)。
  3. 人格可以限定只用哪些工具(persona["tools"],:538)和只用哪些技能(persona["skills"],:510)——这让「客服人格只能用客服工具」成为可能。

人格由 PersonaManager(astrbot/core/persona_mgr.py)管理。

2.2 技能(Skills)

技能是「打包好的能力说明」,会被拼成一段提示注入系统提示(build_skills_prompt,astr_main_agent.py:522)。技能可来自插件或工作区(SkillManager.list_skills / list_workspace_skills,:498-:506)。在沙箱「Neo」模式下还有完整的技能生命周期(创建 payload → 候选 → 发布),见 astr_main_agent.py:1116-:1156 的提示模板。

3. 子 Agent:把活分给专门的小 Agent

3.1 思路

一个「全能 Agent」工具太多会变笨。更好的做法:主 Agent 像个调度员,把特定任务转交给专门的子 Agent(各自有自己的人格和工具集)。这就是 handoff(转交)模式。

3.2 实现:handoff 工具

子 Agent 被包装成一个特殊工具 HandoffTool(astrbot/core/agent/handoff.py:8)——对主 LLM 来说,它看起来就是个普通工具 transfer_to_xxx。主 Agent「调用」这个工具,实际就是把控制权交给对应子 Agent。

装配逻辑在 _ensure_persona_and_skills(astr_main_agent.py:549-:609):若开启 subagent_orchestrator.main_enable,就把编排器里的 handoff 工具加进主 Agent 的工具集(:592),还能去重(把已分给子 Agent 的工具从主 Agent 移除,:596)、注入路由系统提示(:603)。

编排器 SubAgentOrchestrator(astrbot/core/subagent_orchestrator.py)从配置动态构建子 Agent,在生命周期里初始化(core_lifecycle.py:83 _init_or_reload_subagent_orchestrator)。执行转交由上一章的 FunctionToolExecutor 识别 HandoffTool 分派(astr_agent_tool_exec.py)。

4. 沙箱:让 Agent 安全地跑代码

4.1 问题

让 LLM 执行 shell/Python 很强大,但也危险——它可能删文件、跑恶意命令。AstrBot 用 computer_use_runtime 配置控制「代码在哪跑」:

runtime含义
none不给执行工具
local在 AstrBot 主机本地跑(方便但有风险)
sandbox在隔离沙箱里跑(安全)

4.2 三种 runtime 怎么装配

build_main_agent 末尾按 runtime 加不同工具(astr_main_agent.py:1537-:1540):

  • local:_apply_local_env_tools(:398)加 shell/python/文件/grep 工具,注入「你能访问本机环境」的提示。
  • sandbox:_apply_sandbox_tools(:1078)接入沙箱后端(shipyard / shipyard_neo / cua),按沙箱能力(是否支持浏览器等)有条件地加工具(:1140),并注入沙箱专属路径规则和技能生命周期提示。

沙箱客户端在 astrbot/core/computer/,会话级复用沙箱实例(session_booter,astr_main_agent.py:1131)。这呼应了 README 里「Agent Sandbox:隔离、安全地执行代码/shell,会话级资源复用」。

4.3 安全模式

另有 llm_safety_mode(astr_main_agent.py:1068),往系统提示里注入一段「健康安全」提示防止有害输出。还有一个有意思的细节:internal.py:518 把已知恶意主机用 base64 编码硬写进代码,请求前比对 provider 的 api_base,命中就拦截(internal.py:250-:258)——防止用户被诱导接入恶意「中转 API」。

5. 巧妙之处(可借鉴)

  • 上下文「轮次截断 + token 压缩」两级:便宜的硬上限托底,贵的 LLM 压缩精细化;trusted_token_usage 复用上游真实 token 数省去重复计算(manager.py:45tool_loop_agent_runner.py:711)。
  • 子 Agent 伪装成普通工具(handoff):主 LLM 不需要懂「多 Agent 编排」,它只是「调了个工具」,复杂度被封装在执行器和编排器里(handoff.pysubagent_orchestrator.py)。
  • runtime 三档把「能力 vs 安全」做成配置开关:同一套工具循环,换个 runtime 就从「本地全权」切到「沙箱隔离」,无需改 Agent 逻辑(astr_main_agent.py:1537)。
  • 恶意中转 API 的 base64 黑名单:一个小而实的安全护栏,防钓鱼式 provider 配置(internal.py:518)。

6. 边界与局限

  • llm_compress 压缩是有损的,可能丢掉对当前任务关键的早期细节;压缩质量取决于所用模型。
  • 子 Agent 编排依赖配置正确(工具分配、去重),配错可能导致工具重复或缺失。
  • 沙箱依赖外部后端(Shipyard/CUA),没配好就只能退回 localnone

7. 横向对比

上下文压缩、人格、子 Agent、沙箱在前沿 Agent 项目里都是标配方向,但 AstrBot 的取向是聊天场景驱动:人格系统(角色扮演、情感陪伴)是它的招牌用例,比编码 Agent 重得多;子 Agent 用「伪装成工具的 handoff」这种轻量实现而非复杂的图编排;沙箱则对齐了「让 IM 里的 AI 安全地帮你跑代码」这一具体诉求。它不追求最前沿的 Agent 架构,而是把这些机制做成会话级可配置,服务多用户多场景的平台定位。

8. 代码地图(导航索引)

主题文件路径符号名
上下文两级处理astrbot/core/agent/context/manager.pyContextManager.processContextManager._run_compression
上下文配置astrbot/core/agent/context/config.pyContextConfig
压缩器 / token 计数astrbot/core/agent/context/compressor.pytoken_counter.pyContextCompressorTokenCounterEstimateTokenCounter
压缩模型选择astrbot/core/astr_main_agent.py_get_compress_provider
人格 + 技能注入astrbot/core/astr_main_agent.py_ensure_persona_and_skills
人格管理astrbot/core/persona_mgr.pyPersonaManager
子 Agent 编排astrbot/core/subagent_orchestrator.pySubAgentOrchestrator
子 Agent 转交工具astrbot/core/agent/handoff.pyHandoffTool
沙箱/本地工具装配astrbot/core/astr_main_agent.py_apply_sandbox_tools_apply_local_env_tools
沙箱客户端astrbot/core/computer/computer_client.py(session_booter)
安全模式 + 恶意主机拦截astrbot/core/astr_main_agent.py.../agent_sub_stages/internal.py_apply_llm_safety_modedecoded_blocked