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.py(BaseToolkit)。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_impl内while 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 点):
- 无 tool call 且无 response_terminators → 直接 break(3093,最常见的自然终止)。
- 命中 external tool(在
_external_tool_schemas里)→ 收集到external_tool_call_requests后 break(3043),把控制权交还调用方。 max_iteration到顶 → break(有 tool 3046-3051;无 tool 3072-3080)。默认max_iteration=None(无限,直到模型自然停止发 tool call)。stop_event(threading.Event)被 set →_step_terminate(..., "termination_triggered")(2988)。- 上下文超 token →
RuntimeError捕获后_step_terminate(..., "max_tokens_exceeded")(2955)。 - 配了
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_calls;get_context()(169) = retrieve 后交给 ContextCreator 生成(List[OpenAIMessage], token_count)。 - 三种实现(
memories/agent_memories.py):ChatHistoryMemory(默认):ChatHistoryBlock+ 可选window_size滑窗(只取最近 N 条,67-78)。VectorDBMemory:VectorDBBlock向量检索,retrieve_limit=3(189-195)——长期语义记忆。LongtermAgentMemory:ChatHistory + VectorDB 组合,retrieve 时合并两路(229-283)。
- ContextCreator(
memories/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。 - 另有独立
ContextSummarizerToolkit(toolkits/context_summarizer_toolkit.py):把完整历史落盘(summary + history 文件)、可搜索历史、should_compress_context,是”工具化”的上下文管理,agent 可主动调。 - 会话持久化:
save_memory(path)(1705) /load_memory_from_path(path)(1655) /load_memory(memory)(1641);MemoryToolkit(toolkits/memory_toolkit.py)把 save/load/clear 暴露成工具(JSON 序列化)。 prune_tool_calls_from_memory(构造参数)+clean_tool_calls():可从 memory 清掉工具调用细节省 token。
工具体系(定义/调用协议/注册/权限)
- 定义:
toolkits/function_tool.py的FunctionTool(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,450generate_docstring)和synthesize_output(LLM 模拟工具输出)。 - Toolkit 基类:
toolkits/base.pyBaseToolkit——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 / MCPfunc.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)。 - MCP:
toolkits/mcp_toolkit.pyMCPToolkit(230)管理多 MCP server 连接生命周期(connect/disconnect/__aenter__),把 MCP tool 转成 FunctionTool;ensure_strict_json_schema(57) 把 MCP schema 转严格模式。另有mcp_agent.py(449 行)。 - 权限/masking:
mask_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)+ 各领域TextPromptDict。prompts/ai_society.py有ASSISTANT_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=True(structured_output_handler.py)。
Router / 编排(任务分解、多 agent、子 agent)
两条编排路线:
- RolePlaying(
societies/role_playing.py,CAMEL 论文原型):两个 ChatAgent —— AI User(发指令)+ AI Assistant(执行),可选 Critic。init_chat()(548) 起对话,step()(631) 一来一回。是”对话式”协作,非层级调度。 - Workforce(
societies/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 节点类型:
SingleAgentWorker、RolePlayingWorker(worker 内部再跑 role-playing)、嵌套Workforce(可套娃)。 - 失败恢复策略(
WorkforceMode):AUTO_DECOMPOSE(默认,失败时 decompose/replan/新建 worker)vsPIPELINE(简单重试、失败信息传给下游);FailureHandlingConfig配max_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)。
- Coordinator Agent(任务分配):
- 另有
agents/role_assignment_agent.py、agents/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.py的enable_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.pySelfImprovingCoTPipeline(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.py。configure_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 时跳过)。 - AgentOps:
BaseToolkit用AgentOpsMetametaclass,工具调用自动埋点。 - 结构化日志:
logger.py(get_logger/set_log_file/set_log_level)。ChatAgent 内_sanitize_messages_for_logging()(3705) 脱敏后记录;_emit_request_usage()每 iteration 发 token 用量事件。 - Workforce 日志/指标:
societies/workforce/workforce_logger.pyWorkforceLogger(同时实现 WorkforceCallback + WorkforceMetrics):log_task_created/decomposed/assigned/started/updated、log_stream_chunk,log_entries为结构化 dict(含 timestamp/event_type)。事件定义在workforce/events.py。回调机制WorkforceCallback(callbacks=[...])可外接自定义观测。 - 仓库根有
camel_log_viewer.html(本地日志可视化)。
安全与权限(审批门、密钥管理)
- LLM 风险审批门(核心):
runtimes/llm_guard_runtime.pyLLMGuardRuntime(63)。add(funcs, threshold=2)(105) 用 wrapper 包住每个工具:调用前先让一个专门的 guard ChatAgent(system prompt=GUARDPROMPT28,1-3 分风险量表)评估”函数名 + 描述 + 实参”的风险分(用 external toolfunction_risk);score > threshold就拒绝执行、返回{"error": ...}(163-170);否则放行真实函数(185)。配套IgnoreRiskToolkit——可对某函数登记”已知安全”跳过下次评估(138-145)。这是模型驱动的动态审批闸门。 - HITL 审批:
toolkits/human_toolkit.pyHumanToolkit.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。CodeExecutionToolkitunsafe_mode(eval()无检查)默认 False。仓库有SECURITY.md。
沙箱与执行隔离
两层隔离:
- 代码解释器沙箱(
interpreters/):CodeExecutionToolkit(toolkits/code_execution.py)可选sandbox:internal_python(受限 AST 解释器InternalPythonInterpreter+import_white_list白名单)、subprocess(默认,本机子进程)、jupyter(ipython)、docker(DockerInterpreter容器内跑)、e2b(E2B 云沙箱)、microsandbox。host_execution_sandboxes={internal_python, subprocess}标记哪些是”跑在本机”(有风险)。terminal_toolkit 另有 go/java runtime。 - 工具运行时隔离(
runtimes/):把任意 FunctionTool 搬到隔离环境执行——DockerRuntime(docker.from_env(),容器内跑,支持 mount/copy/exec_run,工具被 wrap 成向容器内 FastAPI 发请求)、UbuntuDockerRuntime、DaytonaRuntime(Daytona 云沙箱)、RemoteHTTPRuntime(runtimes/api.py起远程服务)、LLMGuardRuntime(风险闸门,见安全章)。BaseRuntime(runtimes/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作缺省。 - 专门 config:
configs/每家一个 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_convert;ShareGPTDataCollector(sharegpt_collector.py76)把 agent 对话转 ShareGPT 格式(convert()97),AlpacaCollector转 Alpaca。直接产 SFT 数据。 - 合成数据(
datagen/):cot_datagen(CoT)、self_improving_cot(STaR,见自进化章)、self_instruct、source2synth、evol_instruct(Evol-Instruct)。role-playing/workforce 生成的对话是这些 pipeline 的原料(CAMEL 论文主张”role-playing 造大规模对话数据”)。 - RL 环境 + 校验(
environments/+verifiers/):SingleStepEnv(single_step.py,LLM 作 policy,reset/step返 reward)、MultiStepEnv、rlcards_env/tic_tac_toe;verifiers/有 math/physics/python verifier 做结果正确性判定;models/reward/有 RewardModel + Evaluator。构成”轨迹 → reward → 训练”闭环的评测/奖励侧。 - Benchmark(
benchmarks/):内置多 benchmark 跑分。 - 结论:轨迹强反哺训练与评测——这是框架一等目标,不只是日志。运行期 workflow memory(见自进化章)则是轨迹反哺”同一 agent 后续任务”的另一条线。
与同类 harness 的关键差异(1-3 条)
- 造数/训练闭环是一等目标:多数 harness(Claude Code、OpenHands 等)把轨迹当日志;CAMEL 把 role-playing/workforce 产生的对话直接接入
data_collectors(ShareGPT/Alpaca)+datagen(STaR/self-instruct/evol)+environments/verifiers/reward model,系统化转成 SFT/RL 数据——这是它区别于工程型 harness 的最大特征。 - 编排层重、单 agent 轻:单 agent(ChatAgent)只是标准 while-loop tool-calling,重量押在
societies/workforce(coordinator/planner/dynamic worker + AUTO_DECOMPOSE 失败自恢复 + 可套娃嵌套 workforce),偏”多 agent 社会”研究范式,而非单强 agent 打磨。 - 同时具备 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.pytoolkits/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.pymemories/base.py,memories/agent_memories.py,memories/context_creators/score_based.pyruntimes/base.py,runtimes/llm_guard_runtime.py,runtimes/docker_runtime.pysocieties/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.pydatagen/self_improving_cot.py,data_collectors/sharegpt_collector.py,data_collectors/base.pyutils/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.py、agent_memories.py、memories_base.py、score_based.pyfunction_tool.py、toolkits_base.py、skill_toolkit.pyllm_guard_runtime.pyrole_playing.py、workforce.py、workflow_memory_manager.pyself_improving_cot.py、sharegpt_collector.py