CAMEL

一句话定位

CAMEL 是学术出身的多 agent 框架,单 agent(ChatAgent)是标准的 while-loop tool-calling 循环,真正的重量在 societies/ 编排层(role-playing 双 agent + workforce 分层 coordinator/planner/worker),配套 ~90 个 toolkit + MCP + Anthropic 风格 SKILL.md 技能系统、LLM 风险审批闸门与多种沙箱/云运行时,并把多 agent 轨迹系统化转成 SFT/RL 训练数据(data_collectors + datagen + environments + verifiers)。工程”生产级”味道弱于 Claude Code,但”多 agent + 造数/训练闭环”的完整度是同类里最高之一。

核心架构总览(目录结构关键路径 + 引用的 commit)

分析基于 commit 147d92652cd20f0eb3f541c612aa105a4ad12550(2026-07-10,--depth 1 浅克隆,Python,Apache-2.0)。核心包在 camel/ 下:

  • agents/ChatAgent(核心文件 chat_agent.py ~6468 行)+ 一批专用 agent(critic / task / role_assignment / knowledge_graph / mcp / repo / search)。
  • societies/ — 多 agent 编排:role_playing.py(双 agent role-playing,CAMEL 论文原型)+ workforce/(分层多 agent,主文件 workforce.py ~258KB)。
  • toolkits/ — ~90 个 toolkit + function_tool.py(工具封装/schema 生成)+ base.pyBaseToolkit)。
  • memories/ — 记忆系统(ChatHistory / VectorDB / Longterm + ContextCreator)。
  • runtimes/ — 工具执行隔离运行时(docker / daytona / remote_http / ubuntu_docker / llm_guard)。
  • interpreters/ — 代码解释器沙箱(internal_python / subprocess / docker / e2b / ipython / microsandbox)。
  • datagen/data_collectors/environments/verifiers/ — 合成数据 / 轨迹采集 / RL 环境 / 结果校验(训练侧)。
  • .camel/skills/ — 仓库内 SKILL.md(Anthropic 风格技能,见 SkillToolkit)。

结构上可理解为两层:底层 ChatAgent 是单 agent 引擎,上层 societies/ 把多个 ChatAgent 编排起来;旁挂的 datagen/data_collectors/environments/verifiers 是把编排产生的轨迹变成训练数据的配套设施。

Agent Loop(主循环 / 何时继续何时停)

核心在 agents/chat_agent.py。同步链路 step()(2831) → _step_impl()(2884);异步 astep()(3128)/_astep_non_streaming_task()(3194);流式版在 5402 起。

  • 循环体_step_implwhile True:(2940)。每轮:_get_context_with_summarization() 取上下文 → _get_model_response()(3580) 调模型(把 _get_full_tool_schemas() 作为 tool_schemas 传入,除非 disable)→ iteration_count += 1
  • 继续条件:若 response.tool_call_requests 非空(3002),把 assistant tool-call 消息写入 memory,逐个 _execute_tool()(4026) 执行内部工具、结果写回 memory,然后 continue 回到循环顶(3054)——“有工具调用就继续”。
  • 停止条件(多个 break 点):
    1. 无 tool call 且无 response_terminators → 直接 break(3093,最常见的自然终止)。
    2. 命中 external tool(在 _external_tool_schemas 里)→ 收集到 external_tool_call_requests 后 break(3043),把控制权交还调用方。
    3. max_iteration 到顶 → break(有 tool 3046-3051;无 tool 3072-3080)。默认 max_iteration=None(无限,直到模型自然停止发 tool call)。
    4. stop_eventthreading.Event)被 set → _step_terminate(..., "termination_triggered")(2988)。
    5. 上下文超 token → RuntimeError 捕获后 _step_terminate(..., "max_tokens_exceeded")(2955)。
    6. 配了 response_terminators 时:无 tool call 则跑 terminators 判断;若未终止就注入 "Please continue." user 消息再 continue(3082-3090)。
  • HITL 暂停pause_event(threading/asyncio.Event)——循环顶和每个工具执行前都会阻塞等待 event set(2941-2948, 3030-3038),供 workforce 做人工干预/暂停。

结论:CAMEL 单 agent = “一个 while 循环反复喂 tool 结果”,停止判定完全由模型是否继续发 tool call 主导;多 agent 能力不在这个循环里,而在 societies/ 层(见 Router 章)。

记忆与上下文管理(压缩、长期记忆、会话持久化)

记忆分两块:memories/ 抽象 + chat_agent.py 内的渐进式 summarization。

  • AgentMemory 抽象memories/base.py):write_records / retrieve / get_context_creator / clear / clean_tool_callsget_context()(169) = retrieve 后交给 ContextCreator 生成 (List[OpenAIMessage], token_count)
  • 三种实现memories/agent_memories.py):
    • ChatHistoryMemory(默认):ChatHistoryBlock + 可选 window_size 滑窗(只取最近 N 条,67-78)。
    • VectorDBMemoryVectorDBBlock 向量检索,retrieve_limit=3(189-195)——长期语义记忆。
    • LongtermAgentMemory:ChatHistory + VectorDB 组合,retrieve 时合并两路(229-283)。
  • ContextCreatormemories/context_creators/score_based.py):ScoreBasedContextCreator 按 token 预算和分数裁剪;注意注释说 token_limit 现已”保留 API 兼容但不再用于裁剪”(35-38),token 估算有缓存(set_cached_token_count/clear_cache)。
  • 压缩/摘要(chat_agent):构造参数 summarize_threshold=50(默认,占 token_limit 百分比)、summary_window_ratio=0.6_get_context_with_summarization()(1009):summary 累积 token 超 token_limit*0.6 → 全量压缩 summarize(include_summaries=True);否则算 _calculate_next_summary_threshold()(1081)(渐进式阈值),超阈值触发 summarize(include_summaries=False) 增量压缩,_update_memory_with_summary()(1123) 清 memory 后回填 summary。
  • 另有独立 ContextSummarizerToolkittoolkits/context_summarizer_toolkit.py):把完整历史落盘(summary + history 文件)、可搜索历史、should_compress_context,是”工具化”的上下文管理,agent 可主动调。
  • 会话持久化save_memory(path)(1705) / load_memory_from_path(path)(1655) / load_memory(memory)(1641);MemoryToolkittoolkits/memory_toolkit.py)把 save/load/clear 暴露成工具(JSON 序列化)。
  • prune_tool_calls_from_memory(构造参数)+ clean_tool_calls():可从 memory 清掉工具调用细节省 token。

工具体系(定义/调用协议/注册/权限)

  • 定义toolkits/function_tool.pyFunctionTool(517)。核心是 get_openai_tool_schema(func)(228)——从 Python 函数签名 + docstring 自动生成 OpenAI function-calling schema,sanitize_and_enforce_required()(332) 递归加 additionalProperties:false、强制 required(strict schema)。支持 synthesize_schema(无 docstring 时用 LLM 反生成 schema,450 generate_docstring)和 synthesize_output(LLM 模拟工具输出)。
  • Toolkit 基类toolkits/base.py BaseToolkit——get_tools() → List[FunctionTool]__init_subclass__ 给所有方法自动包 with_timeout(TIMEOUT_THRESHOLD),@manual_timeout 装饰器可跳过。metaclass=AgentOpsMeta(可观测埋点)。
  • ~90 个内置 toolkit:search / code_execution / browser(hybrid + playwright MCP) / terminal / file / github / gmail / notion / slack / arxiv / math / sympy / thinking / note_taking / todo / human / memory / message_agent(agent 间通信)等。
  • 调用协议:模型返回 tool_call_requests → _execute_tool()(4026) 从 self._internal_tools(dict, name→FunctionTool)查表,tool(**args) 同步调用;_aexecute_tool()(4077) 按优先级尝试 async_call / MCP func.async_call / 协程 / 线程池兜底同步(4096-4120)。异常被捕获成 "Tool execution failed: ..." 回灌模型(不崩溃,4062-4066)。
  • 注册:构造器 tools=[...](Callable 或 FunctionTool 自动包装);add_tool/add_tools(1215/1220) 运行期加;add_external_tool(1564) 加”外部工具”(只给 schema、执行交回调用方,命中即 break loop)。_external_tool_schemas_internal_tools 二分。
  • RegisteredAgentToolkit:toolkit 可反向持有 agent 引用(构造参数 toolkits_to_register_agent,602-606),供需要回调本 agent 的工具(如 agent-as-tool)。
  • MCPtoolkits/mcp_toolkit.py MCPToolkit(230)管理多 MCP server 连接生命周期(connect/disconnect/__aenter__),把 MCP tool 转成 FunctionTool;ensure_strict_json_schema(57) 把 MCP schema 转严格模式。另有 mcp_agent.py(449 行)。
  • 权限/maskingmask_tool_output(构造参数)→ 工具原始输出存进 _secure_result_store(带锁),回给模型的是占位符 [...output masked...](4052-4059),防敏感输出进上下文。真正的风险审批见安全章。

Prompt 设计(系统提示结构、动态组装)

  • 系统提示:ChatAgent 的 system message 由构造器 system_message(str/BaseMessage,可空)直接给定,没有 Claude Code 那种庞大固定系统提示;框架偏”用户/上层给角色 prompt”。_generate_system_message_for_output_language()(2433) 会在原 system message 后拼一句 "...you must output text in {output_language}."(2449)实现输出语言约束。
  • 角色 prompt 模板prompts/TextPrompt(继承 str,带 key_words / .format() 缺参保留,prompts/base.py92)+ 各领域 TextPromptDictprompts/ai_society.pyASSISTANT_PROMPT/USER_PROMPT/CRITIC_PROMPT===== RULES OF ASSISTANT ===== 结构化块),role-playing 用它给双方注入角色 + 任务。
  • 动态组装:role_playing 里 _get_sys_message_info()(298) 用 task/role 名 format 模板生成双方 system message;workforce 的 coordinator/planner/worker system prompt 在 societies/workforce/prompts.py(~23KB,含 assign/decompose/结构化输出指令)。
  • 结构化输出response_format(Pydantic)参数;不支持 native structured output 的模型走 _handle_response_format_with_non_strict_tools()(prompt 里塞 schema + 正则抽取),workforce 默认 use_structured_output_handler=Truestructured_output_handler.py)。

Router / 编排(任务分解、多 agent、子 agent)

两条编排路线:

  • RolePlayingsocieties/role_playing.py,CAMEL 论文原型):两个 ChatAgent —— AI User(发指令)+ AI Assistant(执行),可选 Critic。init_chat()(548) 起对话,step()(631) 一来一回。是”对话式”协作,非层级调度。
  • Workforcesocieties/workforce/workforce.py,主力,~258KB):层级式多 agent。内部三个专用 ChatAgent(176 docstring 明示):
    • Coordinator Agent(任务分配):_find_assignee()(4042) → _call_coordinator_for_assignment()(3768) 让 coordinator 把 task 批量分给 worker,_validate_assignments()(3883) 校验,失败走 _handle_assignment_retry_and_fallback()(3933)。
    • Task Planner Agent(任务分解):_decompose_task()(1549) + 结果合成。
    • Dynamic Workers:任务反复失败时运行期新建 worker(_create_worker_node_for_task()(4186),默认带 SearchToolkit/CodeExecutionToolkit/ThinkingToolkit)。
    • Worker 节点类型:SingleAgentWorkerRolePlayingWorker(worker 内部再跑 role-playing)、嵌套 Workforce(可套娃)。
    • 失败恢复策略WorkforceMode):AUTO_DECOMPOSE(默认,失败时 decompose/replan/新建 worker)vs PIPELINE(简单重试、失败信息传给下游);FailureHandlingConfigmax_retries/enabled_strategies=["retry","replan"]/halt_on_max_retries
    • 任务流转task_channel.py(共享任务队列/依赖);process_task_async()(2669) 主入口;start()(5822) 事件循环;task 有 dependencies(DAG),_update_task_dependencies_from_assignments()(4011)。
    • 共享记忆share_memory=True 时所有 SingleAgentWorker + coordinator + planner 共享完整对话与工具轨迹(225-233)。
  • 另有 agents/role_assignment_agent.pyagents/task_agent.py(任务分解/规划的独立 agent)。

Skill / 插件体系

有真正的 Anthropic 风格 SKILL.md 系统toolkits/skill_toolkit.py SkillToolkit(27)。

  • 从文件系统按优先级发现 SKILL.md(_skill_roots()188):repo 级 ./.camel/skills./.agents/skills → user 级 ~/.camel/skills~/.config/camel/skills → system 级 /etc/camel/skills;同名 repo 优先。
  • _parse_skill()(229) 解析 YAML frontmatter(name/description)+ 正文;_build_description()(52) 把所有可用 skill 的 name+description 汇总进工具描述(渐进式披露)。
  • 工具:list_skills(292) / list_skill_files(310) / load_skill(name)(396) 按需加载正文进上下文。allowed_skills 可白名单限制。
  • 本仓库自带 .camel/skills/docs-incremental-update.camel/skills/skill-creator(给维护 CAMEL 自身用)。
  • 广义”插件” = ~90 个 toolkit + MCP server 接入(见工具章)。

自进化能力(自我改进 / 学习型记忆 / eval 驱动纠错)

两块,都真实存在:

  • Workflow Memory(学习型记忆,workforce)societies/workforce/workflow_memory_manager.py(~68KB)+ single_agent_worker.pyenable_workflow_memory。worker 完成任务后 save_workflow_memories()(619) → save_workflow()(559):两趟——先 generate_workflow_summary()(627) 用专门 summarizer agent 从这次对话 + 工具轨迹蒸馏出结构化 workflow(步骤/经验),判定 update vs create,再落盘(带 workflow_version 版本号、updated_at)。下次任务开始 load_workflows_by_role()(438) 按角色检索历史 workflow 注入 prompt(WorkflowSelectionMethod:LLM 选 / MOST_RECENT / ALL)。这是”从自身成功轨迹学经验、跨任务复用”的自进化闭环。
  • Self-Improving CoT(STaR 式,datagen)datagen/self_improving_cot.py SelfImprovingCoTPipeline(71)。循环:generate_reasoning_trace()(406) → evaluate_trace()(428)(用 evaluate_agent 或 RewardModel 打分 + AgentTraceEvaluation.feedback)→ 分数不够则 _generate_feedback()(366) + improve_trace()(562) 迭代改,max_iterations 上限;支持 rejection sampling(generate_reasoning_trace_rejection497)和 rationalization。这是 eval/reward 驱动的自我纠错,但产物是训练数据(见轨迹章),不是运行期在线自改权重。
  • 运行期”纠错”更多靠 workforce 的 replan/decompose 失败恢复(见 Router 章)和工具异常回灌(见工具章),而非改自身权重。

可观测性(日志 / trace 格式)

  • Langfuse trace(一等):utils/langfuse.pyconfigure_langfuse()(39) 开关;@observe() 装饰模型调用;_step_impl 开头 set_current_agent_session_id(agent_id)(2899) 把 agent_id 作为 Langfuse session_id 做 trace 分组;update_langfuse_trace()(147) 附 session/user/metadata。is_langfuse_available() 优雅降级(ImportError 时跳过)。
  • AgentOpsBaseToolkitAgentOpsMeta metaclass,工具调用自动埋点。
  • 结构化日志logger.pyget_logger/set_log_file/set_log_level)。ChatAgent 内 _sanitize_messages_for_logging()(3705) 脱敏后记录;_emit_request_usage() 每 iteration 发 token 用量事件。
  • Workforce 日志/指标societies/workforce/workforce_logger.py WorkforceLogger(同时实现 WorkforceCallback + WorkforceMetrics):log_task_created/decomposed/assigned/started/updatedlog_stream_chunklog_entries 为结构化 dict(含 timestamp/event_type)。事件定义在 workforce/events.py。回调机制 WorkforceCallbackcallbacks=[...])可外接自定义观测。
  • 仓库根有 camel_log_viewer.html(本地日志可视化)。

安全与权限(审批门、密钥管理)

  • LLM 风险审批门(核心):runtimes/llm_guard_runtime.py LLMGuardRuntime(63)。add(funcs, threshold=2)(105) 用 wrapper 包住每个工具:调用前先让一个专门的 guard ChatAgent(system prompt=GUARDPROMPT28,1-3 分风险量表)评估”函数名 + 描述 + 实参”的风险分(用 external tool function_risk);score > threshold拒绝执行、返回 {"error": ...}(163-170);否则放行真实函数(185)。配套 IgnoreRiskToolkit——可对某函数登记”已知安全”跳过下次评估(138-145)。这是模型驱动的动态审批闸门。
  • HITL 审批toolkits/human_toolkit.py HumanToolkit.ask_human_via_console()(32) 直接 input() 问人(51);workforce 有 pause_event 人工暂停 + 人工干预路径(_process_task_with_intervention2903)。
  • 输出脱敏mask_tool_output(见工具章)+ 日志 _sanitize_messages_for_logging
  • 密钥管理:靠环境变量(.env.example ~5KB 列各 provider key);无内置 vault。CodeExecutionToolkit unsafe_modeeval() 无检查)默认 False。仓库有 SECURITY.md

沙箱与执行隔离

两层隔离:

  • 代码解释器沙箱interpreters/):CodeExecutionToolkittoolkits/code_execution.py)可选 sandboxinternal_python(受限 AST 解释器 InternalPythonInterpreter + import_white_list 白名单)、subprocess(默认,本机子进程)、jupyter(ipython)、dockerDockerInterpreter 容器内跑)、e2b(E2B 云沙箱)、microsandboxhost_execution_sandboxes={internal_python, subprocess} 标记哪些是”跑在本机”(有风险)。terminal_toolkit 另有 go/java runtime。
  • 工具运行时隔离runtimes/):把任意 FunctionTool 搬到隔离环境执行——DockerRuntimedocker.from_env(),容器内跑,支持 mount/copy/exec_run,工具被 wrap 成向容器内 FastAPI 发请求)、UbuntuDockerRuntimeDaytonaRuntime(Daytona 云沙箱)、RemoteHTTPRuntimeruntimes/api.py 起远程服务)、LLMGuardRuntime(风险闸门,见安全章)。BaseRuntimeruntimes/base.py)统一 add/reset/stop/get_tools + 上下文管理器。.container/ 有 Dockerfile。

与模型的协同设计

  • 模型无关抽象models/ BaseModelBackend + ModelFactory.create(platform, type, config);支持 OpenAI/Anthropic/Gemini/Qwen/DeepSeek/Ollama/vLLM 等几十家;ModelManager 支持多模型(负载均衡/fallback,chat_agent _resolve_model_list746)。构造器可传单 model 或 model list。
  • 能力适配:非严格 structured-output 模型走 prompt + 正则(见 Prompt 章);工具 schema 强制 strict(见工具章)。ModelType.DEFAULT/ModelPlatformType.DEFAULT 作缺省。
  • 专门 configconfigs/ 每家一个 ChatGPTConfig 等;schemas/ OpenAI schema converter。
  • 定位是”通用 harness 适配任意模型”,为某自家模型 co-design;但 RL/datagen 侧(环境 + verifier + reward model)是为训练/精调模型服务的配套(见轨迹章)。

轨迹利用(session/trajectory 是否反哺训练/评测)

CAMEL 的核心卖点之一就是用多 agent 轨迹造数据

  • 轨迹采集 → 训练格式data_collectors/——BaseDataCollector(base.py89) record/convert/llm_convertShareGPTDataCollectorsharegpt_collector.py76)把 agent 对话转 ShareGPT 格式(convert()97),AlpacaCollector 转 Alpaca。直接产 SFT 数据。
  • 合成数据datagen/):cot_datagen(CoT)、self_improving_cot(STaR,见自进化章)、self_instructsource2synthevol_instruct(Evol-Instruct)。role-playing/workforce 生成的对话是这些 pipeline 的原料(CAMEL 论文主张”role-playing 造大规模对话数据”)。
  • RL 环境 + 校验environments/ + verifiers/):SingleStepEnvsingle_step.py,LLM 作 policy,reset/step 返 reward)、MultiStepEnvrlcards_env/tic_tac_toeverifiers/ 有 math/physics/python verifier 做结果正确性判定;models/reward/ 有 RewardModel + Evaluator。构成”轨迹 → reward → 训练”闭环的评测/奖励侧。
  • Benchmarkbenchmarks/):内置多 benchmark 跑分。
  • 结论:轨迹强反哺训练与评测——这是框架一等目标,不只是日志。运行期 workflow memory(见自进化章)则是轨迹反哺”同一 agent 后续任务”的另一条线。

与同类 harness 的关键差异(1-3 条)

  1. 造数/训练闭环是一等目标:多数 harness(Claude Code、OpenHands 等)把轨迹当日志;CAMEL 把 role-playing/workforce 产生的对话直接接入 data_collectors(ShareGPT/Alpaca)+ datagen(STaR/self-instruct/evol)+ environments/verifiers/reward model,系统化转成 SFT/RL 数据——这是它区别于工程型 harness 的最大特征。
  2. 编排层重、单 agent 轻:单 agent(ChatAgent)只是标准 while-loop tool-calling,重量押在 societies/workforce(coordinator/planner/dynamic worker + AUTO_DECOMPOSE 失败自恢复 + 可套娃嵌套 workforce),偏”多 agent 社会”研究范式,而非单强 agent 打磨。
  3. 同时具备 SKILL.md 技能系统 + 模型驱动的风险审批闸门SkillToolkit 是 Anthropic 风格 SKILL.md 发现/按需加载;LLMGuardRuntime 用专门 guard agent 给每次工具调用打风险分并按 threshold 拦截——两者在开源多 agent 框架里同时具备的并不多。

原始源码定位

  • repo: https://github.com/camel-ai/camel
  • commit/version analyzed: 147d92652cd20f0eb3f541c612aa105a4ad12550(2026-07-10 19:41:38 +0800,--depth 1 浅克隆,Apache-2.0,Python)
  • 关键文件列表(相对 camel/ 包):
    • agents/chat_agent.py(主循环 _step_impl、工具执行、summarization、记忆持久化、system prompt)
    • agents/base.py, agents/_types.py, agents/role_assignment_agent.py, agents/task_agent.py
    • toolkits/function_tool.py, toolkits/base.py, toolkits/skill_toolkit.py, toolkits/mcp_toolkit.py, toolkits/code_execution.py, toolkits/human_toolkit.py, toolkits/memory_toolkit.py, toolkits/context_summarizer_toolkit.py
    • memories/base.py, memories/agent_memories.py, memories/context_creators/score_based.py
    • runtimes/base.py, runtimes/llm_guard_runtime.py, runtimes/docker_runtime.py
    • societies/role_playing.py, societies/workforce/workforce.py, societies/workforce/workflow_memory_manager.py, societies/workforce/single_agent_worker.py, societies/workforce/workforce_logger.py, societies/workforce/prompts.py, societies/workforce/events.py
    • datagen/self_improving_cot.py, data_collectors/sharegpt_collector.py, data_collectors/base.py
    • utils/langfuse.py, logger.py, environments/single_step.py

一手源存档(sources/)

/Users/zhao/projects/self-wiki/ai-research/sources/harness/camel/ 下保存:

  • NOTES.md — 第一阶段源码级调研笔记(12 维度,每条带文件 + 行号)。
  • src/ — 13 个核心源文件留档:
    • chat_agent.pyagent_memories.pymemories_base.pyscore_based.py
    • function_tool.pytoolkits_base.pyskill_toolkit.py
    • llm_guard_runtime.py
    • role_playing.pyworkforce.pyworkflow_memory_manager.py
    • self_improving_cot.pysharegpt_collector.py