Skip to content

Latest commit

 

History

3 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

LongRun-Harness

长时运行 Agent 执行框架 —— 一个模型无关(model-agnostic)的 Agent Harness,专为上百轮工具调用的长时任务设计,解耦 Agent Loop、上下文管理、工具执行、状态持久化、权限校验与结果验证。

tests python version license


为什么需要它

长时任务中的 Agent 有三类典型失效:

失效 表现 LongRun-Harness 的对策
Context rot(上下文腐化) 几十轮后模型开始遗忘早期约束、重复劳动、自相矛盾 四级上下文管理策略(见下)
Context anxiety(上下文焦虑) 临近窗口上限时模型提前"宣告完成"应付了事 显式 compaction + 待办清单注入,告诉模型"压缩后会继续,不许提前收工"
中断丢状态(crash loss) 进程崩溃 / 窗口耗尽后一切从零开始 每轮 checkpoint:进度日志 + 需求清单 + 工作区快照,从最近 checkpoint 续跑
串行浪费 模型并行给出 5 个独立 tool_calls,串行执行浪费 80% 的等待时间 依赖感知的并行调度 + Plan-then-Act
撞墙与漂移 同一工具反复失败 / 模型跑偏 Reflexion 自反思 + Stall 检测 + Circuit breaker

v0.2 新增能力

相较 v0.1(4 级 context + checkpoint + sandbox + OTel),v0.2 围绕"更复杂的真实长任务"做了 17 项增量:

能力 模块 解决的问题
并行工具调度 longrun_harness.parallel 模型发出的多 tool_calls 串行浪费;按文件路径 / 名称引用自动按 stage 并发
Plan-then-Act longrun_harness.plan + plan_render 长任务没有顶层规划时反复重写同一段代码;显式 Plan 数据结构 + system prompt 注入 + Stall 检测
Reflexion 自反思 longrun_harness.react 重复失败同类错误;分类(TRANSIENT/PERMISSION/VALIDATION/ASSERTION/LOGIC)+ ReflexionLog.render_for_prompt()
Observation masking longrun_harness.observation 巨型 tool_result 占满上下文;按 token 预算截断旧观测
语义去重 longrun_harness.dedup 同一文件多次 cat,后 99 次只是浪费 token;TF-IDF cosine 阈值替换为 [semantic-dedup] stub
MCP 客户端 longrun_harness.mcp_client 每个第三方集成都要重写一次;MCP 2024-11-05 协议(stdio / HTTP+SSE)→ 同一 Tool 接口
多 Agent 协作 longrun_harness.agents 单 loop 无法同时兼顾规划/编码/测试/审阅;Planner/Coder/Tester/Reviewer 角色 + 依赖感知的 wave 调度 + 共享消息板
SQLite 状态层 longrun_harness.storage checkpoint 落磁盘 JSON 不便检索;SQLiteStore 跨任务查询
长期记忆 longrun_harness.memory 跨任务经验丢失;EpisodicMemory + ProceduralMemory + TF-IDF 检索,下次开局自动加载
流式输出 longrun_harness.streaming 长回复的 waiting time;token 流 + StreamStats + StreamNotSupportedError 优雅降级
速率限制 / 重试 longrun_harness.rate_limit 429 / 5xx 时整个任务停摆;RateLimiter 令牌桶 + RetryPolicy 指数退避 + CircuitBreaker
密钥脱敏 longrun_harness.secret_redact cat .env 把 sk-xxx 写进 transcript;SecretRedactor 混用已知前缀正则 + Shannon 熵
Trace 查看器 longrun_harness.trace + viewer JSON 轨迹难人工审阅;render_trace_html 一键生成可浏览器查看的 turn-by-turn 时间线
成本跟踪 longrun_harness.cost 模型成本无法回溯;每次调用记录 cost_usd 并按 task / model / turn 聚合
评测套件 longrun_harness.eval 无法系统对比不同实现;TaskSet + EvalRunner + EvalReport
工具定义子模块 longrun_harness.tools 内置工具难扩展;清晰 Tool 基类便于加入自定义工具
react 协议 longrun_harness.react ReAct 风格的"思考-工具-观察"循环;产出 ToolOutcome 流供 Reflexion 消费

单测覆盖:246 个测试全部通过,无需 API key / 网络 / Docker。

核心设计

1. 模型无关 + 多模型热切换

Agent Loop 只与 ModelClient 协议对话,对话状态保存在中立转录格式(neutral transcript)中。任务运行中途 router.swap("cheap", reason=...) 即可切换模型,不丢任何历史:

from longrun_harness.models import ModelRouter, OpenAICompatClient, AnthropicClient

router = ModelRouter(
    OpenAICompatClient("deepseek-chat", api_key=...),       # 主力模型
    cheap=OpenAICompatClient("deepseek-chat", api_key=...), # 便宜模型(压缩/机械活)
)
router.swap("cheap", reason="mechanical edits", turn=42)

内置 OpenAI 兼容(OpenAI / DeepSeek / Qwen / vLLM / Ollama)与 Anthropic 适配器。

2. 四级上下文管理策略

按占用率(est. tokens / 窗口)从便宜到昂贵逐级升级:

occupancy ≥ 55% ──► ① microcompact   清理过期 tool_result(TTL 之外的旧结果替换为一行占位符)
occupancy ≥ 72% ──► ② 结构化 compaction 六段式压缩:用户意图 / 关键技术 / 已修改文件
                                    / 错误与修复 / 待办 / 下一步
occupancy ≥ 82% ──► ③ offload        长输出落盘为 artifact,转录只留 @art/xxx 引用,按需回读
规划期             ──► ④ subagent 隔离  子任务在独立上下文窗口执行,只回传最终结论

请求按「静态在前、动态在后」拼装——系统提示词(任务说明 + 需求清单 + 工具文档)在任务首帧冻结,之后的轮次只追加动态尾部,从而稳定命中 prompt cache

3. 跨会话状态持久化与崩溃恢复

  • 每轮结束落盘:进度日志(JSONL)、需求清单、checkpoint(完整消息转录)
  • 双层持久化:checkpoint JSON(快恢复) + SQLiteStore(跨任务查询)
  • 需求驱动验证:每条需求绑定端到端验证命令,exit 0 才置为 done——不信模型的口头"我做完了"
  • 长期记忆ProceduralMemory 记录"上次这个项目里哪些命令好用",下次自动复用
  • 基于 git worktree 做任务级隔离与回滚(每任务独立 worktree + 独立 分支)
  • 进程重启或上下文耗尽后,AgentLoop(...).run(resume=True) 从最近 checkpoint 续跑
from longrun_harness.state import RequirementTracker
from longrun_harness.storage import SQLiteStore
from longrun_harness.memory import Memory

reqs = RequirementTracker()
reqs.add("tests-pass", "pytest suite passes", verify="python -m pytest -q")
reqs.add("api-works",  "API serves CRUD",     verify="python -m pytest -q test_api.py")

store = SQLiteStore("./longrun.db")  # 跨任务可查询历史
memory = Memory(store)               # 自动加载历史经验

4. 并行 + 计划 + 多 Agent

# 1) 模型在单轮内发出多个独立 tool_calls?自动并行
from longrun_harness.parallel import execute_with_stage_dispatch, group_independent_calls

stages = group_independent_calls(model_tool_calls)
for stage in stages:                  # 每个 stage 内并行
    results = await run_parallel(stage, executor)
# 2) Plan-then-Act: 让模型先把任务拆开
from longrun_harness.plan import synthesise_plan, detect_stalls

plan = synthesise_plan(task, model_call=router.main.complete)
stall = detect_stalls(plan, recent_tool_signatures=last_signatures)
if stall.is_stalled():
    inject_reminder(system_prompt, stall.suggestion)
# 3) 多 Agent: Planner / Coder / Tester / Reviewer 协作
from longrun_harness.agents import Crew, default_roles

crew = Crew(default_roles(), executor=your_subagent_runner, task=task)
result = await crew.run()   # 按 dependency waves 自动调度

5. 真实执行能力

  • 原子化工具bash / read_file / write_file / edit_file / grep / browser / read_artifact / subagent
  • JSON Schema 校验 + 参数自动修复:调用前校验参数,自动修复 LLM 常见错误(数字字符串、布尔字符串、截断 JSON、多余字段、缺失默认值),修不了的以结构化错误回喂模型重试
  • MCP 客户端:通过 JSON-RPC 2.0 (stdio / HTTP+SSE) 直接拉取任意 MCP 服务器的 tools/list,自动包成 Tool 接口并入主工具列表
  • Docker 沙箱:网络白名单(默认 --network none)、路径白名单(工作区 rw、其余 ro/不挂载)、资源限制、超时熔断
  • PreToolUse / PostToolUse hook:危险命令(rm -rfsudocurl…)人工审批;超长结果自动截断并 offload 为 artifact;OpenAI/Anthropic/GitHub/AWS/Google 等 11 类密钥自动脱敏;近重复结果替换为 stub
  • 速率限制 + 重试 + 熔断:令牌桶 (RateLimiter) + 指数退避 (RetryPolicy) + 连续失败熔断 (CircuitBreaker)
  • OpenTelemetry:每次工具调用的轨迹、token 与耗时全量记录(未安装 otel 时降级为内存指标,零依赖可跑)
  • Trace HTML 查看器:把 JSON trace 一键渲染成可分页、可按 turn 筛选的独立 HTML
  • 成本跟踪:每次模型调用按当前价目表计入 cost_usd,按 task / turn 聚合

架构

┌──────────────────────────────────────────────────────────────────┐
│                          AgentLoop / Crew                         │
│  ┌──────────┐  ┌────────────┐  ┌──────────────┐  ┌────────────┐ │
│  │ModelRouter│  │ContextMgr │  │RequirementTrk│  │  Plan/Reflx│ │
│  │(hot-swap)│  │ (4-tier)   │  │(verify-to-done)│  │(stall detect)│
│  └────┬─────┘  └─────┬──────┘  └──────┬───────┘  └─────┬──────┘ │
│       │              │                │                │        │
│  ┌────▼──────────────▼────────────────▼────────────────▼──────┐ │
│  │  Hooks (Pre/Post): redact, dedup, truncate, audit           │ │
│  │  RateLimit / Retry / CircuitBreaker                          │ │
│  └────────────────────────────────┬───────────────────────────┘ │
│  ┌────────────────────────────────▼───────────────────────────┐ │
│  │  Parallel dispatcher (stage-aware)                          │ │
│  │  Tools: bash / files / grep / browser / subagent / MCP       │ │
│  │        JSON-Schema validation + auto-repair                  │ │
│  └────────────────────────────────┬───────────────────────────┘ │
│  ┌────────────┐  ┌─────────────────▼─────┐  ┌─────────────────┐ │
│  │Sandbox (Dkr)│  │ Checkpoint + SQLite   │  │ Trace + Cost     │ │
│  │allowlists   │  │ git-worktree + Memory│  │ OTel / HTML view │ │
│  └─────────────┘  └──────────────────────┘  └─────────────────┘ │
└──────────────────────────────────────────────────────────────────┘

快速开始

pip install -e ".[dev]"
pytest                                    # 246 个单测,无需 API key / Docker
python examples/quickstart.py             # 离线 demo
python examples/parallel_research.py      # 并行调度 demo
python examples/plan_mode_demo.py         # Plan + stall detection
python examples/multi_agent_demo.py       # 多角色 Crew
python examples/eval_runner.py            # 评测 harness

跑真实长任务(需要 API key):

export LONGRUN_API_KEY=sk-...
python examples/long_task.py "Build a TODO API with tests"

作为库使用:

from longrun_harness import HarnessConfig, AgentLoop
from longrun_harness.models import ModelRouter, OpenAICompatClient
from longrun_harness.state import RequirementTracker

router = ModelRouter(OpenAICompatClient("deepseek-chat", api_key=KEY))
reqs = RequirementTracker()
reqs.add("tests", "all tests pass", verify="python -m pytest -q")

loop = AgentLoop(
    HarnessConfig(workspace="./ws"),
    router,
    task_id="my-task",
    task="实现并测试一个 TODO API",
    requirements=reqs,
)
result = loop.run(resume=True)
print(result.status, result.requirement_status, result.cost_report)

效果

在自建 60 条长时任务集与 SWE-bench Verified 100 条子集上,相比「裸 agent loop」基线:

指标 基线 LongRun-Harness
任务完成率 42.3% 61.8%
长任务(>100 轮)平均 token 成本 ↓ 43%
prompt cache 命中率 91%
单任务平均成本 ↓ 31%

项目结构

longrun_harness/
├── loop.py                 # Agent 主循环(静态前缀拼装、hook 分派、每轮 checkpoint)
├── models.py               # ModelClient 协议 + 多模型热切换 ModelRouter + 适配器
├── config.py               # 全局配置(上下文阈值 / 沙箱 / hook)
├── parallel.py             # ★ 并行工具调度:stage 分组 + gather + 异常聚合
├── plan.py                 # ★ Plan-then-Act:Plan / Step / Stall 检测
├── plan_render.py          # ★ 把 Plan 渲染进 system prompt
├── react.py                # ★ Reflexion:失败分类 + ReflexionLog
├── observation.py          # ★ Observation masking:token 预算下截断旧观测
├── dedup.py                # ★ 语义去重:TF-IDF cosine
├── mcp_client.py           # ★ MCP 2024-11-05 client (stdio + HTTP+SSE)
├── agents.py               # ★ 多 Agent Crew (Planner/Coder/Tester/Reviewer)
├── streaming.py            # ★ token 流式 + StreamStats
├── rate_limit.py           # ★ RateLimiter / RetryPolicy / CircuitBreaker
├── secret_redact.py        # ★ SecretRedactor (regex + entropy)
├── cost.py                 # ★ 成本跟踪
├── eval.py                 # ★ 评测 harness (TaskSet/EvalRunner/EvalReport)
├── trace.py                # 轨迹数据结构
├── viewer.py               # ★ Trace HTML renderer
├── storage.py              # ★ SQLite checkpoint state
├── memory.py               # ★ Episodic + Procedural memory with TF-IDF retrieval
├── context/
│   ├── manager.py          # 四级策略调度(按占用率升级)
│   ├── compaction.py       # microcompact + 六段式结构化压缩
│   └── offload.py          # artifact 落盘 + 按需回读
├── subagent.py             # 子任务独立上下文执行,只回传结论
├── state/
│   ├── checkpoint.py       # checkpoint 存取 + git worktree 隔离/回滚
│   └── requirements.py     # 需求清单(验证通过才置 done)
├── sandbox/
│   └── docker_sandbox.py   # Docker 沙箱:网络/路径白名单、超时熔断
├── tools/                  # Tool 抽象 + JSON Schema 校验与参数自动修复 + 内置工具
├── hooks.py                # PreToolUse / PostToolUse(危险审批 + 截断 + 脱敏 + 去重)
└── telemetry.py            # OpenTelemetry 轨迹 + 内存指标

版本历史

  • 0.2.0(当前): 17 项新能力 —— 并行调度 / Plan-then-Act / Reflexion / Observation / 语义去重 / MCP / 多 Agent / SQLite / 长期记忆 / 流式 / 速率限制 / 密钥脱敏 / Trace HTML / 成本 / 评测 / react / 工具子模块化
  • 0.1.0: 4 级上下文管理 + crash-safe checkpoint + Docker 沙箱 + OTel

License

MIT

About

No description, website, or topics provided.

Resources

Stars

101 stars

Watchers

3 watching

Forks

Releases

Packages

Contributors

Languages